diff --git a/options-table.c b/options-table.c index 48e2f2c8..2b506b8c 100644 --- a/options-table.c +++ b/options-table.c @@ -122,11 +122,12 @@ const struct options_table_entry options_table[] = { }, { .name = "terminal-overrides", - .type = OPTIONS_TABLE_STRING, + .type = OPTIONS_TABLE_ARRAY, .scope = OPTIONS_TABLE_SERVER, .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" + ":Ss=\\E[%p1%d q:Se=\\E[2 q,screen*:XT", + .separator = "," }, { .name = "assume-paste-time", diff --git a/tmux.1 b/tmux.1 index 347642b3..f30b45f1 100644 --- a/tmux.1 +++ b/tmux.1 @@ -2495,12 +2495,12 @@ disallowedWindowOps: 20,21,SetXprop Or changing this property from the .Xr xterm 1 interactive menu when required. -.It Ic terminal-overrides Ar string -Contains a list of entries which override terminal descriptions read using -.Xr terminfo 5 . -.Ar string -is a comma-separated list of items each a colon-separated string made up of a -terminal type pattern (matched using +.It Ic terminal-overrides[] Ar string +Allow terminal descriptions read using +.Xr terminfo 5 +to be overriden. +Each entry is a colon-separated string made up of a terminal type pattern +(matched using .Xr fnmatch 3 ) and a set of .Em name=value @@ -2511,16 +2511,10 @@ For example, to set the .Xr terminfo 5 entry to .Ql \ee[H\ee[2J -for all terminal types and the -.Ql dch1 -entry to -.Ql \ee[P -for the -.Ql rxvt -terminal type, the option could be set to the string: -.Bd -literal -offset indent -"*:clear=\ee[H\ee[2J,rxvt:dch1=\ee[P" -.Ed +for all terminal types matching +.Ql rxvt* : +.Pp +.Dl "rxvt*:clear=\ee[H\ee[2J" .Pp The terminal entry value is passed through .Xr strunvis 3 diff --git a/tty-term.c b/tty-term.c index 0496f1f3..02305971 100644 --- a/tty-term.c +++ b/tty-term.c @@ -294,86 +294,82 @@ tty_term_strip(const char *s) } static void -tty_term_override(struct tty_term *term, const char *overrides) +tty_term_override(struct tty_term *term, const char *override) { const struct tty_term_code_entry *ent; struct tty_code *code; - char *termnext, *termstr; - char *entnext, *entstr; - char *s, *ptr, *val; + char *next, *s, *copy, *cp, *value; const char *errstr; u_int i; - int n, removeflag; + int n, remove; - s = xstrdup(overrides); + copy = next = xstrdup(override); - termnext = s; - while ((termstr = strsep(&termnext, ",")) != NULL) { - entnext = termstr; - - entstr = strsep(&entnext, ":"); - if (entstr == NULL || entnext == NULL) - continue; - if (fnmatch(entstr, term->name, 0) != 0) - continue; - while ((entstr = strsep(&entnext, ":")) != NULL) { - if (*entstr == '\0') - continue; - - val = NULL; - removeflag = 0; - if ((ptr = strchr(entstr, '=')) != NULL) { - *ptr++ = '\0'; - val = xstrdup(ptr); - if (strunvis(val, ptr) == -1) { - free(val); - val = xstrdup(ptr); - } - } else if (entstr[strlen(entstr) - 1] == '@') { - entstr[strlen(entstr) - 1] = '\0'; - removeflag = 1; - } else - val = xstrdup(""); - - log_debug("%s override: %s %s", - term->name, entstr, removeflag ? "@" : val); - for (i = 0; i < tty_term_ncodes(); i++) { - ent = &tty_term_codes[i]; - if (strcmp(entstr, ent->name) != 0) - continue; - code = &term->codes[i]; - - if (removeflag) { - code->type = TTYCODE_NONE; - continue; - } - switch (ent->type) { - case TTYCODE_NONE: - break; - case TTYCODE_STRING: - if (code->type == TTYCODE_STRING) - free(code->value.string); - code->value.string = xstrdup(val); - code->type = ent->type; - break; - case TTYCODE_NUMBER: - n = strtonum(val, 0, INT_MAX, &errstr); - if (errstr != NULL) - break; - code->value.number = n; - code->type = ent->type; - break; - case TTYCODE_FLAG: - code->value.flag = 1; - code->type = ent->type; - break; - } - } - - free(val); - } + s = strsep(&next, ":"); + if (s == NULL || next == NULL || fnmatch(s, term->name, 0) != 0) { + free(copy); + return; } + while ((s = strsep(&next, ":")) != NULL) { + if (*s == '\0') + continue; + value = NULL; + + remove = 0; + if ((cp = strchr(s, '=')) != NULL) { + *cp++ = '\0'; + value = xstrdup(cp); + if (strunvis(value, cp) == -1) { + free(value); + value = xstrdup(cp); + } + } else if (s[strlen(s) - 1] == '@') { + s[strlen(s) - 1] = '\0'; + remove = 1; + } else + value = xstrdup(""); + + if (remove) + log_debug("%s override: %s@", term->name, s); + else + log_debug("%s override: %s=%s", term->name, s, value); + + for (i = 0; i < tty_term_ncodes(); i++) { + ent = &tty_term_codes[i]; + if (strcmp(s, ent->name) != 0) + continue; + code = &term->codes[i]; + + if (remove) { + code->type = TTYCODE_NONE; + continue; + } + switch (ent->type) { + case TTYCODE_NONE: + break; + case TTYCODE_STRING: + if (code->type == TTYCODE_STRING) + free(code->value.string); + code->value.string = xstrdup(value); + code->type = ent->type; + break; + case TTYCODE_NUMBER: + n = strtonum(value, 0, INT_MAX, &errstr); + if (errstr != NULL) + break; + code->value.number = n; + code->type = ent->type; + break; + case TTYCODE_FLAG: + code->value.flag = 1; + code->type = ent->type; + break; + } + } + + free(value); + } free(s); } @@ -383,7 +379,8 @@ tty_term_find(char *name, int fd, char **cause) struct tty_term *term; const struct tty_term_code_entry *ent; struct tty_code *code; - u_int i; + struct options_entry *o; + u_int size, i; int n, error; const char *s, *acs; @@ -457,8 +454,14 @@ tty_term_find(char *name, int fd, char **cause) } /* Apply terminal overrides. */ - s = options_get_string(global_options, "terminal-overrides"); - tty_term_override(term, s); + o = options_get_only(global_options, "terminal-overrides"); + if (options_array_size(o, &size) != -1) { + for (i = 0; i < size; i++) { + s = options_array_get(o, i); + if (s != NULL) + tty_term_override(term, s); + } + } /* Delete curses data. */ del_curterm(cur_term);