/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Microsoft Corporation, 1989                                 */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/

/**************************************************************************
 *
 * SOURCE FILE NAME = VMPOS.TMP
 *
 * DESCRIPTIVE NAME = Virtual Mouse Device Driver Int 33h Position Services 
 *
 *
 * VERSION =   V2.0
 *
 * DATE        09/10/90
 *
 * DESCRIPTION This module contains the VMD's Int 33h position services. 
 *             
 *
 * FUNCTIONS   
 * 
 *      vmInt33QueryStatus()      Int 33h Query Position/Button Status (function 3)
 *      vmInt33SetPosition()      Int 33h Set Position (function 4)                
 *      vmBoundedX()              Returns closest legal x-coordinate               
 *      vmBoundedY()              Returns closest legal y-coordinate               
 *      vmSetPosition()           Set mouse position to x,y                        
 *      vmCheckOffRegion()        Check if Cursor is in Off Region                 
 *      vmInt33GetPressInfo()     Int 33h Get Button Press Info (function 5)       
 *      vmInt33GetReleaseInfo()   Int 33h Get Button Release Info (function 6)     
 *      vmInt33GetMotionCounts()  Int 33h Get Motion Counters (function 11)        
 * 
 * 
 *  ENTRY POINTS: 
 * 
 * DEPENDENCIES:  
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/
#include "vmdp.h"

#ifdef   VDDSTRICT
MODNAME = __FILE__;
#endif

/*
**    External References
*/

extern SHORT nxPixelsRemain;
extern SHORT nyPixelsRemain;
extern MHARDWARE mhwInstalled;
#pragma  BEGIN_SWAP_CODE

 /****************************************************************************
 *
 *  FUNCTION NAME  :  vmInt33QueryStatus() 
 *
 *  DESCRIPTION    :  Int 33h Query Position/Button Status (function 3) 
 *
 *  INPUT          :
 *                   pcrf -> VDM register frame
 *  OUTPUT         :
 *                    EMULATED
 *                        TRUE
 *                    NOT EMULATED
 *                        FALSE (pass control to next VDD and/or ROM)
 *  USES          :
 *                  32-bit small-model PASCAL calling/register conventions
 *
 *  CONTEXT       :
 *                       VDM Task-time
 *
 *  PSEUDO-CODE   :                                  REFERENCES
 *      store button states into VDM BX;
 *      if 320x200 mode
 *          store even cursor x value into VDM CX;
 *      else
 *          store cursor x value into VDM CX;
 *      store cursor y value into VDM DX;
 **************************************************************************/

BOOL PRIVENTRY vmInt33QueryStatus(register PCRF pcrf)
{
  BX(pcrf) = (WORD)VDMData.flButtons;
  CX(pcrf) = (WORD)(VDMData.mstates.xCur << VDMData.fShiftX);

  if (VDMData.vmss.vmss_ulCellHeight == 1)         /* graphics mode          */
    DX(pcrf) = (WORD)VDMData.mstates.yCur;
  else                                             /* text mode              */
    DX(pcrf) = (WORD)( (VDMData.mstates.yCur *8)/
                         VDMData.vmss.vmss_ulCellHeight);
      
  return  TRUE;
}                                      /* vmInt33QueryStatus                 */

 /****************************************************************************
 *
 *  FUNCTION NAME  :  vmInt33SetPosition() 
 *
 *  DESCRIPTION    :  Int 33h Set Position (function 4) 
 *
 *  INPUT          :
 *                   pcrf -> VDM register frame
 *  OUTPUT         :
 *                   EMULATED
 *                       TRUE
 *                   NOT EMULATED
 *                       FALSE (pass control to next VDD and/or ROM)
 *  USES           :
 *                   32-bit small-model PASCAL calling/register conventions
 *
 *  CONTEXT        :
 *      VDM Task-time
 *
 *  PSEUDO-CODE    :                                 REFERENCES
 *      check x and y against boundaries;
 *      call set mouse pointer postion;
 ****************************************************************************/

