/*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          = EDDBDRAW                                       */
/*                                                                    */
/*   Description     = Display Device Driver DrawBorder function      */
/*                                                                    */
/*   Function        = DrawBorder draws a border in a rectangular     */
/*                     frame, possibly filling the interior           */
/*                                                                    */
/*   Reference       = Winthorn Functional Specification              */
/*                     Device Driver Interface Specification          */
/*                     Display Device Driver Design Specification     */
/*                                                                    */
/*                                                                    */
/**********************************************************************/
#define INCL_DDIMISC
#define INCL_DDICOMFLAGS
#include <eddinclt.h>

#include <eddhcone.h>
#include <eddecone.h>

#include <eddhtype.h>

#include <eddaextf.h>
#include <eddbextf.h>
#include <eddcextf.h>
#include <eddgextf.h>
#include <eddmextf.h>
#ifdef DCAF                                                               //DCAF
#include <dcafextf.h>                                                     //DCAF
#endif                                                                    //DCAF

#include <eddfcone.h>
#include <eddftype.h>

#include <cursor.h>
#include <hwaccess.h>
#ifdef VRAMPTR
#include <eddncach.h>
#endif /* VRAMPTR */

extern CURSORDATA       cursor_data;
extern BITBLTPB         AIxfer;
#ifndef _8514
extern MMReg            ShadowXGARegs;
extern pMMReg           pRealXGARegs;
extern pMMReg           pXGARegs;
#else
extern MM8514Reg        Shadow8514Regs;
extern pMM8514Reg       p8514Regs;
#include <8514.h>
#endif
extern BitmapHeader     NewPatternTable[];
extern ULONG            PixelOp;
extern BYTE             WinToXWay[];
extern BltSPad          SPad;

extern SHORT                    softDrawInUse;
extern ULONG                    LinePatternCur;
extern ULONG                    LinePatternPhys;
extern ULONG                    LinePatternSys;
extern ULONG                    MarkerCur;
extern ULONG                    MarkerPhys;
extern ULONG                    MarkerSys;
extern ULONG                    pCurCacheBasePhy;
extern ULONG                    pSysCacheStartPhy;
extern drawFunctionsTable       softDrawTable;
extern drawFunctionsTable       hardDrawTable;
extern SHORT                    foregroundSession;
extern ULONG                    pPhunkPhys;

extern pDrawFunctionsTable      pDrawFunctions;

/**********************************************************************/
/* DrawBorder draws a border in a rectangular frame, and fills the    */
/* interior. Both the border and the interior may be absent for any   */
/* call.                                                              */
/**********************************************************************/
DDIENTRY eddb_DrawBorder(HDC            hdc,
                         pWcsRect       ArgFrame,
                         ULONG          ArgBorderWidth,
                         ULONG          ArgBorderHeight,
                         ULONG          ArgBorderColor,
                         ULONG          ArgInteriorColor,
                         ULONG          ArgOptions,
                         PDC            pdcArg,
                         ULONG          FunN)

