Annotation of src/usr.bin/tmux/input-keys.c, Revision 1.1
1.1 ! nicm 1: /* $OpenBSD$ */
! 2:
! 3: /*
! 4: * Copyright (c) 2007 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 <stdint.h>
! 22: #include <stdlib.h>
! 23: #include <string.h>
! 24:
! 25: #include "tmux.h"
! 26:
! 27: struct input_key_ent {
! 28: int key;
! 29: const char *data;
! 30:
! 31: int flags;
! 32: #define INPUTKEY_KEYPAD 0x1 /* keypad key */
! 33: #define INPUTKEY_CURSOR 0x2 /* cursor key */
! 34: #define INPUTKEY_CTRL 0x4 /* may be modified with ctrl */
! 35: #define INPUTKEY_XTERM 0x4 /* may have xterm argument appended */
! 36: };
! 37:
! 38: struct input_key_ent input_keys[] = {
! 39: /* Function keys. */
! 40: { KEYC_F1, "\033OP", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 41: { KEYC_F2, "\033OQ", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 42: { KEYC_F3, "\033OR", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 43: { KEYC_F4, "\033OS", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 44: { KEYC_F5, "\033[15~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 45: { KEYC_F6, "\033[17~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 46: { KEYC_F7, "\033[18~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 47: { KEYC_F8, "\033[19~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 48: { KEYC_F9, "\033[20~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 49: { KEYC_F10, "\033[21~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 50: { KEYC_F11, "\033[23~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 51: { KEYC_F12, "\033[24~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 52: { KEYC_F13, "\033[25~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 53: { KEYC_F14, "\033[26~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 54: { KEYC_F15, "\033[28~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 55: { KEYC_F16, "\033[29~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 56: { KEYC_F17, "\033[31~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 57: { KEYC_F18, "\033[32~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 58: { KEYC_F19, "\033[33~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 59: { KEYC_F20, "\033[34~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 60: { KEYC_IC, "\033[2~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 61: { KEYC_DC, "\033[3~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 62: { KEYC_HOME, "\033[1~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 63: { KEYC_END, "\033[4~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 64: { KEYC_NPAGE, "\033[6~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 65: { KEYC_PPAGE, "\033[5~", INPUTKEY_CTRL|INPUTKEY_XTERM },
! 66: { KEYC_BTAB, "\033[Z", INPUTKEY_CTRL },
! 67:
! 68: /* Arrow keys. Cursor versions must come first. */
! 69: { KEYC_ADDCTL(KEYC_UP), "\033Oa", 0 },
! 70: { KEYC_ADDCTL(KEYC_DOWN), "\033Ob", 0 },
! 71: { KEYC_ADDCTL(KEYC_RIGHT), "\033Oc", 0 },
! 72: { KEYC_ADDCTL(KEYC_LEFT), "\033Od", 0 },
! 73:
! 74: { KEYC_ADDSFT(KEYC_UP), "\033[a", 0 },
! 75: { KEYC_ADDSFT(KEYC_DOWN), "\033[b", 0 },
! 76: { KEYC_ADDSFT(KEYC_RIGHT), "\033[c", 0 },
! 77: { KEYC_ADDSFT(KEYC_LEFT), "\033[d", 0 },
! 78:
! 79: { KEYC_UP, "\033OA", INPUTKEY_CURSOR },
! 80: { KEYC_DOWN, "\033OB", INPUTKEY_CURSOR },
! 81: { KEYC_RIGHT, "\033OC", INPUTKEY_CURSOR },
! 82: { KEYC_LEFT, "\033OD", INPUTKEY_CURSOR },
! 83:
! 84: { KEYC_UP, "\033[A", 0 },
! 85: { KEYC_DOWN, "\033[B", 0 },
! 86: { KEYC_RIGHT, "\033[C", 0 },
! 87: { KEYC_LEFT, "\033[D", 0 },
! 88:
! 89: /* Keypad keys. Keypad versions must come first. */
! 90: { KEYC_KP0_1, "/", INPUTKEY_KEYPAD },
! 91: { KEYC_KP0_2, "*", INPUTKEY_KEYPAD },
! 92: { KEYC_KP0_3, "-", INPUTKEY_KEYPAD },
! 93: { KEYC_KP1_0, "7", INPUTKEY_KEYPAD },
! 94: { KEYC_KP1_1, "8", INPUTKEY_KEYPAD },
! 95: { KEYC_KP1_2, "9", INPUTKEY_KEYPAD },
! 96: { KEYC_KP1_3, "+", INPUTKEY_KEYPAD },
! 97: { KEYC_KP2_0, "4", INPUTKEY_KEYPAD },
! 98: { KEYC_KP2_1, "5", INPUTKEY_KEYPAD },
! 99: { KEYC_KP2_2, "6", INPUTKEY_KEYPAD },
! 100: { KEYC_KP3_0, "1", INPUTKEY_KEYPAD },
! 101: { KEYC_KP3_1, "2", INPUTKEY_KEYPAD },
! 102: { KEYC_KP3_2, "3", INPUTKEY_KEYPAD },
! 103: { KEYC_KP3_3, "\n", INPUTKEY_KEYPAD }, /* this can be CRLF too? */
! 104: { KEYC_KP4_0, "0", INPUTKEY_KEYPAD },
! 105: { KEYC_KP4_2, ".", INPUTKEY_KEYPAD },
! 106: { KEYC_KP0_1, "\033Oo", 0 },
! 107: { KEYC_KP0_2, "\033Oj", 0 },
! 108: { KEYC_KP0_3, "\033Om", 0 },
! 109: { KEYC_KP1_0, "\033Ow", 0 },
! 110: { KEYC_KP1_1, "\033Ox", 0 },
! 111: { KEYC_KP1_2, "\033Oy", 0 },
! 112: { KEYC_KP1_3, "\033Ok", 0 },
! 113: { KEYC_KP2_0, "\033Ot", 0 },
! 114: { KEYC_KP2_1, "\033Ou", 0 },
! 115: { KEYC_KP2_2, "\033Ov", 0 },
! 116: { KEYC_KP3_0, "\033Oq", 0 },
! 117: { KEYC_KP3_1, "\033Or", 0 },
! 118: { KEYC_KP3_2, "\033Os", 0 },
! 119: { KEYC_KP3_3, "\033OM", 0 },
! 120: { KEYC_KP4_0, "\033Op", 0 },
! 121: { KEYC_KP4_2, "\033On", 0 },
! 122: };
! 123:
! 124: /* Translate a key code from client into an output key sequence. */
! 125: void
! 126: input_key(struct window_pane *wp, int key)
! 127: {
! 128: struct input_key_ent *ike;
! 129: u_int i;
! 130: char ch;
! 131: size_t dlen;
! 132: int xterm_keys;
! 133:
! 134: log_debug2("writing key 0x%x", key);
! 135:
! 136: if (key != KEYC_NONE && KEYC_REMOVEESC(key) < KEYC_OFFSET) {
! 137: if (KEYC_ISESC(key))
! 138: buffer_write8(wp->out, '\033');
! 139: buffer_write8(wp->out, (uint8_t) KEYC_REMOVEESC(key));
! 140: return;
! 141: }
! 142:
! 143: for (i = 0; i < nitems(input_keys); i++) {
! 144: ike = &input_keys[i];
! 145:
! 146: if ((ike->flags & INPUTKEY_KEYPAD) &&
! 147: !(wp->screen->mode & MODE_KKEYPAD))
! 148: continue;
! 149: if ((ike->flags & INPUTKEY_CURSOR) &&
! 150: !(wp->screen->mode & MODE_KCURSOR))
! 151: continue;
! 152:
! 153: if (KEYC_ISESC(key) && KEYC_ADDESC(ike->key) == key)
! 154: break;
! 155: if (KEYC_ISSFT(key) && KEYC_ADDSFT(ike->key) == key)
! 156: break;
! 157: if (KEYC_ISCTL(key) && KEYC_ADDCTL(ike->key) == key) {
! 158: if (ike->flags & INPUTKEY_CTRL)
! 159: break;
! 160: }
! 161: if (ike->key == key)
! 162: break;
! 163: }
! 164: if (i == nitems(input_keys)) {
! 165: log_debug2("key 0x%x missing", key);
! 166: return;
! 167: }
! 168: dlen = strlen(ike->data);
! 169:
! 170: log_debug2("found key 0x%x: \"%s\"", key, ike->data);
! 171:
! 172: /*
! 173: * If in xterm keys mode, work out and append the modifier as an
! 174: * argument.
! 175: */
! 176: xterm_keys = options_get_number(&wp->window->options, "xterm-keys");
! 177: if (xterm_keys && ike->flags & INPUTKEY_XTERM) {
! 178: ch = '\0';
! 179: if (KEYC_ISSFT(key) && KEYC_ISESC(key) && KEYC_ISCTL(key))
! 180: ch = '8';
! 181: else if (KEYC_ISESC(key) && KEYC_ISCTL(key))
! 182: ch = '7';
! 183: else if (KEYC_ISSFT(key) && KEYC_ISCTL(key))
! 184: ch = '6';
! 185: else if (KEYC_ISCTL(key))
! 186: ch = '5';
! 187: else if (KEYC_ISSFT(key) && KEYC_ISESC(key))
! 188: ch = '4';
! 189: else if (KEYC_ISESC(key))
! 190: ch = '3';
! 191: else if (KEYC_ISSFT(key))
! 192: ch = '2';
! 193: if (ch != '\0') {
! 194: buffer_write(wp->out, ike->data, dlen - 1);
! 195: buffer_write8(wp->out, ';');
! 196: buffer_write8(wp->out, ch);
! 197: buffer_write8(wp->out, ike->data[dlen - 1]);
! 198: } else
! 199: buffer_write(wp->out, ike->data, dlen);
! 200: return;
! 201: }
! 202:
! 203: /*
! 204: * Not in xterm mode. Prefix a \033 for escape, and set bit 5 of the
! 205: * last byte for ctrl.
! 206: */
! 207: if (KEYC_ISESC(key))
! 208: buffer_write8(wp->out, '\033');
! 209: if (KEYC_ISCTL(key) && ike->flags & INPUTKEY_CTRL) {
! 210: buffer_write(wp->out, ike->data, dlen - 1);
! 211: buffer_write8(wp->out, ike->data[dlen - 1] ^ 0x20);
! 212: return;
! 213: }
! 214: buffer_write(wp->out, ike->data, dlen);
! 215: }
! 216:
! 217: /* Handle input mouse. */
! 218: void
! 219: input_mouse(struct window_pane *wp, u_char b, u_char x, u_char y)
! 220: {
! 221: if (wp->screen->mode & MODE_MOUSE) {
! 222: buffer_write(wp->out, "\033[M", 3);
! 223: buffer_write8(wp->out, b + 32);
! 224: buffer_write8(wp->out, x + 33);
! 225: buffer_write8(wp->out, y + 33);
! 226: }
! 227: }