Files
source/Standard Gaming Platform/input.cpp
T

1654 lines
49 KiB
C++

#ifdef JA2_PRECOMPILED_HEADERS
#include "JA2 SGP ALL.H"
#elif defined( WIZ8_PRECOMPILED_HEADERS )
#include "WIZ8 SGP ALL.H"
#else
#include "types.h"
#include <windows.h>
#include <stdio.h>
#include <memory.h>
#include "debug.h"
#include "input.h"
#include "memman.h"
#include "english.h"
#if defined( JA2 ) || defined( UTIL )
#include "video.h"
#else
#include "video2.h"
#endif
#include "local.h"
#endif
#include "zmouse.h"
// Make sure to refer to the translation table which is within one of the following files (depending
// on the language used). ENGLISH.C, JAPANESE.C, FRENCH.C, GERMAN.C, SPANISH.C, etc...
extern UINT16 gsKeyTranslationTable[1024];
extern BOOLEAN gfApplicationActive;
#ifndef JA2
#undef GetCursorPos
#define GetCursorPos SGPMouseGetPos
#endif
// The gfKeyState table is used to track which of the keys is up or down at any one time. This is used while polling
// the interface.
BOOLEAN gfKeyState[256]; // TRUE = Pressed, FALSE = Not Pressed
BOOLEAN fCursorWasClipped = FALSE;
RECT gCursorClipRect;
// The gsKeyTranslationTables basically translates scan codes to our own key value table. Please note that the table is 2 bytes
// wide per entry. This will be used since we will use 2 byte characters for translation purposes.
UINT16 gfShiftState; // TRUE = Pressed, FALSE = Not Pressed
UINT16 gfAltState; // TRUE = Pressed, FALSE = Not Pressed
UINT16 gfCtrlState; // TRUE = Pressed, FALSE = Not Pressed
// These data structure are used to track the mouse while polling
BOOLEAN gfTrackDblClick;
UINT32 guiDoubleClkDelay; // Current delay in milliseconds for a delay
UINT32 guiSingleClickTimer;
UINT32 guiRecordedWParam;
UINT32 guiRecordedLParam;
UINT16 gusRecordedKeyState;
BOOLEAN gfRecordedLeftButtonUp;
UINT32 guiLeftButtonRepeatTimer;
UINT32 guiRightButtonRepeatTimer;
BOOLEAN gfTrackMousePos; // TRUE = queue mouse movement events, FALSE = don't
BOOLEAN gfLeftButtonState; // TRUE = Pressed, FALSE = Not Pressed
BOOLEAN gfRightButtonState; // TRUE = Pressed, FALSE = Not Pressed
UINT16 gusMouseXPos; // X position of the mouse on screen
UINT16 gusMouseYPos; // y position of the mouse on screen
// The queue structures are used to track input events using queued events
InputAtom gEventQueue[256];
UINT16 gusQueueCount;
UINT16 gusHeadIndex;
UINT16 gusTailIndex;
// ATE: Added to signal if we have had input this frame - cleared by the SGP main loop
BOOLEAN gfSGPInputReceived = FALSE;
// This is the WIN95 hook specific data and defines used to handle the keyboard and
// mouse hook
HHOOK ghKeyboardHook;
HHOOK ghMouseHook;
// If the following pointer is non NULL then input characters are redirected to
// the related string
BOOLEAN gfCurrentStringInputState;
StringInput *gpCurrentStringDescriptor;
// Local function headers
void QueueEvent(UINT16 ubInputEvent, UINT32 usParam, UINT32 uiParam);
void RedirectToString(UINT16 uiInputCharacter);
void HandleSingleClicksAndButtonRepeats( void );
void AdjustMouseForWindowOrigin(void);
// These are the hook functions for both keyboard and mouse
LRESULT CALLBACK KeyboardHandler(int Code, WPARAM wParam, LPARAM lParam)
{
#ifndef JA2
if((Code < 0) || (!gfApplicationActive))
#else
if (Code < 0)
#endif
{ // Do not handle this message, pass it on to another window
return CallNextHookEx(ghKeyboardHook, Code, wParam, lParam);
}
if (lParam & TRANSITION_MASK)
{ // The key has been released
KeyUp(wParam, lParam);
//gfSGPInputReceived = TRUE;
}
else
{ // Key was up
KeyDown(wParam, lParam);
gfSGPInputReceived = TRUE;
}
return TRUE;
}
#ifdef JA2
LRESULT CALLBACK MouseHandler(int Code, WPARAM wParam, LPARAM lParam)
{
UINT32 uiParam;
#ifndef JA2
if((Code < 0) || (!gfApplicationActive))
#else
if (Code < 0)
#endif
{ // Do not handle this message, pass it on to another window
return CallNextHookEx(ghMouseHook, Code, wParam, lParam);
}
switch (wParam)
{
case WM_LBUTTONDOWN
: // Update the current mouse position
gusMouseXPos = (UINT16)(((MOUSEHOOKSTRUCT *)lParam)->pt).x;
gusMouseYPos = (UINT16)(((MOUSEHOOKSTRUCT *)lParam)->pt).y;
uiParam = gusMouseYPos;
uiParam = uiParam << 16;
uiParam = uiParam | gusMouseXPos;
// Update the button state
gfLeftButtonState = TRUE;
//Set that we have input
gfSGPInputReceived = TRUE;
// Trigger an input event
QueueEvent(LEFT_BUTTON_DOWN, 0, uiParam);
break;
case WM_LBUTTONUP
: // Update the current mouse position
gusMouseXPos = (UINT16)(((MOUSEHOOKSTRUCT *)lParam)->pt).x;
gusMouseYPos = (UINT16)(((MOUSEHOOKSTRUCT *)lParam)->pt).y;
uiParam = gusMouseYPos;
uiParam = uiParam << 16;
uiParam = uiParam | gusMouseXPos;
// Update the button state
gfLeftButtonState = FALSE;
//Set that we have input
gfSGPInputReceived = TRUE;
// Trigger an input event
QueueEvent(LEFT_BUTTON_UP, 0, uiParam);
break;
case WM_RBUTTONDOWN
: // Update the current mouse position
gusMouseXPos = (UINT16)(((MOUSEHOOKSTRUCT *)lParam)->pt).x;
gusMouseYPos = (UINT16)(((MOUSEHOOKSTRUCT *)lParam)->pt).y;
uiParam = gusMouseYPos;
uiParam = uiParam << 16;
uiParam = uiParam | gusMouseXPos;
// Update the button state
gfRightButtonState = TRUE;
//Set that we have input
gfSGPInputReceived = TRUE;
// Trigger an input event
QueueEvent(RIGHT_BUTTON_DOWN, 0, uiParam);
break;
case WM_RBUTTONUP
: // Update the current mouse position
gusMouseXPos = (UINT16)(((MOUSEHOOKSTRUCT *)lParam)->pt).x;
gusMouseYPos = (UINT16)(((MOUSEHOOKSTRUCT *)lParam)->pt).y;
uiParam = gusMouseYPos;
uiParam = uiParam << 16;
uiParam = uiParam | gusMouseXPos;
// Update the button state
gfRightButtonState = FALSE;
//Set that we have input
gfSGPInputReceived = TRUE;
// Trigger an input event
QueueEvent(RIGHT_BUTTON_UP, 0, uiParam);
break;
case WM_MOUSEMOVE
: // Update the current mouse position
gusMouseXPos = (UINT16)(((MOUSEHOOKSTRUCT *)lParam)->pt).x;
gusMouseYPos = (UINT16)(((MOUSEHOOKSTRUCT *)lParam)->pt).y;
uiParam = gusMouseYPos;
uiParam = uiParam << 16;
uiParam = uiParam | gusMouseXPos;
// Trigger an input event
if (gfTrackMousePos == TRUE)
{
QueueEvent(MOUSE_POS, 0, uiParam);
}
//Set that we have input
gfSGPInputReceived = TRUE;
break;
}
return TRUE;
}
#else
// Wizardry mouse hander
LRESULT CALLBACK MouseHandler(int Code, WPARAM wParam, LPARAM lParam)
{
UINT32 uiParam;
UINT32 uiXPos, uiYPos;
RECT rcClient;
BOOLEAN fOutsideClient=FALSE;
static BOOLEAN fResizing=FALSE;
LRESULT Result;
uiXPos= (((MOUSEHOOKSTRUCT *)lParam)->pt).x;
uiYPos= (((MOUSEHOOKSTRUCT *)lParam)->pt).y;
if(!VideoIsFullScreen())
{
if(wParam==WM_NCLBUTTONDOWN)
fResizing=TRUE;
VideoGetClientRect(&rcClient);
if((uiXPos < (UINT32)rcClient.left) || (uiXPos > (UINT32)rcClient.right) || (uiYPos < (UINT32)rcClient.top) || (uiYPos > (UINT32)rcClient.bottom))
fOutsideClient=TRUE;
}
if((Code < 0) || (!gfApplicationActive) || fOutsideClient || fResizing)
{ // Do not handle this message, pass it on to another window
Result = CallNextHookEx(ghMouseHook, Code, wParam, lParam);
if((wParam==WM_LBUTTONUP) || (wParam==WM_NCLBUTTONUP))
fResizing=FALSE;
return(Result);
}
switch (wParam)
{
case WM_LBUTTONUP:
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_MOUSEMOVE:
if(VideoIsFullScreen())
{
gusMouseXPos = (UINT16)(uiXPos);
gusMouseYPos = (UINT16)(uiYPos);
}
else
{
gusMouseXPos = (UINT16)(uiXPos-rcClient.left);
gusMouseYPos = (UINT16)(uiYPos-rcClient.top);
}
uiParam = (UINT32)gusMouseYPos<<16 | (UINT32)gusMouseXPos;
//Set that we have input
gfSGPInputReceived = TRUE;
break;
}
if ( wParam == WM_MOUSEWHEEL )
{
return( FALSE );
}
switch (wParam)
{
case WM_LBUTTONDOWN:
gfLeftButtonState = TRUE;
QueueEvent(LEFT_BUTTON_DOWN, 0, uiParam);
break;
case WM_LBUTTONUP:
gfLeftButtonState = FALSE;
QueueEvent(LEFT_BUTTON_UP, 0, uiParam);
break;
case WM_RBUTTONDOWN:
gfRightButtonState = TRUE;
QueueEvent(RIGHT_BUTTON_DOWN, 0, uiParam);
break;
case WM_RBUTTONUP:
gfRightButtonState = FALSE;
QueueEvent(RIGHT_BUTTON_UP, 0, uiParam);
break;
case WM_MOUSEMOVE:
if(gfTrackMousePos)
QueueEvent(MOUSE_POS, 0, uiParam);
break;
}
return(TRUE);
}
#endif
BOOLEAN InitializeInputManager(void)
{
// Link to debugger
RegisterDebugTopic(TOPIC_INPUT, "Input Manager");
// Initialize the gfKeyState table to FALSE everywhere
memset(gfKeyState, FALSE, 256);
// Initialize the Event Queue
gusQueueCount = 0;
gusHeadIndex = 0;
gusTailIndex = 0;
// By default, we will not queue mousemove events
gfTrackMousePos = FALSE;
// Initialize other variables
gfShiftState = FALSE;
gfAltState = FALSE;
gfCtrlState = FALSE;
// Initialize variables pertaining to DOUBLE CLIK stuff
gfTrackDblClick = TRUE;
guiDoubleClkDelay = DBL_CLK_TIME;
guiSingleClickTimer = 0;
gfRecordedLeftButtonUp = FALSE;
// Initialize variables pertaining to the button states
gfLeftButtonState = FALSE;
gfRightButtonState = FALSE;
// Initialize variables pertaining to the repeat mechanism
guiLeftButtonRepeatTimer = 0;
guiRightButtonRepeatTimer = 0;
// Set the mouse to the center of the screen
gusMouseXPos = 320;
gusMouseYPos = 240;
// Initialize the string input mechanism
gfCurrentStringInputState = FALSE;
gpCurrentStringDescriptor = NULL;
// Activate the hook functions for both keyboard and Mouse
ghKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) KeyboardHandler, (HINSTANCE) 0, GetCurrentThreadId());
DbgMessage(TOPIC_INPUT, DBG_LEVEL_2, String("Set keyboard hook returned %d", ghKeyboardHook));
ghMouseHook = SetWindowsHookEx(WH_MOUSE, (HOOKPROC) MouseHandler, (HINSTANCE) 0, GetCurrentThreadId());
DbgMessage(TOPIC_INPUT, DBG_LEVEL_2, String("Set mouse hook returned %d", ghMouseHook));
return TRUE;
}
void ShutdownInputManager(void)
{ // There's very little to do when shutting down the input manager. In the future, this is where the keyboard and
// mouse hooks will be destroyed
UnRegisterDebugTopic(TOPIC_INPUT, "Input Manager");
UnhookWindowsHookEx(ghKeyboardHook);
UnhookWindowsHookEx(ghMouseHook);
}
void QueuePureEvent(UINT16 ubInputEvent, UINT32 usParam, UINT32 uiParam)
{
UINT32 uiTimer;
UINT16 usKeyState;
uiTimer = GetTickCount();
usKeyState = gfShiftState | gfCtrlState | gfAltState;
// Can we queue up one more event, if not, the event is lost forever
if (gusQueueCount == 256)
{ // No more queue space
return;
}
// Okey Dokey, we can queue up the event, so we do it
gEventQueue[gusTailIndex].uiTimeStamp = uiTimer;
gEventQueue[gusTailIndex].usKeyState = usKeyState;
gEventQueue[gusTailIndex].usEvent = ubInputEvent;
gEventQueue[gusTailIndex].usParam = usParam;
gEventQueue[gusTailIndex].uiParam = uiParam;
// Increment the number of items on the input queue
gusQueueCount++;
// Increment the gusTailIndex pointer
if (gusTailIndex == 255)
{ // The gusTailIndex is about to wrap around the queue ring
gusTailIndex = 0;
}
else
{ // We simply increment the gusTailIndex
gusTailIndex++;
}
}
void QueueEvent(UINT16 ubInputEvent, UINT32 usParam, UINT32 uiParam)
{
UINT32 uiTimer;
UINT16 usKeyState;
uiTimer = GetTickCount();
usKeyState = gfShiftState | gfCtrlState | gfAltState;
// Can we queue up one more event, if not, the event is lost forever
if (gusQueueCount == 256)
{ // No more queue space
return;
}
if (ubInputEvent == LEFT_BUTTON_DOWN)
{
guiLeftButtonRepeatTimer = uiTimer + BUTTON_REPEAT_TIMEOUT;
}
if (ubInputEvent == RIGHT_BUTTON_DOWN)
{
guiRightButtonRepeatTimer = uiTimer + BUTTON_REPEAT_TIMEOUT;
}
if (ubInputEvent == LEFT_BUTTON_UP)
{
guiLeftButtonRepeatTimer = 0;
}
if (ubInputEvent == RIGHT_BUTTON_UP)
{
guiRightButtonRepeatTimer = 0;
}
if ( (ubInputEvent == LEFT_BUTTON_UP) )
{
// Do we have a double click
if ( ( uiTimer - guiSingleClickTimer ) < DBL_CLK_TIME )
{
guiSingleClickTimer = 0;
// Add a button up first...
gEventQueue[gusTailIndex].uiTimeStamp = uiTimer;
gEventQueue[gusTailIndex].usKeyState = gusRecordedKeyState;
gEventQueue[gusTailIndex].usEvent = LEFT_BUTTON_UP;
gEventQueue[gusTailIndex].usParam = usParam;
gEventQueue[gusTailIndex].uiParam = uiParam;
// Increment the number of items on the input queue
gusQueueCount++;
// Increment the gusTailIndex pointer
if (gusTailIndex == 255)
{ // The gusTailIndex is about to wrap around the queue ring
gusTailIndex = 0;
}
else
{ // We simply increment the gusTailIndex
gusTailIndex++;
}
// Now do double click
gEventQueue[gusTailIndex].uiTimeStamp = uiTimer;
gEventQueue[gusTailIndex].usKeyState = gusRecordedKeyState ;
gEventQueue[gusTailIndex].usEvent = LEFT_BUTTON_DBL_CLK;
gEventQueue[gusTailIndex].usParam = usParam;
gEventQueue[gusTailIndex].uiParam = uiParam;
// Increment the number of items on the input queue
gusQueueCount++;
// Increment the gusTailIndex pointer
if (gusTailIndex == 255)
{ // The gusTailIndex is about to wrap around the queue ring
gusTailIndex = 0;
}
else
{ // We simply increment the gusTailIndex
gusTailIndex++;
}
return;
}
else
{
// Save time
guiSingleClickTimer = uiTimer;
}
}
// Okey Dokey, we can queue up the event, so we do it
gEventQueue[gusTailIndex].uiTimeStamp = uiTimer;
gEventQueue[gusTailIndex].usKeyState = usKeyState;
gEventQueue[gusTailIndex].usEvent = ubInputEvent;
gEventQueue[gusTailIndex].usParam = usParam;
gEventQueue[gusTailIndex].uiParam = uiParam;
// Increment the number of items on the input queue
gusQueueCount++;
// Increment the gusTailIndex pointer
if (gusTailIndex == 255)
{ // The gusTailIndex is about to wrap around the queue ring
gusTailIndex = 0;
}
else
{ // We simply increment the gusTailIndex
gusTailIndex++;
}
}
BOOLEAN DequeueSpecificEvent(InputAtom *Event, UINT32 uiMaskFlags )
{
// Is there an event to dequeue
if (gusQueueCount > 0)
{
memcpy( Event, &( gEventQueue[gusHeadIndex] ), sizeof( InputAtom ) );
// Check if it has the masks!
if ( ( Event->usEvent & uiMaskFlags ) )
{
return( DequeueEvent( Event) );
}
}
return( FALSE );
}
BOOLEAN DequeueEvent(InputAtom *Event)
{
HandleSingleClicksAndButtonRepeats( );
// Is there an event to dequeue
if (gusQueueCount > 0)
{
// We have an event, so we dequeue it
memcpy( Event, &( gEventQueue[gusHeadIndex] ), sizeof( InputAtom ) );
if (gusHeadIndex == 255)
{
gusHeadIndex = 0;
}
else
{
gusHeadIndex++;
}
// Decrement the number of items on the input queue
gusQueueCount--;
// dequeued an event, return TRUE
return TRUE;
}
else
{
// No events to dequeue, return FALSE
return FALSE;
}
}
void KeyChange(UINT32 usParam, UINT32 uiParam, UINT8 ufKeyState)
{
UINT32 ubKey;
UINT16 ubChar;
POINT MousePos;
UINT32 uiTmpLParam;
if ((usParam >= 96)&&(usParam <= 110))
{ // Well this could be a NUMPAD character imitating the center console characters (when NUMLOCK is OFF). Well we
// gotta find out what was pressed and translate it to the actual physical key (i.e. if we think that HOME was
// pressed but NUM_7 was pressed, the we translate the key into NUM_7
switch(usParam)
{ case 96 // NUM_0
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 82)
{ // Well its the NUM_9 key and not actually the PGUP key
ubKey = 223;
}
else
{ // NOP, its the PGUP key all right
ubKey = usParam;
}
break;
case 110 // NUM_PERIOD
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 83)
{ // Well its the NUM_3 key and not actually the PGDN key
ubKey = 224;
}
else
{ // NOP, its the PGDN key all right
ubKey = usParam;
}
break;
case 97 // NUM_1
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 79)
{ // Well its the NUM_1 key and not actually the END key
ubKey = 225;
}
else
{ // NOP, its the END key all right
ubKey = usParam;
}
break;
case 98 // NUM_2
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 80)
{ // Well its the NUM_7 key and not actually the HOME key
ubKey = 226;
}
else
{ // NOP, its the HOME key all right
ubKey = usParam;
}
break;
case 99 // NUM_3
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 81)
{ // Well its the NUM_4 key and not actually the LARROW key
ubKey = 227;
}
else
{ // NOP, it's the LARROW key all right
ubKey = usParam;
}
break;
case 100 // NUM_4
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 75)
{ // Well its the NUM_8 key and not actually the UPARROW key
ubKey = 228;
}
else
{ // NOP, it's the UPARROW key all right
ubKey = usParam;
}
break;
case 101 // NUM_5
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 76)
{ // Well its the NUM_6 key and not actually the RARROW key
ubKey = 229;
}
else
{ // NOP, it's the RARROW key all right
ubKey = usParam;
}
break;
case 102 // NUM_6
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 77)
{ // Well its the NUM_2 key and not actually the DNARROW key
ubKey = 230;
}
else
{ // NOP, it's the DNARROW key all right
ubKey = usParam;
}
break;
case 103 // NUM_7
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 71)
{ // Well its the NUM_0 key and not actually the INSERT key
ubKey = 231;
}
else
{ // NOP, it's the INSERT key all right
ubKey = usParam;
}
break;
case 104 // NUM_8
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 72)
{ // Well its the NUM_PERIOD key and not actually the DELETE key
ubKey = 232;
}
else
{ // NOP, it's the DELETE key all right
ubKey = usParam;
}
break;
case 105 // NUM_9
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 73)
{ // Well its the NUM_PERIOD key and not actually the DELETE key
ubKey = 233;
}
else
{ // NOP, it's the DELETE key all right
ubKey = usParam;
}
break;
default
: ubKey = usParam;
break;
}
}
else
{
if ((usParam >= 33)&&(usParam <= 46))
{ // Well this could be a NUMPAD character imitating the center console characters (when NUMLOCK is OFF). Well we
// gotta find out what was pressed and translate it to the actual physical key (i.e. if we think that HOME was
// pressed but NUM_7 was pressed, the we translate the key into NUM_7
switch(usParam)
{ case 45 // NUM_0
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 82)
{ // Is it the NUM_0 key or the INSERT key
if (((uiParam & EXT_CODE_MASK) >> 17) != 0)
{ // It's the INSERT key
ubKey = 245;
}
else
{ // Is the NUM_0 key with NUM lock off
ubKey = 234;
}
}
else
{
ubKey = usParam;
}
break;
case 46 // NUM_PERIOD
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 83)
{ // Is it the NUM_PERIOD key or the DEL key
if (((uiParam & EXT_CODE_MASK) >> 17) != 0)
{ // It's the DELETE key
ubKey = 246;
}
else
{ // Is the NUM_PERIOD key with NUM lock off
ubKey = 235;
}
}
else
{
ubKey = usParam;
}
break;
case 35 // NUM_1
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 79)
{ // Is it the NUM_1 key or the END key
if (((uiParam & EXT_CODE_MASK) >> 17) != 0)
{ // It's the END key
ubKey = 247;
}
else
{ // Is the NUM_1 key with NUM lock off
ubKey = 236;
}
}
else
{
ubKey = usParam;
}
break;
case 40 // NUM_2
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 80)
{ // Is it the NUM_2 key or the DOWN key
if (((uiParam & EXT_CODE_MASK) >> 17) != 0)
{ // It's the DOWN key
ubKey = 248;
}
else
{ // Is the NUM_2 key with NUM lock off
ubKey = 237;
}
}
else
{
ubKey = usParam;
}
break;
case 34 // NUM_3
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 81)
{ // Is it the NUM_3 key or the PGDN key
if (((uiParam & EXT_CODE_MASK) >> 17) != 0)
{ // It's the PGDN key
ubKey = 249;
}
else
{ // Is the NUM_3 key with NUM lock off
ubKey = 238;
}
}
else
{
ubKey = usParam;
}
break;
case 37 // NUM_4
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 75)
{ // Is it the NUM_4 key or the LEFT key
if (((uiParam & EXT_CODE_MASK) >> 17) != 0)
{ // It's the LEFT key
ubKey = 250;
}
else
{ // Is the NUM_4 key with NUM lock off
ubKey = 239;
}
}
else
{
ubKey = usParam;
}
break;
case 39 // NUM_6
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 77)
{ // Is it the NUM_6 key or the RIGHT key
if (((uiParam & EXT_CODE_MASK) >> 17) != 0)
{ // It's the RIGHT key
ubKey = 251;
}
else
{ // Is the NUM_6 key with NUM lock off
ubKey = 241;
}
}
else
{
ubKey = usParam;
}
break;
case 36 // NUM_7
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 71)
{ // Is it the NUM_7 key or the HOME key
if (((uiParam & EXT_CODE_MASK) >> 17) != 0)
{ // It's the HOME key
ubKey = 252;
}
else
{ // Is the NUM_7 key with NUM lock off
ubKey = 242;
}
}
else
{
ubKey = usParam;
}
break;
case 38 // NUM_8
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 72)
{ // Is it the NUM_8 key or the UP key
if (((uiParam & EXT_CODE_MASK) >> 17) != 0)
{ // It's the UP key
ubKey = 253;
}
else
{ // Is the NUM_8 key with NUM lock off
ubKey = 243;
}
}
else
{
ubKey = usParam;
}
break;
case 33 // NUM_9
: if (((uiParam & SCAN_CODE_MASK) >> 16) == 73)
{ // Is it the NUM_9 key or the PGUP key
if (((uiParam & EXT_CODE_MASK) >> 17) != 0)
{ // It's the PGUP key
ubKey = 254;
}
else
{ // Is the NUM_9 key with NUM lock off
ubKey = 244;
}
}
else
{
ubKey = usParam;
}
break;
default
: ubKey = usParam;
break;
}
}
else
{
if (usParam == 12)
{ // NUM_5 with NUM_LOCK off
ubKey = 240;
}
else
{ // Normal key
ubKey = usParam;
}
}
}
// Find ucChar by translating ubKey using the gsKeyTranslationTable. If the SHIFT, ALT or CTRL key are down, then
// the index into the translation table us changed from ubKey to ubKey+256, ubKey+512 and ubKey+768 respectively
if (gfShiftState == TRUE)
{ // SHIFT is pressed, hence we add 256 to ubKey before translation to ubChar
ubChar = gsKeyTranslationTable[ubKey+256];
}
else
{
//
// Even though gfAltState is checked as if it was a BOOLEAN, it really contains 0x02, which
// is NOT == to true. This is broken, however to fix it would break Ja2 and Wizardry.
// The same thing goes for gfCtrlState and gfShiftState, howver gfShiftState is assigned 0x01 which IS == to TRUE.
// Just something i found, and thought u should know about. DF.
//
if( gfAltState == TRUE )
{ // ALT is pressed, hence ubKey is multiplied by 3 before translation to ubChar
ubChar = gsKeyTranslationTable[ubKey+512];
}
else
{
if (gfCtrlState == TRUE)
{ // CTRL is pressed, hence ubKey is multiplied by 4 before translation to ubChar
ubChar = gsKeyTranslationTable[ubKey+768];
}
else
{ // None of the SHIFT, ALT or CTRL are pressed hence we have a default translation of ubKey
ubChar = gsKeyTranslationTable[ubKey];
}
}
}
GetCursorPos(&MousePos);
uiTmpLParam = ((MousePos.y << 16) & 0xffff0000) | (MousePos.x & 0x0000ffff);
if (ufKeyState == TRUE)
{ // Key has been PRESSED
// Find out if the key is already pressed and if not, queue an event and update the gfKeyState array
if (gfKeyState[ubKey] == FALSE)
{ // Well the key has just been pressed, therefore we queue up and event and update the gsKeyState
if (gfCurrentStringInputState == FALSE)
{
// There is no string input going on right now, so we queue up the event
gfKeyState[ubKey] = TRUE;
QueueEvent(KEY_DOWN, ubChar, uiTmpLParam);
}
else
{ // There is a current input string which will capture this event
RedirectToString(ubChar);
DbgMessage(TOPIC_INPUT, DBG_LEVEL_0, String("Pressed character %d (%d)", ubChar, ubKey));
}
}
else
{ // Well the key gets repeated
if (gfCurrentStringInputState == FALSE)
{ // There is no string input going on right now, so we queue up the event
QueueEvent(KEY_REPEAT, ubChar, uiTmpLParam);
}
else
{ // There is a current input string which will capture this event
RedirectToString(ubChar);
}
}
}
else
{ // Key has been RELEASED
// Find out if the key is already pressed and if so, queue an event and update the gfKeyState array
if (gfKeyState[ubKey] == TRUE)
{ // Well the key has just been pressed, therefore we queue up and event and update the gsKeyState
gfKeyState[ubKey] = FALSE;
QueueEvent(KEY_UP, ubChar, uiTmpLParam);
}
//else if the alt tab key was pressed
else if( ubChar == TAB && gfAltState )
{
// therefore minimize the application
ShowWindow( ghWindow, SW_MINIMIZE );
gfKeyState[ ALT ] = FALSE;
gfAltState = FALSE;
}
}
}
void KeyDown(UINT32 usParam, UINT32 uiParam)
{ // Are we PRESSING down one of SHIFT, ALT or CTRL ???
if (usParam == 16)
{ // SHIFT key is PRESSED
gfShiftState = SHIFT_DOWN;
gfKeyState[16] = TRUE;
}
else
{
if (usParam == 17)
{ // CTRL key is PRESSED
gfCtrlState = CTRL_DOWN;
gfKeyState[17] = TRUE;
}
else
{
if (usParam == 18)
{ // ALT key is pressed
gfAltState = ALT_DOWN;
gfKeyState[18] = TRUE;
}
else
{
if (usParam == SNAPSHOT)
{
//PrintScreen();
// DB Done in the KeyUp function
// this used to be keyed to SCRL_LOCK
// which I believe Luis gave the wrong value
}
else
{
// No special keys have been pressed
// Call KeyChange() and pass TRUE to indicate key has been PRESSED and not RELEASED
KeyChange(usParam, uiParam, TRUE);
}
}
}
}
}
void KeyUp(UINT32 usParam, UINT32 uiParam)
{ // Are we RELEASING one of SHIFT, ALT or CTRL ???
if (usParam == 16)
{ // SHIFT key is RELEASED
gfShiftState = FALSE;
gfKeyState[16] = FALSE;
}
else
{
if (usParam == 17)
{ // CTRL key is RELEASED
gfCtrlState = FALSE;
gfKeyState[17] = FALSE;
}
else
{
if (usParam == 18)
{ // ALT key is RELEASED
gfAltState = FALSE;
gfKeyState[18] = FALSE;
}
else
{
if (usParam == SNAPSHOT)
{
// DB this used to be keyed to SCRL_LOCK
// which I believe Luis gave the wrong value
//#ifndef JA2
if (_KeyDown(CTRL))
VideoCaptureToggle();
else
//#endif
PrintScreen();
}
else
{
// No special keys have been pressed
// Call KeyChange() and pass FALSE to indicate key has been PRESSED and not RELEASED
KeyChange(usParam, uiParam, FALSE);
}
}
}
}
}
void EnableDoubleClk(void)
{
// Obsolete
}
void DisableDoubleClk(void)
{
// Obsolete
}
void GetMousePos(SGPPoint *Point)
{
POINT MousePos;
GetCursorPos(&MousePos);
Point->iX = (UINT32) MousePos.x;
Point->iY = (UINT32) MousePos.y;
return;
}
// These functions will be used for string input
// Since all string input will have to be handle by reentrant capable functions (since we must attend
// to windows messaging as well as network traffic related issues), whenever there is ongoing string input
// going on, we must use InitStringInput() and HandleStringInput() to get the job done. HandleStringInput()
// will return TRUE as long as the string input is going on, and FALSE when its done
//
// During string input, all keyboard are rerouted to the string and hence are not queued up on the
// event queue or registered in the state table. Also note that several string inputs can occur
// at the same time. Use the SetStringFocus() function to manager the focus for multiple
// string inputs
StringInput *InitStringInput(UINT16 *pInputString, UINT16 usLength, UINT16 *pFilter)
{
StringInput *pStringDescriptor;
if ((pStringDescriptor = (StringInput *) MemAlloc(sizeof(StringInput))) == NULL)
{
//
// Hum we failed to allocate memory for the string descriptor
//
DbgMessage(TOPIC_INPUT, DBG_LEVEL_1, "Failed to allocate memory for string descriptor");
return NULL;
}
else
{
if ((pStringDescriptor->pOriginalString = (UINT16 *) MemAlloc(usLength * 2)) == NULL)
{
//
// free up structure before aborting
//
MemFree(pStringDescriptor);
DbgMessage(TOPIC_INPUT, DBG_LEVEL_1, "Failed to allocate memory for string duplicate");
return NULL;
}
memcpy(pStringDescriptor->pOriginalString, pInputString, usLength * 2);
pStringDescriptor->pString = pInputString;
pStringDescriptor->pFilter = pFilter;
pStringDescriptor->usMaxStringLength = usLength;
pStringDescriptor->usStringOffset = 0;
pStringDescriptor->usCurrentStringLength = 0;
while ((pStringDescriptor->usStringOffset < pStringDescriptor->usMaxStringLength)&&(*(pStringDescriptor->pString + pStringDescriptor->usStringOffset) != 0))
{
//
// Find the last character in the string
//
pStringDescriptor->usStringOffset++;
pStringDescriptor->usCurrentStringLength++;
}
if (pStringDescriptor->usStringOffset == pStringDescriptor->usMaxStringLength)
{
//
// Hum the current string has no null terminator. Invalidate the string and
// start from scratch
//
memset(pStringDescriptor->pString, 0, usLength * 2);
pStringDescriptor->usStringOffset = 0;
pStringDescriptor->usCurrentStringLength = 0;
}
pStringDescriptor->fInsertMode = FALSE;
pStringDescriptor->fFocus = FALSE;
pStringDescriptor->pPreviousString = NULL;
pStringDescriptor->pNextString = NULL;
return pStringDescriptor;
}
}
void LinkPreviousString(StringInput *pCurrentString, StringInput *pPreviousString)
{
if (pCurrentString != NULL)
{
if (pCurrentString->pPreviousString != NULL)
{
pCurrentString->pPreviousString->pNextString = NULL;
}
pCurrentString->pPreviousString = pPreviousString;
if (pPreviousString != NULL)
{
pPreviousString->pNextString = pCurrentString;
}
}
}
void LinkNextString(StringInput *pCurrentString, StringInput *pNextString)
{
if (pCurrentString != NULL)
{
if (pCurrentString->pNextString != NULL)
{
pCurrentString->pNextString->pPreviousString = NULL;
}
pCurrentString->pNextString = pNextString;
if (pNextString != NULL)
{
pNextString->pPreviousString = pCurrentString;
}
}
}
BOOLEAN CharacterIsValid(UINT16 usCharacter, UINT16 *pFilter)
{
UINT32 uiIndex, uiEndIndex;
if (pFilter != NULL)
{
uiEndIndex = *pFilter;
for (uiIndex = 1; uiIndex <= *pFilter; uiIndex++)
{
if (usCharacter == *(pFilter + uiIndex))
{
return TRUE;
}
}
return FALSE;
}
return TRUE;
}
void RedirectToString(UINT16 usInputCharacter)
{
UINT16 usIndex;
if (gpCurrentStringDescriptor != NULL)
{
// Handle the new character input
switch (usInputCharacter)
{
case ENTER
: // ENTER is pressed, the last character field should be set to ENTER
if (gpCurrentStringDescriptor->pNextString != NULL)
{
gpCurrentStringDescriptor->fFocus = FALSE;
gpCurrentStringDescriptor = gpCurrentStringDescriptor->pNextString;
gpCurrentStringDescriptor->fFocus = TRUE;
gpCurrentStringDescriptor->usLastCharacter = 0;
}
else
{
gpCurrentStringDescriptor->fFocus = FALSE;
gpCurrentStringDescriptor->usLastCharacter = usInputCharacter;
gfCurrentStringInputState = FALSE;
}
break;
case ESC
: // ESC was pressed, the last character field should be set to ESC
gpCurrentStringDescriptor->fFocus = FALSE;
gpCurrentStringDescriptor->usLastCharacter = usInputCharacter;
gfCurrentStringInputState = FALSE;
break;
case SHIFT_TAB
: // TAB was pressed, the last character field should be set to TAB
if (gpCurrentStringDescriptor->pPreviousString != NULL)
{
gpCurrentStringDescriptor->fFocus = FALSE;
gpCurrentStringDescriptor = gpCurrentStringDescriptor->pPreviousString;
gpCurrentStringDescriptor->fFocus = TRUE;
gpCurrentStringDescriptor->usLastCharacter = 0;
}
break;
case TAB
: // TAB was pressed, the last character field should be set to TAB
if (gpCurrentStringDescriptor->pNextString != NULL)
{
gpCurrentStringDescriptor->fFocus = FALSE;
gpCurrentStringDescriptor = gpCurrentStringDescriptor->pNextString;
gpCurrentStringDescriptor->fFocus = TRUE;
gpCurrentStringDescriptor->usLastCharacter = 0;
}
break;
case UPARROW
: // The UPARROW was pressed, the last character field should be set to UPARROW
if (gpCurrentStringDescriptor->pPreviousString != NULL)
{
gpCurrentStringDescriptor->fFocus = FALSE;
gpCurrentStringDescriptor = gpCurrentStringDescriptor->pPreviousString;
gpCurrentStringDescriptor->fFocus = TRUE;
gpCurrentStringDescriptor->usLastCharacter = 0;
}
break;
case DNARROW
: // The DNARROW was pressed, the last character field should be set to DNARROW
if (gpCurrentStringDescriptor->pNextString != NULL)
{
gpCurrentStringDescriptor->fFocus = FALSE;
gpCurrentStringDescriptor = gpCurrentStringDescriptor->pNextString;
gpCurrentStringDescriptor->fFocus = TRUE;
gpCurrentStringDescriptor->usLastCharacter = 0;
}
break;
case LEFTARROW
: // The LEFTARROW was pressed, move one character to the left
if (gpCurrentStringDescriptor->usStringOffset > 0)
{ // Decrement the offset
gpCurrentStringDescriptor->usStringOffset--;
}
gpCurrentStringDescriptor->usLastCharacter = usInputCharacter;
break;
case RIGHTARROW
: // The RIGHTARROW was pressed, move one character to the right
if (gpCurrentStringDescriptor->usStringOffset < gpCurrentStringDescriptor->usCurrentStringLength)
{ // Ok we can move the cursor one up without going past the end of string
gpCurrentStringDescriptor->usStringOffset++;
}
gpCurrentStringDescriptor->usLastCharacter = usInputCharacter;
break;
case BACKSPACE
: // Delete the character preceding the cursor
if (gpCurrentStringDescriptor->usStringOffset > 0)
{ // Ok, we are not at the beginning of the string, so we may proceed
for (usIndex = gpCurrentStringDescriptor->usStringOffset; usIndex <= gpCurrentStringDescriptor->usCurrentStringLength; usIndex++)
{ // Shift the characters one at a time
*(gpCurrentStringDescriptor->pString + usIndex - 1) = *(gpCurrentStringDescriptor->pString + usIndex);
}
gpCurrentStringDescriptor->usStringOffset--;
gpCurrentStringDescriptor->usCurrentStringLength--;
}
break;
case DEL
: // Delete the character which follows the cursor
if (gpCurrentStringDescriptor->usStringOffset < gpCurrentStringDescriptor->usCurrentStringLength)
{ // Ok we are not at the end of the string, so we may proceed
for (usIndex = gpCurrentStringDescriptor->usStringOffset; usIndex < gpCurrentStringDescriptor->usCurrentStringLength; usIndex++)
{ // Shift the characters one at a time
*(gpCurrentStringDescriptor->pString + usIndex) = *(gpCurrentStringDescriptor->pString + usIndex + 1);
}
gpCurrentStringDescriptor->usCurrentStringLength--;
}
gpCurrentStringDescriptor->usLastCharacter = usInputCharacter;
break;
case INSERT
: // Toggle insert mode
if (gpCurrentStringDescriptor->fInsertMode == TRUE)
{
gpCurrentStringDescriptor->fInsertMode = FALSE;
}
else
{
gpCurrentStringDescriptor->fInsertMode = TRUE;
}
gpCurrentStringDescriptor->usLastCharacter = usInputCharacter;
break;
case HOME
: // Go to the beginning of the input string
gpCurrentStringDescriptor->usStringOffset = 0 ;
gpCurrentStringDescriptor->usLastCharacter = usInputCharacter;
break;
#ifndef JA2
// Stupid definition causes problems with headers that use the keyword END -- DB
case KEY_END
#else
case END
#endif
: // Go to the end of the input string
gpCurrentStringDescriptor->usStringOffset = gpCurrentStringDescriptor->usCurrentStringLength;
gpCurrentStringDescriptor->usLastCharacter = usInputCharacter;
break;
default
: //
// normal input
//
if (CharacterIsValid(usInputCharacter, gpCurrentStringDescriptor->pFilter) == TRUE)
{
if (gpCurrentStringDescriptor->fInsertMode == TRUE)
{ // Before we can shift characters for the insert, we must make sure we have the space
if (gpCurrentStringDescriptor->usCurrentStringLength < (gpCurrentStringDescriptor->usMaxStringLength - 1))
{ // Before we can add a new character we must shift existing ones to for the insert
for (usIndex = gpCurrentStringDescriptor->usCurrentStringLength; usIndex > gpCurrentStringDescriptor->usStringOffset; usIndex--)
{ // Shift the characters one at a time
*(gpCurrentStringDescriptor->pString + usIndex) = *(gpCurrentStringDescriptor->pString + usIndex - 1);
}
// Ok now we introduce the new character
*(gpCurrentStringDescriptor->pString + usIndex) = usInputCharacter;
gpCurrentStringDescriptor->usStringOffset++;
gpCurrentStringDescriptor->usCurrentStringLength++;
}
}
else
{
// Ok, add character to string (by overwriting)
if (gpCurrentStringDescriptor->usStringOffset < (gpCurrentStringDescriptor->usMaxStringLength - 1))
{ // Ok, we have not exceeded the maximum number of characters yet
*(gpCurrentStringDescriptor->pString + gpCurrentStringDescriptor->usStringOffset) = usInputCharacter;
gpCurrentStringDescriptor->usStringOffset++;
}
// Did we push back the current string length (i.e. add character to end of string)
if (gpCurrentStringDescriptor->usStringOffset > gpCurrentStringDescriptor->usCurrentStringLength)
{ // Add a NULL character
*(gpCurrentStringDescriptor->pString + gpCurrentStringDescriptor->usStringOffset) = 0;
gpCurrentStringDescriptor->usCurrentStringLength++;
}
}
gpCurrentStringDescriptor->usLastCharacter = usInputCharacter;
}
break;
}
}
}
UINT16 GetStringInputState(void)
{
if (gpCurrentStringDescriptor != NULL)
{
return gpCurrentStringDescriptor->usLastCharacter;
}
else
{
return 0;
}
}
BOOLEAN StringInputHasFocus(void)
{
return gfCurrentStringInputState;
}
BOOLEAN SetStringFocus(StringInput *pStringDescriptor)
{
if (pStringDescriptor != NULL)
{
if (gpCurrentStringDescriptor != NULL)
{
gpCurrentStringDescriptor->fFocus = FALSE;
}
// Ok overide current entry
gfCurrentStringInputState = TRUE;
gpCurrentStringDescriptor = pStringDescriptor;
gpCurrentStringDescriptor->fFocus = TRUE;
gpCurrentStringDescriptor->usLastCharacter = 0;
return TRUE;
}
else
{
if (gpCurrentStringDescriptor != NULL)
{
gpCurrentStringDescriptor->fFocus = FALSE;
}
// Ok overide current entry
gfCurrentStringInputState = FALSE;
gpCurrentStringDescriptor = NULL;
return TRUE;
}
}
UINT16 GetCursorPositionInString(StringInput *pStringDescriptor)
{
return pStringDescriptor->usStringOffset;
}
BOOLEAN StringHasFocus(StringInput *pStringDescriptor)
{
if (pStringDescriptor != NULL)
{
return pStringDescriptor->fFocus;
}
else
{
return FALSE;
}
}
void RestoreString(StringInput *pStringDescriptor)
{
memcpy(pStringDescriptor->pString, pStringDescriptor->pOriginalString, pStringDescriptor->usMaxStringLength * 2);
pStringDescriptor->usStringOffset = 0;
pStringDescriptor->usCurrentStringLength = 0;
while ((pStringDescriptor->usStringOffset < pStringDescriptor->usMaxStringLength)&&(*(pStringDescriptor->pString + pStringDescriptor->usStringOffset) != 0))
{
//
// Find the last character in the string
//
pStringDescriptor->usStringOffset++;
pStringDescriptor->usCurrentStringLength++;
}
if (pStringDescriptor->usStringOffset == pStringDescriptor->usMaxStringLength)
{
//
// Hum the current string has no null terminator. Invalidate the string and
// start from scratch
//
memset(pStringDescriptor->pString, 0, pStringDescriptor->usMaxStringLength * 2);
pStringDescriptor->usStringOffset = 0;
pStringDescriptor->usCurrentStringLength = 0;
}
pStringDescriptor->fInsertMode = FALSE;
}
void EndStringInput(StringInput *pStringDescriptor)
{ // Make sure we have a valid pStringDescriptor
if (pStringDescriptor != NULL)
{ // make sure the gpCurrentStringDescriptor is NULL if necessary
if (pStringDescriptor == gpCurrentStringDescriptor)
{
gpCurrentStringDescriptor = NULL;
gfCurrentStringInputState = FALSE;
}
// Make sure we have a valid string within the string descriptor
if (pStringDescriptor->pOriginalString != NULL)
{ // free up the string
MemFree(pStringDescriptor->pOriginalString);
}
// free up the descriptor
MemFree(pStringDescriptor);
}
}
//
// Miscellaneous input-related utility functions:
//
void RestrictMouseToXYXY(UINT16 usX1, UINT16 usY1, UINT16 usX2, UINT16 usY2)
{
SGPRect TempRect;
TempRect.iLeft = usX1;
TempRect.iTop = usY1;
TempRect.iRight = usX2;
TempRect.iBottom = usY2;
RestrictMouseCursor(&TempRect);
}
void RestrictMouseCursor(SGPRect *pRectangle)
{
// Make a copy of our rect....
memcpy( &gCursorClipRect, pRectangle, sizeof( gCursorClipRect ) );
ClipCursor((RECT *)pRectangle);
fCursorWasClipped = TRUE;
}
void FreeMouseCursor(void)
{
ClipCursor(NULL);
fCursorWasClipped = FALSE;
}
void RestoreCursorClipRect( void )
{
if ( fCursorWasClipped )
{
ClipCursor( &gCursorClipRect );
}
}
void GetRestrictedClipCursor( SGPRect *pRectangle )
{
GetClipCursor((RECT *) pRectangle );
}
BOOLEAN IsCursorRestricted( void )
{
return( fCursorWasClipped );
}
void SimulateMouseMovement( UINT32 uiNewXPos, UINT32 uiNewYPos )
{
FLOAT flNewXPos, flNewYPos;
// Wizardry NOTE: This function currently doesn't quite work right for in any Windows resolution other than 640x480.
// mouse_event() uses your current Windows resolution to calculate the resulting x,y coordinates. So in order to get
// the right coordinates, you'd have to find out the current Windows resolution through a system call, and then do:
// uiNewXPos = uiNewXPos * SCREEN_WIDTH / WinScreenResX;
// uiNewYPos = uiNewYPos * SCREEN_HEIGHT / WinScreenResY;
//
// JA2 doesn't have this problem, 'cause they use DirectDraw calls that change the Windows resolution properly.
//
// Alex Meduna, Dec. 3, 1997
// Adjust coords based on our resolution
flNewXPos = ( (FLOAT)uiNewXPos / SCREEN_WIDTH ) * 65536;
flNewYPos = ( (FLOAT)uiNewYPos / SCREEN_HEIGHT ) * 65536;
mouse_event( MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, (UINT32)flNewXPos, (UINT32)flNewYPos, 0, 0 );
}
BOOLEAN InputEventInside(InputAtom *Event, UINT32 uiX1, UINT32 uiY1, UINT32 uiX2, UINT32 uiY2)
{
UINT32 uiEventX, uiEventY;
uiEventX = _EvMouseX(Event);
uiEventY = _EvMouseY(Event);
return((uiEventX >= uiX1) && (uiEventX <= uiX2) && (uiEventY >= uiY1) && (uiEventY <= uiY2));
}
void DequeueAllKeyBoardEvents()
{
InputAtom InputEvent;
MSG KeyMessage;
//dequeue all the events waiting in the windows queue
while( PeekMessage( &KeyMessage, ghWindow, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) );
//Deque all the events waiting in the SGP queue
while (DequeueEvent(&InputEvent) == TRUE)
{
//dont do anything
}
}
void HandleSingleClicksAndButtonRepeats( void )
{
UINT32 uiTimer;
uiTimer = GetTickCount();
// Is there a LEFT mouse button repeat
if (gfLeftButtonState)
{
if ((guiLeftButtonRepeatTimer > 0)&&(guiLeftButtonRepeatTimer <= uiTimer))
{
UINT32 uiTmpLParam;
POINT MousePos;
GetCursorPos(&MousePos);
uiTmpLParam = ((MousePos.y << 16) & 0xffff0000) | (MousePos.x & 0x0000ffff);
QueueEvent(LEFT_BUTTON_REPEAT, 0, uiTmpLParam);
guiLeftButtonRepeatTimer = uiTimer + BUTTON_REPEAT_TIME;
}
}
else
{
guiLeftButtonRepeatTimer = 0;
}
// Is there a RIGHT mouse button repeat
if (gfRightButtonState)
{
if ((guiRightButtonRepeatTimer > 0)&&(guiRightButtonRepeatTimer <= uiTimer))
{
UINT32 uiTmpLParam;
POINT MousePos;
GetCursorPos(&MousePos);
uiTmpLParam = ((MousePos.y << 16) & 0xffff0000) | (MousePos.x & 0x0000ffff);
QueueEvent(RIGHT_BUTTON_REPEAT, 0, uiTmpLParam);
guiRightButtonRepeatTimer = uiTimer + BUTTON_REPEAT_TIME;
}
}
else
{
guiRightButtonRepeatTimer = 0;
}
}
INT16 GetMouseWheelDeltaValue( UINT32 wParam )
{
INT16 sDelta = HIWORD( wParam );
return( sDelta / WHEEL_DELTA );
}