/*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 = VIOCSUBS.C
 *
 * DESCRIPTIVE NAME = Avio 'c' subroutines
 *
 *
 * VERSION      V2.0
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS
 *
 * NOTES        NONE
 *
 * STRUCTURES   NONE
 *
 * EXTERNAL REFERENCES
 *
 *              NONE
 *
 * EXTERNAL FUNCTIONS
 *
*/
/*
** Include Statements for all external files.
*/

#define INCL_DOS
#define INCL_SUB
#define INCL_ERRORS
#define INCL_WINWINDOWMGR
#define INCL_WINMESSAGEMGR
#define INCL_WINSYS
#define INCL_GPIREGIONS
#define INCL_GPIBITMAPS
#define INCL_DEV
#define INCL_OS2STD             /* Needed for NULL definition in OS2STD.H */
#include <OS2.H>

#define INCL_WINP
#define INCL_AVIOP
//#include <OS2P.H>             /* 95837 */

#include <pmwinx.h>             /* 95837 */
#include <PMAVIOP.H>            /* 95837 */

#define INCL_DDIMISC
#define INCL_DDIGRE
#define INCL_GREALL
#include <PMDDI.H>

#include <VIOT.H>

/***************************************************************************
 *
 * FUNCTION NAME = CopyDc
 *
 * DESCRIPTION   = Copy Dc - copy the loaded data from one Dc
 *                 to another. N.B Assumes a valid Dc handles
 *                 passed - no error checking.
 *
 * INPUT         = NONE
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

BOOL pascal near CopyDc( SrcDcH, TrgDcH )

    HDC SrcDcH;
    HDC TrgDcH;
{

    ULONG CodePage;

    /*
    **  Copy the Loaded LCIDs and code page
    */


    CodePage = GreGetCodePage(SrcDcH);

    if( GreSetCodePage(TrgDcH, CodePage) == GPI_ERROR )
        return(RcErr);

    if( GreCopyDCLoadData(TrgDcH, 2, SrcDcH) == GPI_ERROR )
        return(RcErr);
    else
        return(RcOk);
}

/***************************************************************************
 *
 * FUNCTION NAME = AvioCreatePS
 *
 * DESCRIPTION   = Create Ps - internal routine
 *                 Create an Avio ps.
 *
 * INPUT         = NONE
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

extern USHORT pascal near AvioCreatePS( lpPS , VioH)

     VioPresentationSpace FAR * lpPS;
     USHORT VioH;

{
    HDC   NewIcH;
    char *IcBlock[2];

    /*
    **  Create an Ic and associate it with the Vio.
    */


    IcBlock[ADDRESS] = 0L;
    IcBlock[DRIVER_NAME] = "DISPLAY";
    NewIcH = DevOpenDC( 0L, OD_INFO, (char far *) "*",
                                        2L, IcBlock, 0L);
    if (NewIcH != 0)
    {


        /*
        **  Set the Vio handle into the new Ic, the Ic handle into
        **  the Vio, turn off the associated bit.
        */


        if( GreSetHandle(NewIcH, (ULONG)VioH, AVIO_PS_HANDLE_INDEX)
                      == GPI_ERROR )
            return(ERROR_VIO_SEE_ERROR_LOG);

        lpPS -> hConsoleDisplayContext = NewIcH;
        lpPS -> rgfAVio &= !fAssociated;  /* not associated       */

        return(RcOk);
    }


    /*
    **  Creating the Ic failed - return error code so memory may be
    **  freed.
    */


    else
        return(ERROR_VIO_SEE_ERROR_LOG);
}

