/*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.                                */
/*                                                                           */
/*****************************************************************************/
/**********************************************************************/
/*                                                                    */
/*   Module          = EDDACLIP                                       */
/*                                                                    */
/*   Description     = Display Device Driver minor function           */
/*                     NotifyClipChange and subroutine                */
/*                     GetClipRectangles                              */
/*                                                                    */
/*   Function        = NotifyClipChange is called by the engine when  */
/*                     the clip regions are changed.                  */
/*                     GetClipRectangles obtains the current clip     */
/*                     rectangles from the graphics engine.           */
/*                                                                    */
/*   Reference       = Winthorn Functional Specification              */
/*                     Device Driver Interface Specification          */
/*                     Display Device Driver Design Specification     */
/*                                                                    */
/*                                                                    */
/*   76352 - JR01 - 12/09/93                                          */
/*           Copy GetClipBounds into a RECTL structure to ensure that */
/*           the values of the structure members are treated as LONG  */
/*           values in LONG variables instead of SHORT values in LONG */
/*           variables.                                               */
/*                                                                    */
/**********************************************************************/
#define INCL_DDICOMFLAGS
#define INCL_GRE_CLIP
#define INCL_GRE_DEVSUPPORT
#define INCL_DDIMISC
#define INCL_GRE_DEVMISC2
#include <eddinclt.h>

#include <edddtypt.h>
#include <eddaextf.h>
#include <eddgextf.h>

extern PPFNL            EnginesDispatchTable;

extern RGNRECT          GetClipsControl;
extern ClipRectangle    GetClipsBounds;
#ifdef TMP                                                  
extern USHORT       foregroundSession; 
#endif 

/**********************************************************************/
/* NotifyClipChange is called by the engine when the clip regions are */
/* changed.                                                           */
/* On completion of processing control is passed on to the engines    */
/* NotifyClipChange function.                                         */
/**********************************************************************/

DDIENTRY edda_NotifyClipChange(HDC          hdc,
                               PRECTL       BoundClip,
                               ULONG        Complexity,
                               ULONG        ClipPath,
                               PDC          pdcArg,
                               ULONG        FunN)
{
    /******************************************************************/
    /* Prevent compiler warnings.                                     */
    /******************************************************************/
    IgnoreParam(hdc);

    /******************************************************************/
    /* We don't want to check for dirty DCs from this call            */
    /******************************************************************/
    EnterDriver(pdcArg, FunN, EDF_STANDARD | EDF_DONT_CLEAN);

    /******************************************************************/
    /* if the ClipPath flag indicating the dc is to be cleaned is set */
    /* then just clear the dirty DC flag and exit                     */
    /******************************************************************/
    if (ClipPath & NCC_CLEANDC)
    {
        pdc->DCIIsDirty = FALSE;
        goto NOTIFYCLIP_OK_EXIT;
    }

    /******************************************************************/
    /* if complexity is zero then stop all drawing (probably dead!)   */
    /* by resetting the COM_DRAW bit in the dc command mask           */
    /* otherwise set this bit of the mask                             */
    /* The mask is ANDed with the command bits passed to each         */
    /* drawing function                                               */
    /******************************************************************/
#ifndef TMP                                                 
    if ( !Complexity )
    {
        pdc->DCICommandMask &= ~((USHORT)(COM_DRAW >> 16));
    }
#else 
    /******************************************************************/
    /* Temp     fix for PMGRE. Currently, PMGRE requires display      */
    /* driver to draw something even if a process makes the request   */
    /* is in background session and not visible. It causes system     */
    /* TRAP, so we have to check it and make walk around for it.      */
    /*                                                                */
    /*                                   PTR JD20/JS04818  92/Dec/07  */
    /******************************************************************/
    if ( !Complexity ||
        (!foregroundSession && (pdc->DCIDCType == OD_DIRECT)))
    {
        pdc->DCICommandMask &= ~((USHORT)(COM_DRAW >> 16));
    }
#endif 
    else /* more than zero clip rects */
    {
        if (pdc->DCIDCType != OD_INFO)
        {
            /**********************************************************/
            /* we must never set the draw bit in an info DC           */
            /* but for all others if we have some clips then we can   */
            /* allow drawing to proceed                               */
            /**********************************************************/
            pdc->DCICommandMask |= (USHORT)(COM_DRAW >> 16);
        }

        if ( Complexity == 1 )
        {
            /**********************************************************/
            /* Only one clip rectangle required so cache it now in    */
            /* the dc as this is bounding rectangle supplied.  Must   */
            /* make this inclusive and convert from SCREEN to AI      */
            /* co-ords which involves swapping the Y0 and Y1 parms.   */
            /**********************************************************/
            pdc->DCIClipRects[0].X0 = (SHORT)BoundClip->xLeft;
            pdc->DCIClipRects[0].X1 = (SHORT)BoundClip->xRight - 1;
            pdc->DCIClipRects[0].Y0 = (SHORT)
                      (pdc->DCIBoundingClip[1].Y - BoundClip->yTop + 1);
            pdc->DCIClipRects[0].Y1 = (SHORT)
                       (pdc->DCIBoundingClip[1].Y - BoundClip->yBottom);

            /**********************************************************/
            /* reset the clip changed flag in the dc to indicate that */
            /* the dc cached clip region is valid                     */
            /*                                                        */
            /**********************************************************/
            pdc->ClipChanged = FALSE;

            /**********************************************************/
            /* set the number of cached clip rectangles to one        */
            /**********************************************************/
            pdc->DCIClipNum = 1;
        }

        else /* Complexity > 1 */
        {
            /**************************************************************/
            /* set the clip changed flag in the dc to indicate that the   */
            /* dc cached clip region is invalid                           */
            /**************************************************************/
            pdc->ClipChanged = TRUE;
        }
    } /* more than zero clip rects */

    /******************************************************************/
    /* Store the new number of clip rectangles comprising the region  */
    /******************************************************************/
    pdc->DCIEngineClips = (USHORT)Complexity;

    /******************************************************************/
    /* Mark the correlation rectangles as invalid                     */
    /******************************************************************/
    pdc->DCICorrInvalid = TRUE;


NOTIFYCLIP_OK_EXIT:
    /******************************************************************/
    /* pass control to the engine.                                    */
    /******************************************************************/
    ExitDriver(pdcArg, FunN, EDF_STANDARD | EDF_DONT_CLEAN);
    return (EnginesDispatchTable[NGreNotifyClipChange & 0xff](
                                                          hdc,
                                                          BoundClip,
                                                          Complexity,
                                                          ClipPath,
                                                          pdc,
                                                          FunN) );

}






