aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornicm <nicm>2018-10-18 07:57:57 +0000
committernicm <nicm>2018-10-18 07:57:57 +0000
commitbc0e527f32642cc9eb2354d1bdc033ab6beca33b (patch)
treea6b154e707a0fad14f57ba8940f76cba024e0330
parentf7c85f3ed8f151501fb72a1c18a48d126d89c83c (diff)
downloadrtmux-bc0e527f32642cc9eb2354d1bdc033ab6beca33b.tar.gz
rtmux-bc0e527f32642cc9eb2354d1bdc033ab6beca33b.tar.bz2
rtmux-bc0e527f32642cc9eb2354d1bdc033ab6beca33b.zip
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.
-rw-r--r--attributes.c56
-rw-r--r--grid.c16
-rw-r--r--input.c46
-rw-r--r--tmux.111
-rw-r--r--tmux.h13
-rw-r--r--tty-term.c48
-rw-r--r--tty.c15
7 files changed, 162 insertions, 43 deletions
diff --git a/attributes.c b/attributes.c
index 1e45e584..1b831733 100644
--- a/attributes.c
+++ b/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');
diff --git a/grid.c b/grid.c
index dcfd95fe..a7c9a67e 100644
--- a/grid.c
+++ b/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);
}
diff --git a/input.c b/input.c
index 254d0e5d..7954099d 100644
--- a/input.c
+++ b/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;
diff --git a/tmux.1 b/tmux.1
index 8eb5aae4..fac01887 100644
--- a/tmux.1
+++ b/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
diff --git a/tmux.h b/tmux.h
index a6770e52..7b451ada 100644
--- a/tmux.h
+++ b/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
diff --git a/tty-term.c b/tty-term.c
index b7536487..7df9a7d1 100644
--- a/tty-term.c
+++ b/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 *
diff --git a/tty.c b/tty.c
index 5bf4a3ca..049ea017 100644
--- a/tty.c
+++ b/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) {