/***************************************************************************/
/*  Description: Mouse.c  Part of CPA INO                                  */
/*                                                                         */
/*  Author: F. Jentey                                                      */
/*  Last Update: 09/08/97                                                  */
/*                                                                         */
/***************************************************************************/
 
 
 
#include "INOInit.h"
#include "Mouse.h"
 
 
#define  M_Mouse()     INO_g_p_stMouseInterface->lpVtbl
 
/*
        tdstMouseStatus : mouse status informations
*/
typedef struct _stMouseStatus
{
    DIDEVCAPS                     m_stCaps;
    DIMOUSESTATE                  m_stStates[2];
    short                         m_wAcquired;
    short                         m_wCurrentBuffer;
    /* Link with a GLD device */
    short                         m_wLinkedWithGLD;
    GLD_tdhDevice                 m_tdGLDDeviceHandle;
    GLD_tdstDeviceAttributes      m_stGLDDeviceAttributes;
    float                         m_fPixelsPerMickeys;
    float                         m_fScreenPosX;
    float                         m_fScreenPosY;
	int							  m_iMousePosX;
	int							  m_iMousePosY;
	int							  m_iOldMousePosX;
	int							  m_iOldMousePosY;
} tdstMouseStatus;
 

 
/* Mouse init OK */
short   INO_g_wMouseInitOk = 0;
 
/* The mouse state structure */
tdstMouseStatus         INO_g_stMouseState;
 
/* Mouse device interface */
LPDIRECTINPUTDEVICE     INO_g_p_stMouseInterface;
 
/* Mouse last error code */
u_long                  INO_g_ulMouseErrorCode;
 
/* Number of INO_fn_wReadMouse() Call */
u_long                  INO_g_ulMouseCounter = 0;
 
 
 
/*********************************************************************
                    INITIALISATION
*********************************************************************/
 
