mirror of
https://github.com/tmux/tmux.git
synced 2024-12-04 19:58:48 +00:00
Support for extended underline styles on terminals which offer them,
enabled by adding the Smulx capability with terminal-overrides (add something like ',vte*:Smulx=\E[4\:%p1%dm'). GitHub issue 1492.
This commit is contained in:
parent
f7c85f3ed8
commit
bc0e527f32
56
attributes.c
56
attributes.c
@ -25,13 +25,13 @@
|
||||
const char *
|
||||
attributes_tostring(int attr)
|
||||
{
|
||||
static char buf[128];
|
||||
static char buf[512];
|
||||
size_t len;
|
||||
|
||||
if (attr == 0)
|
||||
return ("none");
|
||||
|
||||
len = xsnprintf(buf, sizeof buf, "%s%s%s%s%s%s%s%s",
|
||||
len = xsnprintf(buf, sizeof buf, "%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
(attr & GRID_ATTR_BRIGHT) ? "bright," : "",
|
||||
(attr & GRID_ATTR_DIM) ? "dim," : "",
|
||||
(attr & GRID_ATTR_UNDERSCORE) ? "underscore," : "",
|
||||
@ -39,7 +39,11 @@ attributes_tostring(int attr)
|
||||
(attr & GRID_ATTR_REVERSE) ? "reverse," : "",
|
||||
(attr & GRID_ATTR_HIDDEN) ? "hidden," : "",
|
||||
(attr & GRID_ATTR_ITALICS) ? "italics," : "",
|
||||
(attr & GRID_ATTR_STRIKETHROUGH) ? "strikethrough," : "");
|
||||
(attr & GRID_ATTR_STRIKETHROUGH) ? "strikethrough," : "",
|
||||
(attr & GRID_ATTR_UNDERSCORE_2) ? "double-underscore," : "",
|
||||
(attr & GRID_ATTR_UNDERSCORE_3) ? "curly-underscore," : "",
|
||||
(attr & GRID_ATTR_UNDERSCORE_4) ? "dotted-underscore," : "",
|
||||
(attr & GRID_ATTR_UNDERSCORE_5) ? "dashed-underscore," : "");
|
||||
if (len > 0)
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
@ -52,6 +56,25 @@ attributes_fromstring(const char *str)
|
||||
const char delimiters[] = " ,|";
|
||||
int attr;
|
||||
size_t end;
|
||||
u_int i;
|
||||
struct {
|
||||
const char* name;
|
||||
int attr;
|
||||
} table[] = {
|
||||
{ "bright", GRID_ATTR_BRIGHT },
|
||||
{ "bold", GRID_ATTR_BRIGHT },
|
||||
{ "dim", GRID_ATTR_DIM },
|
||||
{ "underscore", GRID_ATTR_UNDERSCORE },
|
||||
{ "blink", GRID_ATTR_BLINK },
|
||||
{ "reverse", GRID_ATTR_REVERSE },
|
||||
{ "hidden", GRID_ATTR_HIDDEN },
|
||||
{ "italics", GRID_ATTR_ITALICS },
|
||||
{ "strikethrough", GRID_ATTR_STRIKETHROUGH },
|
||||
{ "double-underscore", GRID_ATTR_UNDERSCORE_2 },
|
||||
{ "curly-underscore", GRID_ATTR_UNDERSCORE_3 },
|
||||
{ "dotted-underscore", GRID_ATTR_UNDERSCORE_4 },
|
||||
{ "dashed-underscore", GRID_ATTR_UNDERSCORE_5 }
|
||||
};
|
||||
|
||||
if (*str == '\0' || strcspn(str, delimiters) == 0)
|
||||
return (-1);
|
||||
@ -64,24 +87,15 @@ attributes_fromstring(const char *str)
|
||||
attr = 0;
|
||||
do {
|
||||
end = strcspn(str, delimiters);
|
||||
if ((end == 6 && strncasecmp(str, "bright", end) == 0) ||
|
||||
(end == 4 && strncasecmp(str, "bold", end) == 0))
|
||||
attr |= GRID_ATTR_BRIGHT;
|
||||
else if (end == 3 && strncasecmp(str, "dim", end) == 0)
|
||||
attr |= GRID_ATTR_DIM;
|
||||
else if (end == 10 && strncasecmp(str, "underscore", end) == 0)
|
||||
attr |= GRID_ATTR_UNDERSCORE;
|
||||
else if (end == 5 && strncasecmp(str, "blink", end) == 0)
|
||||
attr |= GRID_ATTR_BLINK;
|
||||
else if (end == 7 && strncasecmp(str, "reverse", end) == 0)
|
||||
attr |= GRID_ATTR_REVERSE;
|
||||
else if (end == 6 && strncasecmp(str, "hidden", end) == 0)
|
||||
attr |= GRID_ATTR_HIDDEN;
|
||||
else if (end == 7 && strncasecmp(str, "italics", end) == 0)
|
||||
attr |= GRID_ATTR_ITALICS;
|
||||
else if (end == 13 && strncasecmp(str, "strikethrough", end) == 0)
|
||||
attr |= GRID_ATTR_STRIKETHROUGH;
|
||||
else
|
||||
for (i = 0; i < nitems(table); i++) {
|
||||
if (end != strlen(table[i].name))
|
||||
continue;
|
||||
if (strncasecmp(str, table[i].name, end) == 0) {
|
||||
attr |= table[i].attr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == nitems(table))
|
||||
return (-1);
|
||||
str += end + strspn(str + end, delimiters);
|
||||
} while (*str != '\0');
|
||||
|
16
grid.c
16
grid.c
@ -764,7 +764,11 @@ grid_string_cells_code(const struct grid_cell *lastgc,
|
||||
{ GRID_ATTR_BLINK, 5 },
|
||||
{ GRID_ATTR_REVERSE, 7 },
|
||||
{ GRID_ATTR_HIDDEN, 8 },
|
||||
{ GRID_ATTR_STRIKETHROUGH, 9 }
|
||||
{ GRID_ATTR_STRIKETHROUGH, 9 },
|
||||
{ GRID_ATTR_UNDERSCORE_2, 42 },
|
||||
{ GRID_ATTR_UNDERSCORE_3, 43 },
|
||||
{ GRID_ATTR_UNDERSCORE_4, 44 },
|
||||
{ GRID_ATTR_UNDERSCORE_5, 45 },
|
||||
};
|
||||
n = 0;
|
||||
|
||||
@ -790,11 +794,15 @@ grid_string_cells_code(const struct grid_cell *lastgc,
|
||||
else
|
||||
strlcat(buf, "\033[", len);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (i + 1 < n)
|
||||
xsnprintf(tmp, sizeof tmp, "%d;", s[i]);
|
||||
else
|
||||
if (s[i] < 10)
|
||||
xsnprintf(tmp, sizeof tmp, "%d", s[i]);
|
||||
else {
|
||||
xsnprintf(tmp, sizeof tmp, "%d:%d", s[i] / 10,
|
||||
s[i] % 10);
|
||||
}
|
||||
strlcat(buf, tmp, len);
|
||||
if (i + 1 < n)
|
||||
strlcat(buf, ";", len);
|
||||
}
|
||||
strlcat(buf, "m", len);
|
||||
}
|
||||
|
46
input.c
46
input.c
@ -1835,10 +1835,11 @@ input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i)
|
||||
static void
|
||||
input_csi_dispatch_sgr_colon(struct input_ctx *ictx, u_int i)
|
||||
{
|
||||
char *s = ictx->param_list[i].str, *copy, *ptr, *out;
|
||||
int p[8];
|
||||
u_int n;
|
||||
const char *errstr;
|
||||
struct grid_cell *gc = &ictx->cell.cell;
|
||||
char *s = ictx->param_list[i].str, *copy, *ptr, *out;
|
||||
int p[8];
|
||||
u_int n;
|
||||
const char *errstr;
|
||||
|
||||
for (n = 0; n < nitems(p); n++)
|
||||
p[n] = -1;
|
||||
@ -1857,7 +1858,39 @@ input_csi_dispatch_sgr_colon(struct input_ctx *ictx, u_int i)
|
||||
}
|
||||
free(copy);
|
||||
|
||||
if (n == 0 || (p[0] != 38 && p[0] != 48))
|
||||
if (n == 0)
|
||||
return;
|
||||
if (p[0] == 4) {
|
||||
if (n != 2)
|
||||
return;
|
||||
switch (p[1]) {
|
||||
case 0:
|
||||
gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
|
||||
break;
|
||||
case 1:
|
||||
gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
|
||||
gc->attr |= GRID_ATTR_UNDERSCORE;
|
||||
break;
|
||||
case 2:
|
||||
gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
|
||||
gc->attr |= GRID_ATTR_UNDERSCORE_2;
|
||||
break;
|
||||
case 3:
|
||||
gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
|
||||
gc->attr |= GRID_ATTR_UNDERSCORE_3;
|
||||
break;
|
||||
case 4:
|
||||
gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
|
||||
gc->attr |= GRID_ATTR_UNDERSCORE_4;
|
||||
break;
|
||||
case 5:
|
||||
gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
|
||||
gc->attr |= GRID_ATTR_UNDERSCORE_5;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (p[0] != 38 && p[0] != 48)
|
||||
return;
|
||||
if (p[1] == -1)
|
||||
i = 2;
|
||||
@ -1927,6 +1960,7 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
|
||||
gc->attr |= GRID_ATTR_ITALICS;
|
||||
break;
|
||||
case 4:
|
||||
gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
|
||||
gc->attr |= GRID_ATTR_UNDERSCORE;
|
||||
break;
|
||||
case 5:
|
||||
@ -1948,7 +1982,7 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
|
||||
gc->attr &= ~GRID_ATTR_ITALICS;
|
||||
break;
|
||||
case 24:
|
||||
gc->attr &= ~GRID_ATTR_UNDERSCORE;
|
||||
gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
|
||||
break;
|
||||
case 25:
|
||||
gc->attr &= ~GRID_ATTR_BLINK;
|
||||
|
11
tmux.1
11
tmux.1
@ -2769,8 +2769,12 @@ or a comma-delimited list of one or more of:
|
||||
.Ic reverse ,
|
||||
.Ic hidden ,
|
||||
.Ic italics ,
|
||||
.Ic strikethrough ,
|
||||
.Ic double-underscore
|
||||
.Ic curly-underscore
|
||||
.Ic dotted-underscore
|
||||
or
|
||||
.Ic strikethrough
|
||||
.Ic dashed-underscore
|
||||
to turn an attribute on, or an attribute prefixed with
|
||||
.Ql no
|
||||
to turn one off.
|
||||
@ -4419,6 +4423,11 @@ to change the cursor colour from inside
|
||||
.Bd -literal -offset indent
|
||||
$ printf '\e033]12;red\e033\e\e'
|
||||
.Ed
|
||||
.It Em \&Smulx
|
||||
Set a styled underline.
|
||||
The single parameter is one of: 0 for no underline, 1 for normal
|
||||
underline, 2 for double underline, 3 for curly underline, 4 for dotted
|
||||
underline and 5 for dashed underline.
|
||||
.It Em \&Ss , Se
|
||||
Set or reset the cursor style.
|
||||
If set, a sequence such as this may be used
|
||||
|
13
tmux.h
13
tmux.h
@ -421,6 +421,7 @@ enum tty_code_code {
|
||||
TTYC_SMCUP,
|
||||
TTYC_SMKX,
|
||||
TTYC_SMSO,
|
||||
TTYC_SMULX,
|
||||
TTYC_SMUL,
|
||||
TTYC_SMXX,
|
||||
TTYC_SS,
|
||||
@ -546,6 +547,18 @@ enum utf8_state {
|
||||
#define GRID_ATTR_ITALICS 0x40
|
||||
#define GRID_ATTR_CHARSET 0x80 /* alternative character set */
|
||||
#define GRID_ATTR_STRIKETHROUGH 0x100
|
||||
#define GRID_ATTR_UNDERSCORE_2 0x200
|
||||
#define GRID_ATTR_UNDERSCORE_3 0x400
|
||||
#define GRID_ATTR_UNDERSCORE_4 0x800
|
||||
#define GRID_ATTR_UNDERSCORE_5 0x1000
|
||||
|
||||
/* All underscore attributes. */
|
||||
#define GRID_ATTR_ALL_UNDERSCORE \
|
||||
(GRID_ATTR_UNDERSCORE| \
|
||||
GRID_ATTR_UNDERSCORE_2| \
|
||||
GRID_ATTR_UNDERSCORE_3| \
|
||||
GRID_ATTR_UNDERSCORE_4| \
|
||||
GRID_ATTR_UNDERSCORE_5)
|
||||
|
||||
/* Grid flags. */
|
||||
#define GRID_FLAG_FG256 0x1
|
||||
|
48
tty-term.c
48
tty-term.c
@ -253,6 +253,7 @@ static const struct tty_term_code_entry tty_term_codes[] = {
|
||||
[TTYC_SMCUP] = { TTYCODE_STRING, "smcup" },
|
||||
[TTYC_SMKX] = { TTYCODE_STRING, "smkx" },
|
||||
[TTYC_SMSO] = { TTYCODE_STRING, "smso" },
|
||||
[TTYC_SMULX] = { TTYCODE_STRING, "Smulx" },
|
||||
[TTYC_SMUL] = { TTYCODE_STRING, "smul" },
|
||||
[TTYC_SMXX] = { TTYCODE_STRING, "smxx" },
|
||||
[TTYC_SS] = { TTYCODE_STRING, "Ss" },
|
||||
@ -299,25 +300,53 @@ tty_term_strip(const char *s)
|
||||
return (xstrdup(buf));
|
||||
}
|
||||
|
||||
static char *
|
||||
tty_term_override_next(const char *s, size_t *offset)
|
||||
{
|
||||
static char value[BUFSIZ];
|
||||
size_t n = 0, at = *offset;
|
||||
|
||||
if (s[at] == '\0')
|
||||
return (NULL);
|
||||
|
||||
while (s[at] != '\0') {
|
||||
if (s[at] == ':') {
|
||||
if (s[at + 1] == ':') {
|
||||
value[n++] = ':';
|
||||
at += 2;
|
||||
} else
|
||||
break;
|
||||
} else {
|
||||
value[n++] = s[at];
|
||||
at++;
|
||||
}
|
||||
if (n == (sizeof value) - 1)
|
||||
return (NULL);
|
||||
}
|
||||
if (s[at] != '\0')
|
||||
*offset = at + 1;
|
||||
else
|
||||
*offset = at;
|
||||
value[n] = '\0';
|
||||
return (value);
|
||||
}
|
||||
|
||||
static void
|
||||
tty_term_override(struct tty_term *term, const char *override)
|
||||
{
|
||||
const struct tty_term_code_entry *ent;
|
||||
struct tty_code *code;
|
||||
char *next, *s, *copy, *cp, *value;
|
||||
size_t offset = 0;
|
||||
char *cp, *value, *s;
|
||||
const char *errstr;
|
||||
u_int i;
|
||||
int n, remove;
|
||||
|
||||
copy = next = xstrdup(override);
|
||||
|
||||
s = strsep(&next, ":");
|
||||
if (s == NULL || next == NULL || fnmatch(s, term->name, 0) != 0) {
|
||||
free(copy);
|
||||
s = tty_term_override_next(override, &offset);
|
||||
if (s == NULL || fnmatch(s, term->name, 0) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
while ((s = strsep(&next, ":")) != NULL) {
|
||||
while ((s = tty_term_override_next(override, &offset)) != NULL) {
|
||||
if (*s == '\0')
|
||||
continue;
|
||||
value = NULL;
|
||||
@ -338,6 +367,8 @@ tty_term_override(struct tty_term *term, const char *override)
|
||||
|
||||
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);
|
||||
|
||||
@ -376,7 +407,6 @@ tty_term_override(struct tty_term *term, const char *override)
|
||||
|
||||
free(value);
|
||||
}
|
||||
free(s);
|
||||
}
|
||||
|
||||
struct tty_term *
|
||||
|
15
tty.c
15
tty.c
@ -1832,8 +1832,19 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
|
||||
tty_putcode(tty, TTYC_DIM);
|
||||
if (changed & GRID_ATTR_ITALICS)
|
||||
tty_set_italics(tty);
|
||||
if (changed & GRID_ATTR_UNDERSCORE)
|
||||
tty_putcode(tty, TTYC_SMUL);
|
||||
if (changed & GRID_ATTR_ALL_UNDERSCORE) {
|
||||
if ((changed & GRID_ATTR_UNDERSCORE) ||
|
||||
!tty_term_has(tty->term, TTYC_SMULX))
|
||||
tty_putcode(tty, TTYC_SMUL);
|
||||
else if (changed & GRID_ATTR_UNDERSCORE_2)
|
||||
tty_putcode1(tty, TTYC_SMULX, 2);
|
||||
else if (changed & GRID_ATTR_UNDERSCORE_3)
|
||||
tty_putcode1(tty, TTYC_SMULX, 3);
|
||||
else if (changed & GRID_ATTR_UNDERSCORE_4)
|
||||
tty_putcode1(tty, TTYC_SMULX, 4);
|
||||
else if (changed & GRID_ATTR_UNDERSCORE_5)
|
||||
tty_putcode1(tty, TTYC_SMULX, 5);
|
||||
}
|
||||
if (changed & GRID_ATTR_BLINK)
|
||||
tty_putcode(tty, TTYC_BLINK);
|
||||
if (changed & GRID_ATTR_REVERSE) {
|
||||
|
Loading…
Reference in New Issue
Block a user