/***************************************************************************
 *
 * FUNCTION NAME = SetTextGrays(Environment)
 *
 * DESCRIPTION   =
 *
 *    This routine adjusts the following fields in an AVio presentation
 *    space:
 *
 *        WindowHeight
 *        WindowWidth
 *        WindowOriginRow
 *        PartialCellAdjust
 *
 * The adjustments are necessary to maintain the illusion of having
 * the AVio origin at the top left corner of the LVB and the client
 * window.  In fact the origin coordinates are relative to the
 * bottom left corners of the LVB and the client window.  The
 * PartialCellAdjust field holds a small pel offset used when the
 * client window's height is not an exact multiple of the current
 * cell height.
 *
 * INPUT         = NONE
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

BOOL PASCAL NEAR AdjustWindowOriginAndShape(lpPS)

VioPresentationSpace FAR * lpPS;

{

    /*
    **  Local variables
    */

    HDC    hdc;
    HWND   hwnd;
    USHORT TLOrg, usCellHeight, usCellWidth, usYPels, usXPels;
    RECTL  rcClient;

    if(!(hwnd = WinWindowFromDC(lpPS->hConsoleDisplayContext)))
        return(TRUE);                                          /*@P2C*/

    if (!WinQueryWindowRect(hwnd, &rcClient)) return(FALSE);

    usCellHeight = lpPS -> CellImageHeight;
    usCellWidth  = lpPS -> CellImageWidth;

    TLOrg = ( (lpPS -> WindowHeight == 0) &&
              (lpPS -> WindowOriginRow == 0) )
                ? 0
                : (lpPS -> BufferRowCount -
                   lpPS -> WindowHeight   -
                   lpPS -> WindowOriginRow);

    usYPels = (USHORT) (rcClient.yTop   - rcClient.yBottom);
    usXPels = (USHORT) (rcClient.xRight - rcClient.xLeft);

    lpPS -> WindowHeight = (usYPels + usCellHeight - 1)
                           / usCellHeight;
    lpPS -> WindowWidth  = (usXPels + usCellWidth - 1)
                           / usCellWidth;
    lpPS -> PartialCellAdjust =
        (BYTE) (usYPels - lpPS->WindowHeight * usCellHeight);

    lpPS -> WindowOriginRow = lpPS -> BufferRowCount -
                              lpPS -> WindowHeight - TLOrg;
    return(TRUE);
}