{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    RECTS             Frame;           /* rectangular frame co-ords   */
    USHORT            Result;          /* convert result              */
    ULONG             ForeColor;       /* foreground color            */
    ULONG             BackColor;       /* background color            */
    ULONG             Error;           /* error to be logged          */

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

    /******************************************************************/
    /* Get driver semaphore and perform entry checks                  */
    /******************************************************************/
    EnterDriver(pdcArg, FunN, EDF_STANDARD);

    /******************************************************************/
    /* If the function is being called within an area or path         */
    /* definition then we raise an error and leave immediately.       */
    /* Test both bits together in the normal case and only test for   */
    /* path OR area if an error occurs                                */
    /******************************************************************/
    if ( FunNTest(COM_AREA | COM_PATH) )
    {
        if (FunNTest(COM_AREA))
        {
            Error = PMERR_INV_IN_AREA;
        }
        else /* in a path */
        {
            Error = PMERR_INV_IN_PATH;
        }

        goto DRAWBORDER_LOGERR_EXIT;
    }

    /******************************************************************/
    /* Validate the requested options                                 */
    /******************************************************************/
    if ( ( ArgOptions & ~( DB_ROP |
                           DB_INTERIOR |
                           DB_AREAATTRS |
                           DB_STANDARD |
                           DB_DLGBORDER)   ) ||
          ((BYTE)(ArgOptions & DB_ROP) > DB_AREAMIXMODE) )
    {
        Error = PMERR_INV_DRAW_BORDER_OPTION;
        goto DRAWBORDER_LOGERR_EXIT;
    }

    /******************************************************************/
    /* Validate the border thicknesses. These must be positive word   */
    /* values.                                                        */
    /******************************************************************/
    if ( (ArgBorderWidth | ArgBorderHeight) & 0xFFFF1000 )
    {
        Error = PMERR_INV_LENGTH_OR_COUNT;
        goto DRAWBORDER_LOGERR_EXIT;
    }

    /******************************************************************/
    /* Get the command bits from FunN and                             */
    /* apply the DC command mask to the command bits                  */
    /******************************************************************/
    COMMANDBITS(FunN) &= pdc->DCICommandMask;

    /******************************************************************/
    /* Validate the frame coords. These must be word values sign      */
    /* extended to dwords.                                            */
    /******************************************************************/
    if ((LONG)(Frame.pts1.x = (SHORT)(*ArgFrame)[0].X) !=
                                                     (*ArgFrame)[0].X ||
        (LONG)(Frame.pts1.y = (SHORT)(*ArgFrame)[0].Y) !=
                                                     (*ArgFrame)[0].Y ||
        (LONG)(Frame.pts2.x = (SHORT)(*ArgFrame)[1].X) !=
                                                     (*ArgFrame)[1].X ||
        (LONG)(Frame.pts2.y = (SHORT)(*ArgFrame)[1].Y) !=
                                                      (*ArgFrame)[1].Y )
    {
        /**************************************************************/
        /* One or more coordinates are invalid. Log an error and exit.*/
        /**************************************************************/
        Error = PMERR_INV_COORDINATE;
        goto DRAWBORDER_LOGERR_EXIT;
    }

    /******************************************************************/
    /* The frame must also be well ordered.                           */
    /******************************************************************/
    if ( Frame.pts1.x > Frame.pts2.x ||
         Frame.pts1.y > Frame.pts2.y )
    {
        /**************************************************************/
        /* The frame is badly ordered. Log an error and exit.         */
        /**************************************************************/
        Error = PMERR_INV_RECT;
        goto DRAWBORDER_LOGERR_EXIT;
    }

    /******************************************************************/
    /* If no interior fill is required and the border thicknesses are */
    /* zero, or if the Frame x or y coords are the same, then we can  */
    /* leave as no drawing needs to be done.                          */
    /******************************************************************/
    if ( !(ArgOptions & DB_INTERIOR) &
         !(ArgBorderWidth | ArgBorderHeight) ||
         !(Frame.pts1.x ^ Frame.pts2.x) ||
         !(Frame.pts1.y ^ Frame.pts2.y) )
    {
        goto DRAWBORDER_EXIT;
    }

    /******************************************************************/
    /* Check for currently selected bitmap.                           */
    /******************************************************************/
    if (pdc->DCIBitmapType & BITMAP_NOT_SELECTED)
    {
        Error = PMERR_NO_BITMAP_SELECTED;
        goto DRAWBORDER_LOGERR_EXIT;
    }

    /******************************************************************/
    /* put a pointer to the selected bitmap into the parameter block  */
    /******************************************************************/
    AIxfer.pbmhDest = pdc->DCISelListEntry;

    /******************************************************************/
    /* We need to adjust the coords of the frame to make the top      */
    /* and right edges inclusive.                                     */
    /******************************************************************/
    Frame.pts2.x -= 1;
    Frame.pts2.y -= 1;

    /******************************************************************/
    /* Check bounds bits.                                             */
    /******************************************************************/
    if ( FunNTest(COM_BOUND | COM_ALT_BOUND) )
    {
        /**************************************************************/
        /* Update the global bounds                                   */
        /**************************************************************/
        eddg_AddBounds ( (pDevRect)&Frame,
                         FunN,
                         COORD_DEVICE_WORD);

    }

    /******************************************************************/
    /* If draw bit is not set or there are no clip regions then no    */
    /* further work is required.                                      */
    /******************************************************************/
    if ( !(FunNTest(COM_DRAW) ) )
    {
        goto DRAWBORDER_EXIT;
    }

    /**************************************************************/
    /* Now it is time to set the drawing mode correctly..         */
    /**************************************************************/
    if (pdc->DCIBitmapType == BITMAP_IS_SCREEN)
    {
        SetDrawModeHard;
    }
    else
    {
        SetDrawModeSoft;
    }

    /******************************************************************/
    /* Convert frame coords to AI space                               */
    /* the frame coordinates are now inclusive                        */
    /******************************************************************/
    Frame.pts1.x += pdc->DCIOrigin.X;
    Frame.pts2.x += pdc->DCIOrigin.X;
    Result = pdc->DCIConvFactor - Frame.pts1.y;
    Frame.pts1.y = pdc->DCIConvFactor - Frame.pts2.y;
    Frame.pts2.y = Result;

    /******************************************************************/
    /* set static pointer to the first clip region                    */
    /******************************************************************/
    AIxfer.pNextDestClipRect = pdc->DCIClipRects;

    /******************************************************************/
    /* Set up border colors                                           */
    /******************************************************************/

    if (ArgOptions & DB_AREAATTRS)
    {
        /**************************************************************/
        /* Use pattern colors (fetch RGB values if RGB mode or        */
        /* logical value if in any other mode)                        */
        /**************************************************************/
        ForeColor = pdc->DCICurPtnAts.abnd.lColor;
        BackColor = pdc->DCICurPtnAts.abnd.lBackColor;
    }
    else
    {
        /**************************************************************/
        /* Use border color as foreground and interior color as       */
        /* background.                                                */
        /**************************************************************/
        ForeColor = ArgBorderColor;
        BackColor = ArgInteriorColor;
    }

    /******************************************************************/
    /* before we start to use the hardware, if the cursor is software */
    /* then the cursor may need to be excluded and                    */
    /* further drawing on the mouse interrupt thread must be disabled */
    /******************************************************************/
    if (cursor_data.cursor_status & CURSOR_SOFTWARE )
    {
        eddm_ExcludeCursor((pDevPoint)&Frame, COORD_AI);
    }

    /******************************************************************/
    /* Select foreground and background mixes                         */
    /******************************************************************/
    switch (ArgOptions & DB_ROP)
    {
#ifndef   _8514
        case DB_PATCOPY:
            /**************************************************************/
            /* Pattern Copy mix                                           */
            /**************************************************************/
            ShadowXGARegs.FgMix =
            ShadowXGARegs.BgMix = HWMIX_SOURCE;
            break;

        case DB_PATINVERT:
            /**************************************************************/
            /* Exclusive-OR mix required                                  */
            /**************************************************************/
            ShadowXGARegs.FgMix =
            ShadowXGARegs.BgMix = HWMIX_SOURCE_XOR_DEST;
            break;

        case DB_DESTINVERT:
            /**************************************************************/
            /* Destination invert mix required                            */
            /**************************************************************/
            ShadowXGARegs.FgMix =
            ShadowXGARegs.BgMix = HWMIX_NOTDEST;
            break;

        case DB_AREAMIXMODE:
            /**************************************************************/
            /* Area mixes required                                        */
            /**************************************************************/
            ShadowXGARegs.FgMix =
            ShadowXGARegs.BgMix = WinToXWay[pdc->DCICurPtnAts.abnd.usMixMode];
            break;

    } /* switch */

    ShadowXGARegs.ColCompCond = COLCOMP_ALWAYS;
#else
        case DB_PATCOPY:
            /**************************************************************/
            /* Pattern Copy mix                                           */
            /**************************************************************/
            Shadow8514Regs.Function_1.Mix =
            Shadow8514Regs.Function_0.Mix = FUNC_S;
            break;

        case DB_PATINVERT:
            /**************************************************************/
            /* Exclusive-OR mix required                                  */
            /**************************************************************/
            Shadow8514Regs.Function_1.Mix =
            Shadow8514Regs.Function_0.Mix = FUNC_S_XOR_D;
            break;

        case DB_DESTINVERT:
            /**************************************************************/
            /* Destination invert mix required                            */
            /**************************************************************/
            Shadow8514Regs.Function_1.Mix =
            Shadow8514Regs.Function_0.Mix = FUNC_ND;
            break;

        case DB_AREAMIXMODE:
            /**************************************************************/
            /* Area mixes required                                        */
            /**************************************************************/
            Shadow8514Regs.Function_1.Mix =
            Shadow8514Regs.Function_0.Mix = WinToXWay[pdc->DCICurPtnAts.abnd.usMixMode];
            break;

    } /* switch */

    Shadow8514Regs.Function_1.SrcSelect = FUNC_2OP_COL1;
    Shadow8514Regs.Function_0.SrcSelect = FUNC_2OP_COL0;
    Shadow8514Regs.Mode.UnderPaint = MD_UP_FALSE;
