Annotation of src/usr.bin/tmux/xterm-keys.c, Revision 1.1
1.1 ! nicm 1: /* $OpenBSD: input-keys.c,v 1.4 2009/10/11 07:01:10 nicm Exp $ */
! 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: log_debug("XXX %x %x", entry->key, xterm_keys_modifiers(entry->template, buf, len));
! 150: return (entry->key | xterm_keys_modifiers(entry->template, buf, len));
! 151: }
! 152:
! 153: /* Lookup a key number from the table. */
! 154: char *
! 155: xterm_keys_lookup(int key)
! 156: {
! 157: struct xterm_keys_entry *entry;
! 158: u_int i;
! 159: int modifiers;
! 160: char *out;
! 161:
! 162: #define KEY_MODIFIERS(key, modifiers) \
! 163: (((key) & (KEYC_SHIFT|KEYC_ESCAPE|KEYC_CTRL)) == (modifiers))
! 164: modifiers = 0;
! 165: if (KEY_MODIFIERS(key, KEYC_SHIFT))
! 166: modifiers = 2;
! 167: else if (KEY_MODIFIERS(key, KEYC_ESCAPE))
! 168: modifiers = 3;
! 169: else if (KEY_MODIFIERS(key, KEYC_SHIFT|KEYC_ESCAPE))
! 170: modifiers = 4;
! 171: else if (KEY_MODIFIERS(key, KEYC_CTRL))
! 172: modifiers = 5;
! 173: else if (KEY_MODIFIERS(key, KEYC_SHIFT|KEYC_CTRL))
! 174: modifiers = 6;
! 175: else if (KEY_MODIFIERS(key, KEYC_ESCAPE|KEYC_CTRL))
! 176: modifiers = 7;
! 177: else if (KEY_MODIFIERS(key, KEYC_SHIFT|KEYC_ESCAPE|KEYC_CTRL))
! 178: modifiers = 8;
! 179: #undef KEY_MODIFIERS
! 180:
! 181: /*
! 182: * If the key has no modifiers, return NULL and let it fall through to
! 183: * the normal lookup.
! 184: */
! 185: if (modifiers == 0)
! 186: return (NULL);
! 187:
! 188: /* Otherwise, find the key in the table. */
! 189: key &= ~(KEYC_SHIFT|KEYC_ESCAPE|KEYC_CTRL);
! 190: for (i = 0; i < nitems(xterm_keys_table); i++) {
! 191: entry = &xterm_keys_table[i];
! 192: if (key == entry->key)
! 193: break;
! 194: }
! 195: if (i == nitems(xterm_keys_table))
! 196: return (NULL);
! 197:
! 198: /* Copy the template and replace the modifier. */
! 199: out = xstrdup(entry->template);
! 200: out[strcspn(out, "_")] = '0' + modifiers;
! 201: return (out);
! 202: }