BOOL PRIVENTRY vmInt33SetPosition(register PCRF pcrf)
{
  vmSetPosition(CURRENT_VDM,
                 vmBoundedX(CURRENT_VDM,
                         ((LONG)(SHORT)CX(pcrf)) >> VDMData.fShiftX),
                 vmBoundedY(CURRENT_VDM, 
                         (VDMData.vmss.vmss_ulCellHeight == 1)?
                         ((LONG)(SHORT)DX(pcrf)):
                         ((LONG)(((LONG)(SHORT)DX(pcrf))
                          *VDMData.vmss.vmss_ulCellHeight)/8)), TRUE);
  return  TRUE;
}                                      /* vmInt33SetPosition                 */

 /****************************************************************************
 *
 *  FUNCTION NAME  :  vmBoundedX() 
 *
 *  DESCRIPTION    :  Returns closest legal x-coordinate 
 *
 *  INPUT          :
 *                    hvdm -> VDM
 *                    x - proposed x coordinate
 *  OUTPUT         :
 *                    Closest legal x coordinate
 *  USES           :
 *      32-bit small-model PASCAL calling/register conventions
 *
 *  CONTEXT        :
 *      VDM Task-time
 *
 *  PSEUDO-CODE    :                                 REFERENCES
 *      if pointer outside left bound
 *          set it to left bound;
 *      else if pointer outside right bound
 *          set it to right bound;
 *
 ****************************************************************************/

ULONG PRIVENTRY vmBoundedX(HVDM hvdm,register LONG x)
{
  if ( x < pVDMData(hvdm)->mstates.xMin )
    x = pVDMData(hvdm)->mstates.xMin;
  else
    if ( x > pVDMData(hvdm)->mstates.xMax )
      x = pVDMData(hvdm)->mstates.xMax;
  return  x;
}                                      /* vmBoundedX                         */

 /****************************************************************************
 *
 *  FUNCTION NAME  :  vmBoundedY() 
 *
 *  DESCRIPTION    : Returns closest legal y-coordinate 
 *
 *  INPUT          :
 *                    hvdm -> VDM
 *                    y - proposed y coordinate
 *  OUTPUT         :
 *                   Closest legal y coordinate
 *  USES           :
 *      32-bit small-model PASCAL calling/register conventions
 *
 *  CONTEXT        :
 *      VDM Task-time
 *
 *  PSEUDO-CODE    :                                 REFERENCES
 *      if pointer outside top bound
 *          set it to top bound;
 *      else if pointer outside bottom bound
 *          set it to bottom bound;
 *
 ****************************************************************************/

ULONG PRIVENTRY vmBoundedY(HVDM hvdm,register LONG y)
{
  if ( y < pVDMData(hvdm)->mstates.yMin )
    y = pVDMData(hvdm)->mstates.yMin;
  else
    if ( y > pVDMData(hvdm)->mstates.yMax )
      y = pVDMData(hvdm)->mstates.yMax;
  return  y;
}                                      /* vmBoundedY                         */

 /****************************************************************************
 *
 *  FUNCTION NAME  :  vmSetPosition() 
 *
 *  DESCRIPTION    :  Set mouse position to x,y 
 *
 *  INPUT          :
 *                        hvdm -> VDM
 *                        x == new x coordinate (pre-bounded)
 *                        y == new y coordinate (pre-bounded)
 *          fApp == TRUE if app moved the pointer, FALSE if physical DD did
 *  OUTPUT         :    NONE
 *      
 *  USES           :
 *      32-bit small-model PASCAL calling/register conventions
 *
 *  CONTEXT        :
 *      Task-time
 *
 *  PSEUDO-CODE    :                                 REFERENCES
 *      store new pointer position;
 *      notify PDD the new pointer position;
 *      if pointer is not hidden
 *          show pointer in its new position;
 *
 ***************************************************************************/