#endif //_8514

#ifdef DCAF                                                               //DCAF
    /******************************************************************/  //DCAF
    /* Set a flag in AIxfer to indicate whether we should             */  //DCAF
    /* accumulate DCAF bounds.                                        */  //DCAF
    /******************************************************************/  //DCAF
    AIxfer.fAccumulateDCAFBounds = DCAFBoundsRequired(FunN);              //DCAF                          //DCAF
#endif                                                                    //DCAF

    /******************************************************************/
    /* start drawing the rectangles                                   */
    /* first check that there is a border to be drawn                 */
    /******************************************************************/
    if ( ArgBorderWidth | ArgBorderHeight )
    {
        /**************************************************************/
        /* if the pattern symbol or set has changed then we need to   */
        /* get the new data                                           */
        /**************************************************************/
        if ( pdc->DCIChanged & NEW_PATTERN_SYMBOL )
        {
            if ( !edda_PatternSetUp() )
            {
                goto DRAWBORDER_ERR_EXIT;
            }
        }

        /**************************************************************/
        /* We have to draw a border, set the pattern and the colours  */
        /* SetDithColourAndPattern returns TRUE if dithering has been */
        /* enabled                                                    */
        /**************************************************************/
        if ( eddc_SetDithColourAndPattern(ForeColor) )
        {
            /**********************************************************/
            /* Set the dither origin to be the pattern origin         */
            /**********************************************************/
            AIxfer.ptsPatOrig.x = pdc->DCIPatternOrigin.X;
            AIxfer.ptsPatOrig.y = pdc->DCIPatternOrigin.Y;

            if (pdc->DCISelListEntry->Info.BitCount != 1)
            {
                /******************************************************/
                /* Use the coloured dither pattern                    */
                /* Set up the source bitmap as the dithered pattern   */
                /******************************************************/
                AIxfer.pbmhSrc = &NewPatternTable[PATSYM_DITHERED];

                /******************************************************/
                /* initialise the pixel operation to be used          */
                /* -  background source: source pixel map             */
                /* -  foreground source: source pixel map             */
                /* -  step: PxBlt                                     */
                /* -  source pixel map: Map B                         */
                /* -  destination pixel map: Map A                    */
                /* -  pattern pixel map: foreground (fixed)           */
                /* -  mask pixel map: disabled                        */
                /* -  drawing mode: don't care                        */
                /* -  direction octant: left to right, top to bottom  */
                /******************************************************/
                PixelOp = BACK_SRC_SRC_PIX_MAP |
                          FORE_SRC_SRC_PIX_MAP |
                          STEP_PXBLT |
                          SRC_PIX_MAP_B |
                          DST_PIX_MAP_A |
                          PAT_PIX_MAP_FORE |
                          MASK_PIX_MAP_OFF |
                          DRAW_MODE_DONTCARE |
                          DIR_OCTANT_LRTB;

            }
            else
            {
                /******************************************************/
                /* use the mono dither pattern                        */
                /* Set up the source bitmap as the dithered pattern   */
                /******************************************************/
                AIxfer.pbmhSrc = &NewPatternTable[PATSYM_MONODITH];

                /******************************************************/
                /* initialise the pixel operation to be used          */
                /* -  background source: background colour            */
                /* -  foreground source: foreground colour            */
                /* -  step: PxBlt                                     */
                /* -  source pixel map: don't care                    */
                /* -  destination pixel map: Map A                    */
                /* -  pattern pixel map: Map B                        */
                /* -  mask pixel map: boundary disabled               */
                /* -  drawing mode: don't care                        */
                /* -  direction octant: left to right, top to bottom  */
                /******************************************************/
                PixelOp = BACK_SRC_BACK_COL |
                          FORE_SRC_FORE_COL |
                          STEP_PXBLT |
                          SRC_PIX_MAP_DONTCARE |
                          DST_PIX_MAP_A |
                          PAT_PIX_MAP_B |
                          MASK_PIX_MAP_OFF |
                          DRAW_MODE_DONTCARE |
                          DIR_OCTANT_LRTB;

                /******************************************************/
                /* Set up the colours to use.                         */
                /* these must be 1 and 0                              */
                /******************************************************/
      #ifndef   _8514
                ShadowXGARegs.FgCol = 1;
                ShadowXGARegs.BgCol = 0;
      #else
                Shadow8514Regs.Color_1 = 1;
                Shadow8514Regs.Color_0 = 0;
      #endif
            }

        }

        else /* not a dithered pattern */
        {
            /**********************************************************/
            /* set the parameter block pointer to the pattern bitmap  */
            /**********************************************************/
            AIxfer.pbmhSrc = pdc->TempPattern;

            /**********************************************************/
            /* copy the pattern origin to the parameter block         */
            /**********************************************************/
            AIxfer.ptsPatOrig.x = pdc->DCIPatternOrigin.X;
            AIxfer.ptsPatOrig.y = pdc->DCIPatternOrigin.Y;

            /**********************************************************/
            /* we use different pixel ops according to whether we     */
            /* have a colour or a mono pattern                        */
            /**********************************************************/
            if (pdc->TempPattern->Info.BitCount == 1)
            {
                /******************************************************/
                /* pattern is mono                                    */
                /******************************************************/
                /******************************************************/
                /* initialise the pixel operation to be used          */
                /* -  background source: background colour            */
                /* -  foreground source: foreground colour            */
                /* -  step: PxBlt                                     */
                /* -  source pixel map: don't care                    */
                /* -  destination pixel map: Map A                    */
                /* -  pattern pixel map: Map B                        */
                /* -  mask pixel map: boundary disabled               */
                /* -  drawing mode: don't care                        */
                /* -  direction octant: left to right, top to bottom  */
                /******************************************************/
                PixelOp = BACK_SRC_BACK_COL |
                          FORE_SRC_FORE_COL |
                          STEP_PXBLT |
                          SRC_PIX_MAP_DONTCARE |
                          DST_PIX_MAP_A |
                          PAT_PIX_MAP_B |
                          MASK_PIX_MAP_OFF |
                          DRAW_MODE_DONTCARE |
                          DIR_OCTANT_LRTB;

                /******************************************************/
                /* set the foreground and background colours for the  */
                /* blt.  These are taken from the target atrribute    */
                /* bundle unless colour information was passed in the */
                /* parameters                                         */
                /******************************************************/
      #ifndef _8514
                ShadowXGARegs.FgCol = (USHORT)LogToPhyIndex(ForeColor);
                ShadowXGARegs.BgCol = (USHORT)LogToPhyIndex(BackColor);
      #else
                #ifndef   BPP24
                Shadow8514Regs.Color_1 = (USHORT)LogToPhyIndex(ForeColor);
                Shadow8514Regs.Color_0 = (USHORT)LogToPhyIndex(BackColor);
                #else
                Shadow8514Regs.Color_1 = LogToPhyIndex(ForeColor);
                Shadow8514Regs.Color_0 = LogToPhyIndex(BackColor);
                #endif
      #endif
            }
            else
            {
                /******************************************************/
                /* pattern is colour                                  */
                /* we use the same pixel op as we do in the dithered  */
                /* pattern case                                       */
                /******************************************************/
                /******************************************************/
                /* initialise the pixel operation to be used          */
                /* -  background source: source pixel map             */
                /* -  foreground source: source pixel map             */
                /* -  step: PxBlt                                     */
                /* -  source pixel map: Map B                         */
                /* -  destination pixel map: Map A                    */
                /* -  pattern pixel map: foreground (fixed)           */
                /* -  mask pixel map: disabled                        */
                /* -  drawing mode: don't care                        */
                /* -  direction octant: left to right, top to bottom  */
                /******************************************************/
                PixelOp = BACK_SRC_SRC_PIX_MAP |
                          FORE_SRC_SRC_PIX_MAP |
                          STEP_PXBLT |
                          SRC_PIX_MAP_B |
                          DST_PIX_MAP_A |
                          PAT_PIX_MAP_FORE |
                          MASK_PIX_MAP_OFF |
                          DRAW_MODE_DONTCARE |
                          DIR_OCTANT_LRTB;
            }

        } /* not dithered pattern */

        /**************************************************************/
        /* if the pattern is not in VRAM and we are in hardware       */
        /* drawing mode then we need to copy it into the PHUNK        */
        /**************************************************************/
        if ( (!AIxfer.pbmhSrc->BMPhys) && !softDrawInUse )
        {
            eddb_PhunkThatBitmap(AIxfer.pbmhSrc);
        }

        /**************************************************************/
        /* Transfer the values we have set from the shadow registers  */
        /* to the real hw registers.                                  */
        /**************************************************************/
        TransferShadowRegisters( TSR_COLOUR_MIX );


        /**************************************************************/
        /* check for borders which cover the frame, thus requiring a  */
        /* single draw rectangle (and no interior to do)              */
        /**************************************************************/
        if ( (Frame.pts2.x - Frame.pts1.x) <
                                    (SHORT)2 * (SHORT)ArgBorderWidth ||
             (Frame.pts2.y - Frame.pts1.y) <
                                    (SHORT)2 * (SHORT)ArgBorderHeight )
        {
            /**********************************************************/
            /* draw the covering border...                            */
            /**********************************************************/
            AIxfer.rcsTrg = Frame;
            eddb_FastDrawRectangle();

            /**********************************************************/
            /* ...and return                                          */
            /**********************************************************/
            goto DRAWBORDER_DRAWING_DONE;
        }
        else
        {
            /**********************************************************/
            /* draw each border in the order north, south, west, east */
            /*                                                        */
            /*           . . . . . . . . . . . . . . . . . . .        */
            /*           .     .         1                   .        */
            /*           .     . . . . . . . . . . . . . . . .        */
            /*           .     .                       .     .        */
            /*           .     .                       .     .        */
            /*           .     .                       .     .        */
            /*           .     .                       .     .        */
            /*           .  3  .                       .  4  .        */
            /*           .     .                       .     .        */
            /*           .     .                       .     .        */
            /*           . . . . . . . . . . . . . . . .     .        */
            /*           .               2             .     .        */
            /*           . . . . . . . . . . . . . . . . . . .        */
            /*                                                        */
            /**********************************************************/
            if ( ArgBorderHeight )
            {

                AIxfer.rcsTrg.pts1.x = Frame.pts1.x;
                AIxfer.rcsTrg.pts2.x = Frame.pts2.x - (USHORT)ArgBorderWidth;
                AIxfer.rcsTrg.pts1.y = Frame.pts1.y;
                AIxfer.rcsTrg.pts2.y = AIxfer.rcsTrg.pts1.y +
                                        (USHORT)ArgBorderHeight - (USHORT)1;
                eddb_FastDrawRectangle();


                AIxfer.rcsTrg.pts1.x = Frame.pts1.x + (USHORT)ArgBorderWidth;
                AIxfer.rcsTrg.pts2.x = Frame.pts2.x;
                AIxfer.rcsTrg.pts2.y = Frame.pts2.y;
                AIxfer.rcsTrg.pts1.y = AIxfer.rcsTrg.pts2.y + (USHORT)1 -
                                                  (USHORT)ArgBorderHeight;
                eddb_FastDrawRectangle();

            }

            if ( ArgBorderWidth )
            {
                AIxfer.rcsTrg.pts1.x = Frame.pts1.x;
                AIxfer.rcsTrg.pts2.x = Frame.pts1.x +
                                           (USHORT)ArgBorderWidth - (USHORT)1;
                AIxfer.rcsTrg.pts1.y = Frame.pts1.y +
                                                  (USHORT)ArgBorderHeight;
                AIxfer.rcsTrg.pts2.y = Frame.pts2.y;
                eddb_FastDrawRectangle();


                AIxfer.rcsTrg.pts2.x = Frame.pts2.x;
                AIxfer.rcsTrg.pts1.x = AIxfer.rcsTrg.pts2.x -
                                           (USHORT)ArgBorderWidth + (USHORT)1;
                AIxfer.rcsTrg.pts1.y = Frame.pts1.y;
                AIxfer.rcsTrg.pts2.y = Frame.pts2.y -
                                                  (USHORT)ArgBorderHeight;
                eddb_FastDrawRectangle();

            }

        }

        /**************************************************************/
        /* If we PHUNKed the pattern then we must now unPHUNK it      */
        /**************************************************************/
        if ( AIxfer.pbmhSrc->BMPhys == pPhunkPhys )
        {
            AIxfer.pbmhSrc->BMPhys = FNULL;
        }
    }

    /******************************************************************/
    /* Draw the interior if required                                  */
    /******************************************************************/
    if (ArgOptions & DB_INTERIOR )
    {
        /**************************************************************/
        /* if the pattern symbol or set has changed then we need to   */
        /* get the new data                                           */
        /**************************************************************/
        if ( pdc->DCIChanged & NEW_PATTERN_SYMBOL )
        {
            if ( !edda_PatternSetUp() )
            {
                goto DRAWBORDER_ERR_EXIT;
            }
        }

        /**************************************************************/
        /* The colors are the reverse of those for the border.        */
        /* SetDithColourAndPattern returns TRUE if dithering has been */
        /* enabled                                                    */
        /**************************************************************/
        if ( eddc_SetDithColourAndPattern(BackColor) )
        {
            /**********************************************************/
            /* set the pattern origin                                 */
            /**********************************************************/
            AIxfer.ptsPatOrig.x = pdc->DCIPatternOrigin.X;
            AIxfer.ptsPatOrig.y = pdc->DCIPatternOrigin.Y;

            if (pdc->DCISelListEntry->Info.BitCount != 1)
            {
                /******************************************************/
                /* use the coloured dither pattern                    */
                /* Set up the source bitmap as the dithered pattern   */
                /******************************************************/
                AIxfer.pbmhSrc = &NewPatternTable[PATSYM_DITHERED];

                /******************************************************/
                /* initialise the pixel operation to be used          */
                /* -  background source: source pixel map             */
                /* -  foreground source: source pixel map             */
                /* -  step: PxBlt                                     */
                /* -  source pixel map: Map B                         */
                /* -  destination pixel map: Map A                    */
                /* -  pattern pixel map: foreground (fixed)           */
                /* -  mask pixel map: disabled                        */
                /* -  drawing mode: don't care                        */
                /* -  direction octant: left to right, top to bottom  */
                /******************************************************/
                PixelOp = BACK_SRC_SRC_PIX_MAP |
                          FORE_SRC_SRC_PIX_MAP |
                          STEP_PXBLT |
                          SRC_PIX_MAP_B |
                          DST_PIX_MAP_A |
                          PAT_PIX_MAP_FORE |
                          MASK_PIX_MAP_OFF |
                          DRAW_MODE_DONTCARE |
                          DIR_OCTANT_LRTB;

            }
            else
            {
                /******************************************************/
                /* use the mono dither pattern                        */
                /* Set up the source bitmap as the dithered pattern   */
                /******************************************************/
                AIxfer.pbmhSrc = &NewPatternTable[PATSYM_MONODITH];

                /******************************************************/
                /* initialise the pixel operation to be used          */
                /* -  background source: background colour            */
                /* -  foreground source: foreground colour            */
                /* -  step: PxBlt                                     */
                /* -  source pixel map: don't care                    */
                /* -  destination pixel map: Map A                    */
                /* -  pattern pixel map: Map B                        */
                /* -  mask pixel map: boundary disabled               */
                /* -  drawing mode: don't care                        */
                /* -  direction octant: left to right, top to bottom  */
                /******************************************************/
                PixelOp = BACK_SRC_BACK_COL |
                          FORE_SRC_FORE_COL |
                          STEP_PXBLT |
                          SRC_PIX_MAP_DONTCARE |
                          DST_PIX_MAP_A |
                          PAT_PIX_MAP_B |
                          MASK_PIX_MAP_OFF |
                          DRAW_MODE_DONTCARE |
                          DIR_OCTANT_LRTB;


                /******************************************************/
                /* Set up the colours to use.                         */
                /* these must be 1 and 0                              */
                /******************************************************/
      #ifndef   _8514
                ShadowXGARegs.FgCol = 1;
                ShadowXGARegs.BgCol = 0;
      #else
                Shadow8514Regs.Color_1 = 1;
                Shadow8514Regs.Color_0 = 0;
      #endif
            }

        }

        else /* not a dithered pattern */
        {
            /**********************************************************/
            /* set the parameter block pointer to the pattern bitmap  */
            /**********************************************************/
            AIxfer.pbmhSrc = pdc->TempPattern;


            /**************************************************************/
            /* copy the pattern origin to the parameter block             */
            /**************************************************************/
            AIxfer.ptsPatOrig.x = pdc->DCIPatternOrigin.X;
            AIxfer.ptsPatOrig.y = pdc->DCIPatternOrigin.Y;


            /**************************************************************/
            /* initialise the pixel operation to be used                  */
            /* -  background source: background colour                    */
            /* -  foreground source: foreground colour                    */
            /* -  step: PxBlt                                             */
            /* -  source pixel map: don't care                            */
            /* -  destination pixel map: Map A                            */
            /* -  pattern pixel map: Map B                                */
            /* -  mask pixel map: boundary disabled                       */
            /* -  drawing mode: don't care                                */
            /* -  direction octant: left to right, top to bottom          */
            /**************************************************************/
            PixelOp = BACK_SRC_BACK_COL |
                      FORE_SRC_FORE_COL |
                      STEP_PXBLT |
                      SRC_PIX_MAP_DONTCARE |
                      DST_PIX_MAP_A |
                      PAT_PIX_MAP_B |
                      MASK_PIX_MAP_OFF |
                      DRAW_MODE_DONTCARE |
                      DIR_OCTANT_LRTB;

            /**************************************************************/
            /* set the foreground and background colours for the blt.     */
            /* These are taken from the target atrribute bundle           */
            /* unless colour information was passed in the parameters     */
            /**************************************************************/
       #ifndef  _8514
            ShadowXGARegs.FgCol = (USHORT)LogToPhyIndex(BackColor);
            ShadowXGARegs.BgCol = (USHORT)LogToPhyIndex(ForeColor);
       #else
            #ifndef   BPP24
            Shadow8514Regs.Color_1 = (USHORT)LogToPhyIndex(BackColor);
            Shadow8514Regs.Color_0 = (USHORT)LogToPhyIndex(ForeColor);
            #else
            Shadow8514Regs.Color_1 = LogToPhyIndex(BackColor);
            Shadow8514Regs.Color_0 = LogToPhyIndex(ForeColor);
            #endif
       #endif

        } /* not dithered pattern */


        /**************************************************************/
        /* if the pattern is not in VRAM and we are in hardware       */
        /* drawing mode then we need to copy it into the PHUNK        */
        /**************************************************************/
        if ( (!AIxfer.pbmhSrc->BMPhys) && !softDrawInUse )
        {
            eddb_PhunkThatBitmap(AIxfer.pbmhSrc);
        }

        /**************************************************************/
        /* Transfer the values we have set from the shadow registers  */
        /* to the real hw registers.                                  */
        /**************************************************************/
   #ifndef   _8514
        ShadowXGARegs.ColCompCond = COLCOMP_ALWAYS;
   #else
        Shadow8514Regs.Mode.UnderPaint = MD_UP_FALSE;
   #endif

        TransferShadowRegisters( TSR_COLOUR_MIX );

        /**************************************************************/
        /* Fill the interior                                          */
        /**************************************************************/
        AIxfer.rcsTrg.pts1.x = Frame.pts1.x + (USHORT)ArgBorderWidth;
        AIxfer.rcsTrg.pts1.y = Frame.pts1.y + (USHORT)ArgBorderHeight;
        AIxfer.rcsTrg.pts2.x = Frame.pts2.x - (USHORT)ArgBorderWidth;
        AIxfer.rcsTrg.pts2.y = Frame.pts2.y - (USHORT)ArgBorderHeight;
        eddb_FastDrawRectangle();

        /**************************************************************/
        /* If we PHUNKed the pattern then we must now unPHUNK it      */
        /**************************************************************/
        if ( AIxfer.pbmhSrc->BMPhys == pPhunkPhys )
        {
            AIxfer.pbmhSrc->BMPhys = FNULL;
        }
    }

