/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
Grafx2 is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
of the License.
Grafx2 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Grafx2; if not, see
*/
#include
#include
#ifdef __WIN32__
#include
#include
#endif
#include "global.h"
#include "keyboard.h"
#include "sdlscreen.h"
#include "windows.h"
#include "errors.h"
#include "misc.h"
#include "buttons.h"
#include "input.h"
#include "loadsave.h"
#define RSUPER_EMULATES_META_MOD
// Keyboards with a Super key never seem to have a Meta key at the same time.
// This setting allows the right 'Super' key (the one with a 'Windows' or
// 'Amiga' label to be used as a modifier instead of a normal key.
// This feature is especially useful for AROS where applications should use
// generic defaults like "Right Amiga+Q = Quit".
// In case this is annoying for some platforms, disable it.
#endif
void Handle_window_resize(SDL_ResizeEvent event);
void Handle_window_exit(SDL_QuitEvent event);
int Color_cycling(void);
// public Globals (available as extern)
int Input_sticky_control = 0;
int Snap_axis = 0;
int Snap_axis_origin_X;
int Snap_axis_origin_Y;
char * Drop_file_name = NULL;
// --
// Digital joystick state
byte Directional_up;
byte Directional_up_right;
byte Directional_right;
byte Directional_down_right;
byte Directional_down;
byte Directional_down_left;
byte Directional_left;
byte Directional_up_left;
byte Directional_click;
// Emulated directional controller.
// This has a distinct state from Directional_, because some joysticks send
// "I'm not moving" SDL events when idle, thus stopping the emulated one.
byte Directional_emulated_up;
byte Directional_emulated_right;
byte Directional_emulated_down;
byte Directional_emulated_left;
long Directional_first_move;
long Directional_last_move;
int Mouse_moved; ///< Boolean, Set to true if any cursor movement occurs.
word Input_new_mouse_X;
word Input_new_mouse_Y;
byte Input_new_mouse_K;
byte Button_inverter=0; // State of the key that swaps mouse buttons.
byte Pan_shortcut_pressed;
// Joystick/pad configurations for the various console ports.
// See the #else for the documentation of fields.
// TODO: Make these user-settable somehow.
#if defined(__GP2X__)
#define JOYSTICK_THRESHOLD (4096)
short Joybutton_shift= JOY_BUTTON_L;
short Joybutton_control= JOY_BUTTON_R;
short Joybutton_alt= JOY_BUTTON_CLICK;
short Joybutton_left_click= JOY_BUTTON_B;
short Joybutton_right_click=JOY_BUTTON_Y;
#elif defined(__WIZ__)
#define JOYSTICK_THRESHOLD (4096)
short Joybutton_shift= JOY_BUTTON_X;
short Joybutton_control= JOY_BUTTON_SELECT;
short Joybutton_alt= JOY_BUTTON_Y;
short Joybutton_left_click= JOY_BUTTON_A;
short Joybutton_right_click=JOY_BUTTON_B;
#elif defined(__CAANOO__)
#define JOYSTICK_THRESHOLD (4096)
short Joybutton_shift= JOY_BUTTON_L;
short Joybutton_control= JOY_BUTTON_R;
short Joybutton_alt= JOY_BUTTON_Y;
short Joybutton_left_click= JOY_BUTTON_A;
short Joybutton_right_click=JOY_BUTTON_B;
#else // Default : Any joystick on a computer platform
///
/// This is the sensitivity threshold for the directional
/// pad of a cheap digital joypad on the PC. It has been set through
/// trial and error : If value is too large then the movement is
/// randomly interrupted; if the value is too low the cursor will
/// move by itself, controlled by parasits.
/// YR 04/11/2010: I just observed a -8700 when joystick is idle.
#define JOYSTICK_THRESHOLD (10000)
/// A button that is marked as "modifier" will
short Joybutton_shift=-1; ///< Button number that serves as a "shift" modifier; -1 for none
short Joybutton_control=-1; ///< Button number that serves as a "ctrl" modifier; -1 for none
short Joybutton_alt=-1; ///< Button number that serves as a "alt" modifier; -1 for none
short Joybutton_left_click=0; ///< Button number that serves as left click; -1 for none
short Joybutton_right_click=1; ///< Button number that serves as right-click; -1 for none
#endif
int Has_shortcut(word function)
{
if (function == 0xFFFF)
return 0;
if (function & 0x100)
{
if (Buttons_Pool[function&0xFF].Left_shortcut[0]!=KEY_NONE)
return 1;
if (Buttons_Pool[function&0xFF].Left_shortcut[1]!=KEY_NONE)
return 1;
return 0;
}
if (function & 0x200)
{
if (Buttons_Pool[function&0xFF].Right_shortcut[0]!=KEY_NONE)
return 1;
if (Buttons_Pool[function&0xFF].Right_shortcut[1]!=KEY_NONE)
return 1;
return 0;
}
if(Config_Key[function][0]!=KEY_NONE)
return 1;
if(Config_Key[function][1]!=KEY_NONE)
return 1;
return 0;
}
int Is_shortcut(word key, word function)
{
if (key == 0 || function == 0xFFFF)
return 0;
if (function & 0x100)
{
if (Buttons_Pool[function&0xFF].Left_shortcut[0]==key)
return 1;
if (Buttons_Pool[function&0xFF].Left_shortcut[1]==key)
return 1;
return 0;
}
if (function & 0x200)
{
if (Buttons_Pool[function&0xFF].Right_shortcut[0]==key)
return 1;
if (Buttons_Pool[function&0xFF].Right_shortcut[1]==key)
return 1;
return 0;
}
if(key == Config_Key[function][0])
return 1;
if(key == Config_Key[function][1])
return 1;
return 0;
}
// Called each time there is a cursor move, either triggered by mouse or keyboard shortcuts
int Move_cursor_with_constraints()
{
int feedback=0;
int mouse_blocked=0; ///< Boolean, Set to true if mouse movement was clipped.
// Clip mouse to the editing area. There can be a border when using big
// pixels, if the SDL screen dimensions are not factors of the pixel size.
if (Input_new_mouse_Y>=Screen_height)
{
Input_new_mouse_Y=Screen_height-1;
mouse_blocked=1;
}
if (Input_new_mouse_X>=Screen_width)
{
Input_new_mouse_X=Screen_width-1;
mouse_blocked=1;
}
//Gestion "avancée" du curseur: interdire la descente du curseur dans le
//menu lorsqu'on est en train de travailler dans l'image
if (Operation_stack_size != 0)
{
//Si le curseur ne se trouve plus dans l'image
if(Menu_Y<=Input_new_mouse_Y)
{
//On bloque le curseur en fin d'image
mouse_blocked=1;
Input_new_mouse_Y=Menu_Y-1; //La ligne !!au-dessus!! du menu
}
if(Main_magnifier_mode)
{
if(Operation_in_magnifier==0)
{
if(Input_new_mouse_X>=Main_separator_position)
{
mouse_blocked=1;
Input_new_mouse_X=Main_separator_position-1;
}
}
else
{
if(Input_new_mouse_X Config.Mouse_merge_movement
&& !Operation[Current_operation][Mouse_K_unique]
[Operation_stack_size].Fast_mouse)
feedback=1;
}
if (mouse_blocked)
Set_mouse_position();
return feedback;
}
// WM events management
void Handle_window_resize(SDL_ResizeEvent event)
{
Resize_width = event.w;
Resize_height = event.h;
}
void Handle_window_exit(SDL_QuitEvent event)
{
(void)event, // unused
Quit_is_required = 1;
}
// Mouse events management
int Handle_mouse_move(SDL_MouseMotionEvent event)
{
Input_new_mouse_X = event.x/Pixel_width;
Input_new_mouse_Y = event.y/Pixel_height;
return Move_cursor_with_constraints();
}
int Handle_mouse_click(SDL_MouseButtonEvent event)
{
switch(event.button)
{
case SDL_BUTTON_LEFT:
if (Button_inverter)
Input_new_mouse_K |= 2;
else
Input_new_mouse_K |= 1;
break;
break;
case SDL_BUTTON_RIGHT:
if (Button_inverter)
Input_new_mouse_K |= 1;
else
Input_new_mouse_K |= 2;
break;
break;
case SDL_BUTTON_MIDDLE:
Key = KEY_MOUSEMIDDLE|Key_modifiers(SDL_GetModState());
// TODO: repeat system maybe?
return 0;
case SDL_BUTTON_WHEELUP:
Key = KEY_MOUSEWHEELUP|Key_modifiers(SDL_GetModState());
return 0;
case SDL_BUTTON_WHEELDOWN:
Key = KEY_MOUSEWHEELDOWN|Key_modifiers(SDL_GetModState());
return 0;
default:
return 0;
}
return Move_cursor_with_constraints();
}
int Handle_mouse_release(SDL_MouseButtonEvent event)
{
switch(event.button)
{
case SDL_BUTTON_LEFT:
if (Button_inverter)
Input_new_mouse_K &= ~2;
else
Input_new_mouse_K &= ~1;
break;
case SDL_BUTTON_RIGHT:
if (Button_inverter)
Input_new_mouse_K &= ~1;
else
Input_new_mouse_K &= ~2;
break;
}
return Move_cursor_with_constraints();
}
// Keyboard management
int Handle_key_press(SDL_KeyboardEvent event)
{
//Appui sur une touche du clavier
int modifier;
Key = Keysym_to_keycode(event.keysym);
Key_ANSI = Keysym_to_ANSI(event.keysym);
switch(event.keysym.sym)
{
case SDLK_RSHIFT:
case SDLK_LSHIFT:
modifier=MOD_SHIFT;
break;
case SDLK_RCTRL:
case SDLK_LCTRL:
modifier=MOD_CTRL;
break;
case SDLK_RALT:
case SDLK_LALT:
case SDLK_MODE:
modifier=MOD_ALT;
break;
case SDLK_RMETA:
case SDLK_LMETA:
modifier=MOD_META;
break;
default:
modifier=0;
}
if (Config.Swap_buttons && modifier == Config.Swap_buttons && Button_inverter==0)
{
Button_inverter=1;
if (Input_new_mouse_K)
{
Input_new_mouse_K ^= 3; // Flip bits 0 and 1
return Move_cursor_with_constraints();
}
}
#ifdef RSUPER_EMULATES_META_MOD
if (Key==SDLK_RSUPER)
{
SDL_SetModState(SDL_GetModState() | KMOD_META);
Key=0;
}
#endif
if(Is_shortcut(Key,SPECIAL_MOUSE_UP))
{
Directional_emulated_up=1;
return 0;
}
else if(Is_shortcut(Key,SPECIAL_MOUSE_DOWN))
{
Directional_emulated_down=1;
return 0;
}
else if(Is_shortcut(Key,SPECIAL_MOUSE_LEFT))
{
Directional_emulated_left=1;
return 0;
}
else if(Is_shortcut(Key,SPECIAL_MOUSE_RIGHT))
{
Directional_emulated_right=1;
return 0;
}
else if(Is_shortcut(Key,SPECIAL_CLICK_LEFT) && Keyboard_click_allowed > 0)
{
Input_new_mouse_K=1;
Directional_click=1;
return Move_cursor_with_constraints();
}
else if(Is_shortcut(Key,SPECIAL_CLICK_RIGHT) && Keyboard_click_allowed > 0)
{
Input_new_mouse_K=2;
Directional_click=2;
return Move_cursor_with_constraints();
}
else if(Is_shortcut(Key,SPECIAL_HOLD_PAN))
{
Pan_shortcut_pressed=1;
return 0;
}
return 0;
}
int Release_control(int key_code, int modifier)
{
int need_feedback = 0;
if (modifier == MOD_SHIFT)
{
// Disable "snap axis" mode
Snap_axis = 0;
need_feedback = 1;
}
if (Config.Swap_buttons && modifier == Config.Swap_buttons && Button_inverter==1)
{
Button_inverter=0;
if (Input_new_mouse_K)
{
Input_new_mouse_K ^= 3; // Flip bits 0 and 1
return Move_cursor_with_constraints();
}
}
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_UP][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_UP][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_UP][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_UP][1]&modifier))
{
Directional_emulated_up=0;
}
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_DOWN][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_DOWN][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_DOWN][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_DOWN][1]&modifier))
{
Directional_emulated_down=0;
}
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_LEFT][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_LEFT][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_LEFT][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_LEFT][1]&modifier))
{
Directional_emulated_left=0;
}
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_RIGHT][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_RIGHT][1]&modifier))
{
Directional_emulated_right=0;
}
if((key_code && key_code == (Config_Key[SPECIAL_CLICK_LEFT][0]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_LEFT][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_CLICK_LEFT][1]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_LEFT][1]&modifier))
{
if (Directional_click & 1)
{
Directional_click &= ~1;
Input_new_mouse_K &= ~1;
return Move_cursor_with_constraints() || need_feedback;
}
}
if((key_code && key_code == (Config_Key[SPECIAL_CLICK_RIGHT][0]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_RIGHT][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_CLICK_RIGHT][1]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_RIGHT][1]&modifier))
{
if (Directional_click & 2)
{
Directional_click &= ~2;
Input_new_mouse_K &= ~2;
return Move_cursor_with_constraints() || need_feedback;
}
}
if((key_code && key_code == (Config_Key[SPECIAL_HOLD_PAN][0]&0x0FFF)) || (Config_Key[SPECIAL_HOLD_PAN][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_HOLD_PAN][1]&0x0FFF)) || (Config_Key[SPECIAL_HOLD_PAN][1]&modifier))
{
Pan_shortcut_pressed=0;
need_feedback = 1;
}
// Other keys don't need to be released : they are handled as "events" and procesed only once.
// These clicks are apart because they need to be continuous (ie move while key pressed)
// We are relying on "hardware" keyrepeat to achieve that.
return need_feedback;
}
int Handle_key_release(SDL_KeyboardEvent event)
{
int modifier;
int released_key = Keysym_to_keycode(event.keysym) & 0x0FFF;
switch(event.keysym.sym)
{
case SDLK_RSHIFT:
case SDLK_LSHIFT:
modifier=MOD_SHIFT;
break;
case SDLK_RCTRL:
case SDLK_LCTRL:
modifier=MOD_CTRL;
break;
case SDLK_RALT:
case SDLK_LALT:
case SDLK_MODE:
modifier=MOD_ALT;
break;
#ifdef RSUPER_EMULATES_META_MOD
case SDLK_RSUPER:
SDL_SetModState(SDL_GetModState() & ~KMOD_META);
modifier=MOD_META;
break;
#endif
case SDLK_RMETA:
case SDLK_LMETA:
modifier=MOD_META;
break;
default:
modifier=0;
}
return Release_control(released_key, modifier);
}
// Joystick management
int Handle_joystick_press(SDL_JoyButtonEvent event)
{
if (event.button == Joybutton_shift)
{
SDL_SetModState(SDL_GetModState() | KMOD_SHIFT);
return 0;
}
if (event.button == Joybutton_control)
{
SDL_SetModState(SDL_GetModState() | KMOD_CTRL);
if (Config.Swap_buttons == MOD_CTRL && Button_inverter==0)
{
Button_inverter=1;
if (Input_new_mouse_K)
{
Input_new_mouse_K ^= 3; // Flip bits 0 and 1
return Move_cursor_with_constraints();
}
}
return 0;
}
if (event.button == Joybutton_alt)
{
SDL_SetModState(SDL_GetModState() | (KMOD_ALT|KMOD_META));
if (Config.Swap_buttons == MOD_ALT && Button_inverter==0)
{
Button_inverter=1;
if (Input_new_mouse_K)
{
Input_new_mouse_K ^= 3; // Flip bits 0 and 1
return Move_cursor_with_constraints();
}
}
return 0;
}
if (event.button == Joybutton_left_click)
{
Input_new_mouse_K = Button_inverter ? 2 : 1;
return Move_cursor_with_constraints();
}
if (event.button == Joybutton_right_click)
{
Input_new_mouse_K = Button_inverter ? 1 : 2;
return Move_cursor_with_constraints();
}
switch(event.button)
{
#ifdef JOY_BUTTON_UP
case JOY_BUTTON_UP:
Directional_up=1;
break;
#endif
#ifdef JOY_BUTTON_UPRIGHT
case JOY_BUTTON_UPRIGHT:
Directional_up_right=1;
break;
#endif
#ifdef JOY_BUTTON_RIGHT
case JOY_BUTTON_RIGHT:
Directional_right=1;
break;
#endif
#ifdef JOY_BUTTON_DOWNRIGHT
case JOY_BUTTON_DOWNRIGHT:
Directional_down_right=1;
break;
#endif
#ifdef JOY_BUTTON_DOWN
case JOY_BUTTON_DOWN:
Directional_down=1;
break;
#endif
#ifdef JOY_BUTTON_DOWNLEFT
case JOY_BUTTON_DOWNLEFT:
Directional_down_left=1;
break;
#endif
#ifdef JOY_BUTTON_LEFT
case JOY_BUTTON_LEFT:
Directional_left=1;
break;
#endif
#ifdef JOY_BUTTON_UPLEFT
case JOY_BUTTON_UPLEFT:
Directional_up_left=1;
break;
#endif
default:
break;
}
Key = (KEY_JOYBUTTON+event.button)|Key_modifiers(SDL_GetModState());
// TODO: systeme de répétition
return Move_cursor_with_constraints();
}
int Handle_joystick_release(SDL_JoyButtonEvent event)
{
if (event.button == Joybutton_shift)
{
SDL_SetModState(SDL_GetModState() & ~KMOD_SHIFT);
return Release_control(0,MOD_SHIFT);
}
if (event.button == Joybutton_control)
{
SDL_SetModState(SDL_GetModState() & ~KMOD_CTRL);
return Release_control(0,MOD_CTRL);
}
if (event.button == Joybutton_alt)
{
SDL_SetModState(SDL_GetModState() & ~(KMOD_ALT|KMOD_META));
return Release_control(0,MOD_ALT);
}
if (event.button == Joybutton_left_click)
{
Input_new_mouse_K &= ~1;
return Move_cursor_with_constraints();
}
if (event.button == Joybutton_right_click)
{
Input_new_mouse_K &= ~2;
return Move_cursor_with_constraints();
}
switch(event.button)
{
#ifdef JOY_BUTTON_UP
case JOY_BUTTON_UP:
Directional_up=1;
break;
#endif
#ifdef JOY_BUTTON_UPRIGHT
case JOY_BUTTON_UPRIGHT:
Directional_up_right=1;
break;
#endif
#ifdef JOY_BUTTON_RIGHT
case JOY_BUTTON_RIGHT:
Directional_right=1;
break;
#endif
#ifdef JOY_BUTTON_DOWNRIGHT
case JOY_BUTTON_DOWNRIGHT:
Directional_down_right=1;
break;
#endif
#ifdef JOY_BUTTON_DOWN
case JOY_BUTTON_DOWN:
Directional_down=1;
break;
#endif
#ifdef JOY_BUTTON_DOWNLEFT
case JOY_BUTTON_DOWNLEFT:
Directional_down_left=1;
break;
#endif
#ifdef JOY_BUTTON_LEFT
case JOY_BUTTON_LEFT:
Directional_left=1;
break;
#endif
#ifdef JOY_BUTTON_UPLEFT
case JOY_BUTTON_UPLEFT:
Directional_up_left=1;
break;
#endif
default:
break;
}
return Move_cursor_with_constraints();
}
void Handle_joystick_movement(SDL_JoyAxisEvent event)
{
if (event.axis==JOYSTICK_AXIS_X)
{
Directional_right=Directional_left=0;
if (event.value<-JOYSTICK_THRESHOLD)
{
Directional_left=1;
}
else if (event.value>JOYSTICK_THRESHOLD)
Directional_right=1;
}
else if (event.axis==JOYSTICK_AXIS_Y)
{
Directional_up=Directional_down=0;
if (event.value<-JOYSTICK_THRESHOLD)
{
Directional_up=1;
}
else if (event.value>JOYSTICK_THRESHOLD)
Directional_down=1;
}
}
// Attempts to move the mouse cursor by the given deltas (may be more than 1 pixel at a time)
int Cursor_displace(short delta_x, short delta_y)
{
short x=Input_new_mouse_X;
short y=Input_new_mouse_Y;
if(Main_magnifier_mode && Input_new_mouse_Y < Menu_Y && Input_new_mouse_X > Main_separator_position)
{
// Cursor in zoomed area
if (delta_x<0)
Input_new_mouse_X = Max(Main_separator_position, x-Main_magnifier_factor);
else if (delta_x>0)
Input_new_mouse_X = Min(Screen_width-1, x+Main_magnifier_factor);
if (delta_y<0)
Input_new_mouse_Y = Max(0, y-Main_magnifier_factor);
else if (delta_y>0)
Input_new_mouse_Y = Min(Screen_height-1, y+Main_magnifier_factor);
}
else
{
if (delta_x<0)
Input_new_mouse_X = Max(0, x+delta_x);
else if (delta_x>0)
Input_new_mouse_X = Min(Screen_width-1, x+delta_x);
if (delta_y<0)
Input_new_mouse_Y = Max(0, y+delta_y);
else if (delta_y>0)
Input_new_mouse_Y = Min(Screen_height-1, y+delta_y);
}
return Move_cursor_with_constraints();
}
// This function is the acceleration profile for directional (digital) cursor
// controllers.
int Directional_acceleration(int msec)
{
const int initial_delay = 250;
const int linear_factor = 200;
const int accel_factor = 10000;
// At beginning there is 1 pixel move, then nothing for N milliseconds
if (msecmsg == WM_DROPFILES)
{
int file_count;
HDROP hdrop = (HDROP)(event.syswm.msg->wParam);
if((file_count = DragQueryFile(hdrop,(UINT)-1,(LPTSTR) NULL ,(UINT) 0)) > 0)
{
long len;
// Query filename length
len = DragQueryFile(hdrop,0 ,NULL ,0);
if (len)
{
Drop_file_name=calloc(len+1,1);
if (Drop_file_name)
{
if (DragQueryFile(hdrop,0 ,(LPTSTR) Drop_file_name ,(UINT) MAX_PATH))
{
// Success
}
else
{
free(Drop_file_name);
// Don't report name copy error
}
}
else
{
// Don't report alloc error (for a file name? :/ )
}
}
else
{
// Don't report weird Windows error
}
}
else
{
// Drop of zero files. Thanks for the information, Bill.
}
}
#endif
break;
default:
//DEBUG("Unhandled SDL event number : ",event.type);
break;
}
}
// Directional controller
if (!(Directional_up||Directional_up_right||Directional_right||
Directional_down_right||Directional_down||Directional_down_left||
Directional_left||Directional_up_left||Directional_emulated_up||
Directional_emulated_right||Directional_emulated_down||
Directional_emulated_left))
{
Directional_first_move=0;
}
else
{
long time_now;
int step=0;
time_now=SDL_GetTicks();
if (Directional_first_move==0)
{
Directional_first_move=time_now;
step=1;
}
else
{
// Compute how much the cursor has moved since last call.
// This tries to make smooth cursor movement
// no matter the frequency of calls to Get_input()
step =
Directional_acceleration(time_now - Directional_first_move) -
Directional_acceleration(Directional_last_move - Directional_first_move);
// Clip speed at 3 pixel per visible frame.
if (step > 3)
step=3;
}
Directional_last_move = time_now;
if (step)
{
// Directional controller UP
if ((Directional_up||Directional_emulated_up||Directional_up_left||Directional_up_right) &&
!(Directional_down_right||Directional_down||Directional_emulated_down||Directional_down_left))
{
Cursor_displace(0, -step);
}
// Directional controller RIGHT
if ((Directional_up_right||Directional_right||Directional_emulated_right||Directional_down_right) &&
!(Directional_down_left||Directional_left||Directional_emulated_left||Directional_up_left))
{
Cursor_displace(step,0);
}
// Directional controller DOWN
if ((Directional_down_right||Directional_down||Directional_emulated_down||Directional_down_left) &&
!(Directional_up_left||Directional_up||Directional_emulated_up||Directional_up_right))
{
Cursor_displace(0, step);
}
// Directional controller LEFT
if ((Directional_down_left||Directional_left||Directional_emulated_left||Directional_up_left) &&
!(Directional_up_right||Directional_right||Directional_emulated_right||Directional_down_right))
{
Cursor_displace(-step,0);
}
}
}
// If the cursor was moved since last update,
// it was erased, so we need to redraw it (with the preview brush)
if (Mouse_moved)
{
Compute_paintbrush_coordinates();
Display_cursor();
return 1;
}
if (user_feedback_required)
return 1;
// Nothing significant happened
if (sleep_time)
SDL_Delay(sleep_time);
return 0;
}
void Adjust_mouse_sensitivity(word fullscreen)
{
// Deprecated
(void)fullscreen;
}
void Set_mouse_position(void)
{
SDL_WarpMouse(Mouse_X*Pixel_width, Mouse_Y*Pixel_height);
}
int Color_cycling(void)
{
static byte offset[16];
int i, color;
static SDL_Color PaletteSDL[256];
int changed; // boolean : true if the palette needs a change in this tick.
long now;
static long start=0;
if (start==0)
{
// First run
start = SDL_GetTicks();
return 1;
}
if (!Allow_colorcycling || !Cycling_mode)
return 1;
now = SDL_GetTicks();
changed=0;
// Check all cycles for a change at this tick
for (i=0; i<16; i++)
{
int len;
len=Main_backups->Pages->Gradients->Range[i].End-Main_backups->Pages->Gradients->Range[i].Start+1;
if (len>1 && Main_backups->Pages->Gradients->Range[i].Speed)
{
int new_offset;
new_offset=(now-start)/(int)(1000.0/(Main_backups->Pages->Gradients->Range[i].Speed*0.2856)) % len;
if (!Main_backups->Pages->Gradients->Range[i].Inverse)
new_offset=len - new_offset;
if (new_offset!=offset[i])
changed=1;
offset[i]=new_offset;
}
}
if (changed)
{
// Initialize the palette
for(color=0;color<256;color++)
{
PaletteSDL[color].r=Main_palette[color].R;
PaletteSDL[color].g=Main_palette[color].G;
PaletteSDL[color].b=Main_palette[color].B;
}
for (i=0; i<16; i++)
{
int len;
len=Main_backups->Pages->Gradients->Range[i].End-Main_backups->Pages->Gradients->Range[i].Start+1;
if (len>1 && Main_backups->Pages->Gradients->Range[i].Speed)
{
for(color=Main_backups->Pages->Gradients->Range[i].Start;color<=Main_backups->Pages->Gradients->Range[i].End;color++)
{
PaletteSDL[color].r=Main_palette[Main_backups->Pages->Gradients->Range[i].Start+((color-Main_backups->Pages->Gradients->Range[i].Start+offset[i])%len)].R;
PaletteSDL[color].g=Main_palette[Main_backups->Pages->Gradients->Range[i].Start+((color-Main_backups->Pages->Gradients->Range[i].Start+offset[i])%len)].G;
PaletteSDL[color].b=Main_palette[Main_backups->Pages->Gradients->Range[i].Start+((color-Main_backups->Pages->Gradients->Range[i].Start+offset[i])%len)].B;
}
}
}
SDL_SetPalette(Screen_SDL, SDL_PHYSPAL | SDL_LOGPAL, PaletteSDL,0,256);
}
return 0;
}