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