short INO_fn_wInitMouse(HINSTANCE hInstance, HWND hWindow)
{
    GUID        guid = GUID_SysMouse;
    HRESULT     DInputErr;
 
	if (INO_g_wMouseInitOk) return (0);
 
    /* Init direct input */
    if (!INO_fn_wInitDirectInput(hInstance,hWindow)) return(C_wMouseError);
 
    DInputErr = INO_g_p_stDInputInterface->lpVtbl->CreateDevice(
                                                                INO_g_p_stDInputInterface,
                                                                &guid,
                                                                &INO_g_p_stMouseInterface,
                                                                NULL
                                                               );
    switch (DInputErr)
    {
    case DI_OK:
        break;
        
    case DIERR_INVALIDPARAM:
    case DIERR_OUTOFMEMORY:
    case DIERR_NOINTERFACE:
    case DIERR_DEVICENOTREG:
        INO_fn_vReleaseDirectInput();
        return(C_wMouseError);
    }
 
    /* Get Mouse Capabilities (number of axis and button) */
    INO_g_stMouseState.m_stCaps.dwSize = sizeof(DIDEVCAPS);
    DInputErr = M_Mouse()->GetCapabilities(INO_g_p_stMouseInterface,&INO_g_stMouseState.m_stCaps);
    if (DInputErr != DI_OK)
    {
        /* TO DO, warning, message */
    }
    /* TO DO, check if the device is physicaly attached */
 
    /* Make sure the mouse isn't acquire before calling setDataFormat and    */
    /* SetCooperativeLevel. Return always OK                                 */
    DInputErr = M_Mouse()->Unacquire(INO_g_p_stMouseInterface);
    INO_g_stMouseState.m_wAcquired = 0;
	
	/* Tell DirectInput that we want to receive data in mouse format  */
    DInputErr = M_Mouse()->SetDataFormat(
                                         INO_g_p_stMouseInterface,
                                         &c_dfDIMouse
                                        );
    switch (DInputErr)
    {
    case DI_OK:
        break;
 
    case DIERR_INVALIDPARAM:
    case DIERR_ACQUIRED:
        M_Mouse()->Release(INO_g_p_stMouseInterface);
        INO_fn_vReleaseDirectInput();
        return(C_wMouseError);
		break;
    }
 
    /* Set mouse cooperative level */
    DInputErr = M_Mouse()->SetCooperativeLevel(
                                               INO_g_p_stMouseInterface,
                                               hWindow,
                                               DISCL_EXCLUSIVE | DISCL_FOREGROUND
                                              );
    switch (DInputErr)
    {
    case DI_OK:
        break;
    case DIERR_INVALIDPARAM:
        M_Mouse()->Release(INO_g_p_stMouseInterface);
        INO_fn_vReleaseDirectInput();
        return(C_wMouseError);
    }
 
    /* Try to acquire the mouse */
    DInputErr = M_Mouse()->Acquire(INO_g_p_stMouseInterface);
    switch (DInputErr)
    {
    case DI_OK:
	case S_FALSE:    /* Already acquired, OK */
        INO_g_stMouseState.m_wAcquired = 1;
        break;
    case DIERR_INPUTLOST:
        INO_g_stMouseState.m_wAcquired = 0;
		break;
    case DIERR_INVALIDPARAM:
        INO_g_stMouseState.m_wAcquired = 0;
        M_Mouse()->Release(INO_g_p_stMouseInterface);
        INO_fn_vReleaseDirectInput();
        return(C_wMouseError);
    }
 
    /* Init mouse state */
    INO_g_stMouseState.m_wCurrentBuffer = 0;
    INO_g_stMouseState.m_wLinkedWithGLD = 0;
 
    INO_g_ulMouseCounter = 0;
    INO_g_wMouseInitOk++;
 
    return (0);
}
 
 
short INO_fn_wInitMouseWithGLD(HINSTANCE hInstance, GLD_tdhDevice tdGLDDeviceHandle)
{
    HWND WndHandle;
	POINT Point;
 
	if (INO_g_wMouseInitOk) return (0);
 
    if (!GLD_bIsDeviceHandleValid(tdGLDDeviceHandle))
    {
        INO_g_ulMouseErrorCode = C_ErrMouseInvalidGLDDeviceHandle;
        return (C_wMouseError);
    }
    
    if (GLD_bGetDeviceAttributes(tdGLDDeviceHandle, &INO_g_stMouseState.m_stGLDDeviceAttributes))
    {
        /* Check the window handle of the device */
        if (INO_g_stMouseState.m_stGLDDeviceAttributes.bFullScreen)
            WndHandle = INO_g_stMouseState.m_stGLDDeviceAttributes.hFullScreenModeWnd;
        else
            WndHandle = INO_g_stMouseState.m_stGLDDeviceAttributes.hNormalModeWnd;
        if (INO_fn_wInitMouse(hInstance,WndHandle) != C_wMouseError)
        {
            INO_g_stMouseState.m_wLinkedWithGLD    = 1;
            INO_g_stMouseState.m_tdGLDDeviceHandle = tdGLDDeviceHandle;
            INO_g_stMouseState.m_fPixelsPerMickeys = 1.0;
            INO_g_stMouseState.m_fScreenPosX       = 0.5;
            INO_g_stMouseState.m_fScreenPosY       = 0.5;

			
            return (0);
        }
        else
            return (C_wMouseError);
    }
    else
    {
        if (Erm_M_uwCheckError(GLD,C_ucErmDefaultChannel))
            Erm_M_ClearLastError(C_ucErmDefaultChannel);
        INO_g_ulMouseErrorCode = C_ErrMouseFailedGettingDeviceAttributes;
        return (C_wMouseError);
    }
}
 
 
short INO_fn_vFreeMouse(void)
{
    if (!INO_g_wMouseInitOk)
    {
        INO_g_ulMouseErrorCode = C_ErrMouseNotInitialized;
        return (C_wMouseError);
    }
 
    if (INO_g_stMouseState.m_wAcquired)
    {
        M_Mouse()->Unacquire(INO_g_p_stMouseInterface);
        INO_g_stMouseState.m_wAcquired = 0;
    }
 
    M_Mouse()->Release(INO_g_p_stMouseInterface);
    INO_fn_vReleaseDirectInput();
 
    INO_g_wMouseInitOk = 0;
    return (0);
}
 
 
short INO_fn_wGetMouseNumberOfButtons(void)
{
    if (!INO_g_wMouseInitOk)
    {
        INO_g_ulMouseErrorCode = C_ErrMouseNotInitialized;
        return (C_wMouseError);
    }
 
    return ((short)INO_g_stMouseState.m_stCaps.dwButtons);
}
 
 
short INO_fn_wGetMouseNumberOfAxes(void)
{
    if (!INO_g_wMouseInitOk)
    {
        INO_g_ulMouseErrorCode = C_ErrMouseNotInitialized;
        return (C_wMouseError);
    }
 
    return ((short)INO_g_stMouseState.m_stCaps.dwAxes);
}
 
 
/*********************************************************************
              POLLING FUNCTION, GETTING MOUSE STATE
*********************************************************************/
 
