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

Annotation of src/usr.bin/tmux/xterm-keys.c, Revision 1.20

1.20    ! nicm        1: /* $OpenBSD: xterm-keys.c,v 1.19 2016/10/03 22:52:11 nicm Exp $ */
1.1       nicm        2:
                      3: /*
1.18      nicm        4:  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
1.1       nicm        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 <string.h>
                     22:
                     23: #include "tmux.h"
                     24:
                     25: /*
                     26:  * xterm-style function keys append one of the following values before the last
                     27:  * character:
                     28:  *
                     29:  * 2 Shift
1.5       nicm       30:  * 3 Alt
                     31:  * 4 Shift + Alt
                     32:  * 5 Ctrl
                     33:  * 6 Shift + Ctrl
                     34:  * 7 Alt + Ctrl
1.1       nicm       35:  * 8 Shift + Alt + Ctrl
                     36:  *
                     37:  * Rather than parsing them, just match against a table.
                     38:  *
1.10      nicm       39:  * There are three forms for F1-F4 (\\033O_P and \\033O1;_P and \\033[1;_P).
                     40:  * We accept any but always output the latter (it comes first in the table).
1.1       nicm       41:  */
                     42:
1.19      nicm       43: static int     xterm_keys_match(const char *, const char *, size_t, size_t *,
                     44:                    key_code *);
                     45: static int     xterm_keys_modifiers(const char *, size_t, size_t *,
                     46:                    key_code *);
1.1       nicm       47:
                     48: struct xterm_keys_entry {
1.17      nicm       49:        key_code         key;
1.1       nicm       50:        const char      *template;
                     51: };
                     52:
1.20    ! nicm       53: static const struct xterm_keys_entry xterm_keys_standard[] = {
        !            54:        { KEYC_HOME,    "\033[H" },
        !            55:        { KEYC_END,     "\033[F" },
        !            56: };
        !            57:
        !            58: static const struct xterm_keys_entry xterm_keys_cursor[] = {
        !            59:        { KEYC_HOME,    "\033OH" },
        !            60:        { KEYC_END,     "\033OF" },
        !            61: };
        !            62:
        !            63: static const struct xterm_keys_entry xterm_keys_modified[] = {
1.1       nicm       64:        { KEYC_F1,      "\033[1;_P" },
1.10      nicm       65:        { KEYC_F1,      "\033O1;_P" },
1.3       nicm       66:        { KEYC_F1,      "\033O_P" },
1.1       nicm       67:        { KEYC_F2,      "\033[1;_Q" },
1.10      nicm       68:        { KEYC_F2,      "\033O1;_Q" },
1.3       nicm       69:        { KEYC_F2,      "\033O_Q" },
1.1       nicm       70:        { KEYC_F3,      "\033[1;_R" },
1.10      nicm       71:        { KEYC_F3,      "\033O1;_R" },
1.3       nicm       72:        { KEYC_F3,      "\033O_R" },
1.1       nicm       73:        { KEYC_F4,      "\033[1;_S" },
1.10      nicm       74:        { KEYC_F4,      "\033O1;_S" },
1.3       nicm       75:        { KEYC_F4,      "\033O_S" },
1.1       nicm       76:        { KEYC_F5,      "\033[15;_~" },
                     77:        { KEYC_F6,      "\033[17;_~" },
                     78:        { KEYC_F7,      "\033[18;_~" },
                     79:        { KEYC_F8,      "\033[19;_~" },
                     80:        { KEYC_F9,      "\033[20;_~" },
                     81:        { KEYC_F10,     "\033[21;_~" },
                     82:        { KEYC_F11,     "\033[23;_~" },
                     83:        { KEYC_F12,     "\033[24;_~" },
                     84:        { KEYC_UP,      "\033[1;_A" },
                     85:        { KEYC_DOWN,    "\033[1;_B" },
                     86:        { KEYC_RIGHT,   "\033[1;_C" },
                     87:        { KEYC_LEFT,    "\033[1;_D" },
                     88:        { KEYC_HOME,    "\033[1;_H" },
                     89:        { KEYC_END,     "\033[1;_F" },
                     90:        { KEYC_PPAGE,   "\033[5;_~" },
                     91:        { KEYC_NPAGE,   "\033[6;_~" },
                     92:        { KEYC_IC,      "\033[2;_~" },
                     93:        { KEYC_DC,      "\033[3;_~" },
1.11      nicm       94:
                     95:        { '!',          "\033[27;_;33~" },
                     96:        { '#',          "\033[27;_;35~" },
                     97:        { '(',          "\033[27;_;40~" },
                     98:        { ')',          "\033[27;_;41~" },
                     99:        { '+',          "\033[27;_;43~" },
                    100:        { ',',          "\033[27;_;44~" },
                    101:        { '-',          "\033[27;_;45~" },
                    102:        { '.',          "\033[27;_;46~" },
                    103:        { '0',          "\033[27;_;48~" },
                    104:        { '1',          "\033[27;_;49~" },
                    105:        { '2',          "\033[27;_;50~" },
                    106:        { '3',          "\033[27;_;51~" },
                    107:        { '4',          "\033[27;_;52~" },
                    108:        { '5',          "\033[27;_;53~" },
                    109:        { '6',          "\033[27;_;54~" },
                    110:        { '7',          "\033[27;_;55~" },
                    111:        { '8',          "\033[27;_;56~" },
                    112:        { '9',          "\033[27;_;57~" },
                    113:        { ':',          "\033[27;_;58~" },
                    114:        { ';',          "\033[27;_;59~" },
                    115:        { '<',          "\033[27;_;60~" },
                    116:        { '=',          "\033[27;_;61~" },
                    117:        { '>',          "\033[27;_;62~" },
                    118:        { '?',          "\033[27;_;63~" },
                    119:        { '\'',         "\033[27;_;39~" },
                    120:        { '\r',         "\033[27;_;13~" },
                    121:        { '\t',         "\033[27;_;9~" },
1.1       nicm      122: };
                    123:
1.5       nicm      124: /*
1.4       nicm      125:  * Match key against buffer, treating _ as a wildcard. Return -1 for no match,
                    126:  * 0 for match, 1 if the end of the buffer is reached (need more data).
                    127:  */
1.19      nicm      128: static int
1.14      nicm      129: xterm_keys_match(const char *template, const char *buf, size_t len,
1.17      nicm      130:     size_t *size, key_code *modifiers)
1.1       nicm      131: {
                    132:        size_t  pos;
1.14      nicm      133:        int     retval;
1.16      nicm      134:
                    135:        *modifiers = 0;
1.1       nicm      136:
1.4       nicm      137:        if (len == 0)
1.1       nicm      138:                return (0);
                    139:
                    140:        pos = 0;
                    141:        do {
1.14      nicm      142:                if (*template == '_') {
                    143:                        retval = xterm_keys_modifiers(buf, len, &pos,
                    144:                            modifiers);
                    145:                        if (retval != 0)
                    146:                                return (retval);
1.13      nicm      147:                        continue;
1.14      nicm      148:                }
1.13      nicm      149:                if (buf[pos] != *template)
1.4       nicm      150:                        return (-1);
1.14      nicm      151:                pos++;
                    152:        } while (*++template != '\0' && pos != len);
1.1       nicm      153:
1.4       nicm      154:        if (*template != '\0')  /* partial */
                    155:                return (1);
                    156:
1.14      nicm      157:        *size = pos;
1.4       nicm      158:        return (0);
1.1       nicm      159: }
                    160:
1.14      nicm      161: /* Find modifiers from buffer. */
1.19      nicm      162: static int
1.17      nicm      163: xterm_keys_modifiers(const char *buf, size_t len, size_t *pos,
                    164:     key_code *modifiers)
