1 #include <string.h>
2 #include <stdio.h> /* sprintf */
3 #include <stdlib.h> /* exit */
4 #include "input.h"
5 #include "keyboard.h"
6 #include "joystick.h"
7 #include "../timer.h"
8 #include "../draw/draw.h" /* upd_screen */
9 #include "../game/tetris.h"
10 #ifndef SOCKET
11 #define SOCKET_EMPTY_DEFS 1
12 #undef socket_fd
13 #define socket_fd -1
14 #endif
15 #include "../netw/sock.h"
16
17 #include "../textgfx/textgfx.h" /* upd_termresize */
18 #include "../focus.h"
19
20 extern int close_button_pressed;
21
22 const char input_chr9[9][4] = {
23 "LFT", "RGT", "UP", "DWN", "(A)", "(B)", "BEL", "BS", "HT"
24 };
25
26 int inputdevs_fd[4] = {-1,-1,-1,-1};
27 char inputdevs_player[4] = {0};
28
29 int autorep_a_b_btns = 0;
30 int edit_mode = 0;
31
32 static short spawn_tm[2];
33 static int ignore_dev;
34
init_inputdevs()35 void init_inputdevs()
36 {
37 init_keybd();
38 #if JOYSTICK
39 init_joysticks();
40 #endif
41 }
42
43 #if TWOPLAYER && NUM_INPUTDEVS > 1
player_flag(int i,int flags)44 static int player_flag(int i, int flags)
45 {
46 if (socket_fd > -1) {
47 if (i==3)
48 return PLAYER_2;
49 } else if (inputdevs_player[i] && !(flags & SINGLE_PL))
50 return inputdevs_player[i]==1 ? PLAYER_1 : PLAYER_2;
51 return 0;
52 }
53 #else
54 #define player_flag(i, flags) 0
55 #endif
56
getkeypress_select(int tm,int flags)57 static int getkeypress_select(int tm, int flags)
58 {
59 int keypress = 0;
60 int i;
61 #if TERM_RESIZING
62 if (tm > 80)
63 upd_termresize();
64 #endif
65 #if XLIB || ALLEGRO
66 if (tm > 80 && in_xterm && game && game_running &&
67 !TWOPLAYER_MODE && !xterm_hasfocus())
68 return STARTBTN;
69 #endif
70 for (i = inpselect_dev(tm); i < NUM_INPUTDEVS && !keypress; i++) {
71 if (i+1 == ignore_dev)
72 continue;
73 switch (i) {
74 case 0:
75 keypress = kb_getpress(flags);
76 break;
77 #if JOYSTICK
78 case 1:
79 case 2:
80 keypress = js_getpress(i-1, flags);
81 break;
82 #endif
83 #if SOCKET
84 case 3:
85 keypress = sock_getkeypress(flags);
86 if (ignore_dev)
87 return 0;
88 #endif
89 }
90 }
91 if (keypress)
92 keypress |= player_flag(i-1, flags);
93 return keypress;
94 }
95
getkeypress(int tm,int flags)96 int getkeypress(int tm, int flags)
97 {
98 int t = gettm(0);
99 int keypress;
100 if (socket_fd > -1)
101 flags |= SINGLE_PL;
102 while (1) {
103 if (tm <= 0)
104 return 0;
105 keypress = getkeypress_select(tm, flags);
106 #if JOYSTICK
107 if (!keypress)
108 keypress = getautorepeat(flags);
109 #endif
110 if (keypress)
111 break;
112 if (gettm(t) == t)
113 sleep_msec(1);
114 tm -= gettm(t)-t;
115 t = gettm(0);
116 #ifdef ALLEGRO
117 if (close_button_pressed)
118 exit(0);
119 #endif
120 }
121 return keypress;
122 }
123
getkeypress_block(int flags)124 int getkeypress_block(int flags)
125 {
126 int keypress;
127 while (1) {
128 #if TTY_SOCKET && !NO_MENU
129 if (!(flags & 1) && (invit || checkinvit()))
130 return ESC;
131 #endif
132 keypress = getkeypress(1000, flags);
133 if (keypress)
134 break;
135 sleep_msec(55);
136 }
137 return keypress;
138 }
139
spawn_discard_drops(int pl)140 void spawn_discard_drops(int pl)
141 {
142 int i = 0;
143 if (pl==2) {
144 i = 1;
145 if (socket_fd > -1) {
146 spawn_tm[1] = 0;
147 return;
148 }
149 }
150 spawn_tm[i] = gettm(0);
151 #ifdef ALLEGRO
152 kb_reset_drop(pl);
153 #endif
154 #ifdef JOYSTICK
155 if (!num_joyst)
156 return;
157 i = !js_pressed(0);
158 if (pl==2 && inputdevs_player[i+1] != 2) {
159 if (i || inputdevs_player[2] != 2)
160 return;
161 i = 1;
162 }
163 if (js_pressed(i))
164 js_reset_drop(i);
165 #endif
166 }
167
key_is_valid(unsigned c,int keypr)168 static int key_is_valid(unsigned c, int keypr)
169 {
170 return c == (keypr & 0x7F) ||
171 c > MVRIGHT &&
172 (c > MVDOWN || keypr & IN_GAME) &&
173 c != STARTBTN && c != '\t';
174 }
175
setkeymapping_keybd(int keypr)176 static int setkeymapping_keybd(int keypr)
177 {
178 unsigned char s[5] = "";
179 unsigned c;
180 kb_no_autorep = 1;
181 while (!kb_readkey(s)) {
182 if (c = getkeypress_select(100, SINGLE_PL))
183 return c;
184 sleep_msec(55);
185 }
186 c = !s[1] ? s[0] : ESC+1;
187 if (c == ESC)
188 kb_rmmapping(keypr);
189 else {
190 if (!key_is_valid(c, keypr))
191 return c;
192 if (c == MVUP && (keypr & (63 | IN_GAME)) == MVUP) {
193 c = kb_getchrfor(keypr);
194 if (c == MVUP)
195 return MVUP;
196 }
197 kb_setmapping(s, keypr);
198 if (!c && (!(keypr & PLAYER_2) || inputdevs_player[0]==2))
199 return MVUP;
200 }
201 return MVDOWN;
202 }
203
204 #if JOYSTICK
setkeymapping_js(int i,int keypr)205 static int setkeymapping_js(int i, int keypr)
206 {
207 int b, b2;
208 while (!(b = js_readbtn(i))) {
209 if (inputdevs_fd[i+1] == -1)
210 return STARTBTN;
211 if (b = getkeypress_select(100, SINGLE_PL)) {
212 if (b == ESC) {
213 js_rmmapping(i, keypr);
214 return MVDOWN;
215 }
216 return b;
217 }
218 sleep_msec(55);
219 }
220 b2 = js_readbtn(i);
221 if (b > b2 && b2)
222 b = b2;
223 if (!key_is_valid(b, keypr))
224 return b;
225 if (b == MVUP && keypr == MVUP && js_getbtnfor(i, MVUP) == MVUP)
226 return MVUP;
227 js_setmapping(i, b, keypr);
228 return MVDOWN;
229 }
230 #endif
231
setkeymapping(int dev,int keypr)232 int setkeymapping(int dev, int keypr)
233 {
234 ignore_dev = dev+1;
235 #if JOYSTICK
236 if (dev > 0)
237 keypr = setkeymapping_js(dev-1, keypr);
238 else
239 #endif
240 keypr = setkeymapping_keybd(keypr);
241 kb_no_autorep = 0;
242 ignore_dev = 0;
243 return keypr;
244 }
245
getkeyfor_str_keybd(int keypr,int * c)246 static const char *getkeyfor_str_keybd(int keypr, int *c)
247 {
248 static unsigned char bytes[7];
249 const char *name;
250 int n = kb_getkeyfor(keypr, bytes, 1);
251 if (!n)
252 return "";
253 name = kb_keyname(bytes, n);
254 if (name)
255 return name;
256 bytes[n] = '\0';
257 if (n==1) {
258 n = bytes[0];
259 if (n ==' ')
260 strcpy((char *) bytes, "SPACE");
261 else if (n == DEL)
262 strcpy((char *) bytes, "DEL");
263 else if (n < ' ') {
264 if (n < 10) {
265 *c = n;
266 return NULL;
267 }
268 sprintf((char *) bytes, "%d", n);
269 }
270 }
271 return (const char *) bytes;
272 }
273
getkeyfor_str(int dev,int keypr)274 const char *getkeyfor_str(int dev, int keypr)
275 {
276 const char *name;
277 int c = 0;
278 #if JOYSTICK
279 if (dev) {
280 c = js_getbtnfor(dev-1, keypr);
281 name = js_btnname(c);
282 } else
283 #endif
284 name = getkeyfor_str_keybd(keypr, &c);
285 if (name)
286 return name;
287 if (c > 0 && c < 10)
288 return input_chr9[c-1];
289 return "";
290 }
291
dropsafe(int i)292 static int dropsafe(int i)
293 {
294 int t = spawn_tm[i];
295 if (t && gettm(t)-t < DAS_DELAY)
296 return 1;
297 spawn_tm[i] = 0;
298 return 0;
299 }
300
processkey_ingame(int key,int flags)301 int processkey_ingame(int key, int flags)
302 {
303 static int discard_count;
304 struct player *plr;
305 int i = TWOPLAYER_MODE && key & PLAYER_2;
306 int safe;
307 switch (key & 0x7F) {
308 case ESC:
309 case '\b':
310 game->state = 0;
311 return -2;
312 case 'q':
313 exit(0);
314 case STARTBTN:
315 case 'p':
316 if (flags & NO_PAUSE || !game_running || TWOPLAYER_MODE)
317 break;
318 i = pausegame();
319 textgfx_flags &= ~LOST_FOCUS;
320 return i;
321 }
322 if (flags & DISCARD_MOVES) {
323 if (++discard_count > 5)
324 kb_flushinp();
325 return -1;
326 }
327 discard_count = 0;
328 plr = game->player+i;
329 safe = dropsafe(i);
330 key &= 0x7F;
331 if (!(flags & DISCARD_DROPS)) {
332 switch (key) {
333 case HARDDROP:
334 if (socket_fd > -1 && !i) {
335 sock_sendpiece(plr);
336 if (harddrop(plr, safe) == -1)
337 return -1;
338 sock_sendbyte(HARDDROP);
339 return 0;
340 }
341 return harddrop(plr, safe);
342 case MVDOWN:
343 if (!TWOPLAYER_MODE)
344 return softdrop(softdrop_speed, safe);
345 if (!movedown(plr, 1))
346 return 0;
347 if (socket_fd > -1 && !i)
348 sock_sendbyte(MVDOWN);
349 return 1;
350 }
351 }
352 switch (key) {
353 case MVLEFT:
354 moveleft(plr);
355 break;
356 case MVRIGHT:
357 moveright(plr);
358 break;
359 case MVUP:
360 rotate(plr, plr->rotationsys & ROT_CLOCKWISE);
361 break;
362 case A_BTN:
363 rotate(plr, 1);
364 break;
365 case B_BTN:
366 rotate(plr, 0);
367 break;
368 default:
369 return -1;
370 }
371 if (socket_fd > -1 && !i)
372 sock_sendbyte(key);
373 upd_screen(1+i);
374 return 1;
375 }
376