short INO_fn_wReadMouse(void)
{
    HRESULT       DInputErr;
	POINT         Point; 
	HWND		  WndHandle;
 
    if (!INO_g_wMouseInitOk)
    {
        INO_g_ulMouseErrorCode = C_ErrMouseNotInitialized;
        return (C_wMouseError);
    }
 
    /* Increase the internal frame counter */
    INO_g_ulMouseCounter++;
 
    /* Try to acquire the mouse if not done */
    if (!INO_g_stMouseState.m_wAcquired)
    {
        DInputErr = M_Mouse()->Acquire(INO_g_p_stMouseInterface);
        switch (DInputErr)
        {
        case DI_OK:
		case S_FALSE:
            INO_g_stMouseState.m_wAcquired = 1;
            break;
 
        case DIERR_INPUTLOST:
            INO_g_ulMouseErrorCode = C_ErrMouseFocusLost;
            return (C_wMouseError);
 
        case DIERR_INVALIDPARAM:
            INO_g_stMouseState.m_wAcquired = 0;
            INO_g_ulMouseErrorCode = C_ErrMouseDirectInputError;
            return (C_wMouseError);
 
		default:
		    break;
        }
    }
 
    /* Flip the mouse state buffer */
    INO_g_stMouseState.m_wCurrentBuffer = 1 - INO_g_stMouseState.m_wCurrentBuffer;
 
    /* Get mouse current state */
	DInputErr = M_Mouse()->GetDeviceState(
		                                  INO_g_p_stMouseInterface,
		                                  sizeof(DIMOUSESTATE),
		                                  &INO_g_stMouseState.m_stStates[INO_g_stMouseState.m_wCurrentBuffer]
		                                 );
	switch (DInputErr)
	{
	case DI_OK:
		INO_g_stMouseState.m_wAcquired = 1;
		break;
 
    case E_PENDING:
        break;
		
	case DIERR_INPUTLOST:
    /*case DIERR_NOTACQUIRED:*/
		INO_g_stMouseState.m_wAcquired = 0;
        INO_g_ulMouseErrorCode = C_ErrMouseFocusLost;
        return (C_wMouseError);
		
	case DIERR_INVALIDPARAM:
		INO_g_stMouseState.m_wAcquired = 0;
        INO_g_ulMouseErrorCode = C_ErrMouseDirectInputError;
		return(C_wMouseError);
		
	default:
		break;
	}
 
	//read Cursor Position
    if (INO_g_stMouseState.m_stGLDDeviceAttributes.bFullScreen)
         WndHandle = INO_g_stMouseState.m_stGLDDeviceAttributes.hFullScreenModeWnd;
    else
         WndHandle = INO_g_stMouseState.m_stGLDDeviceAttributes.hNormalModeWnd;

	//swap Postion;
	INO_g_stMouseState.m_iOldMousePosX  =	INO_g_stMouseState.m_iMousePosX;
	INO_g_stMouseState.m_iOldMousePosY  =   INO_g_stMouseState.m_iMousePosY;
	
	GetCursorPos( &Point   ); 
	ScreenToClient( WndHandle, &Point );
	INO_g_stMouseState.m_iMousePosX  = Point.x;
	INO_g_stMouseState.m_iMousePosY  = Point.y;
	


	
    /* If linked with a GLD device, get the device attributes */
    if (INO_g_stMouseState.m_wLinkedWithGLD)
    {
        if (GLD_bGetDeviceAttributes(INO_g_stMouseState.m_tdGLDDeviceHandle,
                                      &INO_g_stMouseState.m_stGLDDeviceAttributes))
        {
            INO_g_stMouseState.m_fScreenPosX +=
                ((float)INO_g_stMouseState.m_stStates[INO_g_stMouseState.m_wCurrentBuffer].lX * INO_g_stMouseState.m_fPixelsPerMickeys)
                       / (float)(INO_g_stMouseState.m_stGLDDeviceAttributes.dwWidth-1);
            if (INO_g_stMouseState.m_fScreenPosX<0.0) INO_g_stMouseState.m_fScreenPosX = 0.0;
            if (INO_g_stMouseState.m_fScreenPosX>1.0) INO_g_stMouseState.m_fScreenPosX = 1.0;
            INO_g_stMouseState.m_fScreenPosY +=
                ((float)INO_g_stMouseState.m_stStates[INO_g_stMouseState.m_wCurrentBuffer].lY * INO_g_stMouseState.m_fPixelsPerMickeys)
                       / (float)(INO_g_stMouseState.m_stGLDDeviceAttributes.dwHeight-1);
            if (INO_g_stMouseState.m_fScreenPosY<0.0) INO_g_stMouseState.m_fScreenPosY = 0.0;
            if (INO_g_stMouseState.m_fScreenPosY>1.0) INO_g_stMouseState.m_fScreenPosY = 1.0;
        }
        else
        {
            if (Erm_M_uwCheckError(GLD,C_ucErmDefaultChannel))
                Erm_M_ClearLastError(C_ucErmDefaultChannel);
            INO_g_ulMouseErrorCode = C_ErrMouseFailedGettingDeviceAttributes;
            return (C_wMouseError);
        }
    }
    return(0);
}
 



	