VOID PRIVENTRY vmSetPosition( HVDM hvdm, ULONG x, ULONG y, BOOL fApp )
{
  register PVDMDATA pvd = pVDMData(hvdm);

#ifdef   VDDSTRICT
  if ( x != vmBoundedX( hvdm, x ) )
  {
    PRINTDEBUG("Bad x-coordinate (%04x)\n", x);
    x = vmBoundedX(hvdm, x);
  } 
  if ( y != vmBoundedY( hvdm, y ) )
  {
    PRINTDEBUG("Bad y-coordinate (%04x)\n", y);
    y = vmBoundedY(hvdm, y);
  } 
#endif
  if ( pvd->vmss.vmss_ulCellHeight == 1 )
  {                                   /* graphics mode                       */
    pvd->mstates.xCur = x;
    pvd->mstates.yCur = y;
  } 
  else
  {         /* text mode: align at character boundary, save Pixel remainder  */
    pvd->mstates.xCur = (x/pvd->vmss.vmss_ulCellWidth)
       *pvd->vmss.vmss_ulCellWidth;

    pvd->mstates.yCur = (y/pvd->vmss.vmss_ulCellHeight)
       *pvd->vmss.vmss_ulCellHeight;

    nxPixelsRemain = x-pvd->mstates.xCur;  /* must be positive since we      */
                                           /* truncated                      */
    nyPixelsRemain = y-pvd->mstates.yCur;
  } 
  if ( !pvd->mstates.fPtrHidden )
    if ( pvd->mstates.fOffEnable && vmCheckOffRegion(hvdm) )
    {
      if ( !pvd->mstates.fInOffRegion )
      {
        pvd->mstates.fInOffRegion = TRUE;
        vmHidePointer(hvdm);
      } 
    } 
    else
    {
      pvd->mstates.fInOffRegion = FALSE;
      vmShowPointer(hvdm);
    } 
}                                      /* vmSetPosition                      */

 /****************************************************************************
 *
 *  FUNCTION NAME  :  vmCheckOffRegion() 
 *
 *  DESCRIPTION    :  Check if Cursor is in Off Region 
 *
 *  INPUT          :
 *                   hvdm -> VDM
 *  OUTPUT         :
 *               TRUE  - mouse cursor is within the conditional off region
 *               FALSE - mouse cursor is outside the conditional off region
 *  USES           :
 *                   32-bit small-model PASCAL calling/register conventions
 *
 *  CONTEXT        :
 *                    Task-time
 *
 *  PSEUDO-CODE    :                                 REFERENCES
 *      compute cursor box coordinates according to text/graphics mode;
 *      if cursor box overlapped with conditional off box
 *          return TRUE;
 *      else
 *          return FALSE;
 *
 ****************************************************************************/

BOOL PRIVENTRY vmCheckOffRegion(HVDM hvdm)
{
  register PVDMDATA pvd = pVDMData(hvdm);
  LONG xCurMin,xCurMax,yCurMin,yCurMax;

  if ( pvd->vmss.vmss_ulCellHeight == 1 )
  {                                   /* graphics mode                       */
    xCurMin = ((pvd->mstates.xCur-pvd->mstates.xHot)/
              pvd->vmss.vmss_ulPtrUnitWidth) *pvd->vmss.vmss_ulPtrUnitWidth;
    yCurMin = pvd->mstates.yCur-pvd->mstates.yHot;
    xCurMax = xCurMin+pvd->vmss.vmss_ulPtrWidth-1;
    yCurMax = yCurMin+pvd->vmss.vmss_ulPtrHeight-1;
  } 
  else
  {                                   /* text mode                           */
    xCurMin = pvd->mstates.xCur;
    yCurMin = pvd->mstates.yCur;
    xCurMax = pvd->mstates.xCur+pvd->vmss.vmss_ulPtrWidth-1;
    yCurMax = pvd->mstates.yCur+pvd->vmss.vmss_ulPtrHeight-1;
  } 

  if ((xCurMax < pvd->mstates.xMinOff) || (xCurMin > pvd->mstates.xMaxOff) ||
      (yCurMax < pvd->mstates.yMinOff) || ( yCurMin > pvd->mstates.yMaxOff))

    return  FALSE;
  else
    return  TRUE;
}                                      /* vmCheckOffRegion                   */



 /****************************************************************************
 *
 *  FUNCTION NAME  :  vmInt33GetPressInfo() 
 *
 *  DESCRIPTION    :  Int 33h Get Button Press Info (function 5) 
 *
 *  INPUT          :
 *                    pcrf -> VDM register frame
 *  OUTPUT         :
 *                    EMULATED
 *                        TRUE
 *                    NOT EMULATED
 *                        FALSE (pass control to next VDD and/or ROM)
 *  USES           :
 *                    32-bit small-model PASCAL calling/register conventions
 *
 *  CONTEXT        :
 *                     VDM Task-time
 *
 *  PSEUDO-CODE    :                                 REFERENCES
 *      store number of button presses into VDM BX;
 *      clear number of button presses;
 *      if 320x200 mode
 *          store x of last press truncated to even into VDM CX;
 *      else
 *          store x of last press into VDM CX;
 *      store y of last press into VDM DX;
 *      store button states into VDM AX;
 *
 ****************************************************************************/

