/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Lexmark 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 = PRDBSUBR
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prdb_HugeIncrement
 *             prdb_HugeDecrement
 *             prdb_HugeSetByte
 *             prdb_HugeGetByte
 *             prdb_ConvertBitmap
 *             prdb_FreeBitmap
 *             prdb_DeleteBitmap
 *             prdb_GetOffsets
 *             prdb_GetGreyScaleInfo
 *             prdb_GreyscaleSourceBitmap
 *             prdb_GetNextColor
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/
#define INCL_32                         /* Convert to C/SET2    CON3201       */
#define INCL_DOSPROCESS                 /* Convert to C/SET2    CON3201       */
#define INCL_DOSSEMAPHORES              /* Convert to C/SET2    CON3201       */
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#define INCL_GPIERRORS
#define INCL_GPILOGCOLORTABLE
#include <os2.h>
#undef INCL_DOSPROCESS                  /* Convert to C/SET2    CON3201       */
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS
#undef INCL_GPIERRORS
#undef INCL_GPILOGCOLORTABLE

#define INCL_DDIBUNDLES
#define INCL_DDIFONTSTRUCS
#define INCL_DDIDEFS
#define INCL_DDIMISC
#include <pmddi.h>
#undef INCL_DDIBUNDLES
#undef INCL_DDIFONTSTRUCS
#undef INCL_DDIDEFS
#undef INCL_DDIMISC

#define INCL_WINP_SELSERVER
#define INCL_WINP_SELECTIVE
#define INCL_WINP_SEI
#include <pmwinx.h>
#undef INCL_WINP_SELSERVER
#undef INCL_WINP_SELECTIVE
#undef INCL_WINP_SEI
#undef INCL_32                          /* Convert to C/SET2    CON3201       */

#include <prdbcone.h>
#include <prddcone.h>

#define NO_CONSTANT_INCL
#include <prdinclt.h>
#undef NO_CONSTANT_INCL

#include <prdbsize.h>
#include <prdbtyp1.h>
#include <prdbextf.h>
#include <prdgextf.h>
#include <prdcextf.h>
#include <prduextf.h>

/******************************************************************************/
/*  A few externals...                                                        */
/******************************************************************************/
/*extern PFSRSEM  lpGlobalHeapSem;    CON3201 */
extern HMTX     hmtxGlobalHeapSem; /* CON3201 */
extern USHORT   prdd_HugeInc;
extern BYTE     greyscale_table[];
extern BYTE     greyscale_table2[];
extern USHORT   DRIVER_TYPE;

/******************************************************************************/
/*  FUNCTION: prdb_HugeIncrement                                              */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  Dptr    OldAddress;  Pointer to increment                                 */
/*  USHORT  Update;      Increment required                                   */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function handles increments in OldAddress which may cross segment    */
/*  boundaries.                                                               */
/*  CON3201 : This function is not necessary for 32-bit code.                 */
/*            Changed to just do a direct pointer increment,                  */
/*            but function can probably be deleted.                           */
/*                                                                            */
/******************************************************************************/
PBYTE prdb_HugeIncrement( PBYTE    OldAddress,
                          USHORT   Update )

