1 #include <string.h>
2 #include "keyboard.h"
3 #include "input.h"
4 #include "escseq.h"
5 
6 int kb_no_autorep = 0;
7 
8 static struct keys {
9 	unsigned short menu_keys[6];
10 	unsigned short ingame_keys[5];
11 } keys_singlepl;
12 
13 #ifdef TWOPLAYER
14 static struct keys keys_1p, keys_2p;
15 #endif
16 
transl_chr_ingame(unsigned c,unsigned short * keys)17 static int transl_chr_ingame(unsigned c, unsigned short *keys)
18 {
19 	int i = 0;
20 	keys += keys_singlepl.ingame_keys - keys_singlepl.menu_keys;
21 	while (i < 5) {
22 		if (keys[i] == c)
23 			return i==4 ? HARDDROP : MVUP+i;
24 		i++;
25 	}
26 	return 0;
27 }
28 
transl_chr(unsigned c,int k)29 static int transl_chr(unsigned c, int k)
30 {
31 	unsigned short *keys;
32 	int i;
33 #ifdef TWOPLAYER
34 	if (k & PLAYER_1)
35 		keys = keys_1p.menu_keys;
36 	else if (k & PLAYER_2)
37 		keys = keys_2p.menu_keys;
38 	else if (!(k & SINGLE_PL)) {
39 		if (i = transl_chr(c, k | PLAYER_1))
40 			return i | PLAYER_1;
41 		if (i = transl_chr(c, k | PLAYER_2))
42 			return i | PLAYER_2;
43 		return 0;
44 	} else
45 #endif
46 	keys = keys_singlepl.menu_keys;
47 	if ((k & IN_GAME) && (k = transl_chr_ingame(c, keys)))
48 		return k;
49 	for (i = 0; i < 6; i++)
50 		if (keys[i] == c)
51 			return MVLEFT+i;
52 	return 0;
53 }
54 
transl_input(const unsigned char * input,int flags)55 static int transl_input(const unsigned char *input, int flags)
56 {
57 	unsigned c = *input;
58 #ifdef TWOPLAYER
59 	if (!(flags & (PLAYER_1 | PLAYER_2))) {
60 		if (inputdevs_player[0] == 1)
61 			flags |= PLAYER_1 | SINGLE_PL;
62 		if (inputdevs_player[0] == 2)
63 			flags |= PLAYER_2 | SINGLE_PL;
64 	}
65 #endif
66 #ifdef ESCSEQ
67 	if (c == ESC)
68 		return transl_escseq((const char *) input+1, flags);
69 #else
70 	c |= input[1] << 8;
71 #endif
72 	return transl_chr(c, flags);
73 }
74 
kb_getpress(int flags)75 int kb_getpress(int flags)
76 {
77 	unsigned char s[5] = "";
78 	unsigned c;
79 	if (!kb_readkey(s))
80 		return 0;
81 	if (c = transl_input(s, flags))
82 		return c;
83 	if (!s[1])
84 		c = s[0];
85 	else if (flags & IN_GAME)
86 		c = ESC+1;
87 	else
88 		c =  kb_toascii(s);
89 	if (!(flags & IN_GAME) || c <= MVDOWN
90 #ifdef TWOPLAYER
91 		&& (flags & SINGLE_PL || inputdevs_player[0] ||
92 		    !keys_1p.menu_keys[c-MVLEFT])
93 #endif
94 	)
95 		return c;
96 	if (strchr("\033\b \npq", c))
97 		return c;
98 	return kb_getpress(flags);
99 }
100 
getchrfor(int keypress)101 static unsigned short *getchrfor(int keypress)
102 {
103 	unsigned short *keys;
104 	int i;
105 #ifdef TWOPLAYER
106 	if (keypress & PLAYER_1)
107 		keys = keys_1p.menu_keys;
108 	else if (keypress & PLAYER_2)
109 		keys = keys_2p.menu_keys;
110 	else
111 #endif
112 	keys = keys_singlepl.menu_keys;
113 	if (keypress & IN_GAME) {
114 		keys += keys_singlepl.ingame_keys - keys_singlepl.menu_keys;
115 		if ((keypress & 63) == HARDDROP)
116 			i = 4;
117 		else
118 			i = (keypress & 7)-MVUP;
119 	} else
120 		i = (keypress & 7)-MVLEFT;
121 	return keys+i;
122 }
123 
key_equals(int keypr,const unsigned char * input)124 static int key_equals(int keypr, const unsigned char *input)
125 {
126 	unsigned c = *input;
127 #if ESCSEQ
128 	if (c == ESC)
129 		return !strncmp((const char *) input+1,
130 				getescseq_str(keypr),  3);
131 #else
132 	c |= input[1] << 8;
133 #endif
134 	return c == *getchrfor(keypr);
135 }
136 
transl_strict(const unsigned char * input,int flags)137 static int transl_strict(const unsigned char *input, int flags)
138 {
139 	int k = transl_input(input, flags | SINGLE_PL);
140 	if (flags & IN_GAME && !key_equals(k | flags, input))
141 		k = 0;
142 	return k;
143 }
144 
rmkey(const unsigned char * input,int keypr)145 static void rmkey(const unsigned char *input, int keypr)
146 {
147 	int flags = keypr & (IN_GAME | PLAYER_1 | PLAYER_2);
148 	int old = transl_strict(input, flags);
149 	if (old && old != (keypr & 63))
150 		kb_rmmapping(old | flags);
151 #ifdef TWOPLAYER
152 	if (!(flags & (PLAYER_1 | PLAYER_2)))
153 		return;
154 	flags ^= PLAYER_1 | PLAYER_2;
155 	if (old = transl_strict(input, flags))
156 		kb_rmmapping(old | flags);
157 	flags ^= IN_GAME;
158 	if (old = transl_strict(input, flags))
159 		kb_rmmapping(old | flags);
160 #endif
161 }
162 
ingame_key_equals(int keypr,unsigned c)163 static int ingame_key_equals(int keypr, unsigned c)
164 {
165 	const char *s;
166 	if (keypr & IN_GAME || (keypr & 7) < MVUP)
167 		return 0;
168 #ifdef ESCSEQ
169 	if (!c) {
170 		s = getescseq_str(keypr);
171 		return *s && !strncmp(s, getescseq_str(keypr | IN_GAME), 3);
172 	}
173 #endif
174 	return c && c == *getchrfor(keypr | IN_GAME);
175 }
176 
kb_setmapping(const unsigned char * input,int keypr)177 void kb_setmapping(const unsigned char *input, int keypr)
178 {
179 	unsigned short *c = getchrfor(keypr);
180 	rmkey(input, keypr);
181 	if (ingame_key_equals(keypr, *c))
182 		kb_setmapping(input, keypr | IN_GAME);
183 #ifdef ESCSEQ
184 	if (!input[0])
185 		return;
186 	if (input[0] == ESC) {
187 		*c = 0;
188 		mapescseq((const char *) input+1, keypr);
189 		return;
190 	}
191 	if (*getescseq_str(keypr))
192 		rmescseq(keypr);
193 #endif
194 	*c  = input[0];
195 #ifndef ESCSEQ
196 	*c |= input[1] << 8;
197 #endif
198 }
199 
test_fallback(int keypr,const unsigned char * input)200 static int test_fallback(int keypr, const unsigned char *input)
201 {
202 	int flags = keypr & IN_GAME;
203 	int k = keypr & 63;
204 #ifdef TWOPLAYER
205 	int pl = keypr & (PLAYER_1 | PLAYER_2);
206 	if (!pl)
207 		flags |= SINGLE_PL;
208 #endif
209 	if ((!(keypr & IN_GAME) || k==HARDDROP) && (k==A_BTN || k==B_BTN
210 #ifdef TWOPLAYER
211 			|| pl==PLAYER_2 && inputdevs_player[0] != 2
212 #endif
213 				))
214 		return 0;
215 	keypr = transl_input(input, flags);
216 	return !keypr ||
217 #ifdef TWOPLAYER
218 		pl == (keypr & (PLAYER_1 | PLAYER_2)) &&
219 #endif
220 		k == (keypr & 63);
221 }
222 
kb_getkeyfor(int keypr,unsigned char * dest,int fallback)223 int kb_getkeyfor(int keypr, unsigned char *dest, int fallback)
224 {
225 	unsigned c = *getchrfor(keypr);
226 #ifdef ESCSEQ
227 	const char *s;
228 	if (c) {
229 		*dest = c;
230 		return 1;
231 	}
232 	s = getescseq_str(keypr);
233 	if (*s) {
234 		dest[0] = ESC;
235 		strncpy((char *) dest+1, s, 3);
236 		dest[4] = '\0';
237 		return strlen((char *) dest);
238 	}
239 #else
240 	if (c) {
241 		*dest = c & 0xFF;
242 		if (c >>= 8) {
243 			dest[1] = c;
244 			return 2;
245 		}
246 		return 1;
247 	}
248 #endif
249 	if (!fallback)
250 		return 0;
251 	*dest = keypr;
252 	dest[1] = 0;
253 	c = 1;
254 	if (keypr & IN_GAME && *dest != HARDDROP)
255 		c = kb_getkeyfor(keypr ^ IN_GAME, dest, 1);
256 	if (c && !test_fallback(keypr, dest))
257 		c = 0;
258 	return c;
259 }
260 
kb_getchrfor(int keypress)261 int kb_getchrfor(int keypress)
262 {
263 	return *getchrfor(keypress);
264 }
265 
kb_rmmapping(int keypress)266 void kb_rmmapping(int keypress)
267 {
268 	unsigned short *c = getchrfor(keypress);
269 	*c = 0;
270 #ifdef ESCSEQ
271 	rmescseq(keypress);
272 #endif
273 }
274