File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / tmux / xterm-keys.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 14 12:22:44 2017 UTC (7 years, 9 months ago) by misho
Branches: tmux, MAIN
CVS tags: v2_4p0, v2_4, HEAD
tmux 2.4

    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>