/**********************************************************************/
/* GetClipRectangles gets either the default clip region or the clip  */
/* regions provided by the engine.                                    */
/**********************************************************************/

USHORT edda_GetClipRectangles (VOID)
{
    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    ULONG              i;              /* loop control variable       */
    SHORT              Swap;
    RECTL              tempRect;                                         /* JR01 */

    /******************************************************************/
    /* Check that the bounding rectangle coordinates are properly     */
    /* ordered ie bottom left and top right                           */
    /******************************************************************/
    if (GetClipsBounds.X0 > GetClipsBounds.X1)
    {
        Swap = GetClipsBounds.X0;
        GetClipsBounds.X0 = GetClipsBounds.X1;
        GetClipsBounds.X1 = Swap;
    }
    if (GetClipsBounds.Y0 > GetClipsBounds.Y1)
    {
        Swap = GetClipsBounds.Y0;
        GetClipsBounds.Y0 = GetClipsBounds.Y1;
        GetClipsBounds.Y1 = Swap;
    }

    /******************************************************************/ /* JR01 */
    /* Copy GetClipBounds into a RECTL structure to ensure that the   */ /* JR01 */
    /* values of the structure members are treated as LONG values     */ /* JR01 */
    /* in LONG variables instead of SHORT values in LONG variables.   */ /* JR01 */
    /******************************************************************/ /* JR01 */
    tempRect.xLeft   = GetClipsBounds.X0;                                /* JR01 */
    tempRect.yBottom = GetClipsBounds.Y0;                                /* JR01 */
    tempRect.xRight  = GetClipsBounds.X1;                                /* JR01 */
    tempRect.yTop    = GetClipsBounds.Y1;                                /* JR01 */
                                                                         /* JR01 */
    /******************************************************************/
    /* Get Clip Rectangles from the engine                            */
    /******************************************************************/
    if (RGN_ERROR == EnginesDispatchTable[NGreGetClipRects & 0xff](
                                      pdc->DCIhdc,
/* JR01                               (PRECTL)&GetClipsBounds,              JR01 */
                                      &tempRect,                         /* JR01 */
                                      (PRGNRECT)&GetClipsControl,
                                      (PRECTL)pdc->DCIClipRects,
                                      NULL,
                                      NGreGetClipRects
                                      ) )
    {
        return(ERROR_ZERO);
    }

    /******************************************************************/ /* JR01 */
    /* Save any changes in the RECTL structure back into the          */ /* JR01 */
    /* GetClipsBounds structure.                                      */ /* JR01 */
    /******************************************************************/ /* JR01 */
    GetClipsBounds.X0 = (SHORT)tempRect.xLeft;                           /* JR01 */
    GetClipsBounds.Y0 = (SHORT)tempRect.yBottom;                         /* JR01 */
    GetClipsBounds.X1 = (SHORT)tempRect.xRight;                          /* JR01 */
    GetClipsBounds.Y1 = (SHORT)tempRect.yTop;                            /* JR01 */
                                                                         /* JR01 */
    /******************************************************************/
    /* Store the number of rectangles returned in the dc              */
    /******************************************************************/
    pdc->DCIClipNum = (USHORT)GetClipsControl.crcReturned;

    /******************************************************************/
    /* If we have now got all the clip rectangles into the cache      */
    /* clear the flag indicating that the clip rectangles have changed*/
    /* The only way to ensure that we have all the clip rectangles in */
    /* the cache is to use the bounding clip as the passed bounds     */
    /* and get the full number of engine clips to fit in the cache    */
    /******************************************************************/
    if ( pdc->DCIEngineClips == pdc->DCIClipNum               &&
         GetClipsBounds.X0   == pdc->DCIBoundingClip[0].X     &&
         GetClipsBounds.X1   == pdc->DCIBoundingClip[1].X + 1 &&
         GetClipsBounds.Y0   == pdc->DCIBoundingClip[0].Y     &&
         GetClipsBounds.Y1   == pdc->DCIBoundingClip[1].Y + 1 )
    {
        pdc->ClipChanged = FALSE;
    }
    else
    {
        pdc->ClipChanged = TRUE;
    }

    /******************************************************************/
    /* Now adjust clip rectangles to internal format                  */
    /******************************************************************/
    for ( i=pdc->DCIClipNum; i--; )
    {
        /**************************************************************/
        /* adjust the returned clip rectangles to AI coordinates      */
        /**************************************************************/
        --pdc->DCIClipRects[i].X1;
        --pdc->DCIClipRects[i].Y1;
        Swap = pdc->DCIConvFactor + pdc->DCIOrigin.Y
                                          - pdc->DCIClipRects[i].Y0;
        pdc->DCIClipRects[i].Y0 =
                             pdc->DCIConvFactor + pdc->DCIOrigin.Y
                                           - pdc->DCIClipRects[i].Y1;
        pdc->DCIClipRects[i].Y1 = Swap;

    }

    return (OK);
}