/***************************************************************************
 *
 * FUNCTION NAME = AvioAssociate
 *
 * DESCRIPTION   = Associate a Vio with a Dc.
 *
 * INPUT         = NONE
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

extern USHORT pascal near AvioAssociate( lpPS, VioH, InDcH )

     VioPresentationSpace FAR * lpPS;
     USHORT VioH;
     HDC    InDcH;

{

    /*
    **  Local Variables
    */


    char   *IcBlock[2];
    USHORT  AssVioH;
    HDC     NewIcH;

    /*
    **  Request was to dissociate
    */


    if (InDcH == 0)
    {

       /*
       **  Request was to dissociate and we are currently associated
       */


       if ((lpPS -> rgfAVio) & fAssociated)  /* associated        */
       {


           /*
           **  Create an Ic, copy relevant data out of the Dc and
           **  remove the Vio handle from the Dc.
           */


           IcBlock[ADDRESS] = 0L;
           IcBlock[DRIVER_NAME] = "DISPLAY";
           NewIcH = DevOpenDC( 0L, OD_INFO, (char far *) "*",
                                       2L, IcBlock, 0L);
           if (NewIcH != 0)
           {

               /*
               **  Set the Vio handle into the new Ic before CopyDC
               **  so that any loaded fonts can be copied
               */


               if( GreSetHandle(NewIcH,
                                (ULONG)VioH,
                                AVIO_PS_HANDLE_INDEX) == GPI_ERROR )
                   return(ERROR_VIO_SEE_ERROR_LOG);

               if( CopyDc(lpPS -> hConsoleDisplayContext, NewIcH) == RcErr )
               {
                   GreCloseDC(NewIcH); /* release just created IC    */
                   return(ERROR_VIO_SEE_ERROR_LOG);
               }

               if( GreSetHandle(lpPS -> hConsoleDisplayContext,
                                (ULONG)NullVioHandle,
                                AVIO_PS_HANDLE_INDEX) == GPI_ERROR )
                   return(ERROR_VIO_SEE_ERROR_LOG);


               /*
               **  Set                                 the Ic handle
               **  into the Vio, turn off the associated bit.
               */


               lpPS -> hConsoleDisplayContext = NewIcH;
               lpPS -> rgfAVio &= !fAssociated; /* not associated */
               return(RcOk);
           }

           else

           /*
           **  Creating the Ic failed - so get out
           */
           {
               return(ERROR_VIO_SEE_ERROR_LOG);
           }
       }


       /*
       **  Request was to dissociate and we are not currently
       **  associated
       */


       else
       {
           return(RcOk);
       }
    }

    /*
    **  Request was to perform an association
    */


    else
    {


       /*
       **  Ensure that neither the Dc nor the Vio is currently
       **  associated
       */


       if ((lpPS -> rgfAVio) & fAssociated)  /* associated        */
       {
           return(ERROR_VIO_ASSOCIATED_DC);
       }

       else
       {
           AssVioH = (USHORT) GreGetHandle(InDcH, AVIO_PS_HANDLE_INDEX);


           /*
           **  Error return from the read handle call - error has
           **  been logged so just get out
           */


           if (AssVioH == VioHandleError)
           {
               return(ERROR_VIO_SEE_ERROR_LOG);
           }

           else if (AssVioH != NullVioHandle)
           {
               return(ERROR_VIO_ASSOCIATED_DC);
           }


           /*
           **  Neither Vio nor Dc is currently associated so perform
           **  the association.
           */


           else
           {


               /*
               **  Set the Vio handle into the Dc     before CopyDC
               **  so that any loaded fonts can be copied
               */


              if( GreSetHandle(InDcH,
                               (ULONG)VioH,
                               AVIO_PS_HANDLE_INDEX) == GPI_ERROR )
                  return(ERROR_VIO_SEE_ERROR_LOG);


              /*
              **  Copy the loaded data from the Ic to the Dc, then
              **  throw away the old Ic.
              */


              if( CopyDc(lpPS -> hConsoleDisplayContext, InDcH) == RcErr )
              {
                  GreSetHandle(InDcH,
                               (ULONG)NullVioHandle,
                               AVIO_PS_HANDLE_INDEX);
                  return(ERROR_VIO_SEE_ERROR_LOG);
              }

              if( GreCloseDC(lpPS -> hConsoleDisplayContext) == GPI_ERROR )
                  return(ERROR_VIO_SEE_ERROR_LOG);


              /*
              **  Set the Dc handle
              **  into the Vio, turn off the associated bit.
              */


              lpPS -> hConsoleDisplayContext = InDcH;
              lpPS -> rgfAVio |= fAssociated; /* associated       */

              /*
              **  Set up the window information in the Vio.
              */


              NULLCHARRECT();

              if (AdjustWindowOriginAndShape(lpPS))
                  return(RcOk);

              else
                  return(ERROR_VIO_SEE_ERROR_LOG);

           }
       }
   }
}

/***************************************************************************
 *
 * FUNCTION NAME = AvioDestroyPS
 *
 * DESCRIPTION   = Vio Destroy Ps (VioDestroyPs)
 *
 * INPUT         = NONE
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

extern USHORT pascal near AvioDestroyPS( lpPS )

VioPresentationSpace FAR * lpPS;

{

    /*
    **  If the Vio is currently associated - that's an error
    */


    if ((lpPS -> rgfAVio) & fAssociated)     /* associated        */
    {
        return(ERROR_VIO_ASSOCIATED_DC);
    }

    /*
    **  All's well - throw away the Ic.
    */


    else
    {
        if( GreCloseDC(lpPS -> hConsoleDisplayContext) == GPI_ERROR )
            return(ERROR_VIO_SEE_ERROR_LOG);

        else
            return(RcOk);
    }
}

