mirror of
https://github.com/tmux/tmux.git
synced 2024-12-04 19:58:48 +00:00
Merge branch 'obsd-master'
This commit is contained in:
commit
c706aadf52
@ -171,6 +171,7 @@ dist_tmux_SOURCES = \
|
||||
tmux.c \
|
||||
tmux.h \
|
||||
tty-acs.c \
|
||||
tty-features.c \
|
||||
tty-keys.c \
|
||||
tty-term.c \
|
||||
tty.c \
|
||||
|
9
client.c
9
client.c
@ -57,7 +57,7 @@ static struct client_files client_files = RB_INITIALIZER(&client_files);
|
||||
static __dead void client_exec(const char *,const char *);
|
||||
static int client_get_lock(char *);
|
||||
static int client_connect(struct event_base *, const char *, int);
|
||||
static void client_send_identify(const char *, const char *);
|
||||
static void client_send_identify(const char *, const char *, int);
|
||||
static void client_signal(int);
|
||||
static void client_dispatch(struct imsg *, void *);
|
||||
static void client_dispatch_attached(struct imsg *);
|
||||
@ -233,7 +233,7 @@ client_exit(void)
|
||||
|
||||
/* Client main loop. */
|
||||
int
|
||||
client_main(struct event_base *base, int argc, char **argv, int flags)
|
||||
client_main(struct event_base *base, int argc, char **argv, int flags, int feat)
|
||||
{
|
||||
struct cmd_parse_result *pr;
|
||||
struct msg_command *data;
|
||||
@ -342,7 +342,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
|
||||
}
|
||||
|
||||
/* Send identify messages. */
|
||||
client_send_identify(ttynam, cwd);
|
||||
client_send_identify(ttynam, cwd, feat);
|
||||
|
||||
/* Send first command. */
|
||||
if (msg == MSG_COMMAND) {
|
||||
@ -408,7 +408,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
|
||||
|
||||
/* Send identify messages to server. */
|
||||
static void
|
||||
client_send_identify(const char *ttynam, const char *cwd)
|
||||
client_send_identify(const char *ttynam, const char *cwd, int feat)
|
||||
{
|
||||
const char *s;
|
||||
char **ss;
|
||||
@ -421,6 +421,7 @@ client_send_identify(const char *ttynam, const char *cwd)
|
||||
if ((s = getenv("TERM")) == NULL)
|
||||
s = "";
|
||||
proc_send(client_peer, MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1);
|
||||
proc_send(client_peer, MSG_IDENTIFY_FEATURES, -1, &feat, sizeof feat);
|
||||
|
||||
proc_send(client_peer, MSG_IDENTIFY_TTYNAME, -1, ttynam,
|
||||
strlen(ttynam) + 1);
|
||||
|
@ -42,22 +42,24 @@ const struct cmd_entry cmd_show_messages_entry = {
|
||||
.exec = cmd_show_messages_exec
|
||||
};
|
||||
|
||||
static int cmd_show_messages_terminals(struct cmdq_item *, int);
|
||||
|
||||
static int
|
||||
cmd_show_messages_terminals(struct cmdq_item *item, int blank)
|
||||
cmd_show_messages_terminals(struct cmd *self, struct cmdq_item *item, int blank)
|
||||
{
|
||||
struct args *args = cmd_get_args(self);
|
||||
struct client *tc = cmdq_get_target_client(item);
|
||||
struct tty_term *term;
|
||||
u_int i, n;
|
||||
|
||||
n = 0;
|
||||
LIST_FOREACH(term, &tty_terms, entry) {
|
||||
if (args_has(args, 't') && term != tc->tty.term)
|
||||
continue;
|
||||
if (blank) {
|
||||
cmdq_print(item, "%s", "");
|
||||
blank = 0;
|
||||
}
|
||||
cmdq_print(item, "Terminal %u: %s [references=%u, flags=0x%x]:",
|
||||
n, term->name, term->references, term->flags);
|
||||
cmdq_print(item, "Terminal %u: %s for %s, flags=0x%x:", n,
|
||||
term->name, term->tty->client->name, term->flags);
|
||||
n++;
|
||||
for (i = 0; i < tty_term_ncodes(); i++)
|
||||
cmdq_print(item, "%s", tty_term_describe(term, i));
|
||||
@ -76,7 +78,7 @@ cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
|
||||
|
||||
done = blank = 0;
|
||||
if (args_has(args, 'T')) {
|
||||
blank = cmd_show_messages_terminals(item, blank);
|
||||
blank = cmd_show_messages_terminals(self, item, blank);
|
||||
done = 1;
|
||||
}
|
||||
if (args_has(args, 'J')) {
|
||||
|
7
format.c
7
format.c
@ -2553,8 +2553,9 @@ format_defaults_client(struct format_tree *ft, struct client *c)
|
||||
format_add(ft, "client_control_mode", "%d",
|
||||
!!(c->flags & CLIENT_CONTROL));
|
||||
|
||||
if (tty->term_name != NULL)
|
||||
format_add(ft, "client_termname", "%s", tty->term_name);
|
||||
format_add(ft, "client_termname", "%s", c->term_name);
|
||||
format_add(ft, "client_termfeatures", "%s",
|
||||
tty_get_features(c->term_features));
|
||||
|
||||
format_add_tv(ft, "client_created", &c->creation_time);
|
||||
format_add_tv(ft, "client_activity", &c->activity_time);
|
||||
@ -2569,7 +2570,7 @@ format_defaults_client(struct format_tree *ft, struct client *c)
|
||||
format_add(ft, "client_prefix", "%d", 1);
|
||||
format_add(ft, "client_key_table", "%s", c->keytable->name);
|
||||
|
||||
if (tty_get_flags(tty) & TERM_UTF8)
|
||||
if (c->flags & CLIENT_UTF8)
|
||||
format_add(ft, "client_utf8", "%d", 1);
|
||||
else
|
||||
format_add(ft, "client_utf8", "%d", 0);
|
||||
|
@ -260,9 +260,16 @@ const struct options_table_entry options_table[] = {
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_ARRAY,
|
||||
.default_str = "xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007"
|
||||
":Cs=\\E]12;%p1%s\\007:Cr=\\E]112\\007"
|
||||
":Ss=\\E[%p1%d q:Se=\\E[2 q,screen*:XT",
|
||||
.default_str = "tmux*:XT,screen*:XT",
|
||||
.separator = ","
|
||||
},
|
||||
|
||||
{ .name = "terminal-features",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_ARRAY,
|
||||
.default_str = "xterm*:clipboard:ccolour:cstyle:title,"
|
||||
"screen*:title",
|
||||
.separator = ","
|
||||
},
|
||||
|
||||
|
@ -294,7 +294,7 @@ server_client_lost(struct client *c)
|
||||
if (c->flags & CLIENT_TERMINAL)
|
||||
tty_free(&c->tty);
|
||||
free(c->ttyname);
|
||||
free(c->term);
|
||||
free(c->term_name);
|
||||
|
||||
status_free(c);
|
||||
|
||||
@ -1843,6 +1843,7 @@ server_client_dispatch(struct imsg *imsg, void *arg)
|
||||
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
|
||||
|
||||
switch (imsg->hdr.type) {
|
||||
case MSG_IDENTIFY_FEATURES:
|
||||
case MSG_IDENTIFY_FLAGS:
|
||||
case MSG_IDENTIFY_TERM:
|
||||
case MSG_IDENTIFY_TTYNAME:
|
||||
@ -2001,7 +2002,7 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
|
||||
{
|
||||
const char *data, *home;
|
||||
size_t datalen;
|
||||
int flags;
|
||||
int flags, feat;
|
||||
char *name;
|
||||
|
||||
if (c->flags & CLIENT_IDENTIFIED)
|
||||
@ -2011,6 +2012,14 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
|
||||
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
|
||||
|
||||
switch (imsg->hdr.type) {
|
||||
case MSG_IDENTIFY_FEATURES:
|
||||
if (datalen != sizeof feat)
|
||||
fatalx("bad MSG_IDENTIFY_FEATURES size");
|
||||
memcpy(&feat, data, sizeof feat);
|
||||
c->term_features |= feat;
|
||||
log_debug("client %p IDENTIFY_FEATURES %s", c,
|
||||
tty_get_features(feat));
|
||||
break;
|
||||
case MSG_IDENTIFY_FLAGS:
|
||||
if (datalen != sizeof flags)
|
||||
fatalx("bad MSG_IDENTIFY_FLAGS size");
|
||||
@ -2021,7 +2030,10 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
|
||||
case MSG_IDENTIFY_TERM:
|
||||
if (datalen == 0 || data[datalen - 1] != '\0')
|
||||
fatalx("bad MSG_IDENTIFY_TERM string");
|
||||
c->term = xstrdup(data);
|
||||
if (*data == '\0')
|
||||
c->term_name = xstrdup("unknown");
|
||||
else
|
||||
c->term_name = xstrdup(data);
|
||||
log_debug("client %p IDENTIFY_TERM %s", c, data);
|
||||
break;
|
||||
case MSG_IDENTIFY_TTYNAME:
|
||||
@ -2086,14 +2098,10 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
|
||||
control_start(c);
|
||||
c->tty.fd = -1;
|
||||
} else if (c->fd != -1) {
|
||||
if (tty_init(&c->tty, c, c->fd, c->term) != 0) {
|
||||
if (tty_init(&c->tty, c, c->fd) != 0) {
|
||||
close(c->fd);
|
||||
c->fd = -1;
|
||||
} else {
|
||||
if (c->flags & CLIENT_UTF8)
|
||||
c->tty.term_flags |= TERM_UTF8;
|
||||
if (c->flags & CLIENT_256COLOURS)
|
||||
c->tty.term_flags |= TERM_256COLOURS;
|
||||
tty_resize(&c->tty);
|
||||
c->flags |= CLIENT_TERMINAL;
|
||||
}
|
||||
|
94
tmux.1
94
tmux.1
@ -28,6 +28,7 @@
|
||||
.Op Fl f Ar file
|
||||
.Op Fl L Ar socket-name
|
||||
.Op Fl S Ar socket-path
|
||||
.Op Fl T Ar features
|
||||
.Op Ar command Op Ar flags
|
||||
.Ek
|
||||
.Sh DESCRIPTION
|
||||
@ -98,6 +99,8 @@ The options are as follows:
|
||||
Force
|
||||
.Nm
|
||||
to assume the terminal supports 256 colours.
|
||||
This is equivalent to
|
||||
.Fl T Ar 256 .
|
||||
.It Fl C
|
||||
Start in control mode (see the
|
||||
.Sx CONTROL MODE
|
||||
@ -186,6 +189,14 @@ that is set does not contain
|
||||
.Qq UTF-8
|
||||
or
|
||||
.Qq UTF8 .
|
||||
This is equivalent to
|
||||
.Fl T Ar UTF-8 .
|
||||
.It Fl T Ar features
|
||||
Set terminal features for the client.
|
||||
This is a comma-separated list of features.
|
||||
See the
|
||||
.Ic terminal-features
|
||||
option.
|
||||
.It Fl v
|
||||
Request verbose logging.
|
||||
Log messages will be saved into
|
||||
@ -3166,6 +3177,63 @@ disallowedWindowOps: 20,21,SetXprop
|
||||
Or changing this property from the
|
||||
.Xr xterm 1
|
||||
interactive menu when required.
|
||||
.It Ic terminal-features[] Ar string
|
||||
Set terminal features for terminal types read from
|
||||
.Xr terminfo 5 .
|
||||
.Nm
|
||||
has a set of named terminal features.
|
||||
Each will apply appropriate changes to the
|
||||
.Xr terminfo 5
|
||||
entry in use.
|
||||
.Pp
|
||||
.Nm
|
||||
can detect features for a few common terminals; this option can be used to
|
||||
easily tell tmux about features supported by terminals it cannot detect.
|
||||
The
|
||||
.Ic terminal-overrides
|
||||
option allows individual
|
||||
.Xr terminfo 5
|
||||
capabilities to be set instead,
|
||||
.Ic terminal-features
|
||||
is intended for classes of functionality supported in a standard way but not
|
||||
reported by
|
||||
.Xr terminfo 5 .
|
||||
Care must be taken only to configure this with features the terminal actually
|
||||
support.
|
||||
.Pp
|
||||
This is an array option where each entry is a colon-separated string made up
|
||||
of a terminal type pattern (matched using
|
||||
.Xr fnmatch 3 )
|
||||
followed by a list of terminal features.
|
||||
The available features are:
|
||||
.Bl -tag -width Ds
|
||||
.It 256
|
||||
Supports 256 colours with the SGR escape sequences.
|
||||
.It clipboard
|
||||
Allows setting the system clipboard.
|
||||
.It ccolour
|
||||
Allows setting the cursor colour.
|
||||
.It cstyle
|
||||
Allows setting the cursor style.
|
||||
.It margins
|
||||
Supports DECSLRM margins.
|
||||
.It overline
|
||||
Supports the overline SGR attribute.
|
||||
.It rectfill
|
||||
Supports the DECFRA rectangle fill escape sequence.
|
||||
.It RGB
|
||||
Supports RGB colour with the SGR escape sequences.
|
||||
.It sync
|
||||
Supports synchronized updates.
|
||||
.It title
|
||||
Supports
|
||||
.Xr xterm 1
|
||||
title setting.
|
||||
.It usstyle
|
||||
Allows underscore style and colour to be set.
|
||||
.It UTF-8
|
||||
Is able to handle UTF-8 output.
|
||||
.El
|
||||
.It Ic terminal-overrides[] Ar string
|
||||
Allow terminal descriptions read using
|
||||
.Xr terminfo 5
|
||||
@ -4383,6 +4451,7 @@ The following variables are available, where appropriate:
|
||||
.It Li "client_readonly" Ta "" Ta "1 if client is readonly"
|
||||
.It Li "client_session" Ta "" Ta "Name of the client's session"
|
||||
.It Li "client_termname" Ta "" Ta "Terminal name of client"
|
||||
.It Li "client_termfeatures" Ta "" Ta "Terminal features of client"
|
||||
.It Li "client_tty" Ta "" Ta "Pseudo terminal of client"
|
||||
.It Li "client_utf8" Ta "" Ta "1 if client supports UTF-8"
|
||||
.It Li "client_width" Ta "" Ta "Width of client"
|
||||
@ -5465,7 +5534,10 @@ The server crashed or otherwise exited without telling the client the reason.
|
||||
.Sh TERMINFO EXTENSIONS
|
||||
.Nm
|
||||
understands some unofficial extensions to
|
||||
.Xr terminfo 5 :
|
||||
.Xr terminfo 5.
|
||||
It is not normally necessary to set these manually, instead the
|
||||
.Ic terminal-features
|
||||
option should be used.
|
||||
.Bl -tag -width Ds
|
||||
.It Em \&Cs , Cr
|
||||
Set the cursor colour.
|
||||
@ -5479,33 +5551,15 @@ $ printf '\e033]12;red\e033\e\e'
|
||||
.Ed
|
||||
.It Em \&Smol
|
||||
Enable the overline attribute.
|
||||
The capability is usually SGR 53 and can be added to
|
||||
.Ic terminal-overrides
|
||||
as:
|
||||
.Bd -literal -offset indent
|
||||
Smol=\eE[53m
|
||||
.Ed
|
||||
.It Em \&Smulx
|
||||
Set a styled underscore.
|
||||
The single parameter is one of: 0 for no underscore, 1 for normal
|
||||
underscore, 2 for double underscore, 3 for curly underscore, 4 for dotted
|
||||
underscore and 5 for dashed underscore.
|
||||
The capability can typically be added to
|
||||
.Ic terminal-overrides
|
||||
as:
|
||||
.Bd -literal -offset indent
|
||||
Smulx=\eE[4::%p1%dm
|
||||
.Ed
|
||||
.It Em \&Setulc
|
||||
Set the underscore colour.
|
||||
The argument is (red * 65536) + (green * 256) + blue where each is between 0
|
||||
and 255.
|
||||
The capability can typically be added to
|
||||
.Ic terminal-overrides
|
||||
as:
|
||||
.Bd -literal -offset indent
|
||||
Setulc=\eE[58::2::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m
|
||||
.Ed
|
||||
.It Em \&Ss , Se
|
||||
Set or reset the cursor style.
|
||||
If set, a sequence such as this may be used
|
||||
@ -5518,7 +5572,7 @@ If
|
||||
.Em Se
|
||||
is not set, \&Ss with argument 0 will be used to reset the cursor style instead.
|
||||
.It Em \&Sync
|
||||
Show that the terminal supports synchronized updates.
|
||||
Start (parameter is 1) or end (parameter is 2) a synchronized update.
|
||||
.It Em \&Tc
|
||||
Indicate that the terminal supports the
|
||||
.Ql direct colour
|
||||
|
20
tmux.c
20
tmux.c
@ -55,7 +55,7 @@ usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: %s [-2CluvV] [-c shell-command] [-f file] [-L socket-name]\n"
|
||||
" [-S socket-path] [command [flags]]\n",
|
||||
" [-S socket-path] [-T features] [command [flags]]\n",
|
||||
getprogname());
|
||||
exit(1);
|
||||
}
|
||||
@ -233,9 +233,11 @@ getversion(void)
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *path, *label, *cause, **var;
|
||||
char *path = NULL, *label = NULL;
|
||||
char *cause, **var;
|
||||
const char *s, *shell, *cwd;
|
||||
int opt, flags, keys;
|
||||
int opt, flags = 0, keys;
|
||||
int feat = 0;
|
||||
const struct options_table_entry *oe;
|
||||
|
||||
if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL &&
|
||||
@ -252,14 +254,11 @@ main(int argc, char **argv)
|
||||
|
||||
if (**argv == '-')
|
||||
flags = CLIENT_LOGIN;
|
||||
else
|
||||
flags = 0;
|
||||
|
||||
label = path = NULL;
|
||||
while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUvV")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:T:uUvV")) != -1) {
|
||||
switch (opt) {
|
||||
case '2':
|
||||
flags |= CLIENT_256COLOURS;
|
||||
tty_add_features(&feat, "256", ":,");
|
||||
break;
|
||||
case 'c':
|
||||
shell_command = optarg;
|
||||
@ -289,6 +288,9 @@ main(int argc, char **argv)
|
||||
free(path);
|
||||
path = xstrdup(optarg);
|
||||
break;
|
||||
case 'T':
|
||||
tty_add_features(&feat, optarg, ":,");
|
||||
break;
|
||||
case 'u':
|
||||
flags |= CLIENT_UTF8;
|
||||
break;
|
||||
@ -396,5 +398,5 @@ main(int argc, char **argv)
|
||||
free(label);
|
||||
|
||||
/* Pass control to the client. */
|
||||
exit(client_main(osdep_event_init(), argc, argv, flags));
|
||||
exit(client_main(event_init(), argc, argv, flags, feat));
|
||||
}
|
||||
|
30
tmux.h
30
tmux.h
@ -476,6 +476,7 @@ enum msgtype {
|
||||
MSG_IDENTIFY_DONE,
|
||||
MSG_IDENTIFY_CLIENTPID,
|
||||
MSG_IDENTIFY_CWD,
|
||||
MSG_IDENTIFY_FEATURES,
|
||||
|
||||
MSG_COMMAND = 200,
|
||||
MSG_DETACH,
|
||||
@ -1178,7 +1179,8 @@ struct tty_key {
|
||||
struct tty_code;
|
||||
struct tty_term {
|
||||
char *name;
|
||||
u_int references;
|
||||
struct tty *tty;
|
||||
int features;
|
||||
|
||||
char acs[UCHAR_MAX + 1][2];
|
||||
|
||||
@ -1189,8 +1191,6 @@ struct tty_term {
|
||||
#define TERM_DECSLRM 0x4
|
||||
#define TERM_DECFRA 0x8
|
||||
#define TERM_RGBCOLOURS 0x10
|
||||
#define TERM_SYNC 0x20
|
||||
#define TERM_UTF8 0x40
|
||||
int flags;
|
||||
|
||||
LIST_ENTRY(tty_term) entry;
|
||||
@ -1254,8 +1254,6 @@ struct tty {
|
||||
int flags;
|
||||
|
||||
struct tty_term *term;
|
||||
char *term_name;
|
||||
int term_flags;
|
||||
|
||||
u_int mouse_last_x;
|
||||
u_int mouse_last_y;
|
||||
@ -1269,7 +1267,6 @@ struct tty {
|
||||
struct event key_timer;
|
||||
struct tty_key *key_tree;
|
||||
};
|
||||
#define tty_term_flags(tty) (tty->term->flags|tty->term_flags)
|
||||
|
||||
/* TTY command context. */
|
||||
struct tty_ctx {
|
||||
@ -1500,7 +1497,9 @@ struct client {
|
||||
char *title;
|
||||
const char *cwd;
|
||||
|
||||
char *term;
|
||||
char *term_name;
|
||||
int term_features;
|
||||
|
||||
char *ttyname;
|
||||
struct tty tty;
|
||||
|
||||
@ -1533,7 +1532,7 @@ struct client {
|
||||
#define CLIENT_CONTROLCONTROL 0x4000
|
||||
#define CLIENT_FOCUSED 0x8000
|
||||
#define CLIENT_UTF8 0x10000
|
||||
#define CLIENT_256COLOURS 0x20000
|
||||
/* 0x20000 unused */
|
||||
#define CLIENT_IDENTIFIED 0x40000
|
||||
#define CLIENT_STATUSFORCE 0x80000
|
||||
#define CLIENT_DOUBLECLICK 0x100000
|
||||
@ -1955,7 +1954,7 @@ void tty_putcode_ptr2(struct tty *, enum tty_code_code, const void *,
|
||||
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);
|
||||
int tty_init(struct tty *, struct client *, int, char *);
|
||||
int tty_init(struct tty *, struct client *, int);
|
||||
void tty_resize(struct tty *);
|
||||
void tty_set_size(struct tty *, u_int, u_int, u_int, u_int);
|
||||
void tty_start_tty(struct tty *);
|
||||
@ -1970,8 +1969,7 @@ void tty_sync_end(struct tty *);
|
||||
int tty_open(struct tty *, char **);
|
||||
void tty_close(struct tty *);
|
||||
void tty_free(struct tty *);
|
||||
void tty_set_flags(struct tty *, int);
|
||||
int tty_get_flags(struct tty *);
|
||||
void tty_update_features(struct tty *);
|
||||
void tty_write(void (*)(struct tty *, const struct tty_ctx *),
|
||||
struct tty_ctx *);
|
||||
void tty_cmd_alignmenttest(struct tty *, const struct tty_ctx *);
|
||||
@ -2001,7 +1999,8 @@ void tty_cmd_syncend(struct tty *, const struct tty_ctx *);
|
||||
/* tty-term.c */
|
||||
extern struct tty_terms tty_terms;
|
||||
u_int tty_term_ncodes(void);
|
||||
struct tty_term *tty_term_find(char *, int, char **);
|
||||
void tty_term_apply(struct tty_term *, const char *, int);
|
||||
struct tty_term *tty_term_create(struct tty *, char *, int *, int, char **);
|
||||
void tty_term_free(struct tty_term *);
|
||||
int tty_term_has(struct tty_term *, enum tty_code_code);
|
||||
const char *tty_term_string(struct tty_term *, enum tty_code_code);
|
||||
@ -2018,6 +2017,11 @@ int tty_term_number(struct tty_term *, enum tty_code_code);
|
||||
int tty_term_flag(struct tty_term *, enum tty_code_code);
|
||||
const char *tty_term_describe(struct tty_term *, enum tty_code_code);
|
||||
|
||||
/* tty-features.c */
|
||||
void tty_add_features(int *, const char *, const char *);
|
||||
const char *tty_get_features(int);
|
||||
void tty_apply_features(struct tty_term *, int);
|
||||
|
||||
/* tty-acs.c */
|
||||
int tty_acs_needed(struct tty *);
|
||||
const char *tty_acs_get(struct tty *, u_char);
|
||||
@ -2163,7 +2167,7 @@ void printflike(2, 3) cmdq_error(struct cmdq_item *, const char *, ...);
|
||||
void cmd_wait_for_flush(void);
|
||||
|
||||
/* client.c */
|
||||
int client_main(struct event_base *, int, char **, int);
|
||||
int client_main(struct event_base *, int, char **, int, int);
|
||||
|
||||
/* key-bindings.c */
|
||||
struct key_table *key_bindings_get_table(const char *, int);
|
||||
|
@ -99,7 +99,7 @@ tty_acs_needed(struct tty *tty)
|
||||
tty_term_number(tty->term, TTYC_U8) == 0)
|
||||
return (1);
|
||||
|
||||
if (tty_get_flags(tty) & TERM_UTF8)
|
||||
if (tty->client->flags & CLIENT_UTF8)
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
263
tty-features.c
Normal file
263
tty-features.c
Normal file
@ -0,0 +1,263 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 Nicholas Marriott <nicholas.marriott@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 "tmux.h"
|
||||
|
||||
/*
|
||||
* Still hardcoded:
|
||||
* - bracket paste (sent if application asks for it);
|
||||
* - mouse (under kmous capability);
|
||||
* - focus events (under focus-events option);
|
||||
* - default colours (under AX or op capabilities);
|
||||
* - AIX colours (under colors >= 16);
|
||||
* - alternate escape (under XT).
|
||||
*
|
||||
* Also:
|
||||
* - XT is used to decide whether to send DA and DSR,
|
||||
* - DECSLRM and DECFRA use a flag instead of capabilities.
|
||||
* - UTF-8 is a separate flag on the client; needed for unattached clients.
|
||||
*/
|
||||
|
||||
/* A named terminal feature. */
|
||||
struct tty_feature {
|
||||
const char *name;
|
||||
const char **capabilities;
|
||||
int flags;
|
||||
};
|
||||
|
||||
/* Terminal has xterm(1) title setting. */
|
||||
static const char *tty_feature_title_capabilities[] = {
|
||||
"tsl=\\E]0;", /* should be using TS really */
|
||||
"fsl=\\a",
|
||||
NULL
|
||||
};
|
||||
static struct tty_feature tty_feature_title = {
|
||||
"title",
|
||||
tty_feature_title_capabilities,
|
||||
0
|
||||
};
|
||||
|
||||
/* Terminal can set the clipboard with OSC 52. */
|
||||
static const char *tty_feature_clipboard_capabilities[] = {
|
||||
"Ms=\\E]52;%p1%s;%p2%s\\a",
|
||||
NULL
|
||||
};
|
||||
static struct tty_feature tty_feature_clipboard = {
|
||||
"clipboard",
|
||||
tty_feature_clipboard_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
|
||||
* 256 palette.
|
||||
*/
|
||||
static const char *tty_feature_rgb_capabilities[] = {
|
||||
"setrgbf=\\E[38;2;%p1%d;%p2%d;%p3%dm",
|
||||
"setrgbb=\\E[48;2;%p1%d;%p2%d;%p3%dm",
|
||||
"setab=\\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m",
|
||||
"setaf=\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m",
|
||||
NULL
|
||||
};
|
||||
static struct tty_feature tty_feature_rgb = {
|
||||
"RGB",
|
||||
tty_feature_rgb_capabilities,
|
||||
(TERM_256COLOURS|TERM_RGBCOLOURS)
|
||||
};
|
||||
|
||||
/* Terminal supports 256 colours. */
|
||||
static const char *tty_feature_256_capabilities[] = {
|
||||
"setab=\\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m",
|
||||
"setaf=\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m",
|
||||
NULL
|
||||
};
|
||||
static struct tty_feature tty_feature_256 = {
|
||||
"256",
|
||||
tty_feature_256_capabilities,
|
||||
TERM_256COLOURS
|
||||
};
|
||||
|
||||
/* Terminal supports overline. */
|
||||
static const char *tty_feature_overline_capabilities[] = {
|
||||
"Smol=\\E[53m",
|
||||
NULL
|
||||
};
|
||||
static struct tty_feature tty_feature_overline = {
|
||||
"overline",
|
||||
tty_feature_overline_capabilities,
|
||||
0
|
||||
};
|
||||
|
||||
/* Terminal supports underscore styles. */
|
||||
static const char *tty_feature_usstyle_capabilities[] = {
|
||||
"Smulx=\E[4::%p1%dm",
|
||||
"Setulc=\E[58::2::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m",
|
||||
NULL
|
||||
};
|
||||
static struct tty_feature tty_feature_usstyle = {
|
||||
"usstyle",
|
||||
tty_feature_usstyle_capabilities,
|
||||
0
|
||||
};
|
||||
|
||||
/* Terminal supports cursor styles. */
|
||||
static const char *tty_feature_cstyle_capabilities[] = {
|
||||
"Ss=\\E[%p1%d q",
|
||||
"Se=\\E[2 q",
|
||||
NULL
|
||||
};
|
||||
static struct tty_feature tty_feature_cstyle = {
|
||||
"cstyle",
|
||||
tty_feature_cstyle_capabilities,
|
||||
0
|
||||
};
|
||||
|
||||
/* Terminal supports cursor colours. */
|
||||
static const char *tty_feature_ccolour_capabilities[] = {
|
||||
"Cs=\\E]12;%p1%s\\a",
|
||||
"Cr=\\E]112\\a",
|
||||
NULL
|
||||
};
|
||||
static struct tty_feature tty_feature_ccolour = {
|
||||
"ccolour",
|
||||
tty_feature_ccolour_capabilities,
|
||||
0
|
||||
};
|
||||
|
||||
/* Terminal supports synchronized updates. */
|
||||
static const char *tty_feature_sync_capabilities[] = {
|
||||
"Sync=\\EP=%p1%ds\\E\\\\",
|
||||
NULL
|
||||
};
|
||||
static struct tty_feature tty_feature_sync = {
|
||||
"sync",
|
||||
tty_feature_sync_capabilities,
|
||||
0
|
||||
};
|
||||
|
||||
/* Terminal supports DECSLRM margins. */
|
||||
static struct tty_feature tty_feature_margins = {
|
||||
"margins",
|
||||
NULL,
|
||||
TERM_DECSLRM
|
||||
};
|
||||
|
||||
/* Terminal supports DECFRA rectangle fill. */
|
||||
static struct tty_feature tty_feature_rectfill = {
|
||||
"rectfill",
|
||||
NULL,
|
||||
TERM_DECFRA
|
||||
};
|
||||
|
||||
/* Available terminal features. */
|
||||
static const struct tty_feature *tty_features[] = {
|
||||
&tty_feature_256,
|
||||
&tty_feature_clipboard,
|
||||
&tty_feature_ccolour,
|
||||
&tty_feature_cstyle,
|
||||
&tty_feature_margins,
|
||||
&tty_feature_overline,
|
||||
&tty_feature_rectfill,
|
||||
&tty_feature_rgb,
|
||||
&tty_feature_sync,
|
||||
&tty_feature_title,
|
||||
&tty_feature_usstyle
|
||||
};
|
||||
|
||||
void
|
||||
tty_add_features(int *feat, const char *s, const char *separators)
|
||||
{
|
||||
const struct tty_feature *tf;
|
||||
char *next, *loop, *copy;
|
||||
u_int i;
|
||||
|
||||
loop = copy = xstrdup(s);
|
||||
while ((next = strsep(&loop, separators)) != NULL) {
|
||||
for (i = 0; i < nitems(tty_features); i++) {
|
||||
tf = tty_features[i];
|
||||
if (strcasecmp(tf->name, next) == 0)
|
||||
break;
|
||||
}
|
||||
if (i == nitems(tty_features)) {
|
||||
log_debug("unknown terminal feature: %s", next);
|
||||
break;
|
||||
}
|
||||
if (~(*feat) & (1 << i)) {
|
||||
log_debug("adding terminal feature: %s", tf->name);
|
||||
(*feat) |= (1 << i);
|
||||
}
|
||||
}
|
||||
free(copy);
|
||||
}
|
||||
|
||||
const char *
|
||||
tty_get_features(int feat)
|
||||
{
|
||||
const struct tty_feature *tf;
|
||||
static char s[512];
|
||||
u_int i;
|
||||
|
||||
*s = '\0';
|
||||
for (i = 0; i < nitems(tty_features); i++) {
|
||||
if (~feat & (1 << i))
|
||||
continue;
|
||||
tf = tty_features[i];
|
||||
|
||||
strlcat(s, tf->name, sizeof s);
|
||||
strlcat(s, ",", sizeof s);
|
||||
}
|
||||
if (*s != '\0')
|
||||
s[strlen(s) - 1] = '\0';
|
||||
return (s);
|
||||
}
|
||||
|
||||
void
|
||||
tty_apply_features(struct tty_term *term, int feat)
|
||||
{
|
||||
const struct tty_feature *tf;
|
||||
const char **capability;
|
||||
u_int i;
|
||||
|
||||
if (feat == 0)
|
||||
return;
|
||||
log_debug("applying terminal features: %s", tty_get_features(feat));
|
||||
|
||||
for (i = 0; i < nitems(tty_features); i++) {
|
||||
if ((term->features & (1 << i)) || (~feat & (1 << i)))
|
||||
continue;
|
||||
tf = tty_features[i];
|
||||
|
||||
log_debug("applying terminal feature: %s", tf->name);
|
||||
if (tf->capabilities != NULL) {
|
||||
capability = tf->capabilities;
|
||||
while (*capability != NULL) {
|
||||
log_debug("adding capability: %s", *capability);
|
||||
tty_term_apply(term, *capability, 1);
|
||||
capability++;
|
||||
}
|
||||
}
|
||||
term->flags |= tf->flags;
|
||||
}
|
||||
term->features |= feat;
|
||||
}
|
62
tty-keys.c
62
tty-keys.c
@ -1020,7 +1020,6 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len,
|
||||
struct client *c = tty->client;
|
||||
u_int i, n = 0;
|
||||
char tmp[64], *endptr, p[32] = { 0 }, *cp, *next;
|
||||
int flags = 0;
|
||||
|
||||
*size = 0;
|
||||
if (tty->flags & TTY_HAVEDA)
|
||||
@ -1060,24 +1059,42 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len,
|
||||
n++;
|
||||
}
|
||||
|
||||
/* Set terminal flags. */
|
||||
/* Add terminal features. */
|
||||
switch (p[0]) {
|
||||
case 41: /* VT420 */
|
||||
flags |= (TERM_DECFRA|TERM_DECSLRM);
|
||||
tty_add_features(&c->term_features,
|
||||
"margins,"
|
||||
"rectfill",
|
||||
",");
|
||||
break;
|
||||
case 'M': /* mintty */
|
||||
flags |= (TERM_256COLOURS|TERM_RGBCOLOURS);
|
||||
tty_add_features(&c->term_features,
|
||||
"256,"
|
||||
"RGB,"
|
||||
"title",
|
||||
",");
|
||||
break;
|
||||
case 'T': /* tmux - new versons reply to DSR which will set RGB */
|
||||
flags |= (TERM_UTF8|TERM_256COLOURS);
|
||||
case 'T': /* tmux */
|
||||
tty_add_features(&c->term_features,
|
||||
"256,"
|
||||
"RGB,"
|
||||
"ccolour,"
|
||||
"cstyle,"
|
||||
"overline,"
|
||||
"title,"
|
||||
"usstyle",
|
||||
",");
|
||||
break;
|
||||
case 'U': /* rxvt-unicode */
|
||||
flags |= (TERM_UTF8);
|
||||
tty_add_features(&c->term_features,
|
||||
"256,"
|
||||
"title",
|
||||
",");
|
||||
break;
|
||||
}
|
||||
log_debug("%s: received secondary DA %.*s", c->name, (int)*size, buf);
|
||||
|
||||
tty_set_flags(tty, flags);
|
||||
tty_update_features(tty);
|
||||
tty->flags |= TTY_HAVEDA;
|
||||
|
||||
return (0);
|
||||
@ -1094,7 +1111,6 @@ tty_keys_device_status_report(struct tty *tty, const char *buf, size_t len,
|
||||
struct client *c = tty->client;
|
||||
u_int i;
|
||||
char tmp[64];
|
||||
int flags = 0;
|
||||
|
||||
*size = 0;
|
||||
if (tty->flags & TTY_HAVEDSR)
|
||||
@ -1125,15 +1141,31 @@ tty_keys_device_status_report(struct tty *tty, const char *buf, size_t len,
|
||||
tmp[i] = '\0';
|
||||
*size = 3 + i;
|
||||
|
||||
/* Set terminal flags. */
|
||||
/* Add terminal features. */
|
||||
if (strncmp(tmp, "ITERM2 ", 7) == 0) {
|
||||
flags |= (TERM_UTF8|TERM_DECSLRM|TERM_SYNC|TERM_256COLOURS|
|
||||
TERM_RGBCOLOURS);
|
||||
} else if (strncmp(tmp, "TMUX ", 5) == 0)
|
||||
flags |= (TERM_UTF8|TERM_256COLOURS|TERM_RGBCOLOURS);
|
||||
tty_add_features(&c->term_features,
|
||||
"256,"
|
||||
"RGB,"
|
||||
"clipboard,"
|
||||
"cstyle,"
|
||||
"margins,"
|
||||
"sync,"
|
||||
"title,",
|
||||
",");
|
||||
} else if (strncmp(tmp, "TMUX ", 5) == 0) {
|
||||
tty_add_features(&c->term_features,
|
||||
"256,"
|
||||
"RGB,"
|
||||
"ccolour,"
|
||||
"cstyle,"
|
||||
"overline,"
|
||||
"title,"
|
||||
"usstyle",
|
||||
",");
|
||||
}
|
||||
log_debug("%s: received DSR %.*s", c->name, (int)*size, buf);
|
||||
|
||||
tty_set_flags(tty, flags);
|
||||
tty_update_features(tty);
|
||||
tty->flags |= TTY_HAVEDSR;
|
||||
|
||||
return (0);
|
||||
|
106
tty-term.c
106
tty-term.c
@ -30,7 +30,6 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
static void tty_term_override(struct tty_term *, const char *);
|
||||
static char *tty_term_strip(const char *);
|
||||
|
||||
struct tty_terms tty_terms = LIST_HEAD_INITIALIZER(tty_terms);
|
||||
@ -263,7 +262,7 @@ static const struct tty_term_code_entry tty_term_codes[] = {
|
||||
[TTYC_SMUL] = { TTYCODE_STRING, "smul" },
|
||||
[TTYC_SMXX] = { TTYCODE_STRING, "smxx" },
|
||||
[TTYC_SS] = { TTYCODE_STRING, "Ss" },
|
||||
[TTYC_SYNC] = { TTYCODE_FLAG, "Sync" },
|
||||
[TTYC_SYNC] = { TTYCODE_STRING, "Sync" },
|
||||
[TTYC_TC] = { TTYCODE_FLAG, "Tc" },
|
||||
[TTYC_TSL] = { TTYCODE_STRING, "tsl" },
|
||||
[TTYC_U8] = { TTYCODE_NUMBER, "U8" },
|
||||
@ -338,22 +337,18 @@ tty_term_override_next(const char *s, size_t *offset)
|
||||
return (value);
|
||||
}
|
||||
|
||||
static void
|
||||
tty_term_override(struct tty_term *term, const char *override)
|
||||
void
|
||||
tty_term_apply(struct tty_term *term, const char *capabilities, int quiet)
|
||||
{
|
||||
const struct tty_term_code_entry *ent;
|
||||
struct tty_code *code;
|
||||
size_t offset = 0;
|
||||
char *cp, *value, *s;
|
||||
const char *errstr;
|
||||
const char *errstr, *name = term->name;
|
||||
u_int i;
|
||||
int n, remove;
|
||||
|
||||
s = tty_term_override_next(override, &offset);
|
||||
if (s == NULL || fnmatch(s, term->name, 0) != 0)
|
||||
return;
|
||||
|
||||
while ((s = tty_term_override_next(override, &offset)) != NULL) {
|
||||
while ((s = tty_term_override_next(capabilities, &offset)) != NULL) {
|
||||
if (*s == '\0')
|
||||
continue;
|
||||
value = NULL;
|
||||
@ -372,12 +367,14 @@ tty_term_override(struct tty_term *term, const char *override)
|
||||
} else
|
||||
value = xstrdup("");
|
||||
|
||||
if (remove)
|
||||
log_debug("%s override: %s@", term->name, s);
|
||||
else if (*value == '\0')
|
||||
log_debug("%s override: %s", term->name, s);
|
||||
else
|
||||
log_debug("%s override: %s=%s", term->name, s, value);
|
||||
if (!quiet) {
|
||||
if (remove)
|
||||
log_debug("%s override: %s@", name, s);
|
||||
else if (*value == '\0')
|
||||
log_debug("%s override: %s", name, s);
|
||||
else
|
||||
log_debug("%s override: %s=%s", name, s, value);
|
||||
}
|
||||
|
||||
for (i = 0; i < tty_term_ncodes(); i++) {
|
||||
ent = &tty_term_codes[i];
|
||||
@ -417,7 +414,7 @@ tty_term_override(struct tty_term *term, const char *override)
|
||||
}
|
||||
|
||||
struct tty_term *
|
||||
tty_term_find(char *name, int fd, char **cause)
|
||||
tty_term_create(struct tty *tty, char *name, int *feat, int fd, char **cause)
|
||||
{
|
||||
struct tty_term *term;
|
||||
const struct tty_term_code_entry *ent;
|
||||
@ -428,19 +425,14 @@ tty_term_find(char *name, int fd, char **cause)
|
||||
u_int i;
|
||||
int n, error;
|
||||
const char *s, *acs;
|
||||
size_t offset;
|
||||
char *first;
|
||||
|
||||
LIST_FOREACH(term, &tty_terms, entry) {
|
||||
if (strcmp(term->name, name) == 0) {
|
||||
term->references++;
|
||||
return (term);
|
||||
}
|
||||
}
|
||||
log_debug("new term: %s", name);
|
||||
log_debug("adding term %s", name);
|
||||
|
||||
term = xmalloc(sizeof *term);
|
||||
term = xcalloc(1, sizeof *term);
|
||||
term->tty = tty;
|
||||
term->name = xstrdup(name);
|
||||
term->references = 1;
|
||||
term->flags = 0;
|
||||
term->codes = xcalloc(tty_term_ncodes(), sizeof *term->codes);
|
||||
LIST_INSERT_HEAD(&tty_terms, term, entry);
|
||||
|
||||
@ -498,12 +490,31 @@ tty_term_find(char *name, int fd, char **cause)
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply terminal features. */
|
||||
o = options_get_only(global_options, "terminal-features");
|
||||
a = options_array_first(o);
|
||||
while (a != NULL) {
|
||||
ov = options_array_item_value(a);
|
||||
s = ov->string;
|
||||
|
||||
offset = 0;
|
||||
first = tty_term_override_next(s, &offset);
|
||||
if (first != NULL && fnmatch(first, term->name, 0) == 0)
|
||||
tty_add_features(feat, s + offset, ":");
|
||||
a = options_array_next(a);
|
||||
}
|
||||
|
||||
/* Apply terminal overrides. */
|
||||
o = options_get_only(global_options, "terminal-overrides");
|
||||
a = options_array_first(o);
|
||||
while (a != NULL) {
|
||||
ov = options_array_item_value(a);
|
||||
tty_term_override(term, ov->string);
|
||||
s = ov->string;
|
||||
|
||||
offset = 0;
|
||||
first = tty_term_override_next(s, &offset);
|
||||
if (first != NULL && fnmatch(first, term->name, 0) == 0)
|
||||
tty_term_apply(term, s + offset, 0);
|
||||
a = options_array_next(a);
|
||||
}
|
||||
|
||||
@ -529,19 +540,18 @@ tty_term_find(char *name, int fd, char **cause)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Set flag if terminal has 256 colours. */
|
||||
if (tty_term_number(term, TTYC_COLORS) >= 256)
|
||||
term->flags |= TERM_256COLOURS;
|
||||
/* Add RGB feature if terminal has RGB colours. */
|
||||
if ((tty_term_flag(term, TTYC_TC) || tty_term_has(term, TTYC_RGB)) &&
|
||||
(!tty_term_has(term, TTYC_SETRGBF) ||
|
||||
!tty_term_has(term, TTYC_SETRGBB)))
|
||||
tty_add_features(feat, "RGB", ":,");
|
||||
|
||||
/* Set flag if terminal has RGB colours. */
|
||||
if ((tty_term_flag(term, TTYC_TC) || tty_term_has(term, TTYC_RGB)) ||
|
||||
(tty_term_has(term, TTYC_SETRGBF) &&
|
||||
tty_term_has(term, TTYC_SETRGBB)))
|
||||
term->flags |= TERM_RGBCOLOURS;
|
||||
/* Add feature if terminal has XT. */
|
||||
if (tty_term_flag(term, TTYC_XT))
|
||||
tty_add_features(feat, "title", ":,");
|
||||
|
||||
/* Set flag if terminal has synchronized updates. */
|
||||
if (tty_term_flag(term, TTYC_SYNC))
|
||||
term->flags |= TERM_SYNC;
|
||||
/* Apply the features. */
|
||||
tty_apply_features(term, *feat);
|
||||
|
||||
/*
|
||||
* Terminals without xenl (eat newline glitch) wrap at at $COLUMNS - 1
|
||||
@ -565,18 +575,6 @@ tty_term_find(char *name, int fd, char **cause)
|
||||
for (; acs[0] != '\0' && acs[1] != '\0'; acs += 2)
|
||||
term->acs[(u_char) acs[0]][0] = acs[1];
|
||||
|
||||
/* On terminals with xterm titles (XT), fill in tsl and fsl. */
|
||||
if (tty_term_flag(term, TTYC_XT) &&
|
||||
!tty_term_has(term, TTYC_TSL) &&
|
||||
!tty_term_has(term, TTYC_FSL)) {
|
||||
code = &term->codes[TTYC_TSL];
|
||||
code->value.string = xstrdup("\033]0;");
|
||||
code->type = TTYCODE_STRING;
|
||||
code = &term->codes[TTYC_FSL];
|
||||
code->value.string = xstrdup("\007");
|
||||
code->type = TTYCODE_STRING;
|
||||
}
|
||||
|
||||
/* Log the capabilities. */
|
||||
for (i = 0; i < tty_term_ncodes(); i++)
|
||||
log_debug("%s%s", name, tty_term_describe(term, i));
|
||||
@ -593,10 +591,7 @@ tty_term_free(struct tty_term *term)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
if (--term->references != 0)
|
||||
return;
|
||||
|
||||
LIST_REMOVE(term, entry);
|
||||
log_debug("removing term %s", term->name);
|
||||
|
||||
for (i = 0; i < tty_term_ncodes(); i++) {
|
||||
if (term->codes[i].type == TTYCODE_STRING)
|
||||
@ -604,6 +599,7 @@ tty_term_free(struct tty_term *term)
|
||||
}
|
||||
free(term->codes);
|
||||
|
||||
LIST_REMOVE(term, entry);
|
||||
free(term->name);
|
||||
free(term);
|
||||
}
|
||||
|
125
tty.c
125
tty.c
@ -74,7 +74,7 @@ static void tty_default_attributes(struct tty *, struct window_pane *,
|
||||
u_int);
|
||||
|
||||
#define tty_use_margin(tty) \
|
||||
(tty_get_flags(tty) & TERM_DECSLRM)
|
||||
(tty->term->flags & TERM_DECSLRM)
|
||||
|
||||
#define tty_pane_full_width(tty, ctx) \
|
||||
((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx)
|
||||
@ -96,27 +96,19 @@ tty_create_log(void)
|
||||
}
|
||||
|
||||
int
|
||||
tty_init(struct tty *tty, struct client *c, int fd, char *term)
|
||||
tty_init(struct tty *tty, struct client *c, int fd)
|
||||
{
|
||||
if (!isatty(fd))
|
||||
return (-1);
|
||||
|
||||
memset(tty, 0, sizeof *tty);
|
||||
|
||||
if (term == NULL || *term == '\0')
|
||||
tty->term_name = xstrdup("unknown");
|
||||
else
|
||||
tty->term_name = xstrdup(term);
|
||||
|
||||
tty->fd = fd;
|
||||
tty->client = c;
|
||||
|
||||
tty->cstyle = 0;
|
||||
tty->ccolour = xstrdup("");
|
||||
|
||||
tty->flags = 0;
|
||||
tty->term_flags = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -256,7 +248,10 @@ tty_write_callback(__unused int fd, __unused short events, void *data)
|
||||
int
|
||||
tty_open(struct tty *tty, char **cause)
|
||||
{
|
||||
tty->term = tty_term_find(tty->term_name, tty->fd, cause);
|
||||
struct client *c = tty->client;
|
||||
|
||||
tty->term = tty_term_create(tty, c->term_name, &c->term_features,
|
||||
tty->fd, cause);
|
||||
if (tty->term == NULL) {
|
||||
tty_close(tty);
|
||||
return (-1);
|
||||
@ -466,28 +461,20 @@ void
|
||||
tty_free(struct tty *tty)
|
||||
{
|
||||
tty_close(tty);
|
||||
|
||||
free(tty->ccolour);
|
||||
free(tty->term_name);
|
||||
}
|
||||
|
||||
void
|
||||
tty_set_flags(struct tty *tty, int flags)
|
||||
tty_update_features(struct tty *tty)
|
||||
{
|
||||
tty->term_flags |= flags;
|
||||
struct client *c = tty->client;
|
||||
|
||||
tty_apply_features(tty->term, c->term_features);
|
||||
|
||||
if (tty_use_margin(tty))
|
||||
tty_puts(tty, "\033[?69h"); /* DECLRMM */
|
||||
}
|
||||
|
||||
int
|
||||
tty_get_flags(struct tty *tty)
|
||||
{
|
||||
if (tty->term != NULL)
|
||||
return (tty->term->flags|tty->term_flags);
|
||||
return (tty->term_flags);
|
||||
}
|
||||
|
||||
void
|
||||
tty_raw(struct tty *tty, const char *s)
|
||||
{
|
||||
@ -585,7 +572,7 @@ tty_putc(struct tty *tty, u_char ch)
|
||||
{
|
||||
const char *acs;
|
||||
|
||||
if ((tty_get_flags(tty) & TERM_NOXENL) &&
|
||||
if ((tty->term->flags & TERM_NOXENL) &&
|
||||
ch >= 0x20 && ch != 0x7f &&
|
||||
tty->cy == tty->sy - 1 &&
|
||||
tty->cx + 1 >= tty->sx)
|
||||
@ -611,7 +598,7 @@ tty_putc(struct tty *tty, u_char ch)
|
||||
* where we think it should be after a line wrap - this
|
||||
* means it works on sensible terminals as well.
|
||||
*/
|
||||
if (tty_get_flags(tty) & TERM_NOXENL)
|
||||
if (tty->term->flags & TERM_NOXENL)
|
||||
tty_putcode2(tty, TTYC_CUP, tty->cy, tty->cx);
|
||||
} else
|
||||
tty->cx++;
|
||||
@ -621,7 +608,7 @@ tty_putc(struct tty *tty, u_char ch)
|
||||
void
|
||||
tty_putn(struct tty *tty, const void *buf, size_t len, u_int width)
|
||||
{
|
||||
if ((tty_get_flags(tty) & TERM_NOXENL) &&
|
||||
if ((tty->term->flags & TERM_NOXENL) &&
|
||||
tty->cy == tty->sy - 1 &&
|
||||
tty->cx + len >= tty->sx)
|
||||
len = tty->sx - tty->cx - 1;
|
||||
@ -1179,7 +1166,7 @@ tty_clear_area(struct tty *tty, struct window_pane *wp, u_int py, u_int ny,
|
||||
* background colour isn't default (because it doesn't work
|
||||
* after SGR 0).
|
||||
*/
|
||||
if ((tty_get_flags(tty) & TERM_DECFRA) && !COLOUR_DEFAULT(bg)) {
|
||||
if ((tty->term->flags & TERM_DECFRA) && !COLOUR_DEFAULT(bg)) {
|
||||
xsnprintf(tmp, sizeof tmp, "\033[32;%u;%u;%u;%u$x",
|
||||
py + 1, px + 1, py + ny, px + nx);
|
||||
tty_puts(tty, tmp);
|
||||
@ -1258,7 +1245,7 @@ tty_check_codeset(struct tty *tty, const struct grid_cell *gc)
|
||||
return (gc);
|
||||
|
||||
/* UTF-8 terminal and a UTF-8 character - fine. */
|
||||
if (tty_get_flags(tty) & TERM_UTF8)
|
||||
if (tty->client->flags & CLIENT_UTF8)
|
||||
return (gc);
|
||||
|
||||
/* Replace by the right number of underscores. */
|
||||
@ -1440,8 +1427,8 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
|
||||
void
|
||||
tty_sync_start(struct tty *tty)
|
||||
{
|
||||
if ((~tty->flags & TTY_SYNCING) && (tty_get_flags(tty) & TERM_SYNC)) {
|
||||
tty_puts(tty, "\033P=1s\033\\");
|
||||
if ((~tty->flags & TTY_SYNCING) && tty_term_has(tty->term, TTYC_SYNC)) {
|
||||
tty_putcode1(tty, TTYC_SYNC, 1);
|
||||
tty->flags |= TTY_SYNCING;
|
||||
}
|
||||
}
|
||||
@ -1449,8 +1436,8 @@ tty_sync_start(struct tty *tty)
|
||||
void
|
||||
tty_sync_end(struct tty *tty)
|
||||
{
|
||||
if (tty_get_flags(tty) & TERM_SYNC) {
|
||||
tty_puts(tty, "\033P=2s\033\\");
|
||||
if ((tty->flags & TTY_SYNCING) && tty_term_has(tty->term, TTYC_SYNC)) {
|
||||
tty_putcode1(tty, TTYC_SYNC, 2);
|
||||
tty->flags &= ~TTY_SYNCING;
|
||||
}
|
||||
}
|
||||
@ -1916,7 +1903,7 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
|
||||
ctx->xoff + ctx->ocx + ctx->num > ctx->ox + ctx->sx)) {
|
||||
if (!ctx->wrapped ||
|
||||
!tty_pane_full_width(tty, ctx) ||
|
||||
(tty_get_flags(tty) & TERM_NOXENL) ||
|
||||
(tty->term->flags & TERM_NOXENL) ||
|
||||
ctx->xoff + ctx->ocx != 0 ||
|
||||
ctx->yoff + ctx->ocy != tty->cy + 1 ||
|
||||
tty->cx < tty->sx ||
|
||||
@ -1977,7 +1964,7 @@ tty_cell(struct tty *tty, const struct grid_cell *gc, struct window_pane *wp)
|
||||
const struct grid_cell *gcp;
|
||||
|
||||
/* Skip last character if terminal is stupid. */
|
||||
if ((tty_get_flags(tty) & TERM_NOXENL) &&
|
||||
if ((tty->term->flags & TERM_NOXENL) &&
|
||||
tty->cy == tty->sy - 1 &&
|
||||
tty->cx == tty->sx - 1)
|
||||
return;
|
||||
@ -2140,7 +2127,7 @@ tty_cursor_pane_unless_wrap(struct tty *tty, const struct tty_ctx *ctx,
|
||||
{
|
||||
if (!ctx->wrapped ||
|
||||
!tty_pane_full_width(tty, ctx) ||
|
||||
(tty_get_flags(tty) & TERM_NOXENL) ||
|
||||
(tty->term->flags & TERM_NOXENL) ||
|
||||
ctx->xoff + cx != 0 ||
|
||||
ctx->yoff + cy != tty->cy + 1 ||
|
||||
tty->cx < tty->sx ||
|
||||
@ -2480,14 +2467,14 @@ tty_check_fg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc)
|
||||
/* Is this a 24-bit colour? */
|
||||
if (gc->fg & COLOUR_FLAG_RGB) {
|
||||
/* Not a 24-bit terminal? Translate to 256-colour palette. */
|
||||
if (tty_get_flags(tty) & TERM_RGBCOLOURS)
|
||||
if (tty->term->flags & TERM_RGBCOLOURS)
|
||||
return;
|
||||
colour_split_rgb(gc->fg, &r, &g, &b);
|
||||
gc->fg = colour_find_rgb(r, g, b);
|
||||
}
|
||||
|
||||
/* How many colours does this terminal have? */
|
||||
if (tty_get_flags(tty) & TERM_256COLOURS)
|
||||
if (tty->term->flags & TERM_256COLOURS)
|
||||
colours = 256;
|
||||
else
|
||||
colours = tty_term_number(tty->term, TTYC_COLORS);
|
||||
@ -2529,14 +2516,14 @@ tty_check_bg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc)
|
||||
/* Is this a 24-bit colour? */
|
||||
if (gc->bg & COLOUR_FLAG_RGB) {
|
||||
/* Not a 24-bit terminal? Translate to 256-colour palette. */
|
||||
if (tty_get_flags(tty) & TERM_RGBCOLOURS)
|
||||
if (tty->term->flags & TERM_RGBCOLOURS)
|
||||
return;
|
||||
colour_split_rgb(gc->bg, &r, &g, &b);
|
||||
gc->bg = colour_find_rgb(r, g, b);
|
||||
}
|
||||
|
||||
/* How many colours does this terminal have? */
|
||||
if (tty_get_flags(tty) & TERM_256COLOURS)
|
||||
if (tty->term->flags & TERM_256COLOURS)
|
||||
colours = 256;
|
||||
else
|
||||
colours = tty_term_number(tty->term, TTYC_COLORS);
|
||||
@ -2597,7 +2584,7 @@ tty_colours_fg(struct tty *tty, const struct grid_cell *gc)
|
||||
|
||||
/* Is this an aixterm bright colour? */
|
||||
if (gc->fg >= 90 && gc->fg <= 97) {
|
||||
if (tty_get_flags(tty) & TERM_256COLOURS) {
|
||||
if (tty->term->flags & TERM_256COLOURS) {
|
||||
xsnprintf(s, sizeof s, "\033[%dm", gc->fg);
|
||||
tty_puts(tty, s);
|
||||
} else
|
||||
@ -2629,7 +2616,7 @@ tty_colours_bg(struct tty *tty, const struct grid_cell *gc)
|
||||
|
||||
/* Is this an aixterm bright colour? */
|
||||
if (gc->bg >= 90 && gc->bg <= 97) {
|
||||
if (tty_get_flags(tty) & TERM_256COLOURS) {
|
||||
if (tty->term->flags & TERM_256COLOURS) {
|
||||
xsnprintf(s, sizeof s, "\033[%dm", gc->bg + 10);
|
||||
tty_puts(tty, s);
|
||||
} else
|
||||
@ -2674,67 +2661,25 @@ static int
|
||||
tty_try_colour(struct tty *tty, int colour, const char *type)
|
||||
{
|
||||
u_char r, g, b;
|
||||
char s[32];
|
||||
|
||||
if (colour & COLOUR_FLAG_256) {
|
||||
/*
|
||||
* If the user has specified -2 to the client (meaning
|
||||
* TERM_256COLOURS is set), setaf and setab may not work (or
|
||||
* they may not want to use them), so send the usual sequence.
|
||||
*
|
||||
* Also if RGB is set, setaf and setab do not support the 256
|
||||
* colour palette so use the sequences directly there too.
|
||||
*/
|
||||
if ((tty_get_flags(tty) & TERM_256COLOURS) ||
|
||||
tty_term_has(tty->term, TTYC_RGB))
|
||||
goto fallback_256;
|
||||
|
||||
/*
|
||||
* If the terminfo entry has 256 colours and setaf and setab
|
||||
* exist, assume that they work correctly.
|
||||
*/
|
||||
if (tty_get_flags(tty) & TERM_256COLOURS) {
|
||||
if (*type == '3') {
|
||||
if (!tty_term_has(tty->term, TTYC_SETAF))
|
||||
goto fallback_256;
|
||||
tty_putcode1(tty, TTYC_SETAF, colour & 0xff);
|
||||
} else {
|
||||
if (!tty_term_has(tty->term, TTYC_SETAB))
|
||||
goto fallback_256;
|
||||
tty_putcode1(tty, TTYC_SETAB, colour & 0xff);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
goto fallback_256;
|
||||
if (*type == '3' && tty_term_has(tty->term, TTYC_SETAF))
|
||||
tty_putcode1(tty, TTYC_SETAF, colour & 0xff);
|
||||
else if (tty_term_has(tty->term, TTYC_SETAB))
|
||||
tty_putcode1(tty, TTYC_SETAB, colour & 0xff);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (colour & COLOUR_FLAG_RGB) {
|
||||
colour_split_rgb(colour & 0xffffff, &r, &g, &b);
|
||||
if (*type == '3') {
|
||||
if (!tty_term_has(tty->term, TTYC_SETRGBF))
|
||||
goto fallback_rgb;
|
||||
if (*type == '3' && tty_term_has(tty->term, TTYC_SETRGBF))
|
||||
tty_putcode3(tty, TTYC_SETRGBF, r, g, b);
|
||||
} else {
|
||||
if (!tty_term_has(tty->term, TTYC_SETRGBB))
|
||||
goto fallback_rgb;
|
||||
else if (tty_term_has(tty->term, TTYC_SETRGBB))
|
||||
tty_putcode3(tty, TTYC_SETRGBB, r, g, b);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (-1);
|
||||
|
||||
fallback_256:
|
||||
xsnprintf(s, sizeof s, "\033[%s;5;%dm", type, colour & 0xff);
|
||||
log_debug("%s: 256 colour fallback: %s", tty->client->name, s);
|
||||
tty_puts(tty, s);
|
||||
return (0);
|
||||
|
||||
fallback_rgb:
|
||||
xsnprintf(s, sizeof s, "\033[%s;2;%d;%d;%dm", type, r, g, b);
|
||||
log_debug("%s: RGB colour fallback: %s", tty->client->name, s);
|
||||
tty_puts(tty, s);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user