mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Merge branch 'obsd-master'
This commit is contained in:
		@@ -150,6 +150,7 @@ dist_tmux_SOURCES = \
 | 
				
			|||||||
	grid-reader.c \
 | 
						grid-reader.c \
 | 
				
			||||||
	grid-view.c \
 | 
						grid-view.c \
 | 
				
			||||||
	grid.c \
 | 
						grid.c \
 | 
				
			||||||
 | 
						hyperlinks.c \
 | 
				
			||||||
	input-keys.c \
 | 
						input-keys.c \
 | 
				
			||||||
	input.c \
 | 
						input.c \
 | 
				
			||||||
	job.c \
 | 
						job.c \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,8 +53,8 @@ const struct cmd_entry cmd_clear_history_entry = {
 | 
				
			|||||||
	.name = "clear-history",
 | 
						.name = "clear-history",
 | 
				
			||||||
	.alias = "clearhist",
 | 
						.alias = "clearhist",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.args = { "t:", 0, 0, NULL },
 | 
						.args = { "Ht:", 0, 0, NULL },
 | 
				
			||||||
	.usage = CMD_TARGET_PANE_USAGE,
 | 
						.usage = "[-H] " CMD_TARGET_PANE_USAGE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.target = { 't', CMD_FIND_PANE, 0 },
 | 
						.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) {
 | 
						if (cmd_get_entry(self) == &cmd_clear_history_entry) {
 | 
				
			||||||
		window_pane_reset_mode_all(wp);
 | 
							window_pane_reset_mode_all(wp);
 | 
				
			||||||
		grid_clear_history(wp->base.grid);
 | 
							grid_clear_history(wp->base.grid);
 | 
				
			||||||
 | 
							if (args_has(args, 'H'))
 | 
				
			||||||
 | 
								screen_reset_hyperlinks(wp->screen);
 | 
				
			||||||
		return (CMD_RETURN_NORMAL);
 | 
							return (CMD_RETURN_NORMAL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -144,7 +144,7 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
 | 
				
			|||||||
		llen = 0;
 | 
							llen = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sx < len * 6 || sy < 5) {
 | 
						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) {
 | 
							if (sx >= len + llen + 1) {
 | 
				
			||||||
			len += llen + 1;
 | 
								len += llen + 1;
 | 
				
			||||||
			tty_cursor(tty, xoff + px - len / 2, yoff + py);
 | 
								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;
 | 
						px -= len * 3;
 | 
				
			||||||
	py -= 2;
 | 
						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++) {
 | 
						for (ptr = buf; *ptr != '\0'; ptr++) {
 | 
				
			||||||
		if (*ptr < '0' || *ptr > '9')
 | 
							if (*ptr < '0' || *ptr > '9')
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
@@ -179,7 +179,7 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (sy <= 6)
 | 
						if (sy <= 6)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	tty_attributes(tty, &fgc, &grid_default_cell, NULL);
 | 
						tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
 | 
				
			||||||
	if (rlen != 0 && sx >= rlen) {
 | 
						if (rlen != 0 && sx >= rlen) {
 | 
				
			||||||
		tty_cursor(tty, xoff + sx - rlen, yoff);
 | 
							tty_cursor(tty, xoff + sx - rlen, yoff);
 | 
				
			||||||
		tty_putn(tty, rbuf, rlen, rlen);
 | 
							tty_putn(tty, rbuf, rlen, rlen);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								grid.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								grid.c
									
									
									
									
									
								
							@@ -37,7 +37,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Default grid cell data. */
 | 
					/* Default grid cell data. */
 | 
				
			||||||
const struct grid_cell grid_default_cell = {
 | 
					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.
 | 
					 * appears in the grid - because of this, they are always extended cells.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static const struct grid_cell grid_padding_cell = {
 | 
					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. */
 | 
					/* Cleared grid cell data. */
 | 
				
			||||||
static const struct grid_cell grid_cleared_cell = {
 | 
					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 = {
 | 
					static const struct grid_cell_entry grid_cleared_entry = {
 | 
				
			||||||
	GRID_FLAG_CLEARED, { .data = { 0, 8, 8, ' ' } }
 | 
						GRID_FLAG_CLEARED, { .data = { 0, 8, 8, ' ' } }
 | 
				
			||||||
@@ -90,6 +90,8 @@ grid_need_extended_cell(const struct grid_cell_entry *gce,
 | 
				
			|||||||
		return (1);
 | 
							return (1);
 | 
				
			||||||
	if (gc->us != 0) /* only supports 256 or RGB */
 | 
						if (gc->us != 0) /* only supports 256 or RGB */
 | 
				
			||||||
		return (1);
 | 
							return (1);
 | 
				
			||||||
 | 
						if (gc->link != 0)
 | 
				
			||||||
 | 
							return (1);
 | 
				
			||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -131,6 +133,7 @@ grid_extended_cell(struct grid_line *gl, struct grid_cell_entry *gce,
 | 
				
			|||||||
	gee->fg = gc->fg;
 | 
						gee->fg = gc->fg;
 | 
				
			||||||
	gee->bg = gc->bg;
 | 
						gee->bg = gc->bg;
 | 
				
			||||||
	gee->us = gc->us;
 | 
						gee->us = gc->us;
 | 
				
			||||||
 | 
						gee->link = gc->link;
 | 
				
			||||||
	return (gee);
 | 
						return (gee);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -231,6 +234,8 @@ grid_cells_look_equal(const struct grid_cell *gc1, const struct grid_cell *gc2)
 | 
				
			|||||||
		return (0);
 | 
							return (0);
 | 
				
			||||||
	if (gc1->attr != gc2->attr || gc1->flags != gc2->flags)
 | 
						if (gc1->attr != gc2->attr || gc1->flags != gc2->flags)
 | 
				
			||||||
		return (0);
 | 
							return (0);
 | 
				
			||||||
 | 
						if (gc1->link != gc2->link)
 | 
				
			||||||
 | 
							return (0);
 | 
				
			||||||
	return (1);
 | 
						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->fg = gee->fg;
 | 
				
			||||||
			gc->bg = gee->bg;
 | 
								gc->bg = gee->bg;
 | 
				
			||||||
			gc->us = gee->us;
 | 
								gc->us = gee->us;
 | 
				
			||||||
 | 
								gc->link = gee->link;
 | 
				
			||||||
			utf8_to_data(gee->data, &gc->data);
 | 
								utf8_to_data(gee->data, &gc->data);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return;
 | 
							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->bg |= COLOUR_FLAG_256;
 | 
				
			||||||
	gc->us = 0;
 | 
						gc->us = 0;
 | 
				
			||||||
	utf8_set(&gc->data, gce->data.data);
 | 
						utf8_set(&gc->data, gce->data.data);
 | 
				
			||||||
 | 
						gc->link = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Get cell for reading. */
 | 
					/* 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_reset_cell(struct input_ctx *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void	input_osc_4(struct input_ctx *, const char *);
 | 
					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_10(struct input_ctx *, const char *);
 | 
				
			||||||
static void	input_osc_11(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 *);
 | 
					static void	input_osc_12(struct input_ctx *, const char *);
 | 
				
			||||||
@@ -2318,6 +2319,9 @@ input_exit_osc(struct input_ctx *ictx)
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case 8:
 | 
				
			||||||
 | 
							input_osc_8(ictx, p);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	case 10:
 | 
						case 10:
 | 
				
			||||||
		input_osc_10(ictx, p);
 | 
							input_osc_10(ictx, p);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
@@ -2562,6 +2566,47 @@ input_osc_4(struct input_ctx *ictx, const char *p)
 | 
				
			|||||||
	free(copy);
 | 
						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. */
 | 
					/* Handle the OSC 10 sequence for setting and querying foreground colour. */
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
input_osc_10(struct input_ctx *ictx, const char *p)
 | 
					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)
 | 
						if (isolates)
 | 
				
			||||||
		tty_puts(tty, START_ISOLATE);
 | 
							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->sel = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s->write_list = NULL;
 | 
						s->write_list = NULL;
 | 
				
			||||||
 | 
						s->hyperlinks = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	screen_reinit(s);
 | 
						screen_reinit(s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -118,6 +119,17 @@ screen_reinit(struct screen *s)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	screen_clear_selection(s);
 | 
						screen_clear_selection(s);
 | 
				
			||||||
	screen_free_titles(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. */
 | 
					/* Destroy a screen. */
 | 
				
			||||||
@@ -136,6 +148,8 @@ screen_free(struct screen *s)
 | 
				
			|||||||
		grid_destroy(s->saved_grid);
 | 
							grid_destroy(s->saved_grid);
 | 
				
			||||||
	grid_destroy(s->grid);
 | 
						grid_destroy(s->grid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (s->hyperlinks != NULL)
 | 
				
			||||||
 | 
							hyperlinks_free(s->hyperlinks);
 | 
				
			||||||
	screen_free_titles(s);
 | 
						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);
 | 
						RB_INIT(&sessions);
 | 
				
			||||||
	key_bindings_init();
 | 
						key_bindings_init();
 | 
				
			||||||
	TAILQ_INIT(&message_log);
 | 
						TAILQ_INIT(&message_log);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	gettimeofday(&start_time, NULL);
 | 
						gettimeofday(&start_time, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_SYSTEMD
 | 
					#ifdef HAVE_SYSTEMD
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								style.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								style.c
									
									
									
									
									
								
							@@ -30,7 +30,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Default style. */
 | 
					/* Default style. */
 | 
				
			||||||
static struct style style_default = {
 | 
					static struct style style_default = {
 | 
				
			||||||
	{ { { ' ' }, 0, 1, 1 }, 0, 0, 8, 8, 0  },
 | 
						{ { { ' ' }, 0, 1, 1 }, 0, 0, 8, 8, 0, 0 },
 | 
				
			||||||
	0,
 | 
						0,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	8,
 | 
						8,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								tmux.1
									
									
									
									
									
								
							@@ -3659,6 +3659,8 @@ Allows setting the cursor style.
 | 
				
			|||||||
Supports extended keys.
 | 
					Supports extended keys.
 | 
				
			||||||
.It focus
 | 
					.It focus
 | 
				
			||||||
Supports focus reporting.
 | 
					Supports focus reporting.
 | 
				
			||||||
 | 
					.It hyperlinks
 | 
				
			||||||
 | 
					Supports OSC 8 hyperlinks.
 | 
				
			||||||
.It ignorefkeys
 | 
					.It ignorefkeys
 | 
				
			||||||
Ignore function keys from
 | 
					Ignore function keys from
 | 
				
			||||||
.Xr terminfo 5
 | 
					.Xr terminfo 5
 | 
				
			||||||
@@ -6125,9 +6127,14 @@ a format for each shortcut key; both are evaluated once for each line.
 | 
				
			|||||||
starts without the preview.
 | 
					starts without the preview.
 | 
				
			||||||
This command works only if at least one client is attached.
 | 
					This command works only if at least one client is attached.
 | 
				
			||||||
.Tg clearhist
 | 
					.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
 | 
					.D1 Pq alias: Ic clearhist
 | 
				
			||||||
Remove and free the history for the specified pane.
 | 
					Remove and free the history for the specified pane.
 | 
				
			||||||
 | 
					.Fl H
 | 
				
			||||||
 | 
					also removes all hyperlinks.
 | 
				
			||||||
.Tg deleteb
 | 
					.Tg deleteb
 | 
				
			||||||
.It Ic delete-buffer Op Fl b Ar buffer-name
 | 
					.It Ic delete-buffer Op Fl b Ar buffer-name
 | 
				
			||||||
.D1 Pq alias: Ic deleteb
 | 
					.D1 Pq alias: Ic deleteb
 | 
				
			||||||
@@ -6415,6 +6422,8 @@ Disable and enable focus reporting.
 | 
				
			|||||||
These are set automatically if the
 | 
					These are set automatically if the
 | 
				
			||||||
.Em XT
 | 
					.Em XT
 | 
				
			||||||
capability is present.
 | 
					capability is present.
 | 
				
			||||||
 | 
					.It Em \&Hls
 | 
				
			||||||
 | 
					Set or clear a hyperlink annotation.
 | 
				
			||||||
.It Em \&Rect
 | 
					.It Em \&Rect
 | 
				
			||||||
Tell
 | 
					Tell
 | 
				
			||||||
.Nm
 | 
					.Nm
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										23
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								tmux.h
									
									
									
									
									
								
							@@ -50,6 +50,8 @@ struct control_state;
 | 
				
			|||||||
struct environ;
 | 
					struct environ;
 | 
				
			||||||
struct format_job_tree;
 | 
					struct format_job_tree;
 | 
				
			||||||
struct format_tree;
 | 
					struct format_tree;
 | 
				
			||||||
 | 
					struct hyperlinks_uri;
 | 
				
			||||||
 | 
					struct hyperlinks;
 | 
				
			||||||
struct input_ctx;
 | 
					struct input_ctx;
 | 
				
			||||||
struct job;
 | 
					struct job;
 | 
				
			||||||
struct menu_data;
 | 
					struct menu_data;
 | 
				
			||||||
@@ -366,6 +368,7 @@ enum tty_code_code {
 | 
				
			|||||||
	TTYC_ENFCS,
 | 
						TTYC_ENFCS,
 | 
				
			||||||
	TTYC_ENMG,
 | 
						TTYC_ENMG,
 | 
				
			||||||
	TTYC_FSL,
 | 
						TTYC_FSL,
 | 
				
			||||||
 | 
						TTYC_HLS,
 | 
				
			||||||
	TTYC_HOME,
 | 
						TTYC_HOME,
 | 
				
			||||||
	TTYC_HPA,
 | 
						TTYC_HPA,
 | 
				
			||||||
	TTYC_ICH,
 | 
						TTYC_ICH,
 | 
				
			||||||
@@ -690,6 +693,7 @@ struct grid_cell {
 | 
				
			|||||||
	int			fg;
 | 
						int			fg;
 | 
				
			||||||
	int			bg;
 | 
						int			bg;
 | 
				
			||||||
	int			us;
 | 
						int			us;
 | 
				
			||||||
 | 
						u_int			link;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Grid extended cell entry. */
 | 
					/* Grid extended cell entry. */
 | 
				
			||||||
@@ -700,6 +704,7 @@ struct grid_extd_entry {
 | 
				
			|||||||
	int			fg;
 | 
						int			fg;
 | 
				
			||||||
	int			bg;
 | 
						int			bg;
 | 
				
			||||||
	int			us;
 | 
						int			us;
 | 
				
			||||||
 | 
						u_int			link;
 | 
				
			||||||
} __packed;
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Grid cell entry. */
 | 
					/* Grid cell entry. */
 | 
				
			||||||
@@ -851,6 +856,8 @@ struct screen {
 | 
				
			|||||||
	struct screen_sel		*sel;
 | 
						struct screen_sel		*sel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct screen_write_cline	*write_list;
 | 
						struct screen_write_cline	*write_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct hyperlinks		*hyperlinks;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Screen write context. */
 | 
					/* Screen write context. */
 | 
				
			||||||
@@ -2247,7 +2254,8 @@ void	tty_update_window_offset(struct window *);
 | 
				
			|||||||
void	tty_update_client_offset(struct client *);
 | 
					void	tty_update_client_offset(struct client *);
 | 
				
			||||||
void	tty_raw(struct tty *, const char *);
 | 
					void	tty_raw(struct tty *, const char *);
 | 
				
			||||||
void	tty_attributes(struct tty *, const struct grid_cell *,
 | 
					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_reset(struct tty *);
 | 
				
			||||||
void	tty_region_off(struct tty *);
 | 
					void	tty_region_off(struct tty *);
 | 
				
			||||||
void	tty_margin_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_putc(struct tty *, u_char);
 | 
				
			||||||
void	tty_putn(struct tty *, const void *, size_t, u_int);
 | 
					void	tty_putn(struct tty *, const void *, size_t, u_int);
 | 
				
			||||||
void	tty_cell(struct tty *, const struct grid_cell *,
 | 
					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 *);
 | 
					int	tty_init(struct tty *, struct client *);
 | 
				
			||||||
void	tty_resize(struct tty *);
 | 
					void	tty_resize(struct tty *);
 | 
				
			||||||
void	tty_set_size(struct tty *, u_int, u_int, u_int, u_int);
 | 
					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_reinit(struct screen *);
 | 
				
			||||||
void	 screen_free(struct screen *);
 | 
					void	 screen_free(struct screen *);
 | 
				
			||||||
void	 screen_reset_tabs(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_style(u_int, enum screen_cursor_style *, int *);
 | 
				
			||||||
void	 screen_set_cursor_colour(struct screen *, int);
 | 
					void	 screen_set_cursor_colour(struct screen *, int);
 | 
				
			||||||
int	 screen_set_title(struct screen *, const char *);
 | 
					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 *);
 | 
					int			 server_acl_join(struct client *);
 | 
				
			||||||
uid_t			 server_acl_get_uid(struct server_acl_user *);
 | 
					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 */
 | 
					#endif /* TMUX_H */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,6 +87,17 @@ static const struct tty_feature tty_feature_clipboard = {
 | 
				
			|||||||
	0
 | 
						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
 | 
					 * Terminal supports RGB colour. This replaces setab and setaf also since
 | 
				
			||||||
 * terminals with RGB have versions that do not allow setting colours from the
 | 
					 * 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_bpaste,
 | 
				
			||||||
	&tty_feature_ccolour,
 | 
						&tty_feature_ccolour,
 | 
				
			||||||
	&tty_feature_clipboard,
 | 
						&tty_feature_clipboard,
 | 
				
			||||||
 | 
						&tty_feature_hyperlinks,
 | 
				
			||||||
	&tty_feature_cstyle,
 | 
						&tty_feature_cstyle,
 | 
				
			||||||
	&tty_feature_extkeys,
 | 
						&tty_feature_extkeys,
 | 
				
			||||||
	&tty_feature_focus,
 | 
						&tty_feature_focus,
 | 
				
			||||||
@@ -444,14 +456,14 @@ tty_default_features(int *feat, const char *name, u_int version)
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{ .name = "tmux",
 | 
							{ .name = "tmux",
 | 
				
			||||||
		  .features = TTY_FEATURES_BASE_MODERN_XTERM
 | 
							  .features = TTY_FEATURES_BASE_MODERN_XTERM
 | 
				
			||||||
			      ",ccolour,cstyle,focus,overline,usstyle"
 | 
								      ",ccolour,cstyle,focus,overline,usstyle,hyperlinks"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ .name = "rxvt-unicode",
 | 
							{ .name = "rxvt-unicode",
 | 
				
			||||||
		  .features = "256,bpaste,ccolour,cstyle,mouse,title,ignorefkeys"
 | 
							  .features = "256,bpaste,ccolour,cstyle,mouse,title,ignorefkeys"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ .name = "iTerm2",
 | 
							{ .name = "iTerm2",
 | 
				
			||||||
		  .features = TTY_FEATURES_BASE_MODERN_XTERM
 | 
							  .features = TTY_FEATURES_BASE_MODERN_XTERM
 | 
				
			||||||
			      ",cstyle,extkeys,margins,usstyle,sync,osc7"
 | 
								      ",cstyle,extkeys,margins,usstyle,sync,osc7,hyperlinks"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ .name = "XTerm",
 | 
							{ .name = "XTerm",
 | 
				
			||||||
		  /*
 | 
							  /*
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,6 +103,7 @@ static const struct tty_term_code_entry tty_term_codes[] = {
 | 
				
			|||||||
	[TTYC_ENFCS] = { TTYCODE_STRING, "Enfcs" },
 | 
						[TTYC_ENFCS] = { TTYCODE_STRING, "Enfcs" },
 | 
				
			||||||
	[TTYC_ENMG] = { TTYCODE_STRING, "Enmg" },
 | 
						[TTYC_ENMG] = { TTYCODE_STRING, "Enmg" },
 | 
				
			||||||
	[TTYC_FSL] = { TTYCODE_STRING, "fsl" },
 | 
						[TTYC_FSL] = { TTYCODE_STRING, "fsl" },
 | 
				
			||||||
 | 
						[TTYC_HLS] = { TTYCODE_STRING, "Hls" },
 | 
				
			||||||
	[TTYC_HOME] = { TTYCODE_STRING, "home" },
 | 
						[TTYC_HOME] = { TTYCODE_STRING, "home" },
 | 
				
			||||||
	[TTYC_HPA] = { TTYCODE_STRING, "hpa" },
 | 
						[TTYC_HPA] = { TTYCODE_STRING, "hpa" },
 | 
				
			||||||
	[TTYC_ICH1] = { TTYCODE_STRING, "ich1" },
 | 
						[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_repeat_space(struct tty *, u_int);
 | 
				
			||||||
static void	tty_draw_pane(struct tty *, const struct tty_ctx *, 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 *,
 | 
					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 int	tty_check_overlay(struct tty *, u_int, u_int);
 | 
				
			||||||
static void	tty_check_overlay_range(struct tty *, u_int, u_int, u_int,
 | 
					static void	tty_check_overlay_range(struct tty *, u_int, u_int, u_int,
 | 
				
			||||||
		    struct overlay_ranges *);
 | 
							    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_term_has(tty->term, TTYC_EL1) &&
 | 
				
			||||||
		    !tty_fake_bce(tty, defaults, 8) &&
 | 
							    !tty_fake_bce(tty, defaults, 8) &&
 | 
				
			||||||
		    c->overlay_check == NULL) {
 | 
							    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_cursor(tty, nx - 1, aty);
 | 
				
			||||||
			tty_putcode(tty, TTYC_EL1);
 | 
								tty_putcode(tty, TTYC_EL1);
 | 
				
			||||||
			cleared = 1;
 | 
								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->fg != last.fg ||
 | 
				
			||||||
		    gcp->bg != last.bg ||
 | 
							    gcp->bg != last.bg ||
 | 
				
			||||||
		    gcp->us != last.us ||
 | 
							    gcp->us != last.us ||
 | 
				
			||||||
 | 
							    gcp->link != last.link ||
 | 
				
			||||||
		    ux + width + gcp->data.width > nx ||
 | 
							    ux + width + gcp->data.width > nx ||
 | 
				
			||||||
		    (sizeof buf) - len < gcp->data.size)) {
 | 
							    (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) {
 | 
								if (last.flags & GRID_FLAG_CLEARED) {
 | 
				
			||||||
				log_debug("%s: %zu cleared", __func__, len);
 | 
									log_debug("%s: %zu cleared", __func__, len);
 | 
				
			||||||
				tty_clear_line(tty, defaults, aty, atx + ux,
 | 
									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;
 | 
									ux += gcp->data.width;
 | 
				
			||||||
		} else if (hidden != 0 || ux + gcp->data.width > nx) {
 | 
							} else if (hidden != 0 || ux + gcp->data.width > nx) {
 | 
				
			||||||
			if (~gcp->flags & GRID_FLAG_PADDING) {
 | 
								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++) {
 | 
									for (j = 0; j < OVERLAY_MAX_RANGES; j++) {
 | 
				
			||||||
					if (r.nx[j] == 0)
 | 
										if (r.nx[j] == 0)
 | 
				
			||||||
						continue;
 | 
											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) {
 | 
							} 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);
 | 
								tty_cursor(tty, atx + ux, aty);
 | 
				
			||||||
			for (j = 0; j < gcp->data.size; j++)
 | 
								for (j = 0; j < gcp->data.size; j++)
 | 
				
			||||||
				tty_putc(tty, gcp->data.data[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)) {
 | 
						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) {
 | 
							if (last.flags & GRID_FLAG_CLEARED) {
 | 
				
			||||||
			log_debug("%s: %zu cleared (end)", __func__, len);
 | 
								log_debug("%s: %zu cleared (end)", __func__, len);
 | 
				
			||||||
			tty_clear_line(tty, defaults, aty, atx + ux, width,
 | 
								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) {
 | 
						if (!cleared && ux < nx) {
 | 
				
			||||||
		log_debug("%s: %u to end of line (%zu cleared)", __func__,
 | 
							log_debug("%s: %u to end of line (%zu cleared)", __func__,
 | 
				
			||||||
		    nx - ux, len);
 | 
							    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);
 | 
							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;
 | 
							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);
 | 
						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;
 | 
							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);
 | 
						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
 | 
					void
 | 
				
			||||||
tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx)
 | 
					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);
 | 
						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;
 | 
							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_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
 | 
				
			||||||
	tty_margin_off(tty);
 | 
						tty_margin_off(tty);
 | 
				
			||||||
@@ -1727,7 +1737,8 @@ tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx)
 | 
				
			|||||||
		return;
 | 
							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_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
 | 
				
			||||||
	tty_margin_off(tty);
 | 
						tty_margin_off(tty);
 | 
				
			||||||
@@ -1740,7 +1751,8 @@ tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx)
 | 
				
			|||||||
void
 | 
					void
 | 
				
			||||||
tty_cmd_clearline(struct tty *tty, const struct tty_ctx *ctx)
 | 
					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);
 | 
						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;
 | 
						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);
 | 
						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
 | 
					void
 | 
				
			||||||
tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx)
 | 
					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);
 | 
						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;
 | 
							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_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
 | 
				
			||||||
	tty_margin_pane(tty, ctx);
 | 
						tty_margin_pane(tty, ctx);
 | 
				
			||||||
@@ -1815,7 +1830,8 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
 | 
				
			|||||||
		return;
 | 
							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_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
 | 
				
			||||||
	tty_margin_pane(tty, ctx);
 | 
						tty_margin_pane(tty, ctx);
 | 
				
			||||||
@@ -1855,7 +1871,8 @@ tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
 | 
				
			|||||||
		return;
 | 
							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_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
 | 
				
			||||||
	tty_margin_pane(tty, ctx);
 | 
						tty_margin_pane(tty, ctx);
 | 
				
			||||||
@@ -1895,7 +1912,8 @@ tty_cmd_scrolldown(struct tty *tty, const struct tty_ctx *ctx)
 | 
				
			|||||||
		return;
 | 
							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_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
 | 
				
			||||||
	tty_margin_pane(tty, ctx);
 | 
						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;
 | 
						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_region_pane(tty, ctx, 0, ctx->sy - 1);
 | 
				
			||||||
	tty_margin_off(tty);
 | 
						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;
 | 
						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_region_pane(tty, ctx, 0, ctx->sy - 1);
 | 
				
			||||||
	tty_margin_off(tty);
 | 
						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;
 | 
						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_region_pane(tty, ctx, 0, ctx->sy - 1);
 | 
				
			||||||
	tty_margin_off(tty);
 | 
						tty_margin_off(tty);
 | 
				
			||||||
@@ -1985,7 +2006,8 @@ tty_cmd_alignmenttest(struct tty *tty, const struct tty_ctx *ctx)
 | 
				
			|||||||
		return;
 | 
							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_region_pane(tty, ctx, 0, ctx->sy - 1);
 | 
				
			||||||
	tty_margin_off(tty);
 | 
						tty_margin_off(tty);
 | 
				
			||||||
@@ -2031,7 +2053,8 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
 | 
				
			|||||||
	tty_margin_off(tty);
 | 
						tty_margin_off(tty);
 | 
				
			||||||
	tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
 | 
						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
 | 
					void
 | 
				
			||||||
@@ -2062,7 +2085,7 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	tty_margin_off(tty);
 | 
						tty_margin_off(tty);
 | 
				
			||||||
	tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
 | 
						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. */
 | 
						/* Get tty position from pane position for overlay check. */
 | 
				
			||||||
	px = ctx->xoff + ctx->ocx - ctx->wox;
 | 
						px = ctx->xoff + ctx->ocx - ctx->wox;
 | 
				
			||||||
@@ -2136,7 +2159,8 @@ tty_cmd_syncstart(struct tty *tty, const struct tty_ctx *ctx)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
tty_cell(struct tty *tty, const struct grid_cell *gc,
 | 
					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;
 | 
						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. */
 | 
						/* Check the output codeset and apply attributes. */
 | 
				
			||||||
	gcp = tty_check_codeset(tty, gc);
 | 
						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 it is a single character, write with putc to handle ACS. */
 | 
				
			||||||
	if (gcp->data.size == 1) {
 | 
						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)
 | 
							if (*gcp->data.data < 0x20 || *gcp->data.data == 0x7f)
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		tty_putc(tty, *gcp->data.data);
 | 
							tty_putc(tty, *gcp->data.data);
 | 
				
			||||||
@@ -2173,6 +2197,8 @@ tty_reset(struct tty *tty)
 | 
				
			|||||||
	struct grid_cell	*gc = &tty->cell;
 | 
						struct grid_cell	*gc = &tty->cell;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!grid_cells_equal(gc, &grid_default_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))
 | 
							if ((gc->attr & GRID_ATTR_CHARSET) && tty_acs_needed(tty))
 | 
				
			||||||
			tty_putcode(tty, TTYC_RMACS);
 | 
								tty_putcode(tty, TTYC_RMACS);
 | 
				
			||||||
		tty_putcode(tty, TTYC_SGR0);
 | 
							tty_putcode(tty, TTYC_SGR0);
 | 
				
			||||||
@@ -2462,9 +2488,29 @@ out:
 | 
				
			|||||||
	tty->cy = cy;
 | 
						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
 | 
					void
 | 
				
			||||||
tty_attributes(struct tty *tty, const struct grid_cell *gc,
 | 
					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;
 | 
						struct grid_cell	*tc = &tty->cell, gc2;
 | 
				
			||||||
	int			 changed;
 | 
						int			 changed;
 | 
				
			||||||
@@ -2482,7 +2528,8 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
 | 
				
			|||||||
	if (gc2.attr == tty->last_cell.attr &&
 | 
						if (gc2.attr == tty->last_cell.attr &&
 | 
				
			||||||
	    gc2.fg == tty->last_cell.fg &&
 | 
						    gc2.fg == tty->last_cell.fg &&
 | 
				
			||||||
	    gc2.bg == tty->last_cell.bg &&
 | 
						    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;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
@@ -2559,6 +2606,9 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
 | 
				
			|||||||
	if ((changed & GRID_ATTR_CHARSET) && tty_acs_needed(tty))
 | 
						if ((changed & GRID_ATTR_CHARSET) && tty_acs_needed(tty))
 | 
				
			||||||
		tty_putcode(tty, TTYC_SMACS);
 | 
							tty_putcode(tty, TTYC_SMACS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Set hyperlink if any. */
 | 
				
			||||||
 | 
						tty_hyperlink(tty, gc, hl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy(&tty->last_cell, &gc2, sizeof tty->last_cell);
 | 
						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
 | 
					static void
 | 
				
			||||||
tty_default_attributes(struct tty *tty, const struct grid_cell *defaults,
 | 
					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;
 | 
						struct grid_cell	gc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy(&gc, &grid_default_cell, sizeof gc);
 | 
						memcpy(&gc, &grid_default_cell, sizeof gc);
 | 
				
			||||||
	gc.bg = bg;
 | 
						gc.bg = bg;
 | 
				
			||||||
	tty_attributes(tty, &gc, defaults, palette);
 | 
						tty_attributes(tty, &gc, defaults, palette, hl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user