/***************************************************************************
 *
 * FUNCTION NAME = AvioSetDeviceCellSize
 *
 * DESCRIPTION   = Vio Set Device Cell Size
 *
 * INPUT         = NONE
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

extern USHORT pascal near AvioSetDeviceCellSize( lpPS, NewCellWidth,
                                                 NewCellHeight )

     VioPresentationSpace FAR * lpPS;
     USHORT NewCellWidth;
     USHORT NewCellHeight;

{

    /*
    **  Local Variables
    */


    VIOFONTCELLSIZE Smallest;                                           /*@P1C*/
    GridRectRef GridRect;
    LONG InCnt, OutCnt, InDat, res;                                     /*@P1A*/

    /*
    **  Get the smallest device cell size from the device caps
    */


    if (!DevQueryCaps(lpPS -> hConsoleDisplayContext,
                      CAPS_SMALL_CHAR_WIDTH,
                      2L,
                      (PLONG)&Smallest))

         return(ERROR_VIO_SEE_ERROR_LOG);                               /*@P1C*/

     /*
     **  Check if the display device supports DEVESC_QUERYVIOCELLSIZE
     */


    InCnt = 4L;                                                         /*@P1A*/
    InDat = DEVESC_QUERYVIOCELLSIZES;                                   /*@P1A*/

    res = DevEscape(lpPS -> hConsoleDisplayContext,
                    DEVESC_QUERYESCSUPPORT,
                    InCnt,
                    (PBYTE)&InDat,
                    &OutCnt,
                    (PBYTE)&OutCnt);                                    /*@P1A*/

    if (res == DEVESC_ERROR)
        return(ERROR_VIO_SEE_ERROR_LOG);           /*@P1A*/

    if (res == DEVESC_NOTIMPLEMENTED)                                   /*@P1A*/
    {

        /*
        **  Check the input values against the device caps. If either
        **  value is less than the corresponding device small cell
        **  size value then use the device small value. The engine
        **  will otherwise use the default value.
        */

        if ( (NewCellWidth  < (USHORT)Smallest.cx) ||
             (NewCellHeight < (USHORT)Smallest.cy))

        {
            NewCellWidth  = (USHORT)Smallest.cx;                        /*@P1C*/
            NewCellHeight = (USHORT)Smallest.cy;                        /*@P1C*/
        }
    }

    else                                                                /*@P1A*/
    {
        LONG NumCellSizes;                                              /*@P1A*/
        USHORT Size, rc, i, Count;                                      /*@P1A*/
        SEL    Selector;                                                /*@P1A*/

        typedef struct
           {
            VIOSIZECOUNT NumSizes;
            VIOFONTCELLSIZE CellSizes[1];
            } VIOCELLINFO;                                              /*@P1A*/

        VIOCELLINFO FAR *pVioCellInfo;                                  /*@P1A*/
        VIOFONTCELLSIZE SmallWth, Current;                              /*@P1A*/
        BOOL ExactMatch = FALSE;                                        /*@P3A*/

        /*
        ** Check how many device cell sizes are supported by the
        ** device so that sufficient storage can be allocated to
        ** receive all the sizes.
        */

        InCnt = 0L;                                                     /*@P1A*/
        InDat = 0L;                                                     /*@P1A*/
        OutCnt = sizeof(LONG);                                          /*@P1A*/

        res = DevEscape(lpPS -> hConsoleDisplayContext,
                        DEVESC_QUERYVIOCELLSIZES,
                        InCnt,
                        (PBYTE)&InDat,
                        &OutCnt,
                        (PBYTE)&NumCellSizes);                          /*@P1A*/

        if (res != DEV_OK)
            return(ERROR_VIO_SEE_ERROR_LOG);             /*@P1A*/

        /*
        **  Allocate storage to accommodate cell information
        */


        Size = (USHORT)(sizeof(VIOSIZECOUNT) +
                        (NumCellSizes * sizeof(VIOFONTCELLSIZE)));      /*@P1A*/

        rc = DosAllocSeg(Size,
                         &Selector,
                         0);                                            /*@P1A*/

        if (rc != NO_ERROR)
            return(rc);                             /*@P1A,@P5*/

        pVioCellInfo = MAKEP(Selector,0);                               /*@P1A*/
        OutCnt = Size;                                                  /*@P1A*/

        res = DevEscape(lpPS -> hConsoleDisplayContext,
                        DEVESC_QUERYVIOCELLSIZES,
                        InCnt,
                        (PBYTE)&InDat,
                        &OutCnt,
                        (PBYTE)pVioCellInfo);                           /*@P1A*/

        if (res != DEV_OK)
            return(ERROR_VIO_SEE_ERROR_LOG);             /*@P1A*/

        /*
        **  Locate smallest cell size by width.
        */


        SmallWth = (*pVioCellInfo).CellSizes[0];                        /*@P1A*/
        Count = (USHORT)(*pVioCellInfo).NumSizes.count;/*returned number  @P1A*/

        for (i=1;i<Count;i++)                                           /*@P1A*/
        {
            Current = (*pVioCellInfo).CellSizes[i];                     /*@P1A*/
            if ( (Current.cx == NewCellWidth) &&                        /*@P3A*/
                 (Current.cy == NewCellHeight))                         /*@P3A*/
            {
                ExactMatch = TRUE;                                      /*@P3A*/
                break;                                                  /*@P3A*/
            }

            if ( (Current.cx < SmallWth.cx) ||
                ((Current.cx == SmallWth.cx) && (Current.cy < SmallWth.cy)))

            {
                SmallWth = Current;                                     /*@P1A*/
            }
        }

        /*
        **  Check the input values against the smallest width
        **  cell size. If either value is less than the
        **  corresponding smallest width cell size value then use the
        **  device small value. The engine will otherwise use the
        **  default value.
        */

        if ( !ExactMatch &&                                             /*@P3C*/
            ((NewCellWidth  < (USHORT)SmallWth.cx) ||                   /*@P3C*/
             (NewCellHeight < (USHORT)SmallWth.cy)))                    /*@P3C*/
        {
            NewCellWidth  = (USHORT)Smallest.cx;                        /*@P1A*/
            NewCellHeight = (USHORT)Smallest.cy;                        /*@P1A*/
        }

        /*
        **  Release allocated storage
        */


        rc = DosFreeSeg(Selector);                                      /*@P1A*/

    }

    lpPS -> CellImageHeight = NewCellHeight;
    lpPS -> CellImageWidth  = NewCellWidth;

    /*
    **  Call engine to set the best fit.
    */


    GridRect.StartRow    = 0;
    GridRect.StartColumn = 0;
    GridRect.RectWidth   = 0;
    GridRect.RectDepth   = 0;

    if( GreCharRect( lpPS -> hConsoleDisplayContext,
                     lpPS,
                     &GridRect ) != RcOk )
        return(ERROR_VIO_SEE_ERROR_LOG);


    /*
    **  Set up the Vio window fields based on the new device cell
    **  size.
    */


    if (AdjustWindowOriginAndShape(lpPS))
        return(RcOk);

    else
        return(ERROR_VIO_SEE_ERROR_LOG);

}