1.1       nicm      165: {
1.14      nicm      166:        u_int   flags;
1.1       nicm      167:
1.14      nicm      168:        if (len - *pos < 2)
                    169:                return (1);
1.6       nicm      170:
1.14      nicm      171:        if (buf[*pos] < '0' || buf[*pos] > '9')
                    172:                return (-1);
                    173:        flags = buf[(*pos)++] - '0';
                    174:        if (buf[*pos] >= '0' && buf[*pos] <= '9')
                    175:                flags = (flags * 10) + (buf[(*pos)++] - '0');
                    176:        flags -= 1;
                    177:
                    178:        *modifiers = 0;
                    179:        if (flags & 1)
                    180:                *modifiers |= KEYC_SHIFT;
                    181:        if (flags & 2)
                    182:                *modifiers |= KEYC_ESCAPE;
                    183:        if (flags & 4)
                    184:                *modifiers |= KEYC_CTRL;
                    185:        if (flags & 8)
                    186:                *modifiers |= KEYC_ESCAPE;
                    187:        return (0);
1.1       nicm      188: }
                    189:
1.4       nicm      190: /*
                    191:  * Lookup key from a buffer against the table. Returns 0 for found (and the
                    192:  * key), -1 for not found, 1 for partial match.
                    193:  */
1.1       nicm      194: int
1.17      nicm      195: xterm_keys_find(const char *buf, size_t len, size_t *size, key_code *key)
1.1       nicm      196: {
1.8       nicm      197:        const struct xterm_keys_entry   *entry;
1.17      nicm      198:        u_int                            i;
1.14      nicm      199:        int                              matched;
1.17      nicm      200:        key_code                         modifiers;
1.1       nicm      201:
1.20    ! nicm      202:        for (i = 0; i < nitems(xterm_keys_modified); i++) {
        !           203:                entry = &xterm_keys_modified[i];
1.14      nicm      204:
                    205:                matched = xterm_keys_match(entry->template, buf, len, size,
                    206:                    &modifiers);
                    207:                if (matched == -1)
                    208:                        continue;
                    209:                if (matched == 0)
                    210:                        *key = entry->key | modifiers;
                    211:                return (matched);
1.1       nicm      212:        }
1.4       nicm      213:        return (-1);
1.1       nicm      214: }
                    215:
                    216: /* Lookup a key number from the table. */
                    217: char *
1.20    ! nicm      218: xterm_keys_lookup(key_code key, int mode)
1.1       nicm      219: {
1.20    ! nicm      220:        const struct xterm_keys_entry   *table, *entry;
        !           221:        u_int                            items, i;
1.17      nicm      222:        key_code                         modifiers;
1.8       nicm      223:        char                            *out;
1.1       nicm      224:
1.6       nicm      225:        modifiers = 1;
                    226:        if (key & KEYC_SHIFT)
                    227:                modifiers += 1;
                    228:        if (key & KEYC_ESCAPE)
                    229:                modifiers += 2;
                    230:        if (key & KEYC_CTRL)
                    231:                modifiers += 4;
1.1       nicm      232:
                    233:        /*
                    234:         * If the key has no modifiers, return NULL and let it fall through to
                    235:         * the normal lookup.
                    236:         */
1.20    ! nicm      237:        if (modifiers != 1) {
        !           238:                table = xterm_keys_modified;
        !           239:                items = nitems(xterm_keys_modified);
        !           240:        } else {
        !           241:                if (mode & MODE_KCURSOR) {
        !           242:                        table = xterm_keys_cursor;
        !           243:                        items = nitems(xterm_keys_cursor);
        !           244:                } else {
        !           245:                        table = xterm_keys_standard;
        !           246:                        items = nitems(xterm_keys_standard);
        !           247:                }
        !           248:        }
1.1       nicm      249:
                    250:        /* Otherwise, find the key in the table. */
                    251:        key &= ~(KEYC_SHIFT|KEYC_ESCAPE|KEYC_CTRL);
1.20    ! nicm      252:        for (i = 0; i < items; i++) {
        !           253:                entry = &table[i];
1.1       nicm      254:                if (key == entry->key)
                    255:                        break;
                    256:        }
1.20    ! nicm      257:        if (i == items)
1.1       nicm      258:                return (NULL);
1.5       nicm      259:
1.1       nicm      260:        /* Copy the template and replace the modifier. */
                    261:        out = xstrdup(entry->template);
1.20    ! nicm      262:        if (modifiers != 1)
        !           263:                out[strcspn(out, "_")] = '0' + modifiers;
1.1       nicm      264:        return (out);
                    265: }