[BACK]Return to tty-features.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/tty-features.c, Revision 1.11

1.11    ! nicm        1: /* $OpenBSD: tty-features.c,v 1.10 2020/05/16 14:31:35 nicm Exp $ */
1.1       nicm        2:
                      3: /*
                      4:  * Copyright (c) 2020 Nicholas Marriott <nicholas.marriott@gmail.com>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
                     15:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                     16:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include <sys/types.h>
                     20:
                     21: #include <stdlib.h>
                     22: #include <string.h>
                     23:
                     24: #include "tmux.h"
                     25:
                     26: /*
                     27:  * Still hardcoded:
                     28:  * - mouse (under kmous capability);
1.8       nicm       29:  * - focus events (under XT and focus-events option);
1.1       nicm       30:  * - default colours (under AX or op capabilities);
                     31:  * - AIX colours (under colors >= 16);
                     32:  * - alternate escape (under XT).
                     33:  *
                     34:  * Also:
1.6       nicm       35:  * - XT is used to decide whether to send DA and XDA;
1.7       nicm       36:  * - DECFRA uses a flag instead of capabilities;
1.1       nicm       37:  * - UTF-8 is a separate flag on the client; needed for unattached clients.
                     38:  */
                     39:
                     40: /* A named terminal feature. */
                     41: struct tty_feature {
                     42:        const char       *name;
                     43:        const char      **capabilities;
                     44:        int               flags;
                     45: };
                     46:
                     47: /* Terminal has xterm(1) title setting. */
                     48: static const char *tty_feature_title_capabilities[] = {
                     49:        "tsl=\\E]0;", /* should be using TS really */
                     50:        "fsl=\\a",
                     51:        NULL
                     52: };
                     53: static struct tty_feature tty_feature_title = {
                     54:        "title",
                     55:        tty_feature_title_capabilities,
                     56:        0
                     57: };
                     58:
                     59: /* Terminal can set the clipboard with OSC 52. */
                     60: static const char *tty_feature_clipboard_capabilities[] = {
                     61:        "Ms=\\E]52;%p1%s;%p2%s\\a",
                     62:        NULL
                     63: };
                     64: static struct tty_feature tty_feature_clipboard = {
                     65:        "clipboard",
                     66:        tty_feature_clipboard_capabilities,
                     67:        0
                     68: };
                     69:
                     70: /*
                     71:  * Terminal supports RGB colour. This replaces setab and setaf also since
                     72:  * terminals with RGB have versions that do not allow setting colours from the
                     73:  * 256 palette.
                     74:  */
                     75: static const char *tty_feature_rgb_capabilities[] = {
1.4       nicm       76:        "AX",
1.1       nicm       77:        "setrgbf=\\E[38;2;%p1%d;%p2%d;%p3%dm",
                     78:        "setrgbb=\\E[48;2;%p1%d;%p2%d;%p3%dm",
                     79:        "setab=\\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m",
                     80:        "setaf=\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m",
                     81:        NULL
                     82: };
                     83: static struct tty_feature tty_feature_rgb = {
                     84:        "RGB",
                     85:        tty_feature_rgb_capabilities,
1.7       nicm       86:        TERM_256COLOURS|TERM_RGBCOLOURS
1.1       nicm       87: };
                     88:
                     89: /* Terminal supports 256 colours. */
                     90: static const char *tty_feature_256_capabilities[] = {
1.4       nicm       91:        "AX",
1.1       nicm       92:        "setab=\\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m",
                     93:        "setaf=\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m",
                     94:        NULL
                     95: };
                     96: static struct tty_feature tty_feature_256 = {
                     97:        "256",
                     98:        tty_feature_256_capabilities,
                     99:        TERM_256COLOURS
                    100: };
                    101:
                    102: /* Terminal supports overline. */
                    103: static const char *tty_feature_overline_capabilities[] = {
                    104:        "Smol=\\E[53m",
                    105:        NULL
                    106: };
                    107: static struct tty_feature tty_feature_overline = {
                    108:        "overline",
                    109:        tty_feature_overline_capabilities,
                    110:        0
                    111: };
                    112:
                    113: /* Terminal supports underscore styles. */
                    114: static const char *tty_feature_usstyle_capabilities[] = {
                    115:        "Smulx=\E[4::%p1%dm",
                    116:        "Setulc=\E[58::2::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m",
                    117:        NULL
                    118: };
                    119: static struct tty_feature tty_feature_usstyle = {
                    120:        "usstyle",
                    121:        tty_feature_usstyle_capabilities,
                    122:        0
                    123: };
                    124:
1.11    ! nicm      125: /* Terminal supports cursor bracketed paste. */
        !           126: static const char *tty_feature_bpaste_capabilities[] = {
        !           127:        "Enbp=\E[?2004h",
        !           128:        "Dsbp=\\E[?2004l",
        !           129:        NULL
        !           130: };
        !           131: static struct tty_feature tty_feature_bpaste = {
        !           132:        "bpaste",
        !           133:        tty_feature_bpaste_capabilities,
        !           134:        0
        !           135: };
        !           136:
1.1       nicm      137: /* Terminal supports cursor styles. */
                    138: static const char *tty_feature_cstyle_capabilities[] = {
                    139:        "Ss=\\E[%p1%d q",
                    140:        "Se=\\E[2 q",
                    141:        NULL
                    142: };
                    143: static struct tty_feature tty_feature_cstyle = {
                    144:        "cstyle",
                    145:        tty_feature_cstyle_capabilities,
                    146:        0
                    147: };
                    148:
                    149: /* Terminal supports cursor colours. */
                    150: static const char *tty_feature_ccolour_capabilities[] = {
                    151:        "Cs=\\E]12;%p1%s\\a",
                    152:        "Cr=\\E]112\\a",
                    153:        NULL
                    154: };
                    155: static struct tty_feature tty_feature_ccolour = {
                    156:        "ccolour",
                    157:        tty_feature_ccolour_capabilities,
                    158:        0
                    159: };
                    160:
1.10      nicm      161: /* Terminal supports strikethrough. */
                    162: static const char *tty_feature_strikethrough_capabilities[] = {
                    163:        "smxx=\\E[9m",
                    164:        NULL
                    165: };
                    166: static struct tty_feature tty_feature_strikethrough = {
                    167:        "strikethrough",
                    168:        tty_feature_strikethrough_capabilities,
                    169:        0
                    170: };
                    171:
1.1       nicm      172: /* Terminal supports synchronized updates. */
                    173: static const char *tty_feature_sync_capabilities[] = {
1.2       nicm      174:        "Sync=\\EP=%p1%ds\\E\\\\",
1.1       nicm      175:        NULL
                    176: };
                    177: static struct tty_feature tty_feature_sync = {
                    178:        "sync",
                    179:        tty_feature_sync_capabilities,
                    180:        0
                    181: };
                    182:
                    183: /* Terminal supports DECSLRM margins. */
1.7       nicm      184: static const char *tty_feature_margins_capabilities[] = {
                    185:        "Enmg=\\E[?69h",
                    186:        "Dsmg=\\E[?69l",
                    187:        "Clmg=\\E[s",
                    188:        "Cmg=\\E[%i%p1%d;%p2%ds",
                    189:        NULL
                    190: };
1.1       nicm      191: static struct tty_feature tty_feature_margins = {
                    192:        "margins",
1.7       nicm      193:        tty_feature_margins_capabilities,
1.1       nicm      194:        TERM_DECSLRM
                    195: };
                    196:
                    197: /* Terminal supports DECFRA rectangle fill. */
                    198: static struct tty_feature tty_feature_rectfill = {
                    199:        "rectfill",
                    200:        NULL,
                    201:        TERM_DECFRA
                    202: };
                    203:
                    204: /* Available terminal features. */
                    205: static const struct tty_feature *tty_features[] = {
                    206:        &tty_feature_256,
1.11    ! nicm      207:        &tty_feature_bpaste,
1.1       nicm      208:        &tty_feature_clipboard,
                    209:        &tty_feature_ccolour,
                    210:        &tty_feature_cstyle,
                    211:        &tty_feature_margins,
                    212:        &tty_feature_overline,
                    213:        &tty_feature_rectfill,
                    214:        &tty_feature_rgb,
1.10      nicm      215:        &tty_feature_strikethrough,
1.1       nicm      216:        &tty_feature_sync,
                    217:        &tty_feature_title,
                    218:        &tty_feature_usstyle
                    219: };
                    220:
                    221: void
                    222: tty_add_features(int *feat, const char *s, const char *separators)
                    223: {
                    224:        const struct tty_feature         *tf;
                    225:        char                             *next, *loop, *copy;
                    226:        u_int                             i;
1.7       nicm      227:
1.9       nicm      228:        log_debug("adding terminal features %s", s);
1.1       nicm      229:
                    230:        loop = copy = xstrdup(s);
                    231:        while ((next = strsep(&loop, separators)) != NULL) {
                    232:                for (i = 0; i < nitems(tty_features); i++) {
                    233:                        tf = tty_features[i];
                    234:                        if (strcasecmp(tf->name, next) == 0)
                    235:                                break;
                    236:                }
                    237:                if (i == nitems(tty_features)) {
                    238:                        log_debug("unknown terminal feature: %s", next);
                    239:                        break;
                    240:                }
                    241:                if (~(*feat) & (1 << i)) {
                    242:                        log_debug("adding terminal feature: %s", tf->name);
                    243:                        (*feat) |= (1 << i);
                    244:                }
                    245:        }
                    246:        free(copy);
                    247: }
                    248:
                    249: const char *
                    250: tty_get_features(int feat)
                    251: {
                    252:        const struct tty_feature        *tf;
                    253:        static char                      s[512];
                    254:        u_int                            i;
                    255:
                    256:        *s = '\0';
                    257:        for (i = 0; i < nitems(tty_features); i++) {
                    258:                if (~feat & (1 << i))
                    259:                        continue;
                    260:                tf = tty_features[i];
                    261:
                    262:                strlcat(s, tf->name, sizeof s);
                    263:                strlcat(s, ",", sizeof s);
                    264:        }
                    265:        if (*s != '\0')
                    266:                s[strlen(s) - 1] = '\0';
                    267:        return (s);
                    268: }
                    269:
1.3       nicm      270: int
1.1       nicm      271: tty_apply_features(struct tty_term *term, int feat)
                    272: {
                    273:        const struct tty_feature         *tf;
                    274:        const char                      **capability;
                    275:        u_int                             i;
                    276:
                    277:        if (feat == 0)
1.3       nicm      278:                return (0);
1.1       nicm      279:        log_debug("applying terminal features: %s", tty_get_features(feat));
                    280:
                    281:        for (i = 0; i < nitems(tty_features); i++) {
                    282:                if ((term->features & (1 << i)) || (~feat & (1 << i)))
                    283:                        continue;
                    284:                tf = tty_features[i];
                    285:
                    286:                log_debug("applying terminal feature: %s", tf->name);
                    287:                if (tf->capabilities != NULL) {
                    288:                        capability = tf->capabilities;
                    289:                        while (*capability != NULL) {
                    290:                                log_debug("adding capability: %s", *capability);
                    291:                                tty_term_apply(term, *capability, 1);
                    292:                                capability++;
                    293:                        }
                    294:                }
                    295:                term->flags |= tf->flags;
                    296:        }
1.3       nicm      297:        if ((term->features | feat) == term->features)
                    298:                return (0);
1.1       nicm      299:        term->features |= feat;
1.3       nicm      300:        return (1);
1.9       nicm      301: }
                    302:
                    303: void
                    304: tty_default_features(int *feat, const char *name, u_int version)
                    305: {
                    306:        static struct {
                    307:                const char      *name;
                    308:                u_int            version;
                    309:                const char      *features;
                    310:        } table[] = {
                    311:                { .name = "mintty",
1.11    ! nicm      312:                  .features = "256,RGB,bpaste,ccolour,clipboard,cstyle,margins,overline,strikethrough,title"
1.9       nicm      313:                },
                    314:                { .name = "tmux",
1.11    ! nicm      315:                  .features = "256,RGB,bpaste,ccolour,clipboard,cstyle,overline,strikethough,title,usstyle"
1.9       nicm      316:                },
                    317:                { .name = "rxvt-unicode",
                    318:                  .features = "256,title"
                    319:                },
                    320:                { .name = "iTerm2",
1.11    ! nicm      321:                  .features = "256,RGB,bpaste,clipboard,cstyle,margins,strikethrough,sync,title"
1.9       nicm      322:                },
                    323:                { .name = "XTerm",
1.11    ! nicm      324:                  .features = "256,RGB,bpaste,ccolour,clipboard,cstyle,margins,rectfill,strikethrough,title"
1.9       nicm      325:                }
                    326:        };
                    327:        u_int   i;
                    328:
                    329:        for (i = 0; i < nitems(table); i++) {
                    330:                if (strcmp(table[i].name, name) != 0)
                    331:                        continue;
                    332:                if (version != 0 && version < table[i].version)
                    333:                        continue;
                    334:                tty_add_features(feat, table[i].features, ",");
                    335:        }
                    336:
1.1       nicm      337: }