mirror of
https://github.com/tmux/tmux.git
synced 2025-01-05 23:38:48 +00:00
Merge branch 'obsd-master'
This commit is contained in:
commit
01c4919f5f
@ -150,6 +150,7 @@ dist_tmux_SOURCES = \
|
||||
grid-reader.c \
|
||||
grid-view.c \
|
||||
grid.c \
|
||||
hyperlinks.c \
|
||||
input-keys.c \
|
||||
input.c \
|
||||
job.c \
|
||||
|
@ -53,8 +53,8 @@ const struct cmd_entry cmd_clear_history_entry = {
|
||||
.name = "clear-history",
|
||||
.alias = "clearhist",
|
||||
|
||||
.args = { "t:", 0, 0, NULL },
|
||||
.usage = CMD_TARGET_PANE_USAGE,
|
||||
.args = { "Ht:", 0, 0, NULL },
|
||||
.usage = "[-H] " CMD_TARGET_PANE_USAGE,
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
@ -204,6 +204,8 @@ cmd_capture_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
if (cmd_get_entry(self) == &cmd_clear_history_entry) {
|
||||
window_pane_reset_mode_all(wp);
|
||||
grid_clear_history(wp->base.grid);
|
||||
if (args_has(args, 'H'))
|
||||
screen_reset_hyperlinks(wp->screen);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
|
||||
llen = 0;
|
||||
|
||||
if (sx < len * 6 || sy < 5) {
|
||||
tty_attributes(tty, &fgc, &grid_default_cell, NULL);
|
||||
tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
|
||||
if (sx >= len + llen + 1) {
|
||||
len += llen + 1;
|
||||
tty_cursor(tty, xoff + px - len / 2, yoff + py);
|
||||
@ -161,7 +161,7 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
|
||||
px -= len * 3;
|
||||
py -= 2;
|
||||
|
||||
tty_attributes(tty, &bgc, &grid_default_cell, NULL);
|
||||
tty_attributes(tty, &bgc, &grid_default_cell, NULL, NULL);
|
||||
for (ptr = buf; *ptr != '\0'; ptr++) {
|
||||
if (*ptr < '0' || *ptr > '9')
|
||||
continue;
|
||||
@ -179,7 +179,7 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
|
||||
|
||||
if (sy <= 6)
|
||||
goto out;
|
||||
tty_attributes(tty, &fgc, &grid_default_cell, NULL);
|
||||
tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
|
||||
if (rlen != 0 && sx >= rlen) {
|
||||
tty_cursor(tty, xoff + sx - rlen, yoff);
|
||||
tty_putn(tty, rbuf, rlen, rlen);
|
||||
|
13
grid.c
13
grid.c
@ -37,7 +37,7 @@
|
||||
|
||||
/* Default grid cell data. */
|
||||
const struct grid_cell grid_default_cell = {
|
||||
{ { ' ' }, 0, 1, 1 }, 0, 0, 8, 8, 0
|
||||
{ { ' ' }, 0, 1, 1 }, 0, 0, 8, 8, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
@ -45,12 +45,12 @@ const struct grid_cell grid_default_cell = {
|
||||
* appears in the grid - because of this, they are always extended cells.
|
||||
*/
|
||||
static const struct grid_cell grid_padding_cell = {
|
||||
{ { '!' }, 0, 0, 0 }, 0, GRID_FLAG_PADDING, 8, 8, 0
|
||||
{ { '!' }, 0, 0, 0 }, 0, GRID_FLAG_PADDING, 8, 8, 0, 0
|
||||
};
|
||||
|
||||
/* Cleared grid cell data. */
|
||||
static const struct grid_cell grid_cleared_cell = {
|
||||
{ { ' ' }, 0, 1, 1 }, 0, GRID_FLAG_CLEARED, 8, 8, 0
|
||||
{ { ' ' }, 0, 1, 1 }, 0, GRID_FLAG_CLEARED, 8, 8, 0, 0
|
||||
};
|
||||
static const struct grid_cell_entry grid_cleared_entry = {
|
||||
GRID_FLAG_CLEARED, { .data = { 0, 8, 8, ' ' } }
|
||||
@ -90,6 +90,8 @@ grid_need_extended_cell(const struct grid_cell_entry *gce,
|
||||
return (1);
|
||||
if (gc->us != 0) /* only supports 256 or RGB */
|
||||
return (1);
|
||||
if (gc->link != 0)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -131,6 +133,7 @@ grid_extended_cell(struct grid_line *gl, struct grid_cell_entry *gce,
|
||||
gee->fg = gc->fg;
|
||||
gee->bg = gc->bg;
|
||||
gee->us = gc->us;
|
||||
gee->link = gc->link;
|
||||
return (gee);
|
||||
}
|
||||
|
||||
@ -231,6 +234,8 @@ grid_cells_look_equal(const struct grid_cell *gc1, const struct grid_cell *gc2)
|
||||
return (0);
|
||||
if (gc1->attr != gc2->attr || gc1->flags != gc2->flags)
|
||||
return (0);
|
||||
if (gc1->link != gc2->link)
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -509,6 +514,7 @@ grid_get_cell1(struct grid_line *gl, u_int px, struct grid_cell *gc)
|
||||
gc->fg = gee->fg;
|
||||
gc->bg = gee->bg;
|
||||
gc->us = gee->us;
|
||||
gc->link = gee->link;
|
||||
utf8_to_data(gee->data, &gc->data);
|
||||
}
|
||||
return;
|
||||
@ -524,6 +530,7 @@ grid_get_cell1(struct grid_line *gl, u_int px, struct grid_cell *gc)
|
||||
gc->bg |= COLOUR_FLAG_256;
|
||||
gc->us = 0;
|
||||
utf8_set(&gc->data, gce->data.data);
|
||||
gc->link = 0;
|
||||
}
|
||||
|
||||
/* Get cell for reading. */
|
||||
|
225
hyperlinks.c
Normal file
225
hyperlinks.c
Normal file
@ -0,0 +1,225 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2021 Will <author@will.party>
|
||||
* Copyright (c) 2022 Jeff Chiang <pobomp@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <vis.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/*
|
||||
* OSC 8 hyperlinks, described at:
|
||||
*
|
||||
* https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
|
||||
*
|
||||
* Each hyperlink and ID combination is assigned a number ("inner" in this
|
||||
* file) which is stored in an extended grid cell and maps into a tree here.
|
||||
*
|
||||
* Each URI has one inner number and one external ID (which tmux uses to send
|
||||
* the hyperlink to the terminal) and one internal ID (which is received from
|
||||
* the sending application inside tmux).
|
||||
*
|
||||
* Anonymous hyperlinks are each unique and are not reused even if they have
|
||||
* the same URI (terminals will not want to tie them together).
|
||||
*/
|
||||
|
||||
#define MAX_HYPERLINKS 5000
|
||||
|
||||
static uint64_t hyperlinks_next_external_id = 1;
|
||||
static u_int global_hyperlinks_count;
|
||||
|
||||
struct hyperlinks_uri {
|
||||
struct hyperlinks *tree;
|
||||
|
||||
u_int inner;
|
||||
const char *internal_id;
|
||||
const char *external_id;
|
||||
const char *uri;
|
||||
|
||||
TAILQ_ENTRY(hyperlinks_uri) list_entry;
|
||||
RB_ENTRY(hyperlinks_uri) by_inner_entry;
|
||||
RB_ENTRY(hyperlinks_uri) by_uri_entry; /* by internal ID and URI */
|
||||
};
|
||||
RB_HEAD(hyperlinks_by_uri_tree, hyperlinks_uri);
|
||||
RB_HEAD(hyperlinks_by_inner_tree, hyperlinks_uri);
|
||||
|
||||
TAILQ_HEAD(hyperlinks_list, hyperlinks_uri);
|
||||
static struct hyperlinks_list global_hyperlinks =
|
||||
TAILQ_HEAD_INITIALIZER(global_hyperlinks);
|
||||
|
||||
struct hyperlinks {
|
||||
u_int next_inner;
|
||||
struct hyperlinks_by_inner_tree by_inner;
|
||||
struct hyperlinks_by_uri_tree by_uri;
|
||||
};
|
||||
|
||||
static int
|
||||
hyperlinks_by_uri_cmp(struct hyperlinks_uri *left, struct hyperlinks_uri *right)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (*left->internal_id == '\0' || *right->internal_id == '\0') {
|
||||
/*
|
||||
* If both URIs are anonymous, use the inner for comparison so
|
||||
* that they do not match even if the URI is the same - each
|
||||
* anonymous URI should be unique.
|
||||
*/
|
||||
if (*left->internal_id != '\0')
|
||||
return (-1);
|
||||
if (*right->internal_id != '\0')
|
||||
return (1);
|
||||
return (left->inner - right->inner);
|
||||
}
|
||||
|
||||
r = strcmp(left->internal_id, right->internal_id);
|
||||
if (r != 0)
|
||||
return (r);
|
||||
return (strcmp(left->uri, right->uri));
|
||||
}
|
||||
RB_PROTOTYPE_STATIC(hyperlinks_by_uri_tree, hyperlinks_uri, by_uri_entry,
|
||||
hyperlinks_by_uri_cmp);
|
||||
RB_GENERATE_STATIC(hyperlinks_by_uri_tree, hyperlinks_uri, by_uri_entry,
|
||||
hyperlinks_by_uri_cmp);
|
||||
|
||||
static int
|
||||
hyperlinks_by_inner_cmp(struct hyperlinks_uri *left,
|
||||
struct hyperlinks_uri *right)
|
||||
{
|
||||
return (left->inner - right->inner);
|
||||
}
|
||||
RB_PROTOTYPE_STATIC(hyperlinks_by_inner_tree, hyperlinks_uri, by_inner_entry,
|
||||
hyperlinks_by_inner_cmp);
|
||||
RB_GENERATE_STATIC(hyperlinks_by_inner_tree, hyperlinks_uri, by_inner_entry,
|
||||
hyperlinks_by_inner_cmp);
|
||||
|
||||
/* Remove a hyperlink. */
|
||||
static void
|
||||
hyperlinks_remove(struct hyperlinks_uri *hlu)
|
||||
{
|
||||
struct hyperlinks *hl = hlu->tree;
|
||||
|
||||
TAILQ_REMOVE(&global_hyperlinks, hlu, list_entry);
|
||||
global_hyperlinks_count--;
|
||||
|
||||
RB_REMOVE(hyperlinks_by_inner_tree, &hl->by_inner, hlu);
|
||||
RB_REMOVE(hyperlinks_by_uri_tree, &hl->by_uri, hlu);
|
||||
|
||||
free((void *)hlu->internal_id);
|
||||
free((void *)hlu->external_id);
|
||||
free((void *)hlu->uri);
|
||||
free(hlu);
|
||||
}
|
||||
|
||||
/* Store a new hyperlink or return if it already exists. */
|
||||
u_int
|
||||
hyperlinks_put(struct hyperlinks *hl, const char *uri_in,
|
||||
const char *internal_id_in)
|
||||
{
|
||||
struct hyperlinks_uri find, *hlu;
|
||||
char *uri, *internal_id, *external_id;
|
||||
|
||||
/*
|
||||
* Anonymous URI are stored with an empty internal ID and the tree
|
||||
* comparator will make sure they never match each other (so each
|
||||
* anonymous URI is unique).
|
||||
*/
|
||||
if (internal_id_in == NULL)
|
||||
internal_id_in = "";
|
||||
|
||||
utf8_stravis(&uri, uri_in, VIS_OCTAL|VIS_CSTYLE);
|
||||
utf8_stravis(&internal_id, internal_id_in, VIS_OCTAL|VIS_CSTYLE);
|
||||
|
||||
if (*internal_id_in != '\0') {
|
||||
find.uri = uri;
|
||||
find.internal_id = internal_id;
|
||||
|
||||
hlu = RB_FIND(hyperlinks_by_uri_tree, &hl->by_uri, &find);
|
||||
if (hlu != NULL) {
|
||||
free (uri);
|
||||
free (internal_id);
|
||||
return (hlu->inner);
|
||||
}
|
||||
}
|
||||
xasprintf(&external_id, "tmux%llX", hyperlinks_next_external_id++);
|
||||
|
||||
hlu = xcalloc(1, sizeof *hlu);
|
||||
hlu->inner = hl->next_inner++;
|
||||
hlu->internal_id = internal_id;
|
||||
hlu->external_id = external_id;
|
||||
hlu->uri = uri;
|
||||
hlu->tree = hl;
|
||||
RB_INSERT(hyperlinks_by_uri_tree, &hl->by_uri, hlu);
|
||||
RB_INSERT(hyperlinks_by_inner_tree, &hl->by_inner, hlu);
|
||||
|
||||
TAILQ_INSERT_TAIL(&global_hyperlinks, hlu, list_entry);
|
||||
if (++global_hyperlinks_count == MAX_HYPERLINKS)
|
||||
hyperlinks_remove(TAILQ_FIRST(&global_hyperlinks));
|
||||
|
||||
return (hlu->inner);
|
||||
}
|
||||
|
||||
/* Get hyperlink by inner number. */
|
||||
int
|
||||
hyperlinks_get(struct hyperlinks *hl, u_int inner, const char **uri_out,
|
||||
const char **external_id_out)
|
||||
{
|
||||
struct hyperlinks_uri find, *hlu;
|
||||
|
||||
find.inner = inner;
|
||||
|
||||
hlu = RB_FIND(hyperlinks_by_inner_tree, &hl->by_inner, &find);
|
||||
if (hlu == NULL)
|
||||
return (0);
|
||||
*external_id_out = hlu->external_id;
|
||||
*uri_out = hlu->uri;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Initialize hyperlink set. */
|
||||
struct hyperlinks *
|
||||
hyperlinks_init(void)
|
||||
{
|
||||
struct hyperlinks *hl;
|
||||
|
||||
hl = xcalloc(1, sizeof *hl);
|
||||
hl->next_inner = 1;
|
||||
RB_INIT(&hl->by_uri);
|
||||
RB_INIT(&hl->by_inner);
|
||||
return (hl);
|
||||
}
|
||||
|
||||
/* Free all hyperlinks but not the set itself. */
|
||||
void
|
||||
hyperlinks_reset(struct hyperlinks *hl)
|
||||
{
|
||||
struct hyperlinks_uri *hlu, *hlu1;
|
||||
|
||||
RB_FOREACH_SAFE(hlu, hyperlinks_by_inner_tree, &hl->by_inner, hlu1)
|
||||
hyperlinks_remove(hlu);
|
||||
}
|
||||
|
||||
/* Free hyperlink set. */
|
||||
void
|
||||
hyperlinks_free(struct hyperlinks *hl)
|
||||
{
|
||||
hyperlinks_reset(hl);
|
||||
free(hl);
|
||||
}
|
45
input.c
45
input.c
@ -135,6 +135,7 @@ static void input_set_state(struct input_ctx *,
|
||||
static void input_reset_cell(struct input_ctx *);
|
||||
|
||||
static void input_osc_4(struct input_ctx *, const char *);
|
||||
static void input_osc_8(struct input_ctx *, const char *);
|
||||
static void input_osc_10(struct input_ctx *, const char *);
|
||||
static void input_osc_11(struct input_ctx *, const char *);
|
||||
static void input_osc_12(struct input_ctx *, const char *);
|
||||
@ -2318,6 +2319,9 @@ input_exit_osc(struct input_ctx *ictx)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
input_osc_8(ictx, p);
|
||||
break;
|
||||
case 10:
|
||||
input_osc_10(ictx, p);
|
||||
break;
|
||||
@ -2562,6 +2566,47 @@ input_osc_4(struct input_ctx *ictx, const char *p)
|
||||
free(copy);
|
||||
}
|
||||
|
||||
/* Handle the OSC 8 sequence for embedding hyperlinks. */
|
||||
static void
|
||||
input_osc_8(struct input_ctx *ictx, const char *p)
|
||||
{
|
||||
struct hyperlinks *hl = ictx->ctx.s->hyperlinks;
|
||||
struct grid_cell *gc = &ictx->cell.cell;
|
||||
const char *start, *end, *uri;
|
||||
char *id = NULL;
|
||||
|
||||
for (start = p; (end = strpbrk(start, ":;")) != NULL; start = end + 1) {
|
||||
if (end - start >= 4 && strncmp(start, "id=", 3) == 0) {
|
||||
if (id != NULL)
|
||||
goto bad;
|
||||
id = xstrndup(start + 3, end - start - 3);
|
||||
}
|
||||
|
||||
/* The first ; is the end of parameters and start of the URI. */
|
||||
if (*end == ';')
|
||||
break;
|
||||
}
|
||||
if (end == NULL || *end != ';')
|
||||
goto bad;
|
||||
uri = end + 1;
|
||||
if (*uri == '\0') {
|
||||
gc->link = 0;
|
||||
free(id);
|
||||
return;
|
||||
}
|
||||
gc->link = hyperlinks_put(hl, uri, id);
|
||||
if (id == NULL)
|
||||
log_debug("hyperlink (anonymous) %s = %u", uri, gc->link);
|
||||
else
|
||||
log_debug("hyperlink (id=%s) %s = %u", id, uri, gc->link);
|
||||
free(id);
|
||||
return;
|
||||
|
||||
bad:
|
||||
log_debug("bad OSC 8 %s", p);
|
||||
free(id);
|
||||
}
|
||||
|
||||
/* Handle the OSC 10 sequence for setting and querying foreground colour. */
|
||||
static void
|
||||
input_osc_10(struct input_ctx *ictx, const char *p)
|
||||
|
@ -738,7 +738,7 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j)
|
||||
}
|
||||
}
|
||||
|
||||
tty_cell(tty, &gc, &grid_default_cell, NULL);
|
||||
tty_cell(tty, &gc, &grid_default_cell, NULL, NULL);
|
||||
if (isolates)
|
||||
tty_puts(tty, START_ISOLATE);
|
||||
}
|
||||
|
14
screen.c
14
screen.c
@ -89,6 +89,7 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
|
||||
s->sel = NULL;
|
||||
|
||||
s->write_list = NULL;
|
||||
s->hyperlinks = NULL;
|
||||
|
||||
screen_reinit(s);
|
||||
}
|
||||
@ -118,6 +119,17 @@ screen_reinit(struct screen *s)
|
||||
|
||||
screen_clear_selection(s);
|
||||
screen_free_titles(s);
|
||||
screen_reset_hyperlinks(s);
|
||||
}
|
||||
|
||||
/* Reset hyperlinks of a screen. */
|
||||
void
|
||||
screen_reset_hyperlinks(struct screen *s)
|
||||
{
|
||||
if (s->hyperlinks == NULL)
|
||||
s->hyperlinks = hyperlinks_init();
|
||||
else
|
||||
hyperlinks_reset(s->hyperlinks);
|
||||
}
|
||||
|
||||
/* Destroy a screen. */
|
||||
@ -136,6 +148,8 @@ screen_free(struct screen *s)
|
||||
grid_destroy(s->saved_grid);
|
||||
grid_destroy(s->grid);
|
||||
|
||||
if (s->hyperlinks != NULL)
|
||||
hyperlinks_free(s->hyperlinks);
|
||||
screen_free_titles(s);
|
||||
}
|
||||
|
||||
|
1
server.c
1
server.c
@ -213,7 +213,6 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base,
|
||||
RB_INIT(&sessions);
|
||||
key_bindings_init();
|
||||
TAILQ_INIT(&message_log);
|
||||
|
||||
gettimeofday(&start_time, NULL);
|
||||
|
||||
#ifdef HAVE_SYSTEMD
|
||||
|
2
style.c
2
style.c
@ -30,7 +30,7 @@
|
||||
|
||||
/* Default style. */
|
||||
static struct style style_default = {
|
||||
{ { { ' ' }, 0, 1, 1 }, 0, 0, 8, 8, 0 },
|
||||
{ { { ' ' }, 0, 1, 1 }, 0, 0, 8, 8, 0, 0 },
|
||||
0,
|
||||
|
||||
8,
|
||||
|
11
tmux.1
11
tmux.1
@ -3659,6 +3659,8 @@ Allows setting the cursor style.
|
||||
Supports extended keys.
|
||||
.It focus
|
||||
Supports focus reporting.
|
||||
.It hyperlinks
|
||||
Supports OSC 8 hyperlinks.
|
||||
.It ignorefkeys
|
||||
Ignore function keys from
|
||||
.Xr terminfo 5
|
||||
@ -6125,9 +6127,14 @@ a format for each shortcut key; both are evaluated once for each line.
|
||||
starts without the preview.
|
||||
This command works only if at least one client is attached.
|
||||
.Tg clearhist
|
||||
.It Ic clear-history Op Fl t Ar target-pane
|
||||
.It Xo Ic clear-history
|
||||
.Op Fl H
|
||||
.Op Fl t Ar target-pane
|
||||
.Xc
|
||||
.D1 Pq alias: Ic clearhist
|
||||
Remove and free the history for the specified pane.
|
||||
.Fl H
|
||||
also removes all hyperlinks.
|
||||
.Tg deleteb
|
||||
.It Ic delete-buffer Op Fl b Ar buffer-name
|
||||
.D1 Pq alias: Ic deleteb
|
||||
@ -6415,6 +6422,8 @@ Disable and enable focus reporting.
|
||||
These are set automatically if the
|
||||
.Em XT
|
||||
capability is present.
|
||||
.It Em \&Hls
|
||||
Set or clear a hyperlink annotation.
|
||||
.It Em \&Rect
|
||||
Tell
|
||||
.Nm
|
||||
|
23
tmux.h
23
tmux.h
@ -50,6 +50,8 @@ struct control_state;
|
||||
struct environ;
|
||||
struct format_job_tree;
|
||||
struct format_tree;
|
||||
struct hyperlinks_uri;
|
||||
struct hyperlinks;
|
||||
struct input_ctx;
|
||||
struct job;
|
||||
struct menu_data;
|
||||
@ -366,6 +368,7 @@ enum tty_code_code {
|
||||
TTYC_ENFCS,
|
||||
TTYC_ENMG,
|
||||
TTYC_FSL,
|
||||
TTYC_HLS,
|
||||
TTYC_HOME,
|
||||
TTYC_HPA,
|
||||
TTYC_ICH,
|
||||
@ -690,6 +693,7 @@ struct grid_cell {
|
||||
int fg;
|
||||
int bg;
|
||||
int us;
|
||||
u_int link;
|
||||
};
|
||||
|
||||
/* Grid extended cell entry. */
|
||||
@ -700,6 +704,7 @@ struct grid_extd_entry {
|
||||
int fg;
|
||||
int bg;
|
||||
int us;
|
||||
u_int link;
|
||||
} __packed;
|
||||
|
||||
/* Grid cell entry. */
|
||||
@ -851,6 +856,8 @@ struct screen {
|
||||
struct screen_sel *sel;
|
||||
|
||||
struct screen_write_cline *write_list;
|
||||
|
||||
struct hyperlinks *hyperlinks;
|
||||
};
|
||||
|
||||
/* Screen write context. */
|
||||
@ -2247,7 +2254,8 @@ void tty_update_window_offset(struct window *);
|
||||
void tty_update_client_offset(struct client *);
|
||||
void tty_raw(struct tty *, const char *);
|
||||
void tty_attributes(struct tty *, const struct grid_cell *,
|
||||
const struct grid_cell *, struct colour_palette *);
|
||||
const struct grid_cell *, struct colour_palette *,
|
||||
struct hyperlinks *);
|
||||
void tty_reset(struct tty *);
|
||||
void tty_region_off(struct tty *);
|
||||
void tty_margin_off(struct tty *);
|
||||
@ -2264,7 +2272,8 @@ void tty_puts(struct tty *, const char *);
|
||||
void tty_putc(struct tty *, u_char);
|
||||
void tty_putn(struct tty *, const void *, size_t, u_int);
|
||||
void tty_cell(struct tty *, const struct grid_cell *,
|
||||
const struct grid_cell *, struct colour_palette *);
|
||||
const struct grid_cell *, struct colour_palette *,
|
||||
struct hyperlinks *);
|
||||
int tty_init(struct tty *, struct client *);
|
||||
void tty_resize(struct tty *);
|
||||
void tty_set_size(struct tty *, u_int, u_int, u_int, u_int);
|
||||
@ -2895,6 +2904,7 @@ void screen_init(struct screen *, u_int, u_int, u_int);
|
||||
void screen_reinit(struct screen *);
|
||||
void screen_free(struct screen *);
|
||||
void screen_reset_tabs(struct screen *);
|
||||
void screen_reset_hyperlinks(struct screen *);
|
||||
void screen_set_cursor_style(u_int, enum screen_cursor_style *, int *);
|
||||
void screen_set_cursor_colour(struct screen *, int);
|
||||
int screen_set_title(struct screen *, const char *);
|
||||
@ -3301,4 +3311,13 @@ void server_acl_user_deny_write(uid_t);
|
||||
int server_acl_join(struct client *);
|
||||
uid_t server_acl_get_uid(struct server_acl_user *);
|
||||
|
||||
/* hyperlink.c */
|
||||
u_int hyperlinks_put(struct hyperlinks *, const char *,
|
||||
const char *);
|
||||
int hyperlinks_get(struct hyperlinks *, u_int,
|
||||
const char **, const char **);
|
||||
struct hyperlinks *hyperlinks_init(void);
|
||||
void hyperlinks_reset(struct hyperlinks *);
|
||||
void hyperlinks_free(struct hyperlinks *);
|
||||
|
||||
#endif /* TMUX_H */
|
||||
|
@ -87,6 +87,17 @@ static const struct tty_feature tty_feature_clipboard = {
|
||||
0
|
||||
};
|
||||
|
||||
/* Terminal supports OSC 8 hyperlinks. */
|
||||
static const char *tty_feature_hyperlinks_capabilities[] = {
|
||||
"*:Hls=\\E]8;%?%p1%l%tid=%p1%s%;;%p2%s\\E\\\\",
|
||||
NULL
|
||||
};
|
||||
static const struct tty_feature tty_feature_hyperlinks = {
|
||||
"hyperlinks",
|
||||
tty_feature_hyperlinks_capabilities,
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* Terminal supports RGB colour. This replaces setab and setaf also since
|
||||
* terminals with RGB have versions that do not allow setting colours from the
|
||||
@ -330,6 +341,7 @@ static const struct tty_feature *tty_features[] = {
|
||||
&tty_feature_bpaste,
|
||||
&tty_feature_ccolour,
|
||||
&tty_feature_clipboard,
|
||||
&tty_feature_hyperlinks,
|
||||
&tty_feature_cstyle,
|
||||
&tty_feature_extkeys,
|
||||
&tty_feature_focus,
|
||||
@ -444,14 +456,14 @@ tty_default_features(int *feat, const char *name, u_int version)
|
||||
},
|
||||
{ .name = "tmux",
|
||||
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
||||
",ccolour,cstyle,focus,overline,usstyle"
|
||||
",ccolour,cstyle,focus,overline,usstyle,hyperlinks"
|
||||
},
|
||||
{ .name = "rxvt-unicode",
|
||||
.features = "256,bpaste,ccolour,cstyle,mouse,title,ignorefkeys"
|
||||
},
|
||||
{ .name = "iTerm2",
|
||||
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
||||
",cstyle,extkeys,margins,usstyle,sync,osc7"
|
||||
",cstyle,extkeys,margins,usstyle,sync,osc7,hyperlinks"
|
||||
},
|
||||
{ .name = "XTerm",
|
||||
/*
|
||||
|
@ -103,6 +103,7 @@ static const struct tty_term_code_entry tty_term_codes[] = {
|
||||
[TTYC_ENFCS] = { TTYCODE_STRING, "Enfcs" },
|
||||
[TTYC_ENMG] = { TTYCODE_STRING, "Enmg" },
|
||||
[TTYC_FSL] = { TTYCODE_STRING, "fsl" },
|
||||
[TTYC_HLS] = { TTYCODE_STRING, "Hls" },
|
||||
[TTYC_HOME] = { TTYCODE_STRING, "home" },
|
||||
[TTYC_HPA] = { TTYCODE_STRING, "hpa" },
|
||||
[TTYC_ICH1] = { TTYCODE_STRING, "ich1" },
|
||||
|
114
tty.c
114
tty.c
@ -69,7 +69,7 @@ static void tty_emulate_repeat(struct tty *, enum tty_code_code,
|
||||
static void tty_repeat_space(struct tty *, u_int);
|
||||
static void tty_draw_pane(struct tty *, const struct tty_ctx *, u_int);
|
||||
static void tty_default_attributes(struct tty *, const struct grid_cell *,
|
||||
struct colour_palette *, u_int);
|
||||
struct colour_palette *, u_int, struct hyperlinks *);
|
||||
static int tty_check_overlay(struct tty *, u_int, u_int);
|
||||
static void tty_check_overlay_range(struct tty *, u_int, u_int, u_int,
|
||||
struct overlay_ranges *);
|
||||
@ -1455,7 +1455,8 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
tty_term_has(tty->term, TTYC_EL1) &&
|
||||
!tty_fake_bce(tty, defaults, 8) &&
|
||||
c->overlay_check == NULL) {
|
||||
tty_default_attributes(tty, defaults, palette, 8);
|
||||
tty_default_attributes(tty, defaults, palette, 8,
|
||||
s->hyperlinks);
|
||||
tty_cursor(tty, nx - 1, aty);
|
||||
tty_putcode(tty, TTYC_EL1);
|
||||
cleared = 1;
|
||||
@ -1480,9 +1481,11 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
gcp->fg != last.fg ||
|
||||
gcp->bg != last.bg ||
|
||||
gcp->us != last.us ||
|
||||
gcp->link != last.link ||
|
||||
ux + width + gcp->data.width > nx ||
|
||||
(sizeof buf) - len < gcp->data.size)) {
|
||||
tty_attributes(tty, &last, defaults, palette);
|
||||
tty_attributes(tty, &last, defaults, palette,
|
||||
s->hyperlinks);
|
||||
if (last.flags & GRID_FLAG_CLEARED) {
|
||||
log_debug("%s: %zu cleared", __func__, len);
|
||||
tty_clear_line(tty, defaults, aty, atx + ux,
|
||||
@ -1515,7 +1518,8 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
ux += gcp->data.width;
|
||||
} else if (hidden != 0 || ux + gcp->data.width > nx) {
|
||||
if (~gcp->flags & GRID_FLAG_PADDING) {
|
||||
tty_attributes(tty, &last, defaults, palette);
|
||||
tty_attributes(tty, &last, defaults, palette,
|
||||
s->hyperlinks);
|
||||
for (j = 0; j < OVERLAY_MAX_RANGES; j++) {
|
||||
if (r.nx[j] == 0)
|
||||
continue;
|
||||
@ -1532,7 +1536,8 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
}
|
||||
}
|
||||
} else if (gcp->attr & GRID_ATTR_CHARSET) {
|
||||
tty_attributes(tty, &last, defaults, palette);
|
||||
tty_attributes(tty, &last, defaults, palette,
|
||||
s->hyperlinks);
|
||||
tty_cursor(tty, atx + ux, aty);
|
||||
for (j = 0; j < gcp->data.size; j++)
|
||||
tty_putc(tty, gcp->data.data[j]);
|
||||
@ -1544,7 +1549,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
}
|
||||
}
|
||||
if (len != 0 && ((~last.flags & GRID_FLAG_CLEARED) || last.bg != 8)) {
|
||||
tty_attributes(tty, &last, defaults, palette);
|
||||
tty_attributes(tty, &last, defaults, palette, s->hyperlinks);
|
||||
if (last.flags & GRID_FLAG_CLEARED) {
|
||||
log_debug("%s: %zu cleared (end)", __func__, len);
|
||||
tty_clear_line(tty, defaults, aty, atx + ux, width,
|
||||
@ -1560,7 +1565,8 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
if (!cleared && ux < nx) {
|
||||
log_debug("%s: %u to end of line (%zu cleared)", __func__,
|
||||
nx - ux, len);
|
||||
tty_default_attributes(tty, defaults, palette, 8);
|
||||
tty_default_attributes(tty, defaults, palette, 8,
|
||||
s->hyperlinks);
|
||||
tty_clear_line(tty, defaults, aty, atx + ux, nx - ux, 8);
|
||||
}
|
||||
|
||||
@ -1646,7 +1652,8 @@ tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
|
||||
|
||||
@ -1668,7 +1675,8 @@ tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
|
||||
|
||||
@ -1678,7 +1686,8 @@ tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx)
|
||||
void
|
||||
tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_clear_pane_line(tty, ctx, ctx->ocy, ctx->ocx, ctx->num, ctx->bg);
|
||||
}
|
||||
@ -1700,7 +1709,8 @@ tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
|
||||
tty_margin_off(tty);
|
||||
@ -1727,7 +1737,8 @@ tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
|
||||
tty_margin_off(tty);
|
||||
@ -1740,7 +1751,8 @@ tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx)
|
||||
void
|
||||
tty_cmd_clearline(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_clear_pane_line(tty, ctx, ctx->ocy, 0, ctx->sx, ctx->bg);
|
||||
}
|
||||
@ -1750,7 +1762,8 @@ tty_cmd_clearendofline(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
u_int nx = ctx->sx - ctx->ocx;
|
||||
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_clear_pane_line(tty, ctx, ctx->ocy, ctx->ocx, nx, ctx->bg);
|
||||
}
|
||||
@ -1758,7 +1771,8 @@ tty_cmd_clearendofline(struct tty *tty, const struct tty_ctx *ctx)
|
||||
void
|
||||
tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_clear_pane_line(tty, ctx, ctx->ocy, 0, ctx->ocx + 1, ctx->bg);
|
||||
}
|
||||
@ -1784,7 +1798,8 @@ tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
|
||||
tty_margin_pane(tty, ctx);
|
||||
@ -1815,7 +1830,8 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
|
||||
tty_margin_pane(tty, ctx);
|
||||
@ -1855,7 +1871,8 @@ tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
|
||||
tty_margin_pane(tty, ctx);
|
||||
@ -1895,7 +1912,8 @@ tty_cmd_scrolldown(struct tty *tty, const struct tty_ctx *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
|
||||
tty_margin_pane(tty, ctx);
|
||||
@ -1914,7 +1932,8 @@ tty_cmd_clearendofscreen(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
u_int px, py, nx, ny;
|
||||
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_region_pane(tty, ctx, 0, ctx->sy - 1);
|
||||
tty_margin_off(tty);
|
||||
@ -1938,7 +1957,8 @@ tty_cmd_clearstartofscreen(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
u_int px, py, nx, ny;
|
||||
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_region_pane(tty, ctx, 0, ctx->sy - 1);
|
||||
tty_margin_off(tty);
|
||||
@ -1962,7 +1982,8 @@ tty_cmd_clearscreen(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
u_int px, py, nx, ny;
|
||||
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
|
||||
tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_region_pane(tty, ctx, 0, ctx->sy - 1);
|
||||
tty_margin_off(tty);
|
||||
@ -1985,7 +2006,8 @@ tty_cmd_alignmenttest(struct tty *tty, const struct tty_ctx *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
tty_attributes(tty, &grid_default_cell, &ctx->defaults, ctx->palette);
|
||||
tty_attributes(tty, &grid_default_cell, &ctx->defaults, ctx->palette,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
tty_region_pane(tty, ctx, 0, ctx->sy - 1);
|
||||
tty_margin_off(tty);
|
||||
@ -2031,7 +2053,8 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
|
||||
tty_margin_off(tty);
|
||||
tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
|
||||
|
||||
tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette);
|
||||
tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette,
|
||||
ctx->s->hyperlinks);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2062,7 +2085,7 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
|
||||
|
||||
tty_margin_off(tty);
|
||||
tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
|
||||
tty_attributes(tty, ctx->cell, &ctx->defaults, ctx->palette);
|
||||
tty_attributes(tty, ctx->cell, &ctx->defaults, ctx->palette, ctx->s->hyperlinks);
|
||||
|
||||
/* Get tty position from pane position for overlay check. */
|
||||
px = ctx->xoff + ctx->ocx - ctx->wox;
|
||||
@ -2136,7 +2159,8 @@ tty_cmd_syncstart(struct tty *tty, const struct tty_ctx *ctx)
|
||||
|
||||
void
|
||||
tty_cell(struct tty *tty, const struct grid_cell *gc,
|
||||
const struct grid_cell *defaults, struct colour_palette *palette)
|
||||
const struct grid_cell *defaults, struct colour_palette *palette,
|
||||
struct hyperlinks *hl)
|
||||
{
|
||||
const struct grid_cell *gcp;
|
||||
|
||||
@ -2152,11 +2176,11 @@ tty_cell(struct tty *tty, const struct grid_cell *gc,
|
||||
|
||||
/* Check the output codeset and apply attributes. */
|
||||
gcp = tty_check_codeset(tty, gc);
|
||||
tty_attributes(tty, gcp, defaults, palette);
|
||||
tty_attributes(tty, gcp, defaults, palette, hl);
|
||||
|
||||
/* If it is a single character, write with putc to handle ACS. */
|
||||
if (gcp->data.size == 1) {
|
||||
tty_attributes(tty, gcp, defaults, palette);
|
||||
tty_attributes(tty, gcp, defaults, palette, hl);
|
||||
if (*gcp->data.data < 0x20 || *gcp->data.data == 0x7f)
|
||||
return;
|
||||
tty_putc(tty, *gcp->data.data);
|
||||
@ -2173,6 +2197,8 @@ tty_reset(struct tty *tty)
|
||||
struct grid_cell *gc = &tty->cell;
|
||||
|
||||
if (!grid_cells_equal(gc, &grid_default_cell)) {
|
||||
if (gc->link != 0)
|
||||
tty_putcode_ptr2(tty, TTYC_HLS, "", "");
|
||||
if ((gc->attr & GRID_ATTR_CHARSET) && tty_acs_needed(tty))
|
||||
tty_putcode(tty, TTYC_RMACS);
|
||||
tty_putcode(tty, TTYC_SGR0);
|
||||
@ -2462,9 +2488,29 @@ out:
|
||||
tty->cy = cy;
|
||||
}
|
||||
|
||||
static void
|
||||
tty_hyperlink(struct tty *tty, const struct grid_cell *gc,
|
||||
struct hyperlinks *hl)
|
||||
{
|
||||
const char *uri, *id;
|
||||
|
||||
if (gc->link == tty->cell.link)
|
||||
return;
|
||||
tty->cell.link = gc->link;
|
||||
|
||||
if (hl == NULL)
|
||||
return;
|
||||
|
||||
if (gc->link == 0 || !hyperlinks_get(hl, gc->link, &uri, &id))
|
||||
tty_putcode_ptr2(tty, TTYC_HLS, "", "");
|
||||
else
|
||||
tty_putcode_ptr2(tty, TTYC_HLS, id, uri);
|
||||
}
|
||||
|
||||
void
|
||||
tty_attributes(struct tty *tty, const struct grid_cell *gc,
|
||||
const struct grid_cell *defaults, struct colour_palette *palette)
|
||||
const struct grid_cell *defaults, struct colour_palette *palette,
|
||||
struct hyperlinks *hl)
|
||||
{
|
||||
struct grid_cell *tc = &tty->cell, gc2;
|
||||
int changed;
|
||||
@ -2482,7 +2528,8 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
|
||||
if (gc2.attr == tty->last_cell.attr &&
|
||||
gc2.fg == tty->last_cell.fg &&
|
||||
gc2.bg == tty->last_cell.bg &&
|
||||
gc2.us == tty->last_cell.us)
|
||||
gc2.us == tty->last_cell.us &&
|
||||
gc2.link == tty->last_cell.link)
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -2559,6 +2606,9 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
|
||||
if ((changed & GRID_ATTR_CHARSET) && tty_acs_needed(tty))
|
||||
tty_putcode(tty, TTYC_SMACS);
|
||||
|
||||
/* Set hyperlink if any. */
|
||||
tty_hyperlink(tty, gc, hl);
|
||||
|
||||
memcpy(&tty->last_cell, &gc2, sizeof tty->last_cell);
|
||||
}
|
||||
|
||||
@ -2924,13 +2974,13 @@ tty_default_colours(struct grid_cell *gc, struct window_pane *wp)
|
||||
|
||||
static void
|
||||
tty_default_attributes(struct tty *tty, const struct grid_cell *defaults,
|
||||
struct colour_palette *palette, u_int bg)
|
||||
struct colour_palette *palette, u_int bg, struct hyperlinks *hl)
|
||||
{
|
||||
struct grid_cell gc;
|
||||
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
gc.bg = bg;
|
||||
tty_attributes(tty, &gc, defaults, palette);
|
||||
tty_attributes(tty, &gc, defaults, palette, hl);
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user