BOOL PRIVENTRY vmInt33GetPressInfo(register PCRF pcrf)
{
  register ULONG nButton = (ULONG)BX(pcrf);   /* button number               */

  if ( nButton >= mhwInstalled.mhw_nButtons ) /* if not a valid button       */
    nButton = mhwInstalled.mhw_nButtons-1;    /* make it the secondary button*/

  BX(pcrf) = (WORD)VDMData.mstates.butinfo[nButton].bi_nPresses;

  VDMData.mstates.butinfo[nButton].bi_nPresses = 0;
  CX(pcrf) = (WORD)(VDMData.mstates.butinfo[nButton].bi_xLastPress << 
                    VDMData.fShiftX);

  if ( VDMData.vmss.vmss_ulCellHeight == 1 )  /* graphics mode               */
    DX(pcrf) = (WORD)VDMData.mstates.butinfo[nButton].bi_yLastPress;
  else                                        /* text mode                   */
    DX(pcrf) = (WORD)((VDMData.mstates.butinfo[nButton].bi_yLastPress *8)/
                                           VDMData.vmss.vmss_ulCellHeight);

  AX(pcrf) = (WORD)VDMData.flButtons;
  return  TRUE;
}                                      /* vmInt33GetPressInfo                */


 /****************************************************************************
 *
 *  FUNCTION NAME  :  vmInt33GetReleaseInfo()
 *
 *  DESCRIPTION    :  Int 33h Get Button Release Info (function 6) 
 *
 *  INPUT          :
 *                     pcrf -> VDM register frame
 *  OUTPUT         :
 *                    EMULATED
 *                        TRUE
 *                    NOT EMULATED
 *                        FALSE (pass control to next VDD and/or ROM)
 *  USES           :
 *      32-bit small-model PASCAL calling/register conventions
 *
 *  CONTEXT        :
 *      VDM Task-time
 *
 *  PSEUDO-CODE    :                                 REFERENCES
 *      store number of button releases into VDM BX;
 *      clear number of button releases;
 *      if 320x200 mode
 *          store x of last release truncated to even into VDM CX;
 *      else
 *          store x of last release into VDM CX;
 *      store y of last release into VDM DX;
 *      store button states into VDM AX;
 *
 ****************************************************************************/

BOOL PRIVENTRY vmInt33GetReleaseInfo(register PCRF pcrf)
{
  register ULONG nButton = (ULONG)BX(pcrf); /* button number                 */

  if (nButton >= mhwInstalled.mhw_nButtons) /* if not a valid button         */
    nButton = mhwInstalled.mhw_nButtons-1;  /* make it the secondary button  */

  BX(pcrf) = (WORD)VDMData.mstates.butinfo[nButton].bi_nReleases;

  VDMData.mstates.butinfo[nButton].bi_nReleases = 0;
  CX(pcrf) = (WORD)(VDMData.mstates.butinfo[nButton].bi_xLastRelease << 
                                          VDMData.fShiftX);

  if (VDMData.vmss.vmss_ulCellHeight == 1)/* graphics mode                   */
    DX(pcrf) = (WORD)VDMData.mstates.butinfo[nButton].bi_yLastRelease;
  else                                    /* text mode                       */
    DX(pcrf) = (WORD)((VDMData.mstates.butinfo[nButton].bi_yLastRelease *8)/
       VDMData.vmss.vmss_ulCellHeight);

  AX(pcrf) = (WORD)VDMData.flButtons;
  return  TRUE;
}                                      /* vmInt33GetReleaseInfo              */

 /****************************************************************************
 *
 *  FUNCTION NAME  :  vmInt33GetMotionCounts() 
 *
 *  DESCRIPTION    :  Int 33h Get Motion Counters (function 11) 
 *
 *  INPUT          :
 *                   pcrf -> VDM register frame
 *  OUTPUT         :
 *                   EMULATED
 *                       TRUE
 *                   NOT EMULATED
 *                       FALSE (pass control to next VDD and/or ROM)
 *  USES           :
 *      32-bit small-model PASCAL calling/register conventions
 *
 *  CONTEXT        :
 *      VDM Task-time
 *
 *  PSEUDO-CODE    :                                 REFERENCES
 *      store x motion count in VDM CX;
 *      store y motion count in VDM DX;
 *      clear both x and y motion counts;
 *
 *************************************************************************/

BOOL PRIVENTRY vmInt33GetMotionCounts(register PCRF pcrf)
{
  CX(pcrf) = (SHORT)(VDMData.mstates.nxMics << VDMData.fShiftX);
  DX(pcrf) = (SHORT)VDMData.mstates.nyMics;

  VDMData.mstates.nxMics = 0;
  VDMData.mstates.nyMics = 0;
  return  TRUE;
}                                      /* vmInt33GetMotionCounts             */
#pragma  END_SWAP_CODE
