/*DDK*************************************************************************/
/*                                                                           */
/* 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 = VVPTR.C
 *
 * DESCRIPTIVE NAME = Virtual Video Pointer Routines
 *
 *
 * VERSION = V2.0
 *
 * DATE      11/10/88
 *
 * DESCRIPTION  This module contains the VVD's pointer show/hide code.
 *
 * FUNCTIONS    VVShowPtr()           Show mouse pointer image
 *              VVHidePtr()           Hide mouse pointer image
 *              VVDefineTextPtr()     Text pointer definition
 *              VVDefineGraphPtr()    Pointer definition
 *              VVSetPtrPage()        Set video page on which to display
 *                                    pointer
 *              VVSetLPenEmulation()  Enable/disable light-pen emulation
 *              VVUpdatePtrContext()  Update VDM hardware cursor pointer in
 *                                    context
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/


#define  IO8BIT         /* CL386 Version 6.00.054 FLAG:                */
#include <mvdm.h>
#include <vvd.h>
#include "vvdp.h"

#ifdef   VDDSTRICT
MODNAME = __FILE__;
#endif

#pragma BEGIN_SWAP_DATA

#ifdef EGAVGA

extern PLE pleSEQData;
extern PLE pleGDCData;

 /*
 ** list of pointer state-related ports
 */

RLE rlePtrSEQMapMask =                                          /*          */
{
  &pleSEQData,
  PORTF_REQUIRED,
  REG_SEQMAPMASK, 0,     /* this MUST be the 1st entry! */
  0,                     /* see vvPtrCopyPtrSaveToScreen for why */
  SEQMAP_ALL,
  {SEQMAP_ALL, SEQMAP_PLANE0, SEQMAP_ALL},
  NULL,
  NULL,
};

RLE rlePtrGDCESR =                                              /*          */
{
  &pleGDCData,
  PORTF_REQUIRED,
  REG_GDCESR, 0,
  0,
  GDCESR_ALL,
  {0x00, 0x00, 0x00},
  NULL,
  NULL,
};

RLE rlePtrGDCRotate =                                           /*          */
{
  &pleGDCData,
  PORTF_REQUIRED,
  REG_GDCROTATE, 0,
  0,
  GDCROTATE_ALL,
  {0x00, 0x00, 0x00},
  NULL,
  NULL,
};

RLE rlePtrGDCMode =                                             /*          */
{
  &pleGDCData,
  PORTF_REQUIRED,
  REG_GDCMODE, 0,        /* this MUST be the 4th entry! */
  0,                     /* see vvPtrPutPointerInScrSave for why */
  GDCMODE_WRITE3 | GDCMODE_READ1 | GDCMODE_ODDEVENDIFF,
  { GDCMODE_WRITE1 |
     GDCMODE_READ0 |
      !GDCMODE_ODDEVENDIFF,
    GDCMODE_WRITE1 |
     GDCMODE_READ0 |
      !GDCMODE_ODDEVENDIFF,
    GDCMODE_WRITE0 |
     GDCMODE_READ0 |
      GDCMODE_ODDEVENDIFF},
  NULL,
  NULL,
};

RLE rlePtrGDCBitMask =                                          /*          */
{
  &pleGDCData,
  PORTF_REQUIRED,
  REG_GDCBITMASK, 0,
  0,
  GDCBITMASK_ALL,
  {GDCBITMASK_ALL, GDCBITMASK_ALL, GDCBITMASK_ALL},
  NULL,
  NULL,
};

PRLE aprlePtrState[] =                                          /*          */
{
  &rlePtrSEQMapMask,
  &rlePtrGDCESR,
  &rlePtrGDCRotate,
  &rlePtrGDCMode,
  &rlePtrGDCBitMask,
  NULL,
};

#endif /* EGAVGA */

#pragma END_SWAP_DATA

#pragma  BEGIN_SWAP_CODE

