+/////////////////////
+// Joystick axis keyevents
+// a sort of hack emulating Arrow keys for joystick axises
+// as some drives dont send such keyevents for them
+// additionally we should block drivers that do send arrow keyevents to prevent double events
+////
+
+static void IN_JoystickKeyeventForAxis(SDL_Joystick *joy, int axis, int key_pos, int key_neg)
+{
+ double joytime;
+
+ if (axis < 0 || axis >= SDL_JoystickNumAxes(joy))
+ return; // no such axis on this joystick
+
+ joytime = Sys_DoubleTime();
+ // no key event, continuous keydown event
+ if (joy_axescache[axis].move == joy_axescache[axis].oldmove)
+ {
+ if (joy_axescache[axis].move != 0 && joytime > joy_axescache[axis].keytime)
+ {
+ //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].move > 0) ? key_pos : key_neg), 1, cl.time);
+ Key_Event((joy_axescache[axis].move > 0) ? key_pos : key_neg, 0, 1);
+ joy_axescache[axis].keytime = joytime + 0.5 / 20;
+ }
+ return;
+ }
+ // generate key up event
+ if (joy_axescache[axis].oldmove)
+ {
+ //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].oldmove > 0) ? key_pos : key_neg), 1, cl.time);
+ Key_Event((joy_axescache[axis].oldmove > 0) ? key_pos : key_neg, 0, 0);
+ }
+ // generate key down event
+ if (joy_axescache[axis].move)
+ {
+ //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].move > 0) ? key_pos : key_neg), 1, cl.time);
+ Key_Event((joy_axescache[axis].move > 0) ? key_pos : key_neg, 0, 1);
+ joy_axescache[axis].keytime = joytime + 0.5;
+ }
+}
+
+static qboolean IN_JoystickBlockDoubledKeyEvents(int keycode)
+{
+ if (!joy_axiskeyevents.integer)
+ return false;
+
+ // block keyevent if it's going to be provided by joystick keyevent system
+ if (vid_numjoysticks && joy_enable.integer && joy_index.integer >= 0 && joy_index.integer < vid_numjoysticks)
+ {
+ SDL_Joystick *joy = vid_joysticks[joy_index.integer];
+
+ if (keycode == K_UPARROW || keycode == K_DOWNARROW)
+ if (IN_JoystickGetAxis(joy, joy_axisforward.integer, 1, 0.01) || joy_axescache[joy_axisforward.integer].move || joy_axescache[joy_axisforward.integer].oldmove)
+ return true;
+ if (keycode == K_RIGHTARROW || keycode == K_LEFTARROW)
+ if (IN_JoystickGetAxis(joy, joy_axisside.integer, 1, 0.01) || joy_axescache[joy_axisside.integer].move || joy_axescache[joy_axisside.integer].oldmove)
+ return true;
+ }
+
+ return false;
+}
+
+/////////////////////
+// Movement handling
+////
+