aboutsummaryrefslogtreecommitdiff
path: root/tty-term.c
diff options
context:
space:
mode:
Diffstat (limited to 'tty-term.c')
-rw-r--r--tty-term.c149
1 files changed, 90 insertions, 59 deletions
diff --git a/tty-term.c b/tty-term.c
index e556df6f..e8ac6634 100644
--- a/tty-term.c
+++ b/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);
@@ -65,6 +64,8 @@ static const struct tty_term_code_entry tty_term_codes[] = {
[TTYC_BOLD] = { TTYCODE_STRING, "bold" },
[TTYC_CIVIS] = { TTYCODE_STRING, "civis" },
[TTYC_CLEAR] = { TTYCODE_STRING, "clear" },
+ [TTYC_CLMG] = { TTYCODE_STRING, "Clmg" },
+ [TTYC_CMG] = { TTYCODE_STRING, "Cmg" },
[TTYC_CNORM] = { TTYCODE_STRING, "cnorm" },
[TTYC_COLORS] = { TTYCODE_NUMBER, "colors" },
[TTYC_CR] = { TTYCODE_STRING, "Cr" },
@@ -85,12 +86,18 @@ static const struct tty_term_code_entry tty_term_codes[] = {
[TTYC_DIM] = { TTYCODE_STRING, "dim" },
[TTYC_DL1] = { TTYCODE_STRING, "dl1" },
[TTYC_DL] = { TTYCODE_STRING, "dl" },
+ [TTYC_DSFCS] = { TTYCODE_STRING, "Dsfcs" },
+ [TTYC_DSBP] = { TTYCODE_STRING, "Dsbp" },
+ [TTYC_DSMG] = { TTYCODE_STRING, "Dsmg" },
[TTYC_E3] = { TTYCODE_STRING, "E3" },
[TTYC_ECH] = { TTYCODE_STRING, "ech" },
[TTYC_ED] = { TTYCODE_STRING, "ed" },
[TTYC_EL1] = { TTYCODE_STRING, "el1" },
[TTYC_EL] = { TTYCODE_STRING, "el" },
[TTYC_ENACS] = { TTYCODE_STRING, "enacs" },
+ [TTYC_ENBP] = { TTYCODE_STRING, "Enbp" },
+ [TTYC_ENFCS] = { TTYCODE_STRING, "Enfcs" },
+ [TTYC_ENMG] = { TTYCODE_STRING, "Enmg" },
[TTYC_FSL] = { TTYCODE_STRING, "fsl" },
[TTYC_HOME] = { TTYCODE_STRING, "home" },
[TTYC_HPA] = { TTYCODE_STRING, "hpa" },
@@ -241,8 +248,8 @@ static const struct tty_term_code_entry tty_term_codes[] = {
[TTYC_OP] = { TTYCODE_STRING, "op" },
[TTYC_REV] = { TTYCODE_STRING, "rev" },
[TTYC_RGB] = { TTYCODE_FLAG, "RGB" },
- [TTYC_RI] = { TTYCODE_STRING, "ri" },
[TTYC_RIN] = { TTYCODE_STRING, "rin" },
+ [TTYC_RI] = { TTYCODE_STRING, "ri" },
[TTYC_RMACS] = { TTYCODE_STRING, "rmacs" },
[TTYC_RMCUP] = { TTYCODE_STRING, "rmcup" },
[TTYC_RMKX] = { TTYCODE_STRING, "rmkx" },
@@ -263,12 +270,13 @@ 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_STRING, "Sync" },
[TTYC_TC] = { TTYCODE_FLAG, "Tc" },
[TTYC_TSL] = { TTYCODE_STRING, "tsl" },
[TTYC_U8] = { TTYCODE_NUMBER, "U8" },
[TTYC_VPA] = { TTYCODE_STRING, "vpa" },
[TTYC_XENL] = { TTYCODE_FLAG, "xenl" },
- [TTYC_XT] = { TTYCODE_FLAG, "XT" },
+ [TTYC_XT] = { TTYCODE_FLAG, "XT" }
};
u_int
@@ -337,22 +345,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;
@@ -371,12 +375,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];
@@ -415,8 +421,32 @@ tty_term_override(struct tty_term *term, const char *override)
}
}
+void
+tty_term_apply_overrides(struct tty_term *term)
+{
+ struct options_entry *o;
+ struct options_array_item *a;
+ union options_value *ov;
+ const char *s;
+ size_t offset;
+ char *first;
+
+ o = options_get_only(global_options, "terminal-overrides");
+ 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_term_apply(term, s + offset, 0);
+ a = options_array_next(a);
+ }
+}
+
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;
@@ -427,19 +457,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);
@@ -497,12 +522,17 @@ tty_term_find(char *name, int fd, char **cause)
}
}
- /* Apply terminal overrides. */
- o = options_get_only(global_options, "terminal-overrides");
+ /* 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);
- 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_add_features(feat, s + offset, ":");
a = options_array_next(a);
}
@@ -512,6 +542,9 @@ tty_term_find(char *name, int fd, char **cause)
del_curterm(cur_term);
#endif
+ /* Apply overrides so any capabilities used for features are changed. */
+ tty_term_apply_overrides(term);
+
/* These are always required. */
if (!tty_term_has(term, TTYC_CLEAR)) {
xasprintf(cause, "terminal does not support clear");
@@ -522,21 +555,33 @@ tty_term_find(char *name, int fd, char **cause)
goto error;
}
- /* These can be emulated so one of the two is required. */
- if (!tty_term_has(term, TTYC_CUD1) && !tty_term_has(term, TTYC_CUD)) {
- xasprintf(cause, "terminal does not support cud1 or cud");
- goto error;
+ /*
+ * If TERM has XT or clear starts with CSI then it is safe to assume
+ * the terminal is derived from the VT100. This controls whether device
+ * attributes requests are sent to get more information.
+ *
+ * This is a bit of a hack but there aren't that many alternatives.
+ * Worst case tmux will just fall back to using whatever terminfo(5)
+ * says without trying to correct anything that is missing.
+ *
+ * Also add few features that VT100-like terminals should either
+ * support or safely ignore.
+ */
+ s = tty_term_string(term, TTYC_CLEAR);
+ if (tty_term_flag(term, TTYC_XT) || strncmp(s, "\033[", 2) == 0) {
+ term->flags |= TERM_VT100LIKE;
+ tty_add_features(feat, "bpaste,focus,title", ",");
}
- /* 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;
+ /* Apply the features and overrides again. */
+ tty_apply_features(term, *feat);
+ tty_term_apply_overrides(term);
/*
* Terminals without xenl (eat newline glitch) wrap at at $COLUMNS - 1
@@ -560,18 +605,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));
@@ -588,10 +621,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)
@@ -599,6 +629,7 @@ tty_term_free(struct tty_term *term)
}
free(term->codes);
+ LIST_REMOVE(term, entry);
free(term->name);
free(term);
}