/***************************************************************************
 *
 * FUNCTION NAME = VVShowPtr()
 *
 * DESCRIPTION   = Show mouse pointer image
 *
 *                 This subroutine is registered with the virtual mouse
 *                 driver during creation of the first VDM, and causes the
 *                 currently defined pointer shape to appear on the screen
 *                 at the specified coordinates.
 *
 * INPUT         = hvdm -> VDM
 *                 xNew == new x-coordinate (always pixels, never cells)
 *                 yNew == new y-coordinate (always pixels, never cells)
 *
 * OUTPUT        = SUCCESS
 *                     TRUE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

BOOL EXPENTRY VVShowPtr(HVDM hvdm,ULONG xNew,ULONG yNew)
{
  BOOL rc = TRUE;
  register PVDMDATA pvd = pVDMData(hvdm);


  if ((pvd->flVDMXVideo&(VDMX_DEVOWNER|VDMX_DSPOWNER|VDMX_ACTIVE)) ==
     (VDMX_DEVOWNER|VDMX_DSPOWNER|VDMX_ACTIVE))
  {                                              /*                         */

    if (!pvd->PtrData.fPtrFrozenVideo)
    {
      RequestMutexSem(pvd->hmxVideoState);

      if (!pvd->PtrData.fPtrFrozenVideo)
        vvPtrDraw(hvdm,
                  xNew,
                  yNew);

      else
        rc = FALSE;
      ReleaseMutexSem(pvd->hmxVideoState);
    }

    if (!(pvd->PtrData.flPtrVideo&PTR_INTERNAL))
    {
      pvd->PtrData.xPtrVideo = xNew;
      pvd->PtrData.yPtrVideo = yNew;
      pvd->PtrData.flPtrVideo |= PTR_ACTIVE;
    }
    return  rc;                                  /*                         */
  }
  return  FALSE;                                 /*                         */
}

/***************************************************************************
 *
 * FUNCTION NAME = VVHidePtr()
 *
 * DESCRIPTION   = Hide mouse pointer image
 *
 *                 This subroutine is registered with the virtual mouse
 *                 driver during creation of the first VDM, and causes the
 *                 currently defined pointer shape to disappear from the
 *                 screen.  If the pointer is already disabled, nothing
 *                 happens.
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = SUCCESS
 *                     TRUE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

BOOL EXPENTRY VVHidePtr(HVDM hvdm)
{
  BOOL rc = TRUE;
  register PVDMDATA pvd = pVDMData(hvdm);


  if ((pvd->flVDMXVideo&(VDMX_DEVOWNER|VDMX_DSPOWNER|VDMX_ACTIVE)) ==
     (VDMX_DEVOWNER|VDMX_DSPOWNER|VDMX_ACTIVE))
  {                                              /*                         */

    if (!pvd->PtrData.fPtrFrozenVideo)
    {
      RequestMutexSem(pvd->hmxVideoState);

      if (!pvd->PtrData.fPtrFrozenVideo)
        vvPtrErase(hvdm);

      else
        rc = FALSE;
      ReleaseMutexSem(pvd->hmxVideoState);
    }

    if (!(pvd->PtrData.flPtrVideo&PTR_INTERNAL))
      pvd->PtrData.flPtrVideo &= ~PTR_ACTIVE;
    return  rc;                                  /*                         */
  }
  return  FALSE;                                 /*                         */
}

/***************************************************************************
 *
 * FUNCTION NAME = VVDefineTextPtr()
 *
 * DESCRIPTION   = Text pointer definition
 *
 *                 This subroutine is registered with the virtual mouse
 *                 driver during creation of the first VDM, and defines a
 *                 new pointer shape for specified VDM.
 *
 * INPUT         = hvdm      -> VDM
 *                 ulANDMask == the "screen" mask
 *                 ulXORMask == the "pointer" mask
 *                 fHW       == TRUE if hardware cursor to be used,
 *                              FALSE if not
 *
 * OUTPUT        = SUCCESS
 *                     TRUE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

BOOL EXPENTRY VVDefineTextPtr(
  HVDM hvdm,
  ULONG ulANDMask,
  ULONG ulXORMask,
  BOOL fHW )
{
  BYTE bCRTIndx;                                                /*          */
  register PVDMDATA pvd = pVDMData(hvdm);


  if(((pvd->flVDMXVideo & (VDMX_DEVOWNER | VDMX_DSPOWNER | VDMX_ACTIVE))
      != (VDMX_DEVOWNER | VDMX_DSPOWNER | VDMX_ACTIVE))         /*          */
     || (pvd->mstateVideo > MEMORY_TEXT) )                      /*          */
    return( FALSE );                                            /*          */
  if( fHW )
  {
    ulANDMask &= 0x0f;
    ulXORMask &= 0x0f;

#ifndef  SETDIRECT
    /*
    ** This method is preferable in that it takes cursor emulation
    ** by ROM into account;  the other method (ifdef'ed out) doesn't
    */
    *(PULONG)VDHQueryHookData(pvd->hhookUpdatePtrContext) =
      ulANDMask | (ulXORMask << 8);

    if (!vdhBTS(&pvd->flVDMXVideo,
                LOG2(VDMX_PTRHOOK)))
      VDHArmContextHook(pvd->hhookUpdatePtrContext,
                        hvdm);
#else
    RequestMutexSem(pvd->hmxVideoState);
    bCRTIndx = vvInput( hvdm,                                   /*          */
                        &pleCRTIndx );                          /*          */
    vvOutput( hvdm,                                             /*          */
              &pleCRTIndx,                                      /*          */
              REG_CRTCURSTSCAN );
    vvOutput( hvdm,                                             /*          */
              &pleCRTData,                                      /*          */
              (BYTE) ulANDMask );
    vvOutput( hvdm,                                             /*          */
              &pleCRTIndx,                                      /*          */
              REG_CRTCURENDSCAN );
    vvOutput( hvdm,                                             /*          */
              &pleCRTData,                                      /*          */
              (BYTE) ulXORMask );
    vvOutput( hvdm,                                             /*          */
              &pleCRTIndx,                                      /*          */
              bCRTIndx );                                       /*          */
    ReleaseMutexSem(pvd->hmxVideoState);
#endif
    pvd->PtrData.flPtrVideo |= PTR_HARDWARE;
    pvd->PtrData.flPtrVideo &= ~PTR_HWDIRTY;
    vvUpdateCursorData(hvdm);
  }
  else
  {
    if( pvd->PtrData.flPtrVideo & PTR_HARDWARE )                /*          */
      pvd->PtrData.flPtrVideo &= ~(PTR_HARDWARE|PTR_DRAWN);     /*          */
    pvd->PtrData.ulTextANDMaskVideo = ulANDMask;
    pvd->PtrData.ulTextXORMaskVideo = ulXORMask;
  }
  if(pVDMData(hvdm)->PtrData.flPtrVideo & PTR_ACTIVE )
  {
    pVDMData(hvdm)->PtrData.flPtrVideo |= PTR_INTERNAL;
    VVHidePtr(hvdm);
    VVShowPtr(hvdm,
              pVDMData(hvdm)->PtrData.xPtrVideo,
              pVDMData(hvdm)->PtrData.yPtrVideo);
    pVDMData(hvdm)->PtrData.flPtrVideo &= ~PTR_INTERNAL;
  }
  return( TRUE );
}

