1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: g_input.c 1566 2020-12-19 06:22:58Z wesleyjohnson $
5 //
6 // Copyright (C) 1998-2016 by DooM Legacy Team.
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; either version 2
11 // of the License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 //
19 // $Log: g_input.c,v $
20 // Revision 1.12  2002/08/24 22:42:02  hurdler
21 // Apply Robert Hogberg patches
22 //
23 // Revision 1.11  2002/07/01 19:59:58  metzgermeister
24 // *** empty log message ***
25 //
26 // Revision 1.10  2001/03/30 17:12:49  bpereira
27 // Revision 1.9  2001/02/24 13:35:19  bpereira
28 // Revision 1.8  2001/02/10 12:27:13  bpereira
29 //
30 // Revision 1.7  2001/01/25 22:15:42  bpereira
31 // added heretic support
32 //
33 // Revision 1.6  2000/11/26 00:46:31  hurdler
34 //
35 // Revision 1.5  2000/10/04 17:03:57  hurdler
36 // This is the formule I propose for mouse sensitivity
37 //
38 // Revision 1.4  2000/04/16 18:38:07  bpereira
39 //
40 // Revision 1.3  2000/04/04 00:32:45  stroggonmeth
41 // Initial Boom compatability plus few misc changes all around.
42 //
43 // Revision 1.2  2000/02/27 00:42:10  hurdler
44 // Revision 1.1.1.1  2000/02/22 20:32:32  hurdler
45 // Initial import into CVS (v1.29 pr3)
46 //
47 //
48 // DESCRIPTION:
49 //      handle mouse/keyboard/joystick inputs,
50 //      maps inputs to game controls (forward,use,open...)
51 //
52 //-----------------------------------------------------------------------------
53 
54 #include "doomincl.h"
55 #include "doomstat.h"
56 #include "g_input.h"
57 #include "keys.h"
58 #include "hu_stuff.h"   //need HUFONT start & end
59 #include "keys.h"
60 #include "d_net.h"
61 #include "console.h"
62 #include "i_joy.h"
63 #include "i_system.h"
64 
65 int num_joybindings = 0;
66 joybinding_t joybindings[MAX_JOYBINDINGS];
67 
68 
69 CV_PossibleValue_t mousesens_cons_t[]={{1,"MIN"},{MAXMOUSESENSITIVITY,"MAXCURSOR"},{INT_MAX,"MAX"},{0,NULL}};
70 CV_PossibleValue_t onecontrolperkey_cons_t[]={{1,"One"},{2,"Several"},{0,NULL}};
71 
72 // mouse values are used once
73 consvar_t  cv_mouse_sens_x    = {"mousesensx","10",CV_SAVE,mousesens_cons_t};
74 consvar_t  cv_mouse_sens_y    = {"mousesensy","10",CV_SAVE,mousesens_cons_t};
75 consvar_t  cv_controlperkey   = {"controlperkey","1",CV_SAVE,onecontrolperkey_cons_t};
76 
77 CV_PossibleValue_t usemouse_cons_t[] = { {0, "Off"}, {1, "On"}, {2, "Force"}, {0, NULL} };
78 consvar_t cv_usemouse[2] = {
79   { "use_mouse", "1", CV_SAVE | CV_CALL, usemouse_cons_t, CV_mouse_OnChange },
80   { "use_mouse2", "0", CV_SAVE | CV_CALL, usemouse_cons_t, I_StartupMouse2 }
81 };
82 
83 #ifdef MOUSE2
84 #ifdef MOUSE2_NIX
85 CV_PossibleValue_t mouse2port_cons_t[] = {
86   {0, "gpmdata"},
87   {1, "mouse2"},  // indirection
88   {2, "ttyS0"}, {3, "ttyS1"}, {4, "ttyS2"}, {5, "ttyS3"}, {6, "ttyS4"}, {7, "ttyS5"}, {8, "ttyS6"},
89   {0, NULL} };
90 #define CV_DEFAULT_PORT  "gpmdata"
91 #endif
92 #ifdef MOUSE2_WIN
93 CV_PossibleValue_t mouse2port_cons_t[] = {
94   {1, "COM1"}, {2, "COM2"}, {3, "COM3"}, {4, "COM4"},
95   {5, "COM5"}, {6, "COM6"}, {7, "COM7"}, {8, "COM8"},  // Some Windows are reported to connect USB or other devices to COM ports
96   {0, NULL} };
97 #define CV_DEFAULT_PORT  "COM2"
98 #endif
99 consvar_t cv_mouse2port = { "mouse2port", CV_DEFAULT_PORT , CV_SAVE|CV_STRING|CV_CALL|CV_NOINIT, mouse2port_cons_t, I_StartupMouse2 };
100 consvar_t cv_mouse2opt = { "mouse2opt", "0", CV_SAVE|CV_STRING|CV_CALL|CV_NOINIT, NULL, I_StartupMouse2 };
101 #if defined( SMIF_SDL ) || defined( SMIF_WIN32 )
102 // Only in SDL, WIN32 for now.
103 CV_PossibleValue_t mouse2type_cons_t[] = { {0, "PC"}, {1, "MS"}, {2, "PS2"}, {0, NULL} };
104 consvar_t cv_mouse2type = { "mouse2type", "0" , CV_SAVE|CV_STRING|CV_CALL|CV_NOINIT, mouse2type_cons_t, I_StartupMouse2 };
105 #endif
106 consvar_t  cv_mouse2_sens_x   = {"mouse2sensx","10",CV_SAVE,mousesens_cons_t};
107 consvar_t  cv_mouse2_sens_y   = {"mouse2sensy","10",CV_SAVE,mousesens_cons_t};
108 #endif
109 
110 #ifdef SMIF_SDL
111 CV_PossibleValue_t mouse_motion_cons_t[]={{0,"Absolute"},{1,"Relative"},{0,NULL}};
112 consvar_t  cv_mouse_motion = {"mousemotion","0", CV_SAVE|CV_CALL|CV_NOINIT, mouse_motion_cons_t, CV_mouse_OnChange };
113 #endif
114 
115 consvar_t  cv_grabinput = {"grabinput","1", CV_SAVE|CV_CALL, CV_OnOff, CV_mouse_OnChange };
116 
117 // A normal double click is approx. 6 tics from previous click.
118 CV_PossibleValue_t double_cons_t[]={{1,"MIN"},{40,"MAX"},{0,NULL}};  // double click threshold
119 consvar_t  cv_mouse_double   = {"mousedouble","8",CV_SAVE, double_cons_t};
120 #ifdef JOY_BUTTONS_DOUBLE
121 consvar_t  cv_joy_double     = {"joydouble",  "8",CV_SAVE, double_cons_t};
122 #endif
123 
124 
125 // Called for cv_grabinput, cv_mouse_motion, use_mouse
CV_mouse_OnChange(void)126 void  CV_mouse_OnChange( void )
127 {
128    I_StartupMouse( !(paused || menuactive) );
129 }
130 
131 
132 int  mousex, mousey;
133 int  mouse2x, mouse2y;
134 
135 // [WDJ] When boolean, the compiler uses 4 bytes for one bit of information.
136 byte  gamekeydown[NUMINPUTS]; // Current state of the keys: true if the key is currently down.
137 byte  gamekeytapped[NUMINPUTS]; // True if the key has been pressed since the last G_BuildTiccmd. Useful for impulse-style controls.
138 
139 
140 // two key codes (or virtual key) per game control
141 int  gamecontrol[num_gamecontrols][2];
142 int  gamecontrol2[num_gamecontrols][2];        // secondary splitscreen player
143 
144 
145 // FIXME: this can be simplified to two bytes
146 // [WDJ] Got it down to 3 bytes.
147 typedef struct {
148   byte  dtime;   // 0..21
149   byte  key_down;
150   byte  clicks;  // 0..2
151 } dclick_t;
152 
153 // FIXME: only one mouse, only one joy
154 static  dclick_t  mouse_dclick[MOUSEBUTTONS];
155 #ifdef JOY_BUTTONS_DOUBLE
156 static  dclick_t  joy_dclick[JOYBUTTONS];
157 #endif
158 
159 static tic_t  clicktic = 0;  // gametic of last button check
160 static unsigned int  click_delta;  // tics since last button check, limited 120
161 
162 //
163 //  General double-click detection routine for any kind of input.
164 //
G_CheckDoubleClick(int key_id,dclick_t * dt,byte double_click_threshold)165 static boolean G_CheckDoubleClick(int key_id, dclick_t *dt, byte double_click_threshold )
166 {
167     // [WDJ] This is only called for each event, so time cannot be determined by counting.
168     byte key_down = gamekeydown[ key_id ];
169     // Limited to 120 tics since last click, anything > 40 tics is a timeout.
170     dt->dtime += click_delta;  // + 0..120, must not overflow
171     // This is called infrequently, so check timeouts first.
172     // A normal double click is approx. 6 tics from previous click.
173     if( dt->dtime > double_click_threshold )     // 1..40
174     {
175         dt->dtime = 121;  // timeout (with room to add 120)
176         dt->clicks = 0;
177         dt->key_down = false;
178     }
179 
180     // Check new state.
181     if( (key_down != dt->key_down) && (dt->dtime > 1) )
182     {
183         dt->key_down = key_down;
184         if( key_down )
185         {
186             dt->clicks++;
187             if(dt->clicks == 2)
188             {
189                 dt->clicks = 0;
190                 dt->dtime = 0;
191                 return true;
192             }
193         }
194         dt->dtime = 0;
195     }
196     return false;
197 }
198 
199 
200 
201 //
202 //  Remaps the inputs to game controls.
203 //
204 //  A game control can be triggered by one or more keys/buttons.
205 //
206 //  Each key/mousebutton/joybutton triggers ONLY ONE game control.
207 //
208 //
G_MapEventsToControls(event_t * ev)209 void  G_MapEventsToControls (event_t *ev)
210 {
211   int i;
212 
213     switch (ev->type)
214     {
215       case ev_keydown:
216         if (ev->data1 < NUMINPUTS)
217         {
218             gamekeydown[ev->data1] = true;
219             gamekeytapped[ev->data1] = true; // reset in G_BuildTiccmd
220         }
221         break;
222 
223       case ev_keyup:
224         if (ev->data1 < NUMINPUTS)
225           gamekeydown[ev->data1] = false;
226         break;
227 
228       case ev_mouse:           // buttons are virtual keys
229         // [WDJ] To handle multiple mouse motion events per frame instead
230         // of letting the last event be the sole mouse motion,
231         // add the mouse events.
232         // Necessary for OpenBSD which reports x and y in separate events.
233         mousex += ev->data2*((cv_mouse_sens_x.value*cv_mouse_sens_x.value)/110.0f + 0.1);
234         mousey += ev->data3*((cv_mouse_sens_y.value*cv_mouse_sens_y.value)/110.0f + 0.1);
235         break;
236 
237 #ifdef MOUSE2
238       case ev_mouse2:           // buttons are virtual keys
239         // add multiple mouse motions
240         mouse2x += ev->data2*((cv_mouse2_sens_x.value*cv_mouse2_sens_x.value)/110.0f + 0.1);
241         mouse2y += ev->data3*((cv_mouse2_sens_y.value*cv_mouse2_sens_y.value)/110.0f + 0.1);
242         break;
243 #endif
244 
245       default:
246         break;
247     }
248 
249     // [WDJ] Only called for events, so click time needs to be based upon gametic.
250     // This is overflow safe, it wraps.
251     click_delta = (gametic - clicktic) / NEWTICRATERATIO;  // must be 35 tic/sec based.
252     if( click_delta > 120 )  click_delta = 120;
253     clicktic = gametic;
254 
255     // ALWAYS check for mouse & joystick double-clicks
256     // even if no mouse event
257     // FIXME: first MOUSE only
258     for (i=0;i<MOUSEBUTTONS;i++)
259       gamekeydown[KEY_MOUSE1DBL+i] = G_CheckDoubleClick( KEY_MOUSE1+i, &mouse_dclick[i], cv_mouse_double.value );
260 
261 #ifdef JOY_BUTTONS_DOUBLE
262     // joystick doubleclicks
263     // FIXME: JOY0 only
264     for (i=0;i<JOYBUTTONS;i++)
265       gamekeydown[KEY_JOY0BUT0DBL+i] = G_CheckDoubleClick( KEY_JOY0BUT0+i, &joy_dclick[i], cv_joy_double.value );
266 #endif
267 }
268 
269 
270 
271 
272 typedef struct {
273     int  keynum;
274     char name[16];
275 } keyname_t;
276 
277 static keyname_t keynames[] =
278 {
279   {KEY_NULL,      "null"},
280 
281   {KEY_BACKSPACE, "backspace"},
282   {KEY_TAB,       "tab"},
283   {KEY_ENTER,     "enter"},
284   {KEY_PAUSE,     "pause"},  // irrelevant, since this key cannot be remapped...
285   {KEY_ESCAPE,    "escape"}, // likewise
286   {KEY_SPACE,     "space"},
287 
288   {KEY_CONSOLE,    "console"},
289 
290   {KEY_NUMLOCK,    "num lock"},
291   {KEY_CAPSLOCK,   "caps lock"},
292   {KEY_SCROLLLOCK, "scroll lock"},
293   {KEY_SYSREQ,     "sysreq"},
294   {KEY_RSHIFT,     "right shift"},
295   {KEY_LSHIFT,     "left shift"},
296   {KEY_RCTRL,      "right ctrl"},
297   {KEY_LCTRL,      "left ctrl"},
298   {KEY_RALT,       "right alt"},
299   {KEY_LALT,       "left alt"},
300   {KEY_LWIN,       "left win"},
301   {KEY_RWIN,       "right win"},
302   {KEY_MODE,       "altgr"},
303   {KEY_MENU,       "menu"},
304 
305   // keypad keys
306   {KEY_KEYPAD0, "keypad 0"},
307   {KEY_KEYPAD1, "keypad 1"},
308   {KEY_KEYPAD2, "keypad 2"},
309   {KEY_KEYPAD3, "keypad 3"},
310   {KEY_KEYPAD4, "keypad 4"},
311   {KEY_KEYPAD5, "keypad 5"},
312   {KEY_KEYPAD6, "keypad 6"},
313   {KEY_KEYPAD7, "keypad 7"},
314   {KEY_KEYPAD8, "keypad 8"},
315   {KEY_KEYPAD9, "keypad 9"},
316   {KEY_KPADPERIOD,"keypad ."},
317   {KEY_KPADSLASH, "keypad /"},
318   {KEY_KPADMULT,  "keypad *"},
319   {KEY_MINUSPAD,  "keypad -"},
320   {KEY_PLUSPAD,   "keypad +"},
321 
322   // extended keys (not keypad)
323   {KEY_UPARROW,   "up arrow"},
324   {KEY_DOWNARROW, "down arrow"},
325   {KEY_RIGHTARROW,"right arrow"},
326   {KEY_LEFTARROW, "left arrow"},
327   {KEY_INS,       "ins"},
328   {KEY_DELETE,    "del"},
329   {KEY_HOME,      "home"},
330   {KEY_END,       "end"},
331   {KEY_PGUP,      "pgup"},
332   {KEY_PGDN,      "pgdown"},
333 
334   // other keys
335   {KEY_F1, "F1"},
336   {KEY_F2, "F2"},
337   {KEY_F3, "F3"},
338   {KEY_F4, "F4"},
339   {KEY_F5, "F5"},
340   {KEY_F6, "F6"},
341   {KEY_F7, "F7"},
342   {KEY_F8, "F8"},
343   {KEY_F9, "F9"},
344   {KEY_F10,"F10"},
345   {KEY_F11,"F11"},
346   {KEY_F12,"F12"},
347 
348   // virtual keys for mouse buttons and joystick buttons
349   {KEY_MOUSE1,  "mouse 1"},
350   {KEY_MOUSE1+1,"mouse 2"},
351   {KEY_MOUSE1+2,"mouse 3"},
352   {KEY_MOUSEWHEELUP, "mwheel up"},
353   {KEY_MOUSEWHEELDOWN,"mwheel down"},
354   {KEY_MOUSE1+5,"mouse 6"},
355   {KEY_MOUSE1+6,"mouse 7"},
356   {KEY_MOUSE1+7,"mouse 8"},
357   {KEY_MOUSE2,  "mouse2 1"},
358   {KEY_MOUSE2+1,"mouse2 2"},
359   {KEY_MOUSE2+2,"mouse2 3"},
360   {KEY_MOUSE2WHEELUP,"m2 mwheel up"},
361   {KEY_MOUSE2WHEELDOWN,"m2 mwheel down"},
362   {KEY_MOUSE2+5,"mouse2 6"},
363   {KEY_MOUSE2+6,"mouse2 7"},
364   {KEY_MOUSE2+7,"mouse2 8"},
365 
366   {KEY_MOUSE1DBL,   "mouse 1 d"},
367   {KEY_MOUSE1DBL+1, "mouse 2 d"},
368   {KEY_MOUSE1DBL+2, "mouse 3 d"},
369   {KEY_MOUSE1DBL+3, "mouse 4 d"},
370   {KEY_MOUSE1DBL+4, "mouse 5 d"},
371   {KEY_MOUSE1DBL+5, "mouse 6 d"},
372   {KEY_MOUSE1DBL+6, "mouse 7 d"},
373   {KEY_MOUSE1DBL+7, "mouse 8 d"},
374   {KEY_MOUSE2DBL,  "mouse2 2 d"},
375   {KEY_MOUSE2DBL+1,"mouse2 1 d"},
376   {KEY_MOUSE2DBL+2,"mouse2 3 d"},
377   {KEY_MOUSE2DBL+3,"mouse2 4 d"},
378   {KEY_MOUSE2DBL+4,"mouse2 5 d"},
379   {KEY_MOUSE2DBL+5,"mouse2 6 d"},
380   {KEY_MOUSE2DBL+6,"mouse2 7 d"},
381   {KEY_MOUSE2DBL+7,"mouse2 8 d"},
382 
383   {KEY_JOY0BUT0, "Joy0 b0"},
384   {KEY_JOY0BUT1, "Joy0 b1"},
385   {KEY_JOY0BUT2, "Joy0 b2"},
386   {KEY_JOY0BUT3, "Joy0 b3"},
387   {KEY_JOY0BUT4, "Joy0 b4"},
388   {KEY_JOY0BUT5, "Joy0 b5"},
389   {KEY_JOY0BUT6, "Joy0 b6"},
390   {KEY_JOY0BUT7, "Joy0 b7"},
391   {KEY_JOY0BUT8, "Joy0 b8"},
392   {KEY_JOY0BUT9, "Joy0 b9"},
393   {KEY_JOY0BUT10, "Joy0 b10"},
394   {KEY_JOY0BUT11, "Joy0 b11"},
395   {KEY_JOY0BUT12, "Joy0 b12"},
396   {KEY_JOY0BUT13, "Joy0 b13"},
397   {KEY_JOY0BUT14, "Joy0 b14"},
398   {KEY_JOY0BUT15, "Joy0 b15"},
399 
400   {KEY_JOY1BUT0, "Joy1 b0"},
401   {KEY_JOY1BUT1, "Joy1 b1"},
402   {KEY_JOY1BUT2, "Joy1 b2"},
403   {KEY_JOY1BUT3, "Joy1 b3"},
404   {KEY_JOY1BUT4, "Joy1 b4"},
405   {KEY_JOY1BUT5, "Joy1 b5"},
406   {KEY_JOY1BUT6, "Joy1 b6"},
407   {KEY_JOY1BUT7, "Joy1 b7"},
408   {KEY_JOY1BUT8, "Joy1 b8"},
409   {KEY_JOY1BUT9, "Joy1 b9"},
410   {KEY_JOY1BUT10, "Joy1 b10"},
411   {KEY_JOY1BUT11, "Joy1 b11"},
412   {KEY_JOY1BUT12, "Joy1 b12"},
413   {KEY_JOY1BUT13, "Joy1 b13"},
414   {KEY_JOY1BUT14, "Joy1 b14"},
415   {KEY_JOY1BUT15, "Joy1 b15"},
416 
417   {KEY_JOY2BUT0, "Joy2 b0"},
418   {KEY_JOY2BUT1, "Joy2 b1"},
419   {KEY_JOY2BUT2, "Joy2 b2"},
420   {KEY_JOY2BUT3, "Joy2 b3"},
421   {KEY_JOY2BUT4, "Joy2 b4"},
422   {KEY_JOY2BUT5, "Joy2 b5"},
423   {KEY_JOY2BUT6, "Joy2 b6"},
424   {KEY_JOY2BUT7, "Joy2 b7"},
425   {KEY_JOY2BUT8, "Joy2 b8"},
426   {KEY_JOY2BUT9, "Joy2 b9"},
427   {KEY_JOY2BUT10, "Joy2 b10"},
428   {KEY_JOY2BUT11, "Joy2 b11"},
429   {KEY_JOY2BUT12, "Joy2 b12"},
430   {KEY_JOY2BUT13, "Joy2 b13"},
431   {KEY_JOY2BUT14, "Joy2 b14"},
432   {KEY_JOY2BUT15, "Joy2 b15"},
433 
434   {KEY_JOY3BUT0, "Joy3 b0"},
435   {KEY_JOY3BUT1, "Joy3 b1"},
436   {KEY_JOY3BUT2, "Joy3 b2"},
437   {KEY_JOY3BUT3, "Joy3 b3"},
438   {KEY_JOY3BUT4, "Joy3 b4"},
439   {KEY_JOY3BUT5, "Joy3 b5"},
440   {KEY_JOY3BUT6, "Joy3 b6"},
441   {KEY_JOY3BUT7, "Joy3 b7"},
442   {KEY_JOY3BUT8, "Joy3 b8"},
443   {KEY_JOY3BUT9, "Joy3 b9"},
444   {KEY_JOY3BUT10, "Joy3 b10"},
445   {KEY_JOY3BUT11, "Joy3 b11"},
446   {KEY_JOY3BUT12, "Joy3 b12"},
447   {KEY_JOY3BUT13, "Joy3 b13"},
448   {KEY_JOY3BUT14, "Joy3 b14"},
449   {KEY_JOY3BUT15, "Joy3 b15"},
450 
451   {KEY_JOY0HATUP, "Joy0 hu"},
452   {KEY_JOY0HATRIGHT, "Joy0 hr"},
453   {KEY_JOY0HATDOWN, "Joy0 hd"},
454   {KEY_JOY0HATLEFT, "Joy0 hl"},
455 
456   {KEY_JOY1HATUP, "Joy1 hu"},
457   {KEY_JOY1HATRIGHT, "Joy1 hr"},
458   {KEY_JOY1HATDOWN, "Joy1 hd"},
459   {KEY_JOY1HATLEFT, "Joy1 hl"},
460 
461   {KEY_JOY2HATUP, "Joy2 hu"},
462   {KEY_JOY2HATRIGHT, "Joy2 hr"},
463   {KEY_JOY2HATDOWN, "Joy2 hd"},
464   {KEY_JOY2HATLEFT, "Joy2 hl"},
465 
466   {KEY_JOY3HATUP, "Joy3 hu"},
467   {KEY_JOY3HATRIGHT, "Joy3 hr"},
468   {KEY_JOY3HATDOWN, "Joy3 hd"},
469   {KEY_JOY3HATLEFT, "Joy3 hl"},
470 
471   {KEY_JOY0LEFTTRIGGER, "Joy0 lt"},
472   {KEY_JOY0RIGHTTRIGGER, "Joy0 rt"},
473 
474   {KEY_JOY1LEFTTRIGGER, "Joy1 lt"},
475   {KEY_JOY1RIGHTTRIGGER, "Joy1 rt"},
476 
477   {KEY_JOY2LEFTTRIGGER, "Joy2 lt"},
478   {KEY_JOY2RIGHTTRIGGER, "Joy2 rt"},
479 
480   {KEY_JOY3LEFTTRIGGER, "Joy3 lt"},
481   {KEY_JOY3RIGHTTRIGGER, "Joy3 rt"},
482 };
483 
484 // Index gamecontrols_e
485 char *gamecontrolname[num_gamecontrols] =
486 {
487     "nothing",        //a key/button mapped to gc_null has no effect
488     "forward",
489     "backward",
490     "strafe",
491     "straferight",
492     "strafeleft",
493     "speed",
494     "turnleft",
495     "turnright",
496     "fire",
497     "use",
498     "lookup",
499     "lookdown",
500     "centerview",
501     "mouseaiming",
502     "weapon1",
503     "weapon2",
504     "weapon3",
505     "weapon4",
506     "weapon5",
507     "weapon6",
508     "weapon7",
509     "weapon8",
510     "talkkey",
511     "scores",
512     "jump",
513     "console",
514     "nextweapon",
515     "prevweapon",
516     "bestweapon",
517     "inventorynext",
518     "inventoryprev",
519     "inventoryuse",
520     "down",
521     "screenshot",
522 // Mouse and joystick only, Fixed assignment for keyboard.
523     "menuesc",  // joystick enter menu, and menu escape key
524     "pause",
525     "automap",
526 };
527 
528 #define NUMKEYNAMES (sizeof(keynames)/sizeof(keyname_t))
529 
530 //
531 //  Detach any keys associated to the given game control
532 //  - pass the pointer to the gamecontrol table for the player being edited
G_Clear_ControlKeys(int (* setupcontrols)[2],int control)533 void  G_Clear_ControlKeys (int (*setupcontrols)[2], int control)
534 {
535     setupcontrols[control][0] = KEY_NULL;
536     setupcontrols[control][1] = KEY_NULL;
537 }
538 
539 //
540 //  Returns the name of a key (or virtual key for mouse and joy)
541 //  the input value being an keynum
542 //
G_KeynumToString(int keynum)543 char* G_KeynumToString (int keynum)
544 {
545 static char keynamestr[8];
546 
547     int    j;
548 
549     // return a string with the ascii char if displayable
550     if (keynum>' ' && keynum<='z' && keynum!=KEY_CONSOLE)
551     {
552         keynamestr[0] = keynum;
553         keynamestr[1] = '\0';
554         return keynamestr;
555     }
556 
557     // find a description for special keys
558     for (j=0;j<NUMKEYNAMES;j++)
559     {
560         if (keynames[j].keynum==keynum)
561             return keynames[j].name;
562     }
563 
564     // create a name for Unknown key
565     sprintf(keynamestr,"key%d",keynum);
566     return keynamestr;
567 }
568 
569 
G_KeyStringtoNum(char * keystr)570 int G_KeyStringtoNum(char *keystr)
571 {
572     int j;
573     int len = strlen(keystr);
574     byte stat = 0;
575 
576 
577     if(keystr[1]==0 && keystr[0]>' ' && keystr[0]<='z')
578         return keystr[0];
579 
580   retry_search:
581     // caseless comparison, uppercase or lowercase input will work
582     for (j=0; j<NUMKEYNAMES; j++)
583     {
584         if (strcasecmp(keynames[j].name,keystr)==0)
585             return keynames[j].keynum;
586     }
587 
588     // failed, try to change _ to space
589     if( stat == 0 )
590     {
591         // [WDJ] Got tired trying to fix bugs about a quoted button name
592         // within a the quoted script string like alias.
593         // Let them specify the button name with underlines and we will
594         // equate it to the name with spaces, and it does not require those
595         // escaped quotes.
596         //   mouse_3  --> "mouse 3"
597         for (j=0; j<len; j++ )
598         {
599             if ( keystr[j] == '_' )
600             {
601                 keystr[j] = ' ';
602                 stat = 1;
603             }
604         }
605         if ( stat )   goto retry_search;  // found some '_', try it again
606     }
607     // not found, try to interpret it as a number
608 
609     if(strlen(keystr)>3)
610         return atoi(&keystr[3]);
611 
612     return 0;
613 }
614 
615 
G_Controldefault(void)616 void G_Controldefault(void)
617 {
618     gamecontrol[gc_forward    ][0]=KEY_UPARROW;
619     gamecontrol[gc_forward    ][1]=KEY_MOUSE1+2;
620     gamecontrol[gc_backward   ][0]=KEY_DOWNARROW;
621     gamecontrol[gc_strafe     ][0]=KEY_LALT;
622     gamecontrol[gc_strafe     ][1]=KEY_MOUSE1+1;
623     gamecontrol[gc_straferight][0]='.';
624     gamecontrol[gc_strafeleft ][0]=',';
625     gamecontrol[gc_speed      ][0]=KEY_LSHIFT;
626     gamecontrol[gc_turnleft   ][0]=KEY_LEFTARROW;
627     gamecontrol[gc_turnright  ][0]=KEY_RIGHTARROW;
628     gamecontrol[gc_fire       ][0]=KEY_RCTRL;
629     gamecontrol[gc_fire       ][1]=KEY_MOUSE1;
630     gamecontrol[gc_use        ][0]=KEY_SPACE;
631     gamecontrol[gc_lookup     ][0]=KEY_PGUP;
632     gamecontrol[gc_lookdown   ][0]=KEY_PGDN;
633     gamecontrol[gc_centerview ][0]=KEY_END;
634     gamecontrol[gc_mouseaiming][0]='s';
635     gamecontrol[gc_weapon1    ][0]='1';
636     gamecontrol[gc_weapon2    ][0]='2';
637     gamecontrol[gc_weapon3    ][0]='3';
638     gamecontrol[gc_weapon4    ][0]='4';
639     gamecontrol[gc_weapon5    ][0]='5';
640     gamecontrol[gc_weapon6    ][0]='6';
641     gamecontrol[gc_weapon7    ][0]='7';
642     gamecontrol[gc_weapon8    ][0]='8';
643     gamecontrol[gc_talkkey    ][0]='t';
644     gamecontrol[gc_scores     ][0]='f';
645     gamecontrol[gc_jump       ][0]='/';
646     gamecontrol[gc_console    ][0]=KEY_CONSOLE;
647     //gamecontrol[gc_nextweapon ][1]=KEY_JOY0BUT4;
648     //gamecontrol[gc_prevweapon ][1]=KEY_JOY0BUT5;
649     gamecontrol[gc_screenshot ][0]=KEY_SYSREQ;
650 
651     if( gamemode == heretic )
652     {
653         gamecontrol[gc_invnext    ][0] = ']';
654         gamecontrol[gc_invprev    ][0] = '[';
655         gamecontrol[gc_invuse     ][0] = KEY_ENTER;
656         gamecontrol[gc_jump       ][0] = KEY_INS;
657         gamecontrol[gc_flydown    ][0] = KEY_DELETE;
658     }
659     else
660     {
661         gamecontrol[gc_nextweapon ][0]=']';
662         gamecontrol[gc_prevweapon ][0]='[';
663     }
664 
665 // Mouse and joystick only, Fixed assignment for keyboard.
666     gamecontrol[gc_menuesc    ][0]=KEY_JOY0BUT7; // Start button on Xbox360 controllers
667     gamecontrol[gc_pause      ][0]=KEY_JOY0BUT6; // Back button on Xbox360 controllers
668     gamecontrol[gc_automap    ][0]=KEY_JOY0BUT8;
669 }
670 
G_SaveKeySetting(FILE * f)671 void G_SaveKeySetting(FILE *f)
672 {
673     int i;
674 
675     for(i=1;i<num_gamecontrols;i++)
676     {
677         fprintf(f,"setcontrol \"%s\" \"%s\"",
678                 gamecontrolname[i],
679                 G_KeynumToString(gamecontrol[i][0]));
680 
681         if(gamecontrol[i][1])
682             fprintf(f," \"%s\"\n",
683                         G_KeynumToString(gamecontrol[i][1]));
684         else
685             fprintf(f,"\n");
686     }
687 
688     for(i=1;i<num_gamecontrols;i++)
689     {
690         fprintf(f, "setcontrol2 \"%s\" \"%s\"",
691                 gamecontrolname[i],
692                 G_KeynumToString(gamecontrol2[i][0]));
693 
694         if(gamecontrol2[i][1])
695             fprintf(f, " \"%s\"\n",
696                     G_KeynumToString(gamecontrol2[i][1]));
697         else
698             fprintf(f,"\n");
699     }
700 
701     // Writes the joystick axis binding commands to the config file.
702     for (i=0; i<num_joybindings; i++)
703     {
704         joybinding_t j = joybindings[i];
705         fprintf(f, "bindjoyaxis %d %d %d %d %f\n",
706                 j.joynum, j.axisnum, j.playnum, (int)(j.action), j.scale);
707     }
708 }
709 
G_CheckDoubleUsage(int keynum)710 void G_CheckDoubleUsage(int keynum)
711 {
712     if( cv_controlperkey.value==1 )
713     {
714         int i;
715         for(i=0;i<num_gamecontrols;i++)
716         {
717             if( gamecontrol[i][0]==keynum )
718                 gamecontrol[i][0]= KEY_NULL;
719             if( gamecontrol[i][1]==keynum )
720                 gamecontrol[i][1]= KEY_NULL;
721             if( gamecontrol2[i][0]==keynum )
722                 gamecontrol2[i][0]= KEY_NULL;
723             if( gamecontrol2[i][1]==keynum )
724                 gamecontrol2[i][1]= KEY_NULL;
725         }
726     }
727 }
728 
729 static
setcontrol(int (* gc)[2],const char * cstr)730 void setcontrol(int (*gc)[2], const char * cstr)
731 {
732     int numctrl;
733     char *namectrl;
734     int keynum;
735     COM_args_t  carg;
736 
737     COM_Args( &carg );
738 
739     if ( carg.num!= 3 && carg.num!=4 )
740     {
741         CONS_Printf ("setcontrol%s <controlname> <keyname> [<2nd keyname>]\n", cstr);
742         return;
743     }
744 
745     namectrl=carg.arg[1];
746     for(numctrl=0;numctrl<num_gamecontrols
747                   && strcasecmp(namectrl,gamecontrolname[numctrl])
748                  ;numctrl++);
749     if(numctrl==num_gamecontrols)
750     {
751         CONS_Printf("Control '%s' unknown\n",namectrl);
752         return;
753     }
754     keynum=G_KeyStringtoNum(carg.arg[2]);
755     G_CheckDoubleUsage(keynum);
756     gc[numctrl][0]=keynum;
757 
758     if(carg.num==4)
759         gc[numctrl][1]=G_KeyStringtoNum(carg.arg[3]);
760     else
761         gc[numctrl][1]=0;
762 }
763 
Command_Setcontrol_f(void)764 void Command_Setcontrol_f(void)
765 {
766     setcontrol(gamecontrol, "");
767 }
768 
Command_Setcontrol2_f(void)769 void Command_Setcontrol2_f(void)
770 {
771     setcontrol(gamecontrol2, "2");
772 }
773 
774 
775 
776 //! Magically converts a console command to a joystick axis binding. Also releases bindings.
Command_BindJoyaxis_f()777 void Command_BindJoyaxis_f()
778 {
779   joybinding_t j;
780   unsigned int i;
781   COM_args_t  carg;
782 
783   COM_Args( &carg );
784 
785   if(carg.num == 1)
786   { // Print bindings.
787     CONS_Printf("%d joysticks found.\n", num_joysticks);
788     if(num_joybindings == 0) {
789       CONS_Printf("No joystick axis bindings defined.\n");
790       return;
791     }
792     CONS_Printf("Current axis bindings.\n");
793     for(i=0; i<num_joybindings; i++) {
794       j = joybindings[i];
795       CONS_Printf("%d %d %d %d %f\n", j.joynum, j.axisnum,
796                   j.playnum, (int)j.action, j.scale);
797     }
798     return;
799   }
800 
801   if (carg.num == 4 || carg.num > 6)
802   {
803     CONS_Printf("bindjoyaxis [joynum] [axisnum] [playnum] [action] [scale]  to bind\n"
804                 "bindjoyaxis [joynum] [axisnum]  to unbind\n");
805     return;
806   }
807 
808   j.joynum  = atoi( carg.arg[1] );
809   if(j.joynum < 0 || j.joynum >= num_joysticks)
810   {
811     CONS_Printf("Attempting to bind/release non-existent joystick %d.\n", j.joynum);
812     return;
813   }
814 
815   j.axisnum = (carg.num >= 3) ? atoi( carg.arg[2] ) : -1;
816   if(j.axisnum < -1 || j.axisnum >= I_JoystickNumAxes(j.joynum))
817   {
818     CONS_Printf("Attempting to bind/release non-existent axis %d.\n", j.axisnum);
819     return;
820   }
821 
822   if (carg.num == 3)
823   { // release binding(s)
824     /* Takes one or two parameters. The first one is the joystick number
825        and the second is the axis number. If either is not specified, all
826        values are assumed to match.
827     */
828 
829     int num_keep_bindings = 0;
830     joybinding_t keep_bindings[MAX_JOYBINDINGS];
831 
832     if(num_joybindings == 0)
833     {
834       CONS_Printf("No bindings to unset.\n");
835       return;
836     }
837 
838     unsigned int i;
839     for(i=0; i<num_joybindings; i++)
840     {
841       joybinding_t temp = joybindings[i];
842       if((j.joynum == temp.joynum) &&
843          (j.axisnum == -1 || j.axisnum == temp.axisnum))
844         continue; // We have a binding to prune.
845 
846       keep_bindings[num_keep_bindings++] = temp; // keep it
847     }
848 
849     // We have the new bindings.
850     if (num_keep_bindings == num_joybindings)
851     {
852       CONS_Printf("No bindings matched the parameters.\n");
853       return;
854     }
855 
856     // replace the bindings
857     num_joybindings = num_keep_bindings;
858     for(i=0; i<num_keep_bindings; i++)
859       joybindings[i] = keep_bindings[i];
860   }
861   else
862   { // create a binding
863     j.playnum = atoi( carg.arg[3] );
864     // carg.arg[0..3] only, use COM_Argv for others
865     j.action  = (joyactions_e)(atoi(COM_Argv(4)));
866     if (carg.num == 6)
867       j.scale = atof(COM_Argv(5));
868     else
869       j.scale = 1.0f;
870 
871     if(j.action < 0 || j.action >= num_joyactions)
872     {
873       CONS_Printf("Attempting to bind non-existent action %d.\n", (int)(j.action));
874       return;
875     }
876 
877     // Overwrite existing binding, if any. Otherwise just append.
878     for(i=0; i<num_joybindings; i++)
879     {
880       joybinding_t j2 = joybindings[i];
881       if(j2.joynum == j.joynum && j2.axisnum == j.axisnum)
882       {
883         joybindings[i] = j;
884         CONS_Printf("Joystick binding modified.\n");
885         return;
886       }
887     }
888     // new binding
889     if (num_joybindings < MAX_JOYBINDINGS)
890     {
891         joybindings[num_joybindings++] = j;
892         CONS_Printf("Joystick binding added.\n");
893     }
894     else
895       CONS_Printf("Maximum number of joystick bindings reached.\n");
896   }
897 }
898