/***************************************************************************
 *
 * FUNCTION NAME = AvioSetOrg
 *
 * DESCRIPTION   = Set the origin in the LVB
 *
 * INPUT         = NONE
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

extern USHORT pascal near AvioSetOrg( lpPS, TLOrgRow, TLOrgCol )

     VioPresentationSpace FAR * lpPS;
     USHORT TLOrgRow;
     USHORT TLOrgCol;

{

    /*
    **  Local Variables
    */


    HWND        WindowH;
    HDC         hdc;
    HPS         hps;
    RECTL       rectlNew, rectlPrev, rectlTail[2];
    HRGN        hrgnTail, hrgnPrev, hrgnNew;
    RGNRECT     rgnrect;
    GridRectRef GridRect;
    SHORT       sNewOrgRow, sPelAdjustment;

    sNewOrgRow = lpPS -> BufferRowCount - lpPS -> WindowHeight - TLOrgRow;

    if (   sNewOrgRow == lpPS->WindowOriginRow  &&
           TLOrgCol == lpPS->WindowOriginColumn   )
        return(RcOk);

    /*
    **  Invalidate the area that the LVB currently occupies.
    */


    WindowH = WinWindowFromDC(hdc= lpPS -> hConsoleDisplayContext);

    hps = (HPS) (((ULONG) hdc) | 1L);  /* Kludge to get MicroPsHandle */

    rectlPrev.xLeft   = (LONG)((SHORT)(-(lpPS -> WindowOriginColumn)) *
                               (SHORT)(lpPS -> CellImageWidth));

    rectlPrev.yBottom = (LONG)((SHORT)(-(lpPS -> WindowOriginRow)) *
                               (SHORT)(lpPS -> CellImageHeight));

    rectlPrev.xRight  = rectlPrev.xLeft +
                        (LONG)((SHORT)(lpPS -> BufferColumnCount) *
                               (SHORT)(lpPS -> CellImageWidth));

    rectlPrev.yTop    = rectlPrev.yBottom +
                        (LONG)((SHORT)(lpPS -> BufferRowCount) *
                               (SHORT)(lpPS -> CellImageHeight));

    sPelAdjustment     = (SHORT) (signed char) lpPS -> PartialCellAdjust;
    rectlPrev.yBottom += sPelAdjustment;

    if (!WinInvalidateRect(WindowH, (PRECTL)&rectlPrev, FALSE))
        return(ERROR_VIO_SEE_ERROR_LOG);

    /*
    **  Set new origin into presentation space and redraw LVB.
    */


    lpPS -> WindowOriginRow    = sNewOrgRow;
    lpPS -> WindowOriginColumn = TLOrgCol;
    GridRect.StartRow    = 0;
    GridRect.StartColumn = 0;
    GridRect.RectWidth   = lpPS -> BufferColumnCount;
    GridRect.RectDepth   = lpPS -> BufferRowCount;

    if( GreCharRect( lpPS -> hConsoleDisplayContext,
                     lpPS,
                     &GridRect ) != RcOk )
        return(ERROR_VIO_SEE_ERROR_LOG);

    /*
    **  Validate the area that the LVB now occupies.
    */

    hrgnPrev= GpiCreateRegion(hps, 1L, (PRECTL) &rectlPrev);
    hrgnTail= hrgnPrev;

    rectlNew.xLeft   = (LONG)((SHORT)(-(lpPS -> WindowOriginColumn)) *
                              (SHORT)(lpPS -> CellImageWidth));

    rectlNew.yBottom = (LONG)((SHORT)(-(lpPS -> WindowOriginRow)) *
                              (SHORT)(lpPS -> CellImageHeight));

    rectlNew.xRight  = rectlNew.xLeft +
                       (LONG)((SHORT)(lpPS -> BufferColumnCount) *
                              (SHORT)(lpPS -> CellImageWidth));

    rectlNew.yTop    = rectlNew.yBottom +
                       (LONG)((SHORT)(lpPS -> BufferRowCount) *
                              (SHORT)(lpPS -> CellImageHeight));

    rectlNew.yBottom += sPelAdjustment;

    hrgnNew= GpiCreateRegion(hps, 1L, (PRECTL) &rectlNew);

    GpiCombineRegion(hps, hrgnTail, hrgnPrev, hrgnNew, CRGN_DIFF);

    rgnrect.ircStart    = 0;
    rgnrect.crc         = 2;
    rgnrect.crcReturned = 0;
    rgnrect.usDirection = RECTDIR_LFRT_TOPBOT;

    GpiQueryRegionRects(hps, hrgnTail, (PRECTL) NULL,
                        (PRGNRECT) & rgnrect, (PRECTL) rectlTail);

    if (rgnrect.crcReturned > 0)
        WinFillRect(hps, (PRECTL) &rectlTail[0], SYSCLR_WINDOW);

    if (rgnrect.crcReturned > 1)
        WinFillRect(hps, (PRECTL) &rectlTail[1], SYSCLR_WINDOW);

    GreDestroyRegion(hps, hrgnPrev);
    GreDestroyRegion(hps, hrgnNew );

    if (!WinValidateRect(WindowH, (PRECTL)&rectlNew, FALSE))
        return(ERROR_VIO_SEE_ERROR_LOG);

    /*
    **  Redraw cursor
    */


    if( GreUpdateCursor( lpPS -> hConsoleDisplayContext,
                         lpPS ) != RcOk )
        return(ERROR_VIO_SEE_ERROR_LOG);

    return(RcOk);

}