/***************************************************************************
 *
 * FUNCTION NAME = VVDefineGraphPtr()
 *
 * DESCRIPTION   = Pointer definition
 *
 *                 This subroutine is registered with the virtual mouse
 *                 driver during creation of the first VDM, and defines a
 *                 new pointer shape for specified VDM.
 *
 * INPUT         = hvdm   -> VDM
 *                 ausPtr -> 32-word pointer definition block
 *                 xHot   == x-coordinate of hot-spot
 *                 yHot   == y-coordinate of hot-spot
 *
 *                 Example of 32-word pointer definition block:
 *
 *                               +------------------------------+
 *                               |          15-----bits-----0   |
 *                               |Screen Mask                   |
 *                               | Word  0:  0011111111111111   |
 *                               | Word  1:  0001111111111111   |
 *                               | Word  2:  0000111111111111   |
 *                               | Word  3:  0000011111111111   |
 *                               | Word  4:  0000001111111111   |
 *                               | Word  5:  0000000111111111   |
 *                               | Word  6:  0000000011111111   |
 *                               | Word  7:  0000000001111111   |
 *                               | Word  8:  0000000000111111   |
 *                               | Word  9:  0000000000011111   |
 *                               | Word 10:  0000000111111111   |
 *                               | Word 11:  0001000011111111   |
 *                               | Word 12:  0011000011111111   |
 *                               | Word 13:  1111100001111111   |
 *                               | Word 14:  1111100001111111   |
 *                               | Word 15:  1111110001111111   |
 *                               |Pointer Mask                  |
 *                               | Word 16:  0000000000000000   |
 *                               | Word 17:  0100000000000000   |
 *                               | Word 18:  0110000000000000   |
 *                               | Word 19:  0111000000000000   |
 *                               | Word 20:  0111100000000000   |
 *                               | Word 21:  0111110000000000   |
 *                               | Word 22:  0111111000000000   |
 *                               | Word 23:  0111111100000000   |
 *                               | Word 24:  0111111110000000   |
 *                               | Word 25:  0111110000000000   |
 *                               | Word 26:  0110110000000000   |
 *                               | Word 27:  0100011000000000   |
 *                               | Word 28:  0000011000000000   |
 *                               | Word 29:  0000001100000000   |
 *                               | Word 30:  0000001100000000   |
 *                               | Word 31:  0000000000000000   |
 *                               +------------------------------+
 *
 * OUTPUT        = SUCCESS
 *                     TRUE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * PSEUDO-CODE
 *                 if pointer active
 *                   erase it
 *                 update shape definition
 *                 if pointer active
 *                   redraw it
 *
 ****************************************************************************/