{

#define TFUNC "prdb_HugeInc"

int3();
#if 0
    /**************************************************************************/
    /*  Local Variables                                                       */
    /**************************************************************************/
    ULONG  Work;                       /* Work variable for manipulating the  */
                                       /* offset                              */

    /**************************************************************************/
    /*  Get the offset of the current address and add the Update to it.       */
    /**************************************************************************/
    if ((Work = OFFSETOF(OldAddress) + Update) < OFFSETOF(OldAddress))
    {

        /**********************************************************************/
        /*  The selector needs bumping up by HugeInc as it has exceeded 65535.*/
        /**********************************************************************/
        SELECTOROF(OldAddress) += prdd_HugeInc;
    }
    return(MAKEP(SELECTOROF(OldAddress), OFFSETOF(Work)));
#endif
    return(OldAddress + Update);                                   /* CON3201 */
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdb_HugeDecrement                                              */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  Dptr    OldAddress;  Pointer to decrement                                 */
/*  USHORT  Update;      Decrement required                                   */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function handles decrements in OldAddress which may cross segment    */
/*  boundaries.  Note Update is an unsigned number which is subtracted from   */
/*  OldAddress.  It returns the actual address.                               */
/*  CON3201 : This function is not necessary for 32-bit code.                 */
/*            Changed to just do a direct pointer decrement,                  */
/*            but function can probably be deleted.                           */
/*                                                                            */
/******************************************************************************/
PBYTE prdb_HugeDecrement( PBYTE   OldAddress,
                          USHORT  Update )

{

#define TFUNC "prdb_HugeDec"
int3();

#if 0
    /**************************************************************************/
    /*  Local Variables                                                       */
    /**************************************************************************/
    USHORT  Work;                      /* Work variable for manipulating the  */
                                       /* offset                              */

    /**************************************************************************/
    /*  Decrement the current offset then determine if this has crossed a     */
    /*  segment boundary.                                                     */
    /**************************************************************************/
    if ((Work = OFFSETOF(OldAddress) - Update) > OFFSETOF(OldAddress))
    {

        /**********************************************************************/
        /*  The selector needs decrementing                                   */
        /**********************************************************************/
        SELECTOROF(OldAddress) -= prdd_HugeInc;
    }
    return(MAKEP(SELECTOROF(OldAddress), OFFSETOF(Work)));
#endif
    return(OldAddress - Update);                                   /* CON3201 */
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdb_HugeSetByte                                                */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  PBYTE    BasePointer;     Address of base segment                         */
/*  ULONG    Offset;          Offset from BasePointer                         */
/*  BYTE     NewByte;         Value to insert                                 */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function writes a byte at the location specified by BasePointer and  */
/*  Offset allowing for crossing segment boundaries.                          */
/*  CON3201 : This function is not necessary for 32-bit code.                 */
/*            Changed to just do a direct byte store,                         */
/*            but function can probably be deleted.                           */
/*                                                                            */
/******************************************************************************/
VOID prdb_HugeSetByte ( PBYTE  BasePointer,
                        ULONG  Offset,
                        BYTE   NewByte )

{

#define TFUNC "prdb_HugeSetByte"
int3();

#if 0
    /**************************************************************************/
    /*  Set up the offset                                                     */
    /**************************************************************************/
    Offset                += OFFSETOF(BasePointer);
    OFFSETOF(BasePointer)  = OFFSETOF(Offset);

    /**************************************************************************/
    /*  Set up segment selector for bitmap address                            */
    /**************************************************************************/
    if (SELECTOROF(Offset))
    {
        SELECTOROF(BasePointer) += SELECTOROF(Offset) * prdd_HugeInc;
    }

    /**************************************************************************/
    /*  Write a single byte to that position.                                 */
    /**************************************************************************/
    /**************************************************************************/
    *((PBYTE)BasePointer) = NewByte;
#endif
    *(BasePointer + Offset) = NewByte;                             /* CON3201 */
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdb_HugeGetByte                                                */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  PBYTE  BasePointer;  Address of base segment                              */
/*  ULONG  Offset;       Offset from BasePointer                              */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function returns the value at the location specified by BasePointer  */
/*  and Offset allowing for crossing segment boundaries.                      */
/*  CON3201 : This function is not necessary for 32-bit code.                 */
/*            Changed to just get a byte directly,                            */
/*            but function can probably be deleted.                           */
/*                                                                            */
/******************************************************************************/
BYTE prdb_HugeGetByte( PBYTE  BasePointer,
                       ULONG  Offset )

{

#define TFUNC "prdb_HugeGetByte"
int3();

#if 0
    /**************************************************************************/
    /*  Set up the offset                                                     */
    /**************************************************************************/
    Offset                += OFFSETOF(BasePointer);
    OFFSETOF(BasePointer)  = OFFSETOF(Offset);

    /**************************************************************************/
    /*  Set up segment selector for bitmap address                            */
    /**************************************************************************/
    if (SELECTOROF(Offset))
    {
        SELECTOROF(BasePointer) += SELECTOROF(Offset) * prdd_HugeInc;
    }

    /**************************************************************************/
    /*  Read a single byte from that address.                                 */
    /**************************************************************************/
    return(*((PBYTE)BasePointer));
#endif
    return(*(BasePointer+Offset));                                 /* CON3201 */
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdb_FreeBitmap                                                 */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  PBYTE  hBitmap;  Handle of bitmap to free                                 */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function frees a bitmap.  The handle gives the selector of the       */
/*  segment.                                                                  */
/******************************************************************************/
USHORT prdb_FreeBitmap(PBYTE hBitmap)
{

#define TFUNC "prdb_FreeBitmap"

    /**************************************************************************/
    /*  Local Variables                                                       */
    /**************************************************************************/
    USHORT  DosResult;                 /* Result of Dos call                  */

    TRACE4("prdbFreeBitmap", "hBitmap", &hBitmap, 1);

    /**************************************************************************/
    /*  If the Dos call fails log an error and return an error.               */
    /**************************************************************************/
 /* if ((DosResult = SSFREESEG(((unsigned far *)&hBitmap)[1])) != DOS_OK) */
    if ((DosResult = SSFREEMEM(hBitmap)) != DOS_OK)                /* CON3201 */
    {
     /* LOGDOSERR ("prdb_FreeBitmap","SSFREESEG failed",&DosResult,1, */
        LOGDOSERR ("prdb_FreeBitmap","SSFREEMEM failed",&DosResult,1,
                   DosResult);
        return(ERROR_ZERO);
    }
    return(OK);
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdb_DeleteBitmap                                               */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  PBYTE   BitmapData;  Pointer to bitmap to delete                          */
/*  USHORT  ProcessID;   Process ID for semaphores                            */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function deletes the bitmap pointed to by BitmapData.  It scans all  */
/*  the entrys in the bitmap list until a match for BitmapData is found in one*/
/*  and then removes that entry from the list and frees the associated memory.*/
/******************************************************************************/
USHORT prdb_DeleteBitmap(pBMListEntry BitmapData)

{

#define TFUNC "prdb_DeleteBitmap"

    /**************************************************************************/
    /*  Get the heap semaphore to allow freeing of global heap                */
    /**************************************************************************/
 /* (VOID)prdg_RequestSemaphore(lpGlobalHeapSem, 0); */
    (VOID)prdg_RequestSemaphore(hmtxGlobalHeapSem, 0);             /* CON3201 */

    /**************************************************************************/
    /*  free the heap used for the bitmap info                                */
    /**************************************************************************/
/*  CON3201 changed cast to PUSHORT*                                          */
/*  (VOID)prdg_FreeGlobalHeapItem(LIST_ENTRY_SIZE, (PUSHORT)&BitmapData);    */
    (VOID)prdg_FreeGlobalHeapItem(LIST_ENTRY_SIZE, (PUSHORT*)&BitmapData);

    /**************************************************************************/
    /*  Clear the heap semaphore                                              */
    /**************************************************************************/
 /* (VOID)prdg_ClearSemaphore(lpGlobalHeapSem); */
    (VOID)prdg_ClearSemaphore(hmtxGlobalHeapSem);                  /* CON3201 */
    return(OK);
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdb_GetOffsets                                                 */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  BitmapListEntry far *  ListEntry;   Pointer to list entry                 */
/*  USHORT                 XCoord,      Coordinates to find location          */
/*                         YCoord;      in bit map of                         */
/*  PULONG                 ByteOffset;  The offset from the start of the      */
/*                                      bitmap in bytes                       */
/*  PUSHORT                BitOffset;   The offset to the required bit (or    */
/*                                      bits) in the byte specified counted   */
/*                                      from the least significant byte       */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function returns an offset in two parts (byte and bit) to the        */
/*  position specified by XCoord and YCoord in the bitmap specified at        */
/*  ListEntry.  It takes account of huge bitmaps when calculating the offset  */
/*  but it is not responsible for the selector                                */
/*  CON3201 : Test for huge bitmaps is not necessary for 32-bit code.         */
/*                                                                            */
/******************************************************************************/
VOID prdb_GetOffsets( pBMListEntry  ListEntry,
                      USHORT        XCoord,
                      USHORT        YCoord,
                      PULONG        ByteOffset,
                      PUSHORT       BitOffset )

{

#define TFUNC "prdb_GetOffsets"

    /**************************************************************************/
    /*  The XCoord and YCoord must be adjusted to take account of the current */
    /*  band in the bitmap's associated DC.  This will only result in a change*/
    /*  for the band bitmap of the Direct DC.                                 */
    /**************************************************************************/
    XCoord += ListEntry->XOrigin;
    YCoord += ListEntry->YOrigin;

    /**************************************************************************/
    /*  Determine the byte offset using the (adjusted) coordinates and        */
    /*  BytesPerRow.                                                          */
    /**************************************************************************/
    /*  CON3201 : Don't care about bitmaps                                    */
#if 0
    if (ListEntry->Huge == 0)
    {

        /**********************************************************************/
        /*  Cast the calculation to a Word as the bitmap is not huge.         */
        /**********************************************************************/
        *ByteOffset = (USHORT)(ListEntry->Parms.BytesPerRow * YCoord) +
                      (((USHORT)ListEntry->Parms.Bitcount * XCoord)/8);
    }
    else
    {
#endif

        /**********************************************************************/
        /*  Calculation done in ULONGs as the bitmap is huge.                 */
        /**********************************************************************/
        *ByteOffset = (ListEntry->Parms.BytesPerRow * YCoord) +
                      ((ListEntry->Parms.Bitcount * XCoord)/8);
/*  } */

    /**************************************************************************/
    /*  Determine the BitOffset for (1,1) and (4,1) bitmaps (for other formats*/
    /*  this is not defined).                                                 */
    /**************************************************************************/
    if (ListEntry->Parms.Bitcount == 1)
    {
        *BitOffset = 7 - (XCoord & 0x07);
    }
    else
    {
        *BitOffset = 7 - ((XCoord * 4) & 0x07);
    }
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdb_GetGreyScaleInfo                                           */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  ULONG    Color;         RGB value, index to logical color table or        */
/*                          negative color index.                             */
/*  PUSHORT  GS_FlagPtr     Pointer to pattern type                           */
/*  PBYTE    *GS_PatternPtr Address of Pointer to the greyscale pattern       */
/*  lpDCI    DCIData                                                          */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function checks the conditions for greyscaling. If favourable,       */
/*  returns TRUE. Also sets the pointer to the greyscale pointer (which is    */
/*  one of the inputs) to the address of the pattern to be used in the        */
/*  appropriate greyscale table. Also sets the contents of the GS_FlagPtr (one*/
/*  of the inputs) to PAT_ALL_ONES if the greyscale index is 0 OR  to         */
/*  PAT_ALL_ZEROS if index is 256 ( 8 * 32 ). Else sets it to 0.              */
/******************************************************************************/
BOOL prdb_GetGreyScaleInfo( ULONG    Color,
                            PUSHORT  GS_FlagPtr,
                            PBYTE   *GS_PatternPtr,
                            lpDCI    DCIData )

{

#define TFUNC "prdb_GetGreyScaleInfo"

    /**************************************************************************/
    /*  Local variables                                                       */
    /**************************************************************************/
    USHORT     ulResWidth;
    BOOL       fGreyScale;             /* true is greyscaling                 */
    USHORT     usPatIndex;             /* index to greyscale pattern table    */
    lpDDTType  lpDDT;                  /* DDT Pointer                         */

    /**************************************************************************/
    /*  Initializations...                                                    */
    /**************************************************************************/
    lpDDT       = &(DCIData->DCIPdbInstance->DDT);
    ulResWidth  = lpDDT->DDTRasterMode->ResWidth;
    *GS_FlagPtr = 0;                   /* initialize contents of flag pointer */

    /**************************************************************************/
    /*  PD00616 : Pick up the RGB color before we do much else...             */
    /**************************************************************************/
    Color = prdc_ColorToRGBValue(Color, DCIData);

    /**************************************************************************/
    /*  Only greyscale if we are not in pure color mode and we're a monochrome*/
    /*  printer.                                                              */
    /*                                                                        */
    /*  PD00567 : Well, this won't work... we've just killed greyscaling for  */
    /*  the 'new' source bitmap greyscaling driver as we have to report that  */
    /*  we support eight colors... what now, Mr. Holmes?                      */
    /**************************************************************************/
    fGreyScale = !(DCIData->DCIColOptions & LCOL_PURECOLOR) &&
                 !((DRIVER_TYPE == DDT_IBM42XX_DRV) &&
                   (DCIData->DCIPdbInstance->PrinterType == IBM_4224_COLOR));

    /**************************************************************************/
    /*  Different set up for greyscaling                                      */
    /**************************************************************************/
    if (fGreyScale)
    {

        /**********************************************************************/
        /*  Now get the greyscale pattern information                         */
        /**********************************************************************/
        usPatIndex = prdu_GetGreyScaleIndex(Color,
                                            lpDDT->DDTRasterMode->ResWidth);
        if (ulResWidth < 180)
        {
            *GS_PatternPtr = (PBYTE) &greyscale_table2[usPatIndex];
        }
        else
        {
            *GS_PatternPtr = (PBYTE) &greyscale_table[usPatIndex];
        }

        /**********************************************************************/
        /*  Pattern is all ones.  There is quick processing for this          */
        /*                                                                    */
        /*  600DPI : 64 pattern greyscale table.                              */
        /**********************************************************************/
        if (usPatIndex == GS_WHITE_INDEX)
        {
            *GS_FlagPtr = PAT_ALL_ZEROS; /* OS/2 is backwards - 0 means print */
        }
        else
        {

            /******************************************************************/
            /*  Pattern is all zeros.  There is quick processing for this.    */
            /******************************************************************/
            if (usPatIndex == GS_BLACK_INDEX)
            {
               *GS_FlagPtr = PAT_ALL_ONES;
            }
        }
    }
    return(fGreyScale);
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdb_GreyscaleSourceBitmap                                      */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  lpBltParms    BB                                                          */
/*  pBMListEntry  lpNewLE                                                     */
/*  lpDCI         DCIData                                                     */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function will take the current source bitmap, which is a 4,1 bitmap, */
/*  and convert the bitmap into a greyscaled 1,1 bitmap, replacing the source */
/*  bitmap in the BB structure with the 1,1 greyscaled bitmap.                */
/*  CON3201 : Test for huge bitmaps is not necessary for 32-bit code.         */
/*                                                                            */
/******************************************************************************/
VOID prdb_GreyScaleSourceBitmap( lpBltParms    BB,
                                 pBMListEntry  lpNewLE,
                                 lpDCI         DCIData )

{

#define TFUNC "prdb_GreyScaleSourceBitmap"

    /**************************************************************************/
    /*  Local variables...                                                    */
    /**************************************************************************/
    ULONG            ulXfer;           /* Register for dword packing          */
    lpDDTType        lpDDT;            /* DDT Pointer                         */
    PBYTE            lpSrcPtr;         /* Local pointer to source bitmap      */
    PBYTE            lpTrgPtr;         /* Local pointer to target bitmap      */
    PBYTE            GSTabPtr;         /* Pointer to a greyscale pattern      */
    ULONG            ulRGBColor;       /* Current RGB for portion of scan line*/
    ULONG            ulMask;           /* Pattern to place in target          */
    USHORT           usDWords;         /* # of DWORDs to place in target      */
    USHORT           usBytes;          /* # of BYTEs to place in target       */
    register USHORT  usPartialByte;    /* # of pels to complete last byte     */
    register USHORT  usRemains;        /* # of pels to place in target        */
    USHORT           usFilled;         /* 8 - usPartialByte                   */
    USHORT           usSrcWidth;       /* Width of source bitmap in pels      */
    USHORT           usTrgWidth;       /* Width of target bitmap              */
    USHORT           usBitHeight;      /* Height of source bitmap             */
    USHORT           usSrcPels;        /* # of pels in source                 */
    USHORT           usPelsWritten;    /* # of bytes written to target        */
    USHORT           usPels;           /* # of pels of the same color         */
    USHORT           usPelPos;         /* Nibble indicator for source         */
    USHORT           usXOrigin;        /* Pattern X-origin                    */
    USHORT           usYOrigin;        /* Pattern Y-origin                    */
    USHORT           usXDelta;         /* Adjusted pattern X-origin           */
    USHORT           usYDelta;         /* Adjusted pattern Y-origin           */
    USHORT           i, j, k, l;       /* Loop counters                       */
    USHORT           usPatIndex;       /* Index to greyscale pattern table    */
    BYTE             bPad;             /* # of bytes to DWORD align target    */
    BYTE             bPatt;            /* Temporary greyscale pattern byte    */
    BYTE             bTemp;            /* Temporary target byte               */
    BOOL             fSSafe;           /* Segment boundary flag      CON3201  */
 /* BOOL             fTSafe; */        /* Segment boundary flag      CON3201  */
 /* BOOL             fTHuge; */        /* Target is a huge bitmap    CON3201  */
    BOOL             fRGB;             /* RGB mode flag                       */

    /**************************************************************************/
    /*  First we need to init a few things here...                            */
    /*                                                                        */
    /*  P500123 : Calculate usBitHeight and us?Origin from the values in      */
    /*  BB->SaveTrgRect as the values here are the original blit parms and    */
    /*  have not been messed with.  The BB->TrgRect values have been adjusted */
    /*  for various reasons...                                                */
    /**************************************************************************/
    /*  CON3201 : Don't care about huge bitmaps for 32-bit code               */
#if 0
    fTHuge      = (lpNewLE->Huge != 0);
    fTSafe      = TRUE;                /* Be optomistic...                    */
#endif
    fRGB        = (DCIData->DCIColFormat == LCOLF_RGB);
    lpDDT       = &(DCIData->DCIPdbInstance->DDT);
    usBitHeight = (USHORT)(BB->SaveTrgRect[1].Y - BB->SaveTrgRect[0].Y);
    usSrcWidth  = (USHORT)BB->SrcLE->Parms.BytesPerRow;
    usSrcPels   = usSrcWidth * 2;
    usTrgWidth  = (USHORT)lpNewLE->Parms.BytesPerRow;
    bPad        = (BYTE)(usTrgWidth - (usSrcWidth / 4));
    lpSrcPtr    = (PBYTE)(BB->SrcLE->Bitmap);
    lpTrgPtr    = (PBYTE)(lpNewLE->Bitmap);

    /**************************************************************************/
    /*  Get the x and y origin of the pattern adjusting for the source origin */
    /*  as well as the target rectangle coordinates for the blit...           */
    /**************************************************************************/
    usXOrigin  = DCIData->DCIPattOriDev.X + BB->TrgLE->XOrigin +
                 BB->SaveTrgRect[0].X;
    usXOrigin %= GS_PATTERN_WIDTH;
    usYOrigin  = DCIData->DCIPattOriDev.Y + BB->TrgLE->YOrigin +
                 BB->SaveTrgRect[0].Y;
    usYOrigin %= GS_PATTERN_HEIGHT;

    /**************************************************************************/
    /*  We now have to deal with the problem at hand.  We have a source bitmap*/
    /*  we need to convert from 4,1 format to 1,1 format and we need to       */
    /*  greyscale the colors as we convert.  This may span multiple segments, */
    /*  thus the do...  while loop.  If this is not the case, we'll go through*/
    /*  the code below once and we'll be done.  If this is the case, we'll    */
    /*  huge-increment the source bitmap at the bottom of the loop and go     */
    /*  through again as necessary to satisfy the entire source bitmap.  Loop */
    /*  through each of the source scan lines...                              */
    /**************************************************************************/
    for (i = 0; i < usBitHeight; i++)
    {
        usPartialByte = 0;
        usFilled      = 0;
        usPelsWritten = 0;
        usPelPos      = 1;
    /*  CON3201 : Don't care about huge bitmaps for 32-bit code               */
     /* fSSafe        = (usSrcWidth < ((USHORT)(65535L - OFFSETOF(lpSrcPtr))));*/
        fSSafe        = TRUE;                                      /* CON3201 */

        /**********************************************************************/
        /*  P500152 : Have to concern ourselves with a huge target bitmap.    */
        /*  However, this is often not a problem, so let's try to save a few  */
        /*  clock cycles here with this check...                              */
        /**********************************************************************/
        /*  CON3201 : Don't care about huge bitmaps for 32-bit code           */
#if 0
        if (fTHuge)
        {
            fTSafe = (usTrgWidth < ((USHORT)(65535L - OFFSETOF(lpTrgPtr))));
        }

        /**********************************************************************/
        /*  P500152 : A big chunk of nearly identical code here, strictly for */
        /*  the purpose of performance.  If we're fTSafe, that means we don't */
        /*  have to worry about huge increments to the target bitmap.  If     */
        /*  we're not, we have to fiddle around with each byte we write, using*/
        /*  POSTINC to increment the target pointer...                        */
        /**********************************************************************/
        if (fTSafe)
        {
#endif

            /******************************************************************/
            /*  Loop through all of the bytes in each scan line on a per RGB  */
            /*  basis...                                                      */
            /******************************************************************/
            while (usPelsWritten != usSrcPels)
            {

                /**************************************************************/
                /*  Find out what the next RGB color is in the source bitmap  */
                /*  and how many consecutive pels are set to that color.  Note*/
                /*  that the third parameter is the number of pels to read    */
                /*  from the source bitmap.                                   */
                /**************************************************************/
                ulRGBColor = prdb_GetNextColor(&lpSrcPtr, fSSafe, fRGB,
                                               (usSrcPels - usPelsWritten),
                                               &usPels, &usPelPos, DCIData);

                /**************************************************************/
                /*  Need here to work out the number of DWORDs, BYTEs and pels*/
                /*  that usPels represents.  If we can work in DWORDs, things */
                /*  will certainly go faster.  If there is a remaining partial*/
                /*  byte AND if there are enough new pels to complete the     */
                /*  partial remaining byte, we need to factor this into the   */
                /*  computations below.                                       */
                /**************************************************************/
                if ((usPartialByte) && (usPels >= usPartialByte))
                {
                    usDWords  = (usPels  - usPartialByte) / 32;
                    usBytes   = ((usPels - usPartialByte) % 32) / 8;
                    usRemains = (usPels  - usPartialByte) % 8;
                }
                else
                {
                    usDWords  = usPels  / 32;
                    usBytes   = (usPels % 32) / 8;
                    usRemains = usPels  % 8;
                }

                /**************************************************************/
                /*  Now determine the index into the greyscale pattern table  */
                /*  for the current RGB color...                              */
                /**************************************************************/
                usPatIndex = prdu_GetGreyScaleIndex(
                                                ulRGBColor,
                                                lpDDT->DDTRasterMode->ResWidth);

                /**************************************************************/
                /*  If the index is for black or white, we can be sneaky      */
                /*  here...                                                   */
                /**************************************************************/
                if ((usPatIndex == GS_BLACK_INDEX) ||
                    (usPatIndex == GS_WHITE_INDEX))
                {

                    /**********************************************************/
                    /*  If the index is for black, we'll just write the       */
                    /*  pels...                                               */
                    /**********************************************************/
                    if (usPatIndex == GS_BLACK_INDEX)
                    {
                        ulMask = 0L;

                        /******************************************************/
                        /*  If there was a partial byte written last time     */
                        /*  through, we need to complete it so we can get back*/
                        /*  on a BYTE boundary...                             */
                        /******************************************************/
                        if ((usPartialByte) && (usPels >= usPartialByte))
                        {
                            *lpTrgPtr     &= (BYTE)(0xff << usPartialByte);
                            usPelsWritten += usPartialByte;
                            usPartialByte  = 0;
                            usFilled       = 0;
                            lpTrgPtr++;
                        }
                        if (usDWords)
                        {

                            /**************************************************/
                            /*  Write as many DWORDs as possible...           */
                            /**************************************************/
                            for (k = 0; k < usDWords; k++)
                            {
                                *((PULONG)lpTrgPtr) = ulMask;
                                lpTrgPtr           += 4;
                            }
                        }
                        if (usBytes)
                        {

                            /**************************************************/
                            /*  Write any remaining full BYTEs...             */
                            /**************************************************/
                            for (k = 0; k < usBytes; k++)
                            {
                                *lpTrgPtr = (BYTE)ulMask;
                                lpTrgPtr++;
                            }
                        }

                        /******************************************************/
                        /*  May still have a partial byte to write...         */
                        /******************************************************/
                        if (usRemains)
                        {

                            /**************************************************/
                            /*  If usPartialByte at this point has a value    */
                            /*  other than zero, we are in the middle of the  */
                            /*  current byte; therefore we must preserve the  */
                            /*  pels that have already been written.  If, on  */
                            /*  the other hand, usPartialByte is zero here, we*/
                            /*  can simply zero out usRemains pels.           */
                            /**************************************************/
                            if (usPartialByte)
                            {
                                *lpTrgPtr = (*lpTrgPtr & (0xff << usPartialByte)) |
                                            (0xff >> (usFilled + usRemains));
                            }
                            else
                            {
                                *lpTrgPtr = (BYTE)(0xff >> (usRemains));
                            }
                        }
                    }
                    else
                    {

                        /******************************************************/
                        /*  Don't need to do anything for the case where there*/
                        /*  are a bunch of white pels as the target is        */
                        /*  initialized to all white at CreateBitmap time...  */
                        /*  just need to move the target pointer.             */
                        /*                                                    */
                        /*  If there was a partial byte written last time     */
                        /*  through, we need to complete it so we can get back*/
                        /*  on a BYTE boundary...                             */
                        /******************************************************/
                        if ((usPartialByte) && (usPels >= usPartialByte))
                        {
                            usPelsWritten += usPartialByte;
                            usPartialByte  = 0;
                            usFilled       = 0;
                            lpTrgPtr++;
                        }

                        /******************************************************/
                        /*  ...otherwise, just increment the number of DWORDs */
                        /*  and BYTEs...                                      */
                        /******************************************************/
                        lpTrgPtr += (usDWords * 4) + usBytes;
                    }
                }
                else
                {

                    /**********************************************************/
                    /*  We have usPels worth of area which we must greyscale. */
                    /*                                                        */
                    /*  Grab a pointer to the correct greyscale pattern based */
                    /*  on the current resolution...                          */
                    /*                                                        */
                    /*  06/30/92 cpk, change 1 This problem has been addressed*/
                    /*  by keeping the greyscale images inverted in           */
                    /*  greyscale_table and greyscale_table2                  */
                    /**********************************************************/
                    if (lpDDT->DDTRasterMode->ResWidth < 180)
                    {
                        GSTabPtr = (PBYTE)&greyscale_table2[usPatIndex];
                    }
                    else
                    {
                        GSTabPtr = (PBYTE)&greyscale_table[usPatIndex];
                    }

                    /**********************************************************/
                    /*  Note that following the computations below, usXOrigin */
                    /*  is the amount of rotation required for the greyscale  */
                    /*  pattern and usYOrigin is the index into the greyscale */
                    /*  pattern byte array.                                   */
                    /**********************************************************/
                    usXDelta = (usXOrigin + usFilled) % GS_PATTERN_WIDTH;
                    usYDelta = (usYOrigin + i) % GS_PATTERN_HEIGHT;
                    bPatt    = GSTabPtr[usYDelta];

                    /**********************************************************/
                    /*  Now that we have the required row of the greyscale    */
                    /*  pattern we need for this scan line, we need to expand */
                    /*  this into a DWORD and rotate it to synch up with the  */
                    /*  X-origin.                                             */
                    /**********************************************************/
                    ulXfer  = (ULONG)bPatt;
                    ulXfer |= ulXfer << 8;
                    ulMask  = (ulXfer | (ulXfer << 16));
                 /* ulMask  = _lrotl(ulMask, usXDelta); */
                    ulMask  = prdu_lrotl(ulMask, usXDelta);        /* CON3201 */

                    /**********************************************************/
                    /*  If there was a partial byte written last time through,*/
                    /*  we need to complete it so we can get back on a DWORD  */
                    /*  or BYTE boundary...                                   */
                    /**********************************************************/
                    if ((usPartialByte) && (usPels >= usPartialByte))
                    {
                        *lpTrgPtr      = (*lpTrgPtr & (0xff << usPartialByte)) |
                                         (BYTE)(((BYTE)ulMask &
                                               (0xff << usFilled)) >> usFilled);
                        usPelsWritten += usPartialByte;

                        /******************************************************/
                        /*  Need to rotate the pattern by usPartialByte as we */
                        /*  have used a portion of the pattern DWORD here and */
                        /*  we must resynch before we go further...           */
                        /******************************************************/
                     /* ulMask        = _lrotl(ulMask, usPartialByte); */
                        ulMask        = prdu_lrotl(ulMask, usPartialByte);/*CON3201*/
                        usPartialByte = 0;
                        usFilled      = 0;
                        lpTrgPtr++;
                    }
                    if (usDWords)
                    {

                        /******************************************************/
                        /*  Write as many DWORDs as possible...               */
                        /******************************************************/
                        for (k = 0; k < usDWords; k++)
                        {
                            *((PULONG)lpTrgPtr) = ulMask;
                            lpTrgPtr           += 4;
                        }
                    }
                    if (usBytes)
                    {

                        /******************************************************/
                        /*  Write any remaining full BYTEs...                 */
                        /******************************************************/
                        for (k = 0; k < usBytes; k++)
                        {
                            *lpTrgPtr = (BYTE)ulMask;
                            lpTrgPtr++;
                        }
                    }

                    /**********************************************************/
                    /*  May still have a partial byte to write...             */
                    /**********************************************************/
                    if (usRemains)
                    {

                        /******************************************************/
                        /*  If usPartialByte at this point has a value other  */
                        /*  than zero, we are in the middle of the current    */
                        /*  byte; therefore we must preserve the pels that    */
                        /*  have already been written.  If, on the other hand,*/
                        /*  usPartialByte is zero here, we can write usRemains*/
                        /*  pels of the pattern DWORD.  We need to ensure that*/
                        /*  we don't disturb the pels to the right of the pels*/
                        /*  we write here...  otherwise we'd mess up the white*/
                        /*  pel fast path above.                              */
                        /******************************************************/
                        if (usPartialByte)
                        {
                            bTemp      = *lpTrgPtr & (0xff << usPartialByte);
                            bTemp     |= ((BYTE)ulMask &
                                         (0xff << (8 - usRemains))) >> usFilled;
                            bTemp     |= 0xff >> (usFilled + usRemains);
                            *lpTrgPtr  = bTemp;
                        }
                        else
                        {
                            bTemp      = (BYTE)((BYTE)ulMask &
                                                (0xff << (8 - usRemains)));
                            bTemp     |= 0xff >> usRemains;
                            *lpTrgPtr  = bTemp;
                        }
                    }
                }

                /**************************************************************/
                /*  Finally, update usPelsWritten and usPartialByte.  Note    */
                /*  that we don't need to update usPartialByte unless         */
                /*  usRemains is greater than zero (since usPartialByte has   */
                /*  either been set to zero above or has not changed due to   */
                /*  usRemains being set to zero).                             */
                /**************************************************************/
                usPelsWritten += (usDWords * 32) + (usBytes * 8) + usRemains;
                if (usRemains)
                {

                    /**********************************************************/
                    /*  Remember...  usPartialByte represents the number of   */
                    /*  pels left to be written in the current byte.  If we   */
                    /*  had a previous partial byte and this iteration of the */
                    /*  loop did not satisfy it, we have to subtract the scant*/
                    /*  few pels that we did fold into the current byte from  */
                    /*  the previous partial byte value, otherwise we need to */
                    /*  simply subtract the remains of the pel count from 8 to*/
                    /*  tell us how many pels are left i.e.  how many more    */
                    /*  pels we require to complete the current byte.         */
                    /**********************************************************/
                    usPartialByte = usPartialByte ? usPartialByte - usRemains :
                                                    8 - usRemains;
                    usFilled      = 8 - usPartialByte;
                }
            }

            /******************************************************************/
            /*  Increment the target pointer by the DWORD pad...              */
            /******************************************************************/
            lpTrgPtr += bPad;

        /*  CON3201 : Don't care about huge bitmaps for 32-bit code           */
#if 0
        }
        else
        {

            /******************************************************************/
            /*  Loop through all of the bytes in each scan line on a per RGB  */
            /*  basis...                                                      */
            /******************************************************************/
            while (usPelsWritten != usSrcPels)
            {

                /**************************************************************/
                /*  Find out what the next RGB color is in the source bitmap  */
                /*  and how many consecutive pels are set to that color.  Note*/
                /*  that the third parameter is the number of pels to read    */
                /*  from the source bitmap.                                   */
                /**************************************************************/
                ulRGBColor = prdb_GetNextColor(&lpSrcPtr, fSSafe, fRGB,
                                               (usSrcPels - usPelsWritten),
                                               &usPels, &usPelPos, DCIData);

                /**************************************************************/
                /*  Need here to work out the number of DWORDs, BYTEs and pels*/
                /*  that usPels represents.  If we can work in DWORDs, things */
                /*  will certainly go faster.  If there is a remaining partial*/
                /*  byte AND if there are enough new pels to complete the     */
                /*  partial remaining byte, we need to factor this into the   */
                /*  computations below.                                       */
                /**************************************************************/
                if ((usPartialByte) && (usPels >= usPartialByte))
                {
                    usDWords  = (usPels  - usPartialByte) / 32;
                    usBytes   = ((usPels - usPartialByte) % 32) / 8;
                    usRemains = (usPels  - usPartialByte) % 8;
                }
                else
                {
                    usDWords  = usPels  / 32;
                    usBytes   = (usPels % 32) / 8;
                    usRemains = usPels  % 8;
                }

                /**************************************************************/
                /*  Now determine the index into the greyscale pattern table  */
                /*  for the current RGB color...                              */
                /**************************************************************/
                usPatIndex = prdu_GetGreyScaleIndex(
                                                ulRGBColor,
                                                lpDDT->DDTRasterMode->ResWidth);

                /**************************************************************/
                /*  If the index is for black or white, we can be sneaky      */
                /*  here...                                                   */
                /**************************************************************/
                if ((usPatIndex == GS_BLACK_INDEX) ||
                    (usPatIndex == GS_WHITE_INDEX))
                {

                    /**********************************************************/
                    /*  If the index is for black, we'll just write the       */
                    /*  pels...                                               */
                    /**********************************************************/
                    if (usPatIndex == GS_BLACK_INDEX)
                    {
                        ulMask = 0L;

                        /******************************************************/
                        /*  If there was a partial byte written last time     */
                        /*  through, we need to complete it so we can get back*/
                        /*  on a BYTE boundary...                             */
                        /******************************************************/
                        if ((usPartialByte) && (usPels >= usPartialByte))
                        {
                            *lpTrgPtr     &= (BYTE)(0xff << usPartialByte);
                            usPelsWritten += usPartialByte;
                            usPartialByte  = 0;
                            usFilled       = 0;
                            POSTINC(lpTrgPtr);
                        }
                        if (usDWords)
                        {

                            /**************************************************/
                            /*  Write as many DWORDs as possible...           */
                            /**************************************************/
                            for (k = 0; k < usDWords; k++)
                            {
                                *lpTrgPtr = (BYTE)ulMask;
                                POSTINC(lpTrgPtr);
                                *lpTrgPtr = (BYTE)ulMask;
                                POSTINC(lpTrgPtr);
                                *lpTrgPtr = (BYTE)ulMask;
                                POSTINC(lpTrgPtr);
                                *lpTrgPtr = (BYTE)ulMask;
                                POSTINC(lpTrgPtr);
                            }
                        }
                        if (usBytes)
                        {

                            /**************************************************/
                            /*  Write any remaining full BYTEs...             */
                            /**************************************************/
                            for (k = 0; k < usBytes; k++)
                            {
                                *lpTrgPtr = (BYTE)ulMask;
                                POSTINC(lpTrgPtr);
                            }
                        }

                        /******************************************************/
                        /*  May still have a partial byte to write...         */
                        /******************************************************/
                        if (usRemains)
                        {

                            /**************************************************/
                            /*  If usPartialByte at this point has a value    */
                            /*  other than zero, we are in the middle of the  */
                            /*  current byte; therefore we must preserve the  */
                            /*  pels that have already been written.  If, on  */
                            /*  the other hand, usPartialByte is zero here, we*/
                            /*  can simply zero out usRemains pels.           */
                            /**************************************************/
                            if (usPartialByte)
                            {
                                *lpTrgPtr = (*lpTrgPtr &
                                             (0xff << usPartialByte)) |
                                             (0xff >> (usFilled + usRemains));
                            }
                            else
                            {
                                *lpTrgPtr = (BYTE)(0xff >> (usRemains));
                            }
                        }
                    }
                    else
                    {

                        /******************************************************/
                        /*  Don't need to do anything for the case where there*/
                        /*  are a bunch of white pels as the target is        */
                        /*  initialized to all white at CreateBitmap time...  */
                        /*  just need to move the target pointer.             */
                        /*                                                    */
                        /*  If there was a partial byte written last time     */
                        /*  through, we need to complete it so we can get back*/
                        /*  on a BYTE boundary...                             */
                        /******************************************************/
                        if ((usPartialByte) && (usPels >= usPartialByte))
                        {
                            usPelsWritten += usPartialByte;
                            usPartialByte  = 0;
                            usFilled       = 0;
                            POSTINC(lpTrgPtr);
                        }

                        /******************************************************/
                        /*  ...otherwise, just increment the number of DWORDs */
                        /*  and BYTEs...                                      */
                        /******************************************************/
                        l = (usDWords * 4) + usBytes;
                        for (j = 0; j < l; j++)
                        {
                            POSTINC(lpTrgPtr);
                        }
                    }
                }
                else
                {

                    /**************************************************************/
                    /*  We have usPels worth of area which we must greyscale.     */
                    /*                                                            */
                    /**********************************************************/
                    /*  Grab a pointer to the correct greyscale pattern based */
                    /*  on the current resolution...                          */
                    /*                                                        */
                    /*  06/30/92 cpk, change 1 This problem has been addressed*/
                    /*  by keeping the greyscale images inverted in           */
                    /*  greyscale_table and greyscale_table2                  */
                    /**********************************************************/
                    if (lpDDT->DDTRasterMode->ResWidth < 180)
                    {
                        GSTabPtr = (PBYTE)&greyscale_table2[usPatIndex];
                    }
                    else
                    {
                        GSTabPtr = (PBYTE)&greyscale_table[usPatIndex];
                    }

                    /**********************************************************/
                    /*  Note that following the computations below, usXOrigin */
                    /*  is the amount of rotation required for the greyscale  */
                    /*  pattern and usYOrigin is the index into the greyscale */
                    /*  pattern byte array.                                   */
                    /**********************************************************/
                    usXDelta = (usXOrigin + usFilled) % GS_PATTERN_WIDTH;
                    usYDelta = (usYOrigin + i) % GS_PATTERN_HEIGHT;
                    bPatt    = GSTabPtr[usYDelta];

                    /**********************************************************/
                    /*  Now that we have the required row of the greyscale    */
                    /*  pattern we need for this scan line, we need to expand */
                    /*  this into a DWORD and rotate it to synch up with the  */
                    /*  X-origin.                                             */
                    /**********************************************************/
                    ulXfer  = (ULONG)bPatt;
                    ulXfer |= ulXfer << 8;
                    ulMask  = (ulXfer | (ulXfer << 16));
                 /* ulMask  = _lrotl(ulMask, usXDelta); */
                    ulMask  = prdu_lrotl(ulMask, usXDelta);        /* CON3201 */

                    /**********************************************************/
                    /*  If there was a partial byte written last time through,*/
                    /*  we need to complete it so we can get back on a DWORD  */
                    /*  or BYTE boundary...                                   */
                    /**********************************************************/
                    if ((usPartialByte) && (usPels >= usPartialByte))
                    {
                        *lpTrgPtr      = (*lpTrgPtr & (0xff << usPartialByte)) |
                                         (BYTE)(((BYTE)ulMask &
                                               (0xff << usFilled)) >> usFilled);
                        usPelsWritten += usPartialByte;

                        /******************************************************/
                        /*  Need to rotate the pattern by usPartialByte as we */
                        /*  have used a portion of the pattern DWORD here and */
                        /*  we must resynch before we go further...           */
                        /******************************************************/
                     /* ulMask        = _lrotl(ulMask, usPartialByte); */
                        ulMask        = prdu_lrotl(ulMask, usPartialByte);/*CON3201*/
                        usPartialByte = 0;
                        usFilled      = 0;
                        POSTINC(lpTrgPtr);
                    }
                    if (usDWords)
                    {

                        /******************************************************/
                        /*  Write as many DWORDs as possible...               */
                        /******************************************************/
                        for (k = 0; k < usDWords; k++)
                        {
                            *lpTrgPtr = (BYTE)ulMask;
                            POSTINC(lpTrgPtr);
                            *lpTrgPtr = (BYTE)ulMask;
                            POSTINC(lpTrgPtr);
                            *lpTrgPtr = (BYTE)ulMask;
                            POSTINC(lpTrgPtr);
                            *lpTrgPtr = (BYTE)ulMask;
                            POSTINC(lpTrgPtr);
                        }
                    }
                    if (usBytes)
                    {

                        /******************************************************/
                        /*  Write any remaining full BYTEs...                 */
                        /******************************************************/
                        for (k = 0; k < usBytes; k++)
                        {
                            *lpTrgPtr = (BYTE)ulMask;
                            POSTINC(lpTrgPtr);
                        }
                    }

                    /**********************************************************/
                    /*  May still have a partial byte to write...             */
                    /**********************************************************/
                    if (usRemains)
                    {

                        /******************************************************/
                        /*  If usPartialByte at this point has a value other  */
                        /*  than zero, we are in the middle of the current    */
                        /*  byte; therefore we must preserve the pels that    */
                        /*  have already been written.  If, on the other hand,*/
                        /*  usPartialByte is zero here, we can write usRemains*/
                        /*  pels of the pattern DWORD.  We need to ensure that*/
                        /*  we don't disturb the pels to the right of the pels*/
                        /*  we write here...  otherwise we'd mess up the white*/
                        /*  pel fast path above.                              */
                        /******************************************************/
                        if (usPartialByte)
                        {
                            bTemp      = *lpTrgPtr & (0xff << usPartialByte);
                            bTemp     |= ((BYTE)ulMask &
                                         (0xff << (8 - usRemains))) >> usFilled;
                            bTemp     |= 0xff >> (usFilled + usRemains);
                            *lpTrgPtr  = bTemp;
                        }
                        else
                        {
                            bTemp      = (BYTE)((BYTE)ulMask &
                                                (0xff << (8 - usRemains)));
                            bTemp     |= 0xff >> usRemains;
                            *lpTrgPtr  = bTemp;
                        }
                    }
                }

                /**************************************************************/
                /*  Finally, update usPelsWritten and usPartialByte.  Note    */
                /*  that we don't need to update usPartialByte unless         */
                /*  usRemains is greater than zero (since usPartialByte has   */
                /*  either been set to zero above or has not changed due to   */
                /*  usRemains being set to zero).                             */
                /**************************************************************/
                usPelsWritten += (usDWords * 32) + (usBytes * 8) + usRemains;
                if (usRemains)
                {

                    /**********************************************************/
                    /*  Remember...  usPartialByte represents the number of   */
                    /*  pels left to be written in the current byte.  If we   */
                    /*  had a previous partial byte and this iteration of the */
                    /*  loop did not satisfy it, we have to subtract the scant*/
                    /*  few pels that we did fold into the current byte from  */
                    /*  the previous partial byte value, otherwise we need to */
                    /*  simply subtract the remains of the pel count from 8 to*/
                    /*  tell us how many pels are left i.e.  how many more    */
                    /*  pels we require to complete the current byte.         */
                    /**********************************************************/
                    usPartialByte = usPartialByte ? usPartialByte - usRemains :
                                                    8 - usRemains;
                    usFilled      = 8 - usPartialByte;
                }
            }

            /******************************************************************/
            /*  Increment the target pointer by the DWORD pad...              */
            /******************************************************************/
            for (j = 0; j < bPad; j++)
            {
                POSTINC(lpTrgPtr);
            }
        }
#endif
    }

    /**************************************************************************/
    /*  Last item of work to do...  replace references to the old ListEntry   */
    /*  and the 4,1 bitmap in the BB structure with the new 1,1 greyscaled    */
    /*  bitmap and it's ListEntry.                                            */
    /**************************************************************************/
    lpNewLE->DCHandle = BB->SrcLE->DCHandle;
    BB->SrcLE         = lpNewLE;
    BB->SrcBM         = lpNewLE->Bitmap;
    return;
}
#undef TFUNC
