Annotation of embedaddon/tmux/xterm-keys.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>