/***************************************************************************
 *
 * FUNCTION NAME = AvioDeleteSetId
 *
 * DESCRIPTION   = Vio Delete SetId
 *
 * INPUT         = NONE
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

extern USHORT pascal near AvioDeleteSetId( lpPS, Lcid )

     VioPresentationSpace FAR * lpPS;
     LONG   Lcid;

{

    if( Lcid == -1L )
    {

        LONG  n = 3L;
        LONG  types[3], lcids[3];
        STR8  names[3];
        USHORT i;

        if( GreQuerySetIds(lpPS -> hConsoleDisplayContext,
                           n,
                           types,
                           names,
                           lcids,
                           LCID_RANGE_AVIO) == GPI_ERROR )
            return(ERROR_VIO_SEE_ERROR_LOG);

        for ( i=0; i<3; i++ )
        {
            if(  ( lcids[i] != 0L )  &&
                 ( GreDeleteSetId(lpPS -> hConsoleDisplayContext,
                                  lcids[i]) == GPI_ERROR ))
                return(ERROR_VIO_SEE_ERROR_LOG);
        }

    }

    else
    {
        if( (Lcid < 1) || (Lcid > 3) )
            return(ERROR_VIO_INVALID_PARMS);

        if( GreDeleteSetId(lpPS -> hConsoleDisplayContext,
                           -(Lcid + 1)) == GPI_ERROR )
            return(ERROR_VIO_SEE_ERROR_LOG);
    }

    return(RcOk);
}

/***************************************************************************
 *
 * FUNCTION NAME = AvioQuerySetIds
 *
 * DESCRIPTION   = Vio Query SetIds
 *
 * INPUT         = NONE
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

extern USHORT pascal near AvioQuerySetIds( lpPS, n, types, names, Lcids)

     VioPresentationSpace FAR * lpPS;
     LONG   n;
     PLONG  types, Lcids;
     PSTR8  names;

{

    /*
    **  Local Variables
    */


    USHORT i;

    if( (n < 1) || (n > 3) )
        return(ERROR_VIO_INVALID_PARMS);

    if( GreQuerySetIds(lpPS -> hConsoleDisplayContext,
                       n,
                       types,
                       names,
                       Lcids,
                       LCID_RANGE_AVIO) == GPI_ERROR )
        return(ERROR_VIO_SEE_ERROR_LOG);

    for ( i=0; i<(USHORT)n; i++ )
    {
        if( Lcids[i] != 0L )
            (LONG)Lcids[i] = -((LONG)Lcids[i] + 1);
    }

    return(RcOk);
}

/***************************************************************************
 *
 * FUNCTION NAME = AvioQueryFonts
 *
 * DESCRIPTION   = Vio Query Fonts
 *
 * INPUT         = NONE
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

extern USHORT pascal near AvioQueryFonts( lpPS, options, facename,
                                          fonts, count, metrics,
                                          remfonts )
     VioPresentationSpace FAR * lpPS;
     ULONG  options;
     PSZ    facename;
     PLONG  fonts, remfonts;
     LONG   count;
     PFONTMETRICS metrics;

{

    /*
    **  Local Variables
    */


    LONG EngVal;

    EngVal =  GreQueryFonts(lpPS -> hConsoleDisplayContext,
                            options,
                            facename,
                            metrics,
                            count,
                            fonts);

    if( EngVal == -1L )
        return(ERROR_VIO_SEE_ERROR_LOG);

    else
    {
       *remfonts = EngVal;
        return( RcOk );
    }

}