short INO_fn_wGetMousePosition(int *p_iX, int *p_iY)
{
    if (!INO_g_wMouseInitOk)
    {
        INO_g_ulMouseErrorCode = C_ErrMouseNotInitialized;
        return (C_wMouseError);
    }
    if (!INO_g_stMouseState.m_wLinkedWithGLD)
    {
        INO_g_ulMouseErrorCode = C_ErrNoGLDDeviceLinkedWithMouse;
        return (C_wMouseError);
    }
    *p_iX = INO_g_stMouseState.m_iMousePosX;
    *p_iY = INO_g_stMouseState.m_iMousePosY;

	if(	(INO_g_stMouseState.m_iMousePosX >=0) &&
		(INO_g_stMouseState.m_iMousePosY >=0) &&
		(INO_g_stMouseState.m_iMousePosX <= INO_g_stMouseState.m_stGLDDeviceAttributes.dwWidth) &&
		(INO_g_stMouseState.m_iMousePosY <= INO_g_stMouseState.m_stGLDDeviceAttributes.dwHeight) 
	  )
		return C_wMouseTrue;
	else
		return C_wMouseFalse;

}



short INO_fn_wGetMousePositionInGldDevice(float *p_fX, float *p_fY)
{
    if (!INO_g_wMouseInitOk)
    {
        INO_g_ulMouseErrorCode = C_ErrMouseNotInitialized;
        return (C_wMouseError);
    }
    if (!INO_g_stMouseState.m_wLinkedWithGLD)
    {
        INO_g_ulMouseErrorCode = C_ErrNoGLDDeviceLinkedWithMouse;
        return (C_wMouseError);
    }
    *p_fX = INO_g_stMouseState.m_fScreenPosX;
    *p_fY = INO_g_stMouseState.m_fScreenPosY;
 
    return (0);
}
 
 
short INO_fn_wLeftMouseButtonDown(void)
{
    if (!INO_g_wMouseInitOk)
    {
        INO_g_ulMouseErrorCode = C_ErrMouseNotInitialized;
        return (C_wMouseError);
    }
    if (INO_g_stMouseState.m_stStates[INO_g_stMouseState.m_wCurrentBuffer].rgbButtons[0])
        return (C_wMouseTrue);
    else
        return (C_wMouseFalse);
}
 