DRAWBORDER_DRAWING_DONE:
    /******************************************************************/
    /* if the cursor is software then cursor drawing will have been   */
    /* disabled while drawborder used the hardware. If this is the    */
    /* case then the cursor EXCLUDED status will be set and we should */
    /* set it up to do a redraw on the next MoveCursor (CheckCursor)  */
    /******************************************************************/
    reenable_cursor();

#ifdef VRAMPTR
    /******************************************************************/
    /* If the target bitmap is cached then evict it since it has      */
    /* been drawn to.                                                 */
    /******************************************************************/
    if ( BITMAP_IS_CACHED(AIxfer.pbmhDest) )
    {
      evict_cached_bitmap(AIxfer.pbmhDest->bm_cache_slot);
    }
#endif /* VRAMPTR */


DRAWBORDER_EXIT:
    /******************************************************************/
    /* Release driver semaphore                                       */
    /******************************************************************/
    ExitDriver(pdcArg, FunN, EDF_STANDARD);
    return(OK);


DRAWBORDER_LOGERR_EXIT:
    ExitDriver(pdcArg, FunN, EDF_STANDARD);
    LogError(Error);
    return(ERROR_ZERO);


DRAWBORDER_ERR_EXIT:
    reenable_cursor();
    ExitDriver(pdcArg, FunN, EDF_STANDARD);
    return(ERROR_ZERO);

}