/**********************************************************************/



DDIENTRY edda_DeviceInvalidateVisRegion(HDC          hdc,
                                        ULONG        ArraySize,
                                        PDC_BLOCK    DCArray,
                                        PDC          pdcArg,
                                        ULONG        FunN)

{
    /******************************************************************/
    /* DeviceInvalidateVisRegion is passed an array of structures     */
    /* that each contain a DC handle and a pointer to the DC instance */
    /* data. The function has to pass through this array and mark     */
    /* every DC as 'dirty', which indicates that its clip regions are */
    /* no longer valid. The clip regions for a DC will only be        */
    /* recalculated when the DC needs to perform its next drawing     */
    /* action.                                                        */
    /******************************************************************/

    /******************************************************************/
    /* Local variable                                                 */
    /******************************************************************/
    ULONG              i;        /* Loop variable                     */
    PDC                pdcThisOne;

    /******************************************************************/
    /* Prevent compiler warnings.                                     */
    /******************************************************************/
    IgnoreParam(hdc);

    /******************************************************************/
    /* We do not need exclusive access as a LockDevice call will      */
    /* always be made before an InvalidateVisRegion call.             */
    /*                                                                */
    /* ...but do this anyway incase the above statement is not true!  */
    /******************************************************************/
    EnterDriver(pdcArg, FunN, EDF_EXCLUSIVE | EDF_DC_NULL | EDF_DONT_CLEAN);

    for (i = 0; i < ArraySize; i++)
    {
        /**************************************************************/
        /* Check that the pdc is non null                             */
        /**************************************************************/
        pdcThisOne = (PDC)DCArray[i].hddc;
        if (pdcThisOne)
        {
            /**********************************************************/
            /* Everything looks good, so set the DCIIsDirty flag to   */
            /* be on.                                                 */
            /**********************************************************/
            pdcThisOne->DCIIsDirty = TRUE;
        }
    }

    ExitDriver(pdcArg, FunN, EDF_EXCLUSIVE | EDF_DC_NULL | EDF_DONT_CLEAN);
    return(OK);
}
