xref: /openbsd-src/usr.bin/tmux/key-string.c (revision 43003dfe3ad45d1698bed8a37f2b0f5b14f20d4f)
1 /* $OpenBSD: key-string.c,v 1.8 2009/10/06 07:32:26 nicm Exp $ */
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 <string.h>
22 
23 #include "tmux.h"
24 
25 int	key_string_search_table(const char *);
26 
27 struct {
28 	const char *string;
29 	int	 key;
30 } key_string_table[] = {
31 	/* Function keys. */
32 	{ "F1",		KEYC_F1 },
33 	{ "F2",		KEYC_F2 },
34 	{ "F3",		KEYC_F3 },
35 	{ "F4",		KEYC_F4 },
36 	{ "F5",		KEYC_F5 },
37 	{ "F6",		KEYC_F6 },
38 	{ "F7",		KEYC_F7 },
39 	{ "F8",		KEYC_F8 },
40 	{ "F9",		KEYC_F9 },
41 	{ "F10",	KEYC_F10 },
42 	{ "F11",	KEYC_F11 },
43 	{ "F12",	KEYC_F12 },
44 	{ "F13",	KEYC_F13 },
45 	{ "F14",	KEYC_F14 },
46 	{ "F15",	KEYC_F15 },
47 	{ "F16",	KEYC_F16 },
48 	{ "F17",	KEYC_F17 },
49 	{ "F18",	KEYC_F18 },
50 	{ "F19",	KEYC_F19 },
51 	{ "F20",	KEYC_F20 },
52 	{ "IC",		KEYC_IC },
53 	{ "DC",		KEYC_DC },
54 	{ "Home",	KEYC_HOME },
55 	{ "End",	KEYC_END },
56 	{ "NPage",	KEYC_NPAGE },
57 	{ "PPage",	KEYC_PPAGE },
58 	{ "Tab",	'\011' },
59 	{ "BTab",	KEYC_BTAB },
60 	{ "Space",	' ' },
61 	{ "BSpace",	KEYC_BSPACE },
62 	{ "Enter",	'\r' },
63 	{ "Escape",	'\033' },
64 
65 	/* Arrow keys. */
66 	{ "Up",		KEYC_UP },
67 	{ "Down",	KEYC_DOWN },
68 	{ "Left",	KEYC_LEFT },
69 	{ "Right",	KEYC_RIGHT },
70 
71 	/* Numeric keypad. */
72 	{ "KP/", 	KEYC_KP0_1 },
73 	{ "KP*",	KEYC_KP0_2 },
74 	{ "KP-",	KEYC_KP0_3 },
75 	{ "KP7",	KEYC_KP1_0 },
76 	{ "KP8",	KEYC_KP1_1 },
77 	{ "KP9",	KEYC_KP1_2 },
78 	{ "KP+",	KEYC_KP1_3 },
79 	{ "KP4",	KEYC_KP2_0 },
80 	{ "KP5",	KEYC_KP2_1 },
81 	{ "KP6",	KEYC_KP2_2 },
82 	{ "KP1",	KEYC_KP3_0 },
83 	{ "KP2",	KEYC_KP3_1 },
84 	{ "KP3",	KEYC_KP3_2 },
85 	{ "KPEnter",	KEYC_KP3_3 },
86 	{ "KP0",	KEYC_KP4_0 },
87 	{ "KP.",	KEYC_KP4_2 },
88 };
89 
90 int
91 key_string_search_table(const char *string)
92 {
93 	u_int	i;
94 
95 	for (i = 0; i < nitems(key_string_table); i++) {
96 		if (strcasecmp(string, key_string_table[i].string) == 0)
97 			return (key_string_table[i].key);
98 	}
99 	return (KEYC_NONE);
100 }
101 
102 int
103 key_string_lookup_string(const char *string)
104 {
105 	int	      	 key;
106 	const u_char	*ptr;
107 
108 	if (string[0] == '\0')
109 		return (KEYC_NONE);
110 	if (string[1] == '\0')
111 		return (string[0]);
112 
113 	ptr = NULL;
114 	if ((string[0] == 'C' || string[0] == 'c') && string[1] == '-')
115 		ptr = string + 2;
116 	else if (string[0] == '^')
117 		ptr = string + 1;
118 	if (ptr != NULL) {
119 		if (ptr[0] == '\0')
120 			return (KEYC_NONE);
121 		if (ptr[1] == '\0') {
122 			if (ptr[0] == 32)
123 				return (0);
124 			if (ptr[0] == 63)
125 				return (KEYC_BSPACE);
126 			if (ptr[0] >= 64 && ptr[0] <= 95)
127 				return (ptr[0] - 64);
128 			if (ptr[0] >= 97 && ptr[0] <= 122)
129 				return (ptr[0] - 96);
130 			return (KEYC_NONE);
131 		}
132 		key = key_string_search_table(ptr);
133 		if (key != KEYC_NONE)
134 			return (key | KEYC_CTRL);
135 		return (KEYC_NONE);
136 	}
137 
138 	if ((string[0] == 'M' || string[0] == 'm') && string[1] == '-') {
139 		ptr = string + 2;
140 		if (ptr[0] == '\0')
141 			return (KEYC_NONE);
142 		if (ptr[1] == '\0') {
143 			if (ptr[0] < 32 || ptr[0] > 127)
144 				return (KEYC_NONE);
145 			return (ptr[0] | KEYC_ESCAPE);
146 		}
147 		key = key_string_lookup_string(ptr);
148 		if (key != KEYC_NONE)
149 			return (key | KEYC_ESCAPE);
150 		return (KEYC_NONE);
151 	}
152 
153 	return (key_string_search_table(string));
154 }
155 
156 const char *
157 key_string_lookup_key(int key)
158 {
159 	static char tmp[24], tmp2[24];
160 	const char *s;
161 	u_int	    i;
162 
163 	if (key == 127)
164 		return (NULL);
165 
166 	if (key & KEYC_ESCAPE) {
167 		if ((s = key_string_lookup_key(key & ~KEYC_ESCAPE)) == NULL)
168 			return (NULL);
169 		xsnprintf(tmp2, sizeof tmp2, "M-%s", s);
170 		return (tmp2);
171 	}
172 	if (key & KEYC_CTRL) {
173 		if ((s = key_string_lookup_key(key & ~KEYC_CTRL)) == NULL)
174 			return (NULL);
175 		xsnprintf(tmp2, sizeof tmp2, "C-%s", s);
176 		return (tmp2);
177 	}
178 	if (key & KEYC_SHIFT) {
179 		if ((s = key_string_lookup_key(key & ~KEYC_SHIFT)) == NULL)
180 			return (NULL);
181 		xsnprintf(tmp2, sizeof tmp2, "S-%s", s);
182 		return (tmp2);
183 	}
184 
185 	for (i = 0; i < nitems(key_string_table); i++) {
186 		if (key == key_string_table[i].key)
187 			return (key_string_table[i].string);
188 	}
189 
190 	if (key >= 32 && key <= 255) {
191 		tmp[0] = key;
192 		tmp[1] = '\0';
193 		return (tmp);
194 	}
195 
196 	if (key >= 0 && key <= 32) {
197 		if (key == 0 || key > 26)
198 			xsnprintf(tmp, sizeof tmp, "C-%c", 64 + key);
199 		else
200 			xsnprintf(tmp, sizeof tmp, "C-%c", 96 + key);
201 		return (tmp);
202 	}
203 
204 	return (NULL);
205 }
206