/**********************************************************************/
/* clips the target coordinates in the AIxfer blt parameter block and */
/* calls the blt hardware interface to draw a solid rectangle.        */
/* Colours and mixes have already been set in the hardware            */
/**********************************************************************/

VOID DRIVERCALL eddb_FastDrawRectangle(VOID)
{

    /******************************************************************/
    /* calculate the blt dimensions and put the starting coordinate   */
    /* in the parameter block, clipping the destination to the bitmap */
    /******************************************************************/
    /**************************************************************/
    /* if the left edge of the target is to the left of the bitmap*/
    /* then set the destination x coordinate to 0 (the left edge  */
    /* of the bitmap), otherwise just use the calculated coord    */
    /**************************************************************/
    if ( AIxfer.rcsTrg.pts1.x < 0 )
    {
        /**********************************************************/
        /* exit now if the the right edge of the target is to the */
        /* left of the left edge                                  */
        /**********************************************************/
        if ( AIxfer.rcsTrg.pts2.x < 0 )
        {
            return;
        }

        AIxfer.rcsTrg.pts1.x = 0;
    }


    /**************************************************************/
    /* if the bottom edge of the target is below  the bottom of   */
    /* the bitmap then set the destination y coordinate to 0 (the */
    /* bottom edge of the bitmap), otherwise just use the         */
    /* calculated coordinate                                      */
    /**************************************************************/
    if ( AIxfer.rcsTrg.pts1.y < 0 )
    {
        /**********************************************************/
        /* exit now if the the top edge of the target is below the*/
        /* bottom edge                                            */
        /**********************************************************/
        if ( AIxfer.rcsTrg.pts2.y < 0 )
        {
            return;
        }

        AIxfer.rcsTrg.pts1.y = 0;
    }


    /**************************************************************/
    /* if the right edge of the target is to the right of         */
    /* the bitmap then set the destination width to be the bitmap */
    /* hardware width less the start coordinate, otherwise        */
    /* subtract the start coordinate from the calculated right    */
    /* edge                                                       */
    /**************************************************************/
    AIxfer.rcsTrg.pts2.x = min((SHORT)AIxfer.pbmhDest->Info.HWWidth,
                               AIxfer.rcsTrg.pts2.x);
    if ( AIxfer.rcsTrg.pts1.x > AIxfer.rcsTrg.pts2.x)
    {
        return;
    }

    /**************************************************************/
    /* if the top edge of the target is above the bitmap          */
    /* then set the destination height to be the bitmap           */
    /* hardware height less the start coordinate, otherwise       */
    /* subtract the start coordinate from the calculated top edge */
    /**************************************************************/
    AIxfer.rcsTrg.pts2.y = min((SHORT)AIxfer.pbmhDest->Info.HWHeight,
                               AIxfer.rcsTrg.pts2.y);
    if ( AIxfer.rcsTrg.pts1.y > AIxfer.rcsTrg.pts2.y)
    {
        return;
    }

#ifdef DCAF                                                               //DCAF
    /******************************************************************/  //DCAF
    /* Accumulate DCAF screen bounds if necessary                     */  //DCAF
    /******************************************************************/  //DCAF
    if (AIxfer.fAccumulateDCAFBounds)                                     //DCAF
    {                                                                     //DCAF
        AccumulateScreenBoundsThroughClips( (pDevRect)&AIxfer.rcsTrg,     //DCAF
                                            COORD_AI );                   //DCAF
    }                                                                     //DCAF
#endif                                                                    //DCAF

    /******************************************************************/
    /* go do the blt to the destination                               */
    /******************************************************************/
    SPad.BltFunction = (*pDrawFunctions)[index_PatDestBlt];
    PixBltThroughClips();


} /* eddb_FastDrawRectangle */