short INO_fn_wRightMouseButtonDown(void)
{
    if (!INO_g_wMouseInitOk)
    {
        INO_g_ulMouseErrorCode = C_ErrMouseNotInitialized;
        return (C_wMouseError);
    }
    if (INO_g_stMouseState.m_stStates[INO_g_stMouseState.m_wCurrentBuffer].rgbButtons[1])
        return (C_wMouseTrue);
    else
        return (C_wMouseFalse);
}
 
short INO_fn_wLeftMouseButtonJustDown(void)
{
    if (!INO_g_wMouseInitOk)
    {
        INO_g_ulMouseErrorCode = C_ErrMouseNotInitialized;
        return (C_wMouseError);
    }
    if ( (INO_g_stMouseState.m_stStates[INO_g_stMouseState.m_wCurrentBuffer].rgbButtons[0]) &&
         (!INO_g_stMouseState.m_stStates[1-INO_g_stMouseState.m_wCurrentBuffer].rgbButtons[0]) )
        return (C_wMouseTrue);
    else
        return (C_wMouseFalse);
}
 
short INO_fn_wRightMouseButtonJustDown(void)
{
    if (!INO_g_wMouseInitOk)
    {
        INO_g_ulMouseErrorCode = C_ErrMouseNotInitialized;
        return (C_wMouseError);
    }
    if ( (INO_g_stMouseState.m_stStates[INO_g_stMouseState.m_wCurrentBuffer].rgbButtons[1]) &&
         (!INO_g_stMouseState.m_stStates[1-INO_g_stMouseState.m_wCurrentBuffer].rgbButtons[1]) )
        return (C_wMouseTrue);
    else
        return (C_wMouseFalse);
}
 
short INO_fn_wLeftMouseButtonJustUp(void)
{
    if (!INO_g_wMouseInitOk)
    {
        INO_g_ulMouseErrorCode = C_ErrMouseNotInitialized;
        return (C_wMouseError);
    }
    if ( (!INO_g_stMouseState.m_stStates[INO_g_stMouseState.m_wCurrentBuffer].rgbButtons[0]) &&
         (INO_g_stMouseState.m_stStates[1-INO_g_stMouseState.m_wCurrentBuffer].rgbButtons[0]) )
        return (C_wMouseTrue);
    else
        return (C_wMouseFalse);
}
 
short INO_fn_wRightMouseButtonJustUp(void)
{
    if (!INO_g_wMouseInitOk)
    {
        INO_g_ulMouseErrorCode = C_ErrMouseNotInitialized;
        return (C_wMouseError);
    }
    if ( (!INO_g_stMouseState.m_stStates[INO_g_stMouseState.m_wCurrentBuffer].rgbButtons[1]) &&
         (INO_g_stMouseState.m_stStates[1-INO_g_stMouseState.m_wCurrentBuffer].rgbButtons[1]) )
        return (C_wMouseTrue);
    else
        return (C_wMouseFalse);
}
 
 
 
u_long INO_fn_ulGetMouseErrorCode(void)
{
    return(INO_g_ulMouseErrorCode);
}
