[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.2

1.2     ! nicm        1: /* $OpenBSD: xterm-keys.c,v 1.1 2009/10/26 17:46:33 nicm Exp $ */
1.1       nicm        2:
                      3: /*
                      4:  * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
                      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 two forms for F1-F4 (\\033O_P or \\033[1;_P). We accept either but
                     40:  * always output the latter (it comes first in the table).
                     41:  */
                     42:
                     43: int    xterm_keys_match(const char *, const char *, size_t);
                     44: int    xterm_keys_modifiers(const char *, const char *, size_t);
                     45:
                     46: struct xterm_keys_entry {
                     47:        int              key;
                     48:        const char      *template;
                     49: };
                     50:
                     51: struct xterm_keys_entry xterm_keys_table[] = {
                     52:        { KEYC_F1,      "\033[1;_P" },
                     53:        { KEYC_F1,      "\033[O_P" },
                     54:        { KEYC_F2,      "\033[1;_Q" },
                     55:        { KEYC_F2,      "\033[O_Q" },
                     56:        { KEYC_F3,      "\033[1;_R" },
                     57:        { KEYC_F3,      "\033[O_R" },
                     58:        { KEYC_F4,      "\033[1;_S" },
                     59:        { KEYC_F4,      "\033[O_S" },
                     60:        { KEYC_F5,      "\033[15;_~" },
                     61:        { KEYC_F6,      "\033[17;_~" },
                     62:        { KEYC_F7,      "\033[18;_~" },
                     63:        { KEYC_F8,      "\033[19;_~" },
                     64:        { KEYC_F9,      "\033[20;_~" },
                     65:        { KEYC_F10,     "\033[21;_~" },
                     66:        { KEYC_F11,     "\033[23;_~" },
                     67:        { KEYC_F12,     "\033[24;_~" },
                     68:        { KEYC_F13,     "\033[25;_~" },
                     69:        { KEYC_F14,     "\033[26;_~" },
                     70:        { KEYC_F15,     "\033[28;_~" },
                     71:        { KEYC_F16,     "\033[29;_~" },
                     72:        { KEYC_F17,     "\033[31;_~" },
                     73:        { KEYC_F18,     "\033[32;_~" },
                     74:        { KEYC_F19,     "\033[33;_~" },
                     75:        { KEYC_F20,     "\033[34;_~" },
                     76:        { KEYC_UP,      "\033[1;_A" },
                     77:        { KEYC_DOWN,    "\033[1;_B" },
                     78:        { KEYC_RIGHT,   "\033[1;_C" },
                     79:        { KEYC_LEFT,    "\033[1;_D" },
                     80:        { KEYC_HOME,    "\033[1;_H" },
                     81:        { KEYC_END,     "\033[1;_F" },
                     82:        { KEYC_PPAGE,   "\033[5;_~" },
                     83:        { KEYC_NPAGE,   "\033[6;_~" },
                     84:        { KEYC_IC,      "\033[2;_~" },
                     85:        { KEYC_DC,      "\033[3;_~" },
                     86: };
                     87:
                     88: /* Match key against buffer, treating _ as a wildcard. */
                     89: int
                     90: xterm_keys_match(const char *template, const char *buf, size_t len)
                     91: {
                     92:        size_t  pos;
                     93:
                     94:        if (len == 0 || len < strlen(template))
                     95:                return (0);
                     96:
                     97:        pos = 0;
                     98:        do {
                     99:                if (*template != '_' && buf[pos] != *template)
                    100:                        return (0);
                    101:        } while (pos++ != len && *++template != '\0');
                    102:
                    103:        return (1);
                    104: }
                    105:
                    106: /* Find modifiers based on template. */
                    107: int
                    108: xterm_keys_modifiers(const char *template, const char *buf, size_t len)
                    109: {
                    110:        size_t  idx;
                    111:
                    112:        idx = strcspn(template, "_");
                    113:        if (idx >= len)
                    114:                return (0);
                    115:        switch (buf[idx]) {
                    116:        case '2':
                    117:                return (KEYC_SHIFT);
                    118:        case '3':
                    119:                return (KEYC_ESCAPE);
                    120:        case '4':
                    121:                return (KEYC_SHIFT|KEYC_ESCAPE);
                    122:        case '5':
                    123:                return (KEYC_CTRL);
                    124:        case '6':
                    125:                return (KEYC_SHIFT|KEYC_CTRL);
                    126:        case '7':
                    127:                return (KEYC_ESCAPE|KEYC_CTRL);
                    128:        case '8':
                    129:                return (KEYC_SHIFT|KEYC_ESCAPE|KEYC_CTRL);
                    130:        }
                    131:        return (0);
                    132: }
                    133:
                    134: /* Lookup key from buffer against table. */
                    135: int
                    136: xterm_keys_find(const char *buf, size_t len, size_t *size)
                    137: {
                    138:        struct xterm_keys_entry *entry;
                    139:        u_int                    i;
                    140:
                    141:        for (i = 0; i < nitems(xterm_keys_table); i++) {
                    142:                entry = &xterm_keys_table[i];
                    143:                if (xterm_keys_match(entry->template, buf, len))
                    144:                        break;
                    145:        }
                    146:        if (i == nitems(xterm_keys_table))
                    147:                return (KEYC_NONE);
                    148:        *size = strlen(entry->template);
                    149:        return (entry->key | xterm_keys_modifiers(entry->template, buf, len));
                    150: }
                    151:
                    152: /* Lookup a key number from the table. */
                    153: char *
                    154: xterm_keys_lookup(int key)
                    155: {
                    156:        struct xterm_keys_entry *entry;
                    157:        u_int                    i;
                    158:        int                      modifiers;
                    159:        char                    *out;
                    160:
                    161: #define KEY_MODIFIERS(key, modifiers) \
                    162:        (((key) & (KEYC_SHIFT|KEYC_ESCAPE|KEYC_CTRL)) == (modifiers))
                    163:        modifiers = 0;
                    164:        if (KEY_MODIFIERS(key, KEYC_SHIFT))
                    165:                modifiers = 2;
                    166:        else if (KEY_MODIFIERS(key, KEYC_ESCAPE))
                    167:                modifiers = 3;
                    168:        else if (KEY_MODIFIERS(key, KEYC_SHIFT|KEYC_ESCAPE))
                    169:                modifiers = 4;
                    170:        else if (KEY_MODIFIERS(key, KEYC_CTRL))
                    171:                modifiers = 5;
                    172:        else if (KEY_MODIFIERS(key, KEYC_SHIFT|KEYC_CTRL))
                    173:                modifiers = 6;
                    174:        else if (KEY_MODIFIERS(key, KEYC_ESCAPE|KEYC_CTRL))
                    175:                modifiers = 7;
                    176:        else if (KEY_MODIFIERS(key, KEYC_SHIFT|KEYC_ESCAPE|KEYC_CTRL))
                    177:                modifiers = 8;
                    178: #undef KEY_MODIFIERS
                    179:
                    180:        /*
                    181:         * If the key has no modifiers, return NULL and let it fall through to
                    182:         * the normal lookup.
                    183:         */
                    184:        if (modifiers == 0)
                    185:                return (NULL);
                    186:
                    187:        /* Otherwise, find the key in the table. */
                    188:        key &= ~(KEYC_SHIFT|KEYC_ESCAPE|KEYC_CTRL);
                    189:        for (i = 0; i < nitems(xterm_keys_table); i++) {
                    190:                entry = &xterm_keys_table[i];
                    191:                if (key == entry->key)
                    192:                        break;
                    193:        }
                    194:        if (i == nitems(xterm_keys_table))
                    195:                return (NULL);
                    196:
                    197:        /* Copy the template and replace the modifier. */
                    198:        out = xstrdup(entry->template);
                    199:        out[strcspn(out, "_")] = '0' + modifiers;
                    200:        return (out);
                    201: }