BOOL EXPENTRY VVDefineGraphPtr(HVDM hvdm,USHORT ausMasks[],ULONG xHot,ULONG
                                yHot)
{

  if (((pVDMData(hvdm)->flVDMXVideo&(VDMX_DEVOWNER|VDMX_DSPOWNER|VDMX_ACTIVE))
     != (VDMX_DEVOWNER|VDMX_DSPOWNER|VDMX_ACTIVE))/*                        */
     || (pVDMData(hvdm)->mstateVideo == MEMORY_TEXT))/*                     */
    return  FALSE;                               /*                         */

  pVDMData(hvdm)->PtrData.xHotVideo = xHot;
  pVDMData(hvdm)->PtrData.yHotVideo = yHot;
  vvPtrSetMasks(hvdm,
                ausMasks);

  if (pVDMData(hvdm)->PtrData.flPtrVideo&PTR_ACTIVE)
  {
    pVDMData(hvdm)->PtrData.flPtrVideo |= PTR_INTERNAL;
    VVHidePtr(hvdm);
    VVShowPtr(hvdm,
              pVDMData(hvdm)->PtrData.xPtrVideo,
              pVDMData(hvdm)->PtrData.yPtrVideo);
    pVDMData(hvdm)->PtrData.flPtrVideo &= ~PTR_INTERNAL;
  }
  if (pVDMData(hvdm)->PtrData.flPtrVideo & PTR_HARDWARE)           /* DMH02 */
      pVDMData(hvdm)->PtrData.flPtrVideo &= ~(PTR_HARDWARE);       /* DMH02 */
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = VVSetPtrPage()
 *
 * DESCRIPTION   = Set video page on which to display pointer
 *
 *                 This subroutine is registered with the virtual mouse
 *                 driver during creation of the first VDM, and allows the
 *                 mouse driver to select the video page on which the
 *                 pointer should be drawn.
 *
 *                 Rather interesting the DOS driver didn't architect this
 *                 function to to move the pointer if it was no longer on the
 *                 selected page....
 *
 * INPUT         = hvdm -> VDM
 *                 ulPage == video page #
 *
 * OUTPUT        = SUCCESS
 *                     TRUE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

BOOL EXPENTRY VVSetPtrPage(HVDM hvdm,ULONG ulPage)
{

  if ((pVDMData(hvdm)->flVDMXVideo&(VDMX_DEVOWNER|VDMX_DSPOWNER|VDMX_ACTIVE))
     != (VDMX_DEVOWNER|VDMX_DSPOWNER|VDMX_ACTIVE))/*                        */
    return  FALSE;                               /*                         */

  pVDMData(hvdm)->PtrData.ulPtrPage = ulPage;
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = VVSetLPenEmulation()
 *
 * DESCRIPTION   = Enable/disable light-pen emulation
 *
 *                 This subroutine is registered with the virtual mouse
 *                 driver during creation of the first VDM, and allows the
 *                 mouse driver to turn light pen emulation on/off.
 *
 * INPUT         = hvdm -> VDM
 *                 fEnable == TRUE to enable, FALSE to disable
 *
 * OUTPUT        = SUCCESS
 *                     TRUE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

BOOL EXPENTRY VVSetLPenEmulation(HVDM hvdm,BOOL fEnable)
{

  if ((pVDMData(hvdm)->flVDMXVideo&(VDMX_DEVOWNER|VDMX_DSPOWNER|VDMX_ACTIVE))
     != (VDMX_DEVOWNER|VDMX_DSPOWNER|VDMX_ACTIVE))/*                        */
    return  FALSE;                               /*                         */

  SETBIT(pVDMData(hvdm)->PtrData.flPtrVideo,
         PTR_LPENEM,
         fEnable);
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = VVUpdatePtrContext()
 *
 * DESCRIPTION   = Update VDM hardware cursor pointer in context
 *
 * INPUT         = pulCursor == cursor type
 *                 pcrf      -> VDM register frame
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID HOOKENTRY VVUpdatePtrContext(register PULONG pulCursor,PCRF pcrf)
{

  if (!((PVVSTRING)(VDMData.pInt10ReturnData))->vva_nChars)
  {
    VDHPushRegs(VDHREG_AX|VDHREG_CX|VDHREG_BP);
    AH(pcrf) = INT10_SETCURSORTYPE;
    CH(pcrf) = (BYTE)(*pulCursor&0xff);
    CL(pcrf) = (BYTE)(*pulCursor >> 8);
    VDHPushInt(BIOSINT_VIDEO);
    ((PVVSTRING)(VDMData.pInt10ReturnData))->vva_nChars = -INT10_SETCURSORTYPE
       ;
    VDHArmReturnHook(VDMData.hhookInt10Return,
                     VDHARH_NORMAL_IRET);
  }
  VDMData.flVDMXVideo &= ~VDMX_PTRHOOK;
}

#pragma  END_SWAP_CODE

