/*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 = PRDPRAST
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prdp_PrintBandRaster
 *             prdp_PrintMakeRaster8
 *             prdp_PrintMakeRaster24
 *             prdp_PrintMakeRasterColor
 *             prdp_PrintRaster
 *             prdp_PrintRasterColor
 *             prdp_GetPrinterColor
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define INCL_32                      /* CON3201 */
#define INCL_DOSPROCESS              /* CON3201 */
#define INCL_DOSMISC                 /* CON3201 */
#define INCL_DOSSEMAPHORES
#define INCL_GREALL
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#define INCL_SPL
#include <os2.h>
#undef INCL_DOSPROCESS               /* CON3201 */
#define INCL_DOSMISC                 /* CON3201 */
#undef INCL_DOSSEMAPHORES
#undef INCL_GREALL
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS
#undef INCL_SPL

#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_SELECTIVE
#define INCL_WINP_SEI
#define INCL_WINP_SELSERVER
#include <pmwinx.h>
#undef INCL_WINP_SELECTIVE
#undef INCL_WINP_SEI
#undef INCL_WINP_SELSERVER
#undef INCL_32                            /* CON3201 */

#include <prdccone.h>
#include <prdconse.h>
#include <prddcone.h>
#include <prdpcone.h>
#include <prdtcone.h>

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

#include <prderre.h>                               /* INKJET */
#include <prdncone.h>
#include <prdgextf.h>
#include <prdpextf.h>
#include <prdbtyp1.h>
#include <prdbextf.h>
#include <prdjextf.h>
#include <prdyextf.h>
#include <prdtextf.h>
#include <prduextf.h>
#include <prdnextf.h>
#include <prdztrcf.h>

/* extern USHORT    prdd_HugeInc;        CON3201 */
extern USHORT    Remainder;

/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdp_PrintBandRaster                                   */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpDCI    DCIData                                                 */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function outputs a complete band ( i.e. a bitmap with       */
/*   associated text chain) to the printer. The                       */
/*   function does raster output (ie graphics/engine fonts) and       */
/*   printer fonts in two passes:  the first for the printer text and */
/*   the second for the raster.                                       */
/*                                                                    */
/*   Note: we no longer support printers that automatically put a     */
/*   carriage return after a variable line feed.                      */
/**********************************************************************/

/* USHORT prdp_PrintBandRaster( lpDCI DCIData ) CON3201 - Make return value
                                           short since it may be negative    */

SHORT prdp_PrintBandRaster( lpDCI DCIData )

{
#define TFUNC "prdp_PrintBandRaster"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    lpBand               hBand;        /* pointer to Band for thread  */
    lpPDBI               PDBInst;      /* pointer to PDB Instance Data*/
    lpDDTType            pDDT;         /* Pointer to DDT              */
    lpGTBEntry           TextEntryPtr; /* pointer to text string entry*/
    BitmapListEntry     *ListEntry;    /* points to bitmap structure  */

    ColOutputType        ColOutput;    /* Structure for colour output */
    PBYTE                OutputBuffer; /* holds text and raster in    */
                                       /* printer-readable form       */
    USHORT               BufferSize;   /* length of OutputBuffer      */
    USHORT               BufferIndex;  /* position in OutputBuffer    */
    PBYTE                CommandBuffer;/* for storing move commands   */
    USHORT               CommandSize;  /* size of CommandBuffer       */
    USHORT               CommandIndex; /* position in CommandBuffer   */

    USHORT               HeadYPos;     /* Current position of head    */
    USHORT               HeadYStart;   /* Initial Y head position     */
    USHORT               HeadYErr;     /* error due to vert resolution*/
    SHORT                NewPosX;      /* AddHorizMovStr correction   */
    ULONG                BitHeight;    /* height of band in scanlines */
    PBYTE                ScanLinePtr;  /* current scanline            */
    USHORT               SwatheSize;   /*number of scanlines in swathe*/
    SHORT                SwatheIncrement;  /* how to move from one    */
                                       /* raster swathe to the next   */
    SHORT                ScanLowY;     /* bottom Y of current swathe  */
    SHORT                ScanLowYAbs;  /* bottom Y of current swathe  */
                                       /* including previous bands    */
    USHORT               RasterLength; /* length of non-empty bit of  */
                                       /* raster                      */
    USHORT               HeadCorrection;/*Corrector for text positions*/
    ULONG                Temp;         /* needed to calculate         */
                                       /* ScanLinePtr initially       */
                                       /* Also index to colours       */

// CON3201    SEL                 selGlobalSeg;  /* these are for access to     */
// CON3201    SEL                 selLocalSeg;   /* timer for performance       */
// CON3201    GINFOSEG     *      pGlobalInfoSeg;/* measurements                */
    SHORT               Result;        /* CON3203 CHANGED USHORT TO SHORT */
    USHORT              QualityId;
    /* PD00556 */
    PBYTE               PassBuffer;    /* Contains data to output for the pass*/
    USHORT              BytesPerColumn;/* Number of bytes in a horizontal move*/
    PBYTE               InputBuffer;   /* Buffer to store 6 360x360 bytes */
    PBYTE               OutputBuffer1; /* Storage for first scanline */
    PBYTE               OutputBuffer2; /* Storage for second scanline */
    PBYTE               TempPointer1;  /* Pointer used to switch buffers */
    USHORT              FirstOrSecondPass;/* Which pass is current */
    USHORT              RasterLengthPrev;/* Length of previous raster */
    BOOL                FlipPointers; /* Flag to tell if buffers were flipped */
    /* PD00556 */
    USHORT              RasterLength1; /* Length of non-empty bit raster */
    USHORT              RasterLength2; /* Length of non-empty bit raster */
    USHORT              PrintQuality;  /* holds ID of correct escape sequence */
                                       /* to send to 4072 printer */
    SHORT               TempScanLowY;  /* bottom Y of current swathe -PD00726 */

    ULONG               ulMsecs;       /* Millisecond counter used for debug  */

    /* INKJET */


    TRACE8(TFUNC, "Started", FNULL, 0);
    /******************************************************************/
    /* Set up access to timer for performance measurements.           */
    /******************************************************************/
/* CON3201 ************************************************************/
/*  Will use DosQuerySysInfo to get the current time.  This info is   */
/*  is not contained in the TIB or PIB structures                     */
/*  DosGetInfoSeg(&selGlobalSeg, &selLocalSeg);                       */
/*  pGlobalInfoSeg = MAKEPGINFOSEG(selGlobalSeg);                     */
/**********************************************************************/
    DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &ulMsecs, 4);

    /******************************************************************/
    /* Output time at start of routine on debug terminal.             */
    /******************************************************************/
/* CON3201 ************************************************************/
/* Use the time from DosQuerySysInfo                                  */
/*  OutputPair( "PrintBand start time (msecs)is ",                    */
/*              pGlobalInfoSeg->msecs , DECIMAL );                    */
/**********************************************************************/

    OutputPair( "PrintBand start time (msecs)is ",
                ulMsecs , DECIMAL );


    /******************************************************************/
    /* Set up local access to Instance and Device Data.               */
    /******************************************************************/
    PDBInst = DCIData->DCIPdbInstance;
    pDDT    = &PDBInst->DDT;
    hBand   = &DCIData->DCICurrBand;

    /******************************************************************/
    /* Set up local Band access, the Text Entry pointer and the       */
    /* Graphics Band bitmap list entry.                               */
    /******************************************************************/
    TextEntryPtr = hBand->BDTextBand;
    ListEntry    = (BitmapListEntry *)hBand->BDGraphicsBand;

    /******************************************************************/
    /* If ListEntry is a null pointer then return an error back up    */
    /* to the application. Can occur when CreateBitMap fails.         */
    /******************************************************************/
    if ( !ListEntry )
    {
        return( ERROR );
    }

    /******************************************************************/
    /* Get SwatheSize out of the DDT. This says how many lines are    */
    /* in a raster swathe and is either 8 or 24 initially.            */
    /******************************************************************/
    SwatheSize = pDDT->DDTRasterMode->VertLinePels;

    TRACE6(TFUNC, "Swathe size", &SwatheSize, 1);

    /******************************************************************/
    /* PD00556 : Initialize special control variables for 360x360.    */
    /* These will only be changed for 360x360 and must be controlled  */
    /* carefully.                                                     */
    /******************************************************************/
    FirstOrSecondPass = 2;
    RasterLengthPrev = 0;
    /******************************************************************/
    /* Initialise ScanLinePtr to point in the bitmap to the beginning */
    /* if the first scanline to do. This is the top left of the       */
    /* bitmap if portrait and the bottom left if landscape.           */
    /******************************************************************/
    ScanLinePtr =(PBYTE)(((pBMListEntry)hBand->BDGraphicsBand)->Bitmap);
    OutputPair("Bitmap bottom at ",(LONG)ScanLinePtr,HEX);

    /******************************************************************/
    /* Get the Band Height from the Band Coordinates.                 */
    /******************************************************************/
    /******************************************************************/
    /* Work out SwatheIncrement, which is the amount we need to add   */
    /* (possibly with a Huge increment or decrement) to ScanLinePtr   */
    /* to get to the start of the next swathe. This depends on the    */
    /* orientation and also on SwatheSize.                            */
    /******************************************************************/

    if ( (PDBInst->Orientation == PORTRAIT) ||
         (pDDT->DDTInitFlags & DDT_INIT_ORIENTATION) )
    {
        BitHeight = ListEntry->Parms.Height;


        SwatheIncrement = -(SwatheSize *
                                  (USHORT)ListEntry->Parms.BytesPerRow);

        /**********************************************************************/
        /*  INKJET : Add support for a SwatheSize of 48                       */
        /*  INKJET : If it is 360 x 360 on a 4070 or 4072 then we only want   */
        /*  a swathe increment of half the size because ScanLinePtr is        */
        /*  advanced twice for these printers.                                */
        /**********************************************************************/
        if (SwatheSize == 48)
        {
            SwatheIncrement /= 2;
        }
        if (( SwatheSize == 24 ) || ( SwatheSize == 48 ))
        {
            BufferSize = max(3 * ListEntry->Parms.Width, /* CON3201 removed     */
                                         MIN_TEXT_SIZE); /* USHORT cast         */

        }
        else
            BufferSize = max(ListEntry->Parms.Width,   /* CON3201 removed     */
                                       MIN_TEXT_SIZE); /* USHORT cast         */

        /**************************************************************/
        /* If portrait we must adjust ScanLinePtr to point to the top */
        /* left of the bitmap rather than the bottom left. We use the */
        /* temporary variable Temp.       Note that we cannot use     */
        /* prdb_HugeIncrement, since that function can't copy with    */
        /* increments of size more than 64K.                          */
        /**************************************************************/
/* CON3201 *******************************************************************/
/*      Temp = (BitHeight - 1) * ListEntry->Parms.BytesPerRow                */
/*                                              + OFFSETOF(ScanLinePtr);     */
/*      OFFSETOF(ScanLinePtr) = OFFSETOF(Temp);                              */
/*      if (SELECTOROF(Temp))                                                */
/*          SELECTOROF(ScanLinePtr) += SELECTOROF(Temp) * prdd_HugeInc;      */
/*****************************************************************************/

        Temp = (ULONG)((BitHeight - 1) * ListEntry->Parms.BytesPerRow
                                                + (ULONG)ScanLinePtr);
        ScanLinePtr = (PBYTE)Temp;

    }
    else
    {
        BitHeight = ListEntry->Parms.Width;

        /**********************************************************************/
        /*  INKJET : Add support for a SwatheSize of 48                       */
        /**********************************************************************/
        if (( SwatheSize == 24 ) || ( SwatheSize == 48 ))
        {
            SwatheIncrement = 3;
            BufferSize = max(3 * ListEntry->Parms.Height, /* CON3201 removed */
                                          MIN_TEXT_SIZE); /* USHORT cast     */
        }
        else
        {
            if (DCIData->DCIPdbInstance->PrinterType == IBM_4224_COLOR)
                SwatheIncrement = 4;
            else
                SwatheIncrement = 1;
            BufferSize = max(ListEntry->Parms.Height, /* CON3201 removed */
                                      MIN_TEXT_SIZE); /* USHORT cast     */
        }
    }

    /******************************************************************/
    /* Acquire the memory for the data (ie control sequences and      */
    /* codepoints) to be sent to the Printer. The same memory is used */
    /* by both Raster and Text filling.                               */
    /*                                                                */
    /* Acquire sufficient memory so that the raster filling routine   */
    /* always accumulates a whole line of raster output, and this     */
    /* routine doesn't need multiple calls to MakeRaster to do a      */
    /* raster swathe.                                                 */
    /*                                                                */
    /* Sufficient memory for raster output is the width of the Band   */
    /* in bits (because each bit goes into a successive output byte)  */
    /* for a 9 wire raster and 3 times this for a 24 wire raster.     */
    /*                                                                */
    /* It is not possible to exactly predict the number of control    */
    /* sequences and codepoints for a text line, as this depends on   */
    /* how often the text attributes change, and how long the control */
    /* sequences for changing the attributes are for a particular     */
    /* printer. So the maximum of the bitwidth and a minimum constant */
    /* size is used.                                                  */
    /******************************************************************/

    /******************************************************************/
    /* Need 8 blocks for colour 4224                                  */
    /******************************************************************/
    if (DCIData->DCIPdbInstance->PrinterType == IBM_4224_COLOR)
    {
        TRACE4(TFUNC, "BufferSize", &BufferSize, 1);

        for ( Temp = 0; Temp  < 8; Temp++ )
        {
            if ( prdg_AllocHeapItem(
                          DCIData,
                          BufferSize,
                          (PUSHORT *)&ColOutput.Output[Temp] ) != OK )
            {
                return( ERROR );
            }
        }
        ColOutput.OutputSize = BufferSize;
        OutputBuffer = ColOutput.Output[0];
    }
    else
    {
        if ( prdg_AllocHeapItem( DCIData,
                                 BufferSize,
                                 (PUSHORT *)&OutputBuffer ) != OK )
        {
            return( ERROR );
        }

        /*********************************************************************/
        /* PD00556 : If 360x360 then allocate buffers for the two scanlines  */
        /* and a small buffer to serialize data.                             */
        /*********************************************************************/
        if (pDDT->DDTRasterMode->ResDepth == 360)
        {
           if ( prdg_AllocHeapItem( DCIData,
                                    BufferSize,
                                    (PUSHORT *)&OutputBuffer2 ) != OK )
           {
              return( ERROR );
           }
           if ( prdg_AllocHeapItem( DCIData,
                                    BufferSize,
                                    (PUSHORT *)&OutputBuffer1 ) != OK )
           {
              return( ERROR );
           }
           if ( prdg_AllocHeapItem( DCIData,
                                    6,
                                    (PUSHORT *)&InputBuffer ) != OK )
           {
              return( ERROR );
           }
        }

        /*********************************************************************/
        /* PD00556 For all cases allocate a buffer to put the data for each  */
        /* pass into before sending it to the printer.                       */
        /*********************************************************************/
        if ( (pDDT->DDTDriverType == DDT_IBM42XX_DRV) &&
             ( (pDDT->DDTRasterMode->ResWidth == 360) ||
               (pDDT->DDTRasterMode->ResWidth == 240) ) )
        {
           if ( prdg_AllocHeapItem( DCIData,
                                    BufferSize,
                                    (PUSHORT *)&PassBuffer ) != OK )
           {
              return( ERROR );
           }
        }
    }
    /******************************************************************/
    /* Acquire some memory big enough to put the moving commands in   */
    /* when we've made the raster but before we print it out.         */
    /******************************************************************/
    CommandSize = 1000;

    if ( prdg_AllocHeapItem( DCIData,
                             CommandSize,
                             (PUSHORT *)&CommandBuffer ) != OK )
    {
        return( ERROR );
    }
    CommandIndex = 0;

    /******************************************************************/
    /* Work out the correction to allow for the fact that in high     */
    /* resolution modes just the top eight pins of the 32 are being   */
    /* used for graphics, wheras text printing uses all 32. The head  */
    /* position is thus different for text and graphics by 16 for 120 */
    /* x120 resolution, and by 24 for 240x240 resolution.             */
    /*    This correction is done by working out HeadCorrection and   */
    /* temporarily decreasing HeadYPos during PrintText by           */
    /* that amount.                                                   */
    /******************************************************************/
    HeadCorrection = 0;

    TRACE6(TFUNC, "Head Correction", &HeadCorrection, 1);

    /******************************************************************/
    /* This flag get set in prdn_SendInitAndPage routine.             */
    /******************************************************************/
    if (DCIData->FirstBand)                   /* PD00473              */
    {
        /******************************************************************/
        /* Set up current head position to top of band.                   */
        /******************************************************************/
        HeadYPos = (USHORT)BitHeight + PDBInst->FormYOffset;

        /*******************************************************************/
        /* PD00476 : Added FormYOffset term to the following two statements*/
        /*******************************************************************/
        if ( HeadYPos > (PDBInst->PageDepthPels + PDBInst->FormYOffset) )
            HeadYPos = PDBInst->PageDepthPels + PDBInst->FormYOffset;

        /**********************************************************************/
        /* PD00613 : call function to loop thru all text chain entries and    */
        /* add any strikeout lines to the graphics band.                      */
        /**********************************************************************/
        Result = prdp_StrikeOutToBand(DCIData, TextEntryPtr);
    }
    else
    {
        /******************************************************************/
        /* Set up current head position to top of band.                   */
        /******************************************************************/
        HeadYPos = (USHORT)BitHeight;

        if ( HeadYPos > PDBInst->PageDepthPels  )
            HeadYPos = PDBInst->PageDepthPels;
    }


    HeadYPos -= SwatheSize;
    HeadYStart = HeadYPos;
    HeadYErr = 0;

    /******************************************************************/
    /* Set the initial font settings to NOT SET values (-1).          */
    /* These are used in the calls to prdp_PrintText to avoid         */
    /* unnecessary escape sequences to set the font on the printer.   */
    /*                                                                */
    /* The font setting for colour (for the 4224) is reset at         */
    /* the start of each call to prdp_PrintText since the colour      */
    /* printer setting could be affected by printing the raster.      */
    /******************************************************************/
    PDBInst->FontSettings.LastMatchNo    = VALUE_NOT_SET;
    PDBInst->FontSettings.LastFontId     = VALUE_NOT_SET;
    PDBInst->FontSettings.LastCodePageNo = VALUE_NOT_SET;
    PDBInst->FontSettings.LastWidth      = VALUE_NOT_SET;
    PDBInst->FontSettings.LastHeight     = VALUE_NOT_SET;
#ifdef SHEAR_ADDED
    PDBInst->FontSettings.LastShear      = VALUE_NOT_SET;
#endif


    /******************************************************************/
    /* Work out SwatheIncrement, which is the amount we need to add   */
    /* (possibly with a Huge increment or decrement) to ScanLinePtr   */
    /* to get to the start of the next swathe. This depends on the    */
    /* orientation and also on SwatheSize.                            */
    /******************************************************************/

    /******************************************************************/
    /* Initialise ScanLowY, which is the Y coordinate of the lowest   */
    /* scanline in the current swathe. As the bottom of the bitmap is */
    /* always at Y = 0, the last pass round the loop will be when     */
    /* ScanLowY = 0. We initialise ScanLowY to the top of the bitmap  */
    /* because it is decremented at the top of the main loop.         */
    /******************************************************************/
    ScanLowY = BitHeight;     /* CON3201 - Removed USHORT cast        */

    OutputString("Starting loop\n");

    /******************************************************************/
    /* PD00520: Set scanLowYAbs releative to form position.           */
    /******************************************************************/
    ScanLowYAbs =  PDBInst->PageDepthPels - ( ScanLowY * DCIData->BandCount );

    /*******************************************************************/
    /* If this is not first band then purge any text outside of this   */
    /* band. PD00520                                                   */
    /*******************************************************************/
    if ( !DCIData->FirstBand )
    {
        while ( TextEntryPtr )
        {
            if ( (TextEntryPtr->GTBTxtPos.y) > (ScanLowYAbs - SwatheSize) )
            {
                TextEntryPtr = TextEntryPtr->GTBNextEntry;
            }
            else
            {
                break;
            }
        }
    }

    /**************************************************************************/
    /*  INKJET : Do not do this for 360 x 360 for the 4070 and 4072.  This    */
    /*           will also make it IBM42XX specific which is OK unless we     */
    /*           add an IBM52XX printer with a Y-resoltion of 360.            */
    /**************************************************************************/
    if ( (pDDT->DDTRasterMode->ResDepth == 360) &&
         (pDDT->DDTDriverType == DDT_IBM42XX_DRV) &&
         (PDBInst->PrinterType <= IBM_2390_PS1) )
    {
       FirstOrSecondPass = 1;
    }

    while( ScanLowY )
    {
        /**************************************************************/
        /* This is the main loop. Each time round we adjust ScanLowY  */
        /* and if necessary SwatheSize (if we've reached the bottom   */
        /* swathe in the bitmap) then we output the                   */
        /* text in the swathe, make the raster and output the raster. */
        /* Then, if there is more raster to do, we move ScanLinePtr   */
        /* to point to the beginning of the next swathe. Then we go   */
        /* back to the top of the loop. Once we have passed through   */
        /* the loop with ScanLowY = 0, we have done the bottom of the */
        /* bitmap, so exit.                                           */
        /*                                                            */
        /* Throughout we keep track of the current head position and  */
        /* move the head as necessary.                                */
        /**************************************************************/

        TempScanLowY = ScanLowY;                      /* PD00726      */
        /**************************************************************/
        /* Adjust ScanLowY and if necessary SwatheSize for next pass  */
        /* round the loop.                                            */
        /**************************************************************/
        ScanLowY -= SwatheSize;
        ScanLowYAbs -= SwatheSize;               /* PD00520           */

        if ( ScanLowY < 0 )
        {
            SwatheSize += ScanLowY;
            ScanLowY = 0;
        }

        if ( ScanLowYAbs < 0 )                   /* PD00596           */
        {
            ScanLowYAbs = 0;
        }

        if ( TextEntryPtr )
        {
            /**********************************************************/
            /* If there is something in the text band then print.     */
            /**********************************************************/
            TRACE6(TFUNC, "Print Text", FNULL, 0);

            /**********************************************************/
            /* Allow for printer head size.                           */
            /**********************************************************/
            HeadYPos    -= HeadCorrection;
            ScanLowY    -= HeadCorrection;
            ScanLowYAbs -= HeadCorrection;       /* PD00520           */

            /******************************************************************/
            /* PD00076 : Added the OR code to the following if statement to   */
            /* call prdp_PrintText for strikeout text even if only the strike */
            /* out is in the current swathe.                                  */
            /******************************************************************/
            if (  TextEntryPtr -> GTBTxtPos.y >= ScanLowYAbs )
            {
                /******************************************************/
                /* Only print text if it is in swathe.                */
                /******************************************************/
                BufferIndex = 0;

                if ( (Result = prdp_PrintText(
                                     DCIData,
                                     &TextEntryPtr,
                                     (PBYTE)OutputBuffer,
                                     &BufferIndex, /* CON3201 Removed        */
                                                   /* PUSHORT cast           */
                                     BufferSize,
                                     ScanLowYAbs,
                                     (PUSHORT)&HeadYPos,
                                     (PUSHORT)&HeadYErr) ) != OK )
                {
                    return( Result );
                }
            }

            HeadYPos    += HeadCorrection;
            ScanLowY    += HeadCorrection;
            ScanLowYAbs += HeadCorrection;      /* PD00520            */

        }

        /**************************************************************/
        /* If the text only flag is TRUE then this DC has used        */
        /* only printer resident fonts. In this case we can skip      */
        /* scanning of band raster data and we needn't move           */
        /* ScanLinePtr, so skip back to the top of the loop.          */
        /**************************************************************/
        if ( DCIData->TextOnlyDC == TRUE )
            continue;

        /**************************************************************/
        /* Print the Bitmap part of the Band as a Raster.             */
        /* Pass in the current scanline, output memory, count of scan-*/
        /* lines in this group, and width of scanline in both bits    */
        /* and bytes (adjusted to 32 bits).                           */
        /**************************************************************/
        TRACE6(TFUNC, "Print Raster", FNULL, 0);

        if ( pDDT->DDTRasterMode->VertLinePels == 24 )
        {
            /******************************************************/
            /* Clear output buffer prior to putting raster in.    */
            /******************************************************/
            /**************************************************************/
            /* PD00556 If this is not 360x360 then just put the data in   */
            /* the normal buffer.                                         */
            /**************************************************************/
            if (pDDT->DDTRasterMode->ResDepth != 360)
            {
               (VOID) prdu_memset ( (PBYTE) OutputBuffer,
                                    '\0',
                                    BufferSize);
               RasterLength = prdp_PrintMakeRaster24(
                                    PDBInst,
                                    (PBYTE)ScanLinePtr,
                                    (PBYTE)OutputBuffer,
                                    SwatheSize,
                                    ListEntry);
            }
            else
            {
               /***************************************************************/
               /* PD00556 If this is 360x360 then put the raster data in one  */
               /* of the two buffers.  Cannot use OutputBuffer because it is  */
               /* used for text so data can not be stored across scanlines.   */
               /***************************************************************/
               if ((FirstOrSecondPass == 2) &&
                   (pDDT->DDTRasterMode->ResDepth == 360))
               {
                  (VOID) prdu_memset ( (PBYTE) OutputBuffer2,
                                       '\0',
                                       BufferSize);
                  RasterLength = prdp_PrintMakeRaster24(
                                        PDBInst,
                                        (PBYTE)ScanLinePtr,
                                        (PBYTE)OutputBuffer2,
                                        SwatheSize,
                                        ListEntry);
               }
               else
               {
                  if ((FirstOrSecondPass == 1) &&
                      (pDDT->DDTRasterMode->ResDepth == 360))
                  {
                     (VOID) prdu_memset ( (PBYTE) OutputBuffer1,
                                          '\0',
                                          BufferSize);
                     RasterLength = prdp_PrintMakeRaster24(
                                           PDBInst,
                                           (PBYTE)ScanLinePtr,
                                           (PBYTE)OutputBuffer1,
                                           SwatheSize,
                                           ListEntry);
                     RasterLengthPrev = RasterLength;
                  }
               }
            }
        }
        else if (DCIData->DCIPdbInstance->PrinterType == IBM_4224_COLOR)
        {
            (void)prdp_PrintMakeRasterColor(
                                   PDBInst,
                                   ScanLinePtr,
                                   (lpColOutputType)&ColOutput,
                                   SwatheSize,
                                   ListEntry);

            RasterLength = 1;            /* So it is non-zero     */
        }
        else
        {
            /******************************************************/
            /* Clear output buffer prior to putting raster in.    */
            /******************************************************/
            (VOID) prdu_memset ( (PBYTE) OutputBuffer,
                                 '\0',
                                 BufferSize);

            RasterLength = prdp_PrintMakeRaster8(
                                   PDBInst,
                                   (PBYTE)ScanLinePtr,
                                   (PBYTE)OutputBuffer,
                                   SwatheSize,
                                   ListEntry);
        }

        /**************************************************************/
        /* If the raster length is non-zero then print it             */
        /**************************************************************/
        /**********************************************************************/
        /* PD00556 If there is data to output from this scanline or the       */
        /* previous and this is the second pass or the last pass for 360x360  */
        /* then output the raster.                                            */
        /*  INKJET : Don't do this for the 4070 or the 4072                   */
        /**********************************************************************/
        if ( (RasterLength || RasterLengthPrev) && ( (FirstOrSecondPass == 2) ||
             ( (FirstOrSecondPass == 1) && ScanLowY == 0) ))
        {
            TRACE6(TFUNC, "Raster length", &RasterLength, 1);

            /**********************************************************/
            /* Output a Carriage Return before printing the raster.   */
            /* We do this with AddString rather than PrintSimple      */
            /* so that everything is written to buffer first, so      */
            /* that testing for print errors is easier.               */
            /**********************************************************/
            if ( (Result = prdp_AddString (
                                 EST_CARRIAGE_RETURN,
                                 USE_GLOBAL_TABLE,
                                 FNULL,
                                 CommandBuffer,
                                 (PUSHORT)&CommandIndex,
                                 CommandSize,
                                 DCIData )) != OK)
            {
                return( ERROR );
            }

            /******************************************************************/
            /*  PD00547 : Clear out the accumulating errors.                  */
            /******************************************************************/
            DCIData->Remainder = 0;

            /**********************************************************/
            /* Move Print head to bottom of raster                    */
            /**********************************************************/
            if ( HeadYPos > ScanLowY )
            {
               /***************************************************************/
               /* PD00556 For 360x360 need to move to ScanLowY + 1 because    */
               /* the three bytes end one shy of ScanLowY on the output of    */
               /* bits 0...46.  Then in the 360x360 routine the printhead is  */
               /* moved one down for the output of bits 1..47.  Therefore     */
               /* it will be moved to ScanLowY.                               */
               /*  INKJET:360 x 360 moves vertically 48 for graphics          */
               /***************************************************************/
               if ((pDDT->DDTRasterMode->ResDepth == 360) &&
                   (pDDT->DDTRasterMode->VertLinePels != 48))
               {
                     if ( (Result = prdp_PrintMoveDown(
                                              (PUSHORT)&HeadYPos,
                                              (PUSHORT)&HeadYErr,
                                              (ScanLowY + 1),
                                              CommandBuffer,
                                              (PUSHORT)&CommandIndex,
                                              CommandSize,
                                              DCIData )) != OK )
                     {
                        return( Result );
                     }
               }
               else
               {

                     if ( (ScanLowY == 0) &&
                          (pDDT->DDTRasterMode->VertLinePels == 48) &&
                          (PDBInst->Orientation == LANDSCAPE) )
                     {
                         HeadYPos += (48 - TempScanLowY);
                     }

                     if ( (Result = prdp_PrintMoveDown(
                                              (PUSHORT)&HeadYPos,
                                              (PUSHORT)&HeadYErr,
                                              ScanLowY,
                                              CommandBuffer,
                                              (PUSHORT)&CommandIndex,
                                              CommandSize,
                                              DCIData )) != OK )
                     {
                        return( Result );
                     }
               }
            }

            /**********************************************************/
            /* Move head across to allow for X Offset, due to new     */
            /* coordinate system (origin at clip origin, not paper    */
            /* corner).                                               */
            /* NOTE AddHorizMoveString now works in font resolution,  */
            /* so convert the offset to font coords here.             */
            /**********************************************************/
            NewPosX = prdt_XformFontValue(
                            -PDBInst->FormXOffset,
                            DEVICE_TO_FONT | CONV_X_VALUE,
                            (lpFontDataType)&DCIData->DCIFontData );

            prdp_AddHorizMoveString( 0,
                                     NewPosX,
                                     CommandBuffer,
                                     (PUSHORT)&CommandIndex,
                                     CommandSize,
                                     DCIData );

            /**********************************************************/
            /* Output all the move commands to the spool file or      */
            /* printer before printing the raster.                    */
            /**********************************************************/
            if ( (Result = prdp_PrintMemory ( CommandBuffer,
                                              CommandIndex,
                                              DCIData ) ) != OK )
            {
                return( Result );
            }

            CommandIndex = 0;


            /**********************************************************/
            /* Print the raster                                       */
            /**********************************************************/
            if (DCIData->DCIPdbInstance->PrinterType == IBM_4224_COLOR)
            {
                if ( (Result = prdp_PrintRasterColor(
                                   DCIData,
                                   (lpColOutputType)&ColOutput) ) != OK )
                {
                    TRACE4(TFUNC, "Error in Raster", FNULL, 0);
                    return( Result );
                }
            }
            else
            {
               /***************************************************************/
               /* PD00556 For the new enhanced resolutions only for the 42xx  */
               /* driver output the scanlines in passes.                      */
               /***************************************************************/
               if ( (pDDT->DDTDriverType == DDT_IBM42XX_DRV) &&
                    ( (pDDT->DDTRasterMode->ResWidth == 360) ||
                      (pDDT->DDTRasterMode->ResWidth == 240) ) &&
                    (PDBInst->PrinterType <= IBM_2390_PS1) )
               {
                  /************************************************************/
                  /* PD00556 This is for 360x360.                             */
                  /************************************************************/
                  if (pDDT->DDTRasterMode->ResDepth == 360)
                  {
                     FlipPointers = FALSE;
                     /*********************************************************/
                     /* PD00556 If this is the last pass then OutputBuffer2   */
                     /* must be cleared and the pointers swapped.  This is    */
                     /* done because only one raster is there.  The zeros have*/
                     /* to go on top because ScanLowY only decreased by one   */
                     /* swathe.  The zeros will print over the previous line  */
                     /*********************************************************/
                     if (FirstOrSecondPass == 1)
                     {
                        (VOID) prdu_memset ( (PBYTE) OutputBuffer2,
                                             '\0',
                                             BufferSize);
                        RasterLengthPrev = 0;
                        TempPointer1 = OutputBuffer1;
                        OutputBuffer1 = OutputBuffer2;
                        OutputBuffer2 = TempPointer1;
                        FlipPointers = TRUE;
                     }
                     else
                     {
                        /*****************************************************/
                        /* Reinitialize because we are about to output the   */
                        /* data.                                             */
                        /*****************************************************/
                        FirstOrSecondPass = 1;
                     }
                     /********************************************************/
                     /* Have to output for the longest line.                 */
                     /********************************************************/
                     if (RasterLengthPrev > RasterLength)
                     {
                        RasterLength = RasterLengthPrev;
                     }

                     if ( prdp_Print360by360 (pDDT, PassBuffer, BufferSize,
                                              OutputBuffer1,OutputBuffer2,
                                              CommandBuffer,
                                              (PUSHORT)&CommandIndex,
                                              CommandSize, NewPosX,
                                              (PUSHORT)&HeadYPos, DCIData,
                                              RasterLength, InputBuffer) != OK )
                     {
                        return( ERROR );
                     }
                     /*********************************************************/
                     /* If necessary reflip the pointers.                     */
                     /*********************************************************/
                     if (FlipPointers)
                     {
                        TempPointer1 = OutputBuffer1;
                        OutputBuffer1 = OutputBuffer2;
                        OutputBuffer2 = TempPointer1;
                     }
                  }
                  else
                  {
                     /********************************************************/
                     /* If 360x180 there are three bytes per column.  For 240*/
                     /* x72 there is one byte per column.                    */
                     /********************************************************/
                     if (pDDT->DDTRasterMode->ResWidth == 360)
                     {
                        BytesPerColumn = 3;
                     }
                     if (pDDT->DDTRasterMode->ResWidth == 240)
                     {
                        BytesPerColumn = 1;
                     }
                     if ( prdp_Print360by180 (PassBuffer, OutputBuffer,
                                              CommandBuffer,
                                              (PUSHORT)&CommandIndex,
                                              CommandSize, NewPosX,
                                              DCIData, RasterLength,
                                              BytesPerColumn) != OK )
                     {
                        return( ERROR );
                     }
                  }
               }
               else
               {
                  if ( pDDT->DDTRasterMode->VertLinePels == 24 )
                  {
                     if ( (Result = prdp_PrintRaster(
                                       DCIData,
                                       RasterLength,
                                       (PBYTE)OutputBuffer) ) != OK )
                     {
                         TRACE4(TFUNC, "Error in Raster", FNULL, 0);
                         return( Result );
                     }
                  }
                  else    /*  9-wire raster  */
                  {
                      if ( (Result = prdp_PrintRaster(
                                        DCIData,
                                        RasterLength,
                                        (PBYTE)OutputBuffer) ) != OK )
                      {
                          TRACE4(TFUNC, "Error in Raster", FNULL, 0);
                          return( Result );
                      }
                  }
               }
            }
        }
        else
        {
           /******************************************************************/
           /* PD00556 Clear out the previous raster length because it is not */
           /* valid any longer if this is the second pass.  Set this to the  */
           /* second pass.                                                   */
           /******************************************************************/
           if (FirstOrSecondPass == 2)
           {
              RasterLengthPrev = 0;
           }
           FirstOrSecondPass = 2;
        }

        /**************************************************************/
        /* Decrement ScanLinePtr to the first scan line in the next   */
        /* group. This is done using SwatheIncrement.                 */
        /**************************************************************/
        TRACE4(TFUNC, "Dec ScanLinePtr", FNULL, 0);

/* CON3201 *******************************************************************/
/* We no longer care about Huge so just increment ScanLinePtr                */
/*      if ( !(ListEntry->Huge) )                                            */
/*          ScanLinePtr += SwatheIncrement;                                  */
/*      else                                                                 */
/*      {                                                                    */
/*          if (SwatheIncrement > 0)                                         */
/*          {                                                                */
/*               ScanLinePtr = prdb_HugeIncrement(ScanLinePtr,               */
/*                                                SwatheIncrement);          */
/*          }                                                                */
/*          else                                                             */
/*          {                                                                */
/*               ScanLinePtr = prdb_HugeDecrement(ScanLinePtr,               */
/*                                             (- SwatheIncrement));         */
/*          }                                                                */
/*      }                                                                    */
/*****************************************************************************/

        ScanLinePtr += SwatheIncrement;
        OutputPair("New ScanLinePtr ",(LONG)ScanLinePtr,HEX);

    } /* ...while (ScanLowY) */

    /******************************************************************/
    /* Note: Formfeed now done in prdn_SendInitAndPage (prdprint.c).  */
    /******************************************************************/

#ifdef DDT_BANDING
    /******************************************************************/
    /* If this is not the last band in a page, then move the printer  */
    /* head down to the next line, ready for the next band. Otherwise */
    /* do nothing (a formfeed will be issued by SendInitAndPage).     */
    /******************************************************************/
    if ( !prdj_LastBand( DCIData ) )
    {
        CommandIndex = 0;
          HeadYPos +=  pDDT->DDTRasterMode->VertLinePels;  /* PD00520 */
//        HeadYPos += SwatheSize; /* extra gap ... */

        if ( (Result = prdp_AddString (
                             EST_CARRIAGE_RETURN,
                             USE_GLOBAL_TABLE,
                             FNULL,
                             CommandBuffer,
                             (PUSHORT)&CommandIndex,
                             CommandSize,
                             DCIData )) != OK)
        {
            return( ERROR );
        }

        /******************************************************************/
        /*  PD00547 : Clear out the accumulating errors.                  */
        /******************************************************************/
        DCIData->Remainder = 0;

        if ( (Result = prdp_PrintMoveDown(
                             (PUSHORT)&HeadYPos,
                             (PUSHORT)&HeadYErr,
                             0,
                             CommandBuffer,
                             (PUSHORT)&CommandIndex,
                             CommandSize,
                             DCIData )) != OK )
        {
            return( Result );
        }
        /**************************************************************/
        /* Output all the move commands to the spool file or printer  */
        /**************************************************************/
        if ( (Result = prdp_PrintMemory ( CommandBuffer,
                                          CommandIndex,
                                          DCIData )) != OK )
        {
            return( Result );
        }

    } /* ...if !LastBand */
#endif

    /******************************************************************/
    /* Finished Band.                                                 */
    /******************************************************************/
    TRACE4(TFUNC, "Finished Band", FNULL, 0);

    /******************************************************************/
    /* Free the memory used for the string of control sequence bytes  */
    /* and codepoints sent to the Printer.                            */
    /******************************************************************/
    /**************************************************************************/
    /* PD00671 : Added && (pDDT->DDTMaxColors != DDT_EIGHT_COLORS to if stmt  */
    /**************************************************************************/
    if ((pDDT->DDTDriverType == DDT_IBM42XX_DRV) &&
        ((pDDT->DDTRasterMode->ResWidth == 360) ||
           (pDDT->DDTRasterMode->ResWidth == 240)) &&
        (DCIData->DCIPdbInstance->PrinterType != IBM_4224_COLOR))
    {
       (void)prdg_FreeHeapItem( DCIData,
                                BufferSize,
                                (PUSHORT)PassBuffer );
    }
    if (pDDT->DDTRasterMode->ResDepth == 360)
    {
       (void)prdg_FreeHeapItem( DCIData,
                                BufferSize,
                                (PUSHORT)OutputBuffer2 );
       (void)prdg_FreeHeapItem( DCIData,
                                BufferSize,
                                (PUSHORT)OutputBuffer1 );
       (void)prdg_FreeHeapItem( DCIData,
                                6,
                                (PUSHORT)InputBuffer );
    }
    if (DCIData->DCIPdbInstance->PrinterType == IBM_4224_COLOR)
    {
       for ( Temp = 0; Temp < 8; Temp++ )
       {
          (void)prdg_FreeHeapItem(
                       DCIData,
                       BufferSize,
                       (PUSHORT)( ColOutput.Output[Temp] ) );
       }
    }
    else
    {
       (void)prdg_FreeHeapItem( DCIData,
                                BufferSize,
                                (PUSHORT)OutputBuffer );
    }

    (void)prdg_FreeHeapItem( DCIData,
                             CommandSize,
                             (PUSHORT)CommandBuffer );


    /******************************************************************/
    /* Output time at end of routine on debug terminal.               */
    /******************************************************************/
    DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &ulMsecs, 4);
    OutputPair( "PrintBand end time (msecs)is ",
                ulMsecs , DECIMAL );

    return( OK );

}
#undef TFUNC
/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdp_PrintMakeRaster8                                  */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpPDBI          PDBInst;      Pointer to the PDB Instance data   */
/*   PBYTE           ScanLinePtr;  Pointer to the start of the first  */
/*                                 scanline of the group to print     */
/*   PBYTE           RasterPtr;    Pointer to buffer for forming      */
/*                                 raster output in                   */
/*   USHORT          GroupCount;   Number of scan lines to do         */
/*   BitmapListEntry far *ListEntry;  Contains bitmap info            */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function converts the scanlines passed to it into raster    */
/*   scans which are compatible with the printer (ie horizontal       */
/*   scanlines to vertical printer rastor bytes).  It returns with    */
/*   the buffer indicated by RasterPtr containing the raster data     */
/*   for the printer and it returns the number of bytes until the     */
/*   last non-zero byte in the buffer.  See in line commenting for    */
/*   different approaches to portrait and landscape mode.             */
/*                                                                    */
/*   This function is used for 8-wire raster output.                  */
/*                                                                    */
/**********************************************************************/
/*CON3201
USHORT pascal prdp_PrintMakeRaster8 ( PDBInst,
                                   ScanLinePtr,
                                   RasterPtr,
                                   GroupCount,
                                   ListEntry
                                  )

lpPDBI               PDBInst;
PBYTE                ScanLinePtr;
PBYTE                RasterPtr;
USHORT               GroupCount;
BitmapListEntry far *ListEntry;
                               */

USHORT prdp_PrintMakeRaster8 (lpPDBI               PDBInst,
                             PBYTE                ScanLinePtr,
                             PBYTE                RasterPtr,
                             USHORT               GroupCount,
                             BitmapListEntry     *ListEntry)

{
#define TFUNC "prdp_PrMkeRast8"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    PBYTE       CurrScanPtr;           /* The current position within */
                                       /* the scanline                */
    PBYTE       SaveScanPtr;           /* The position of the start   */
                                       /* of the scanline (used for   */
                                       /* updating position to start  */
                                       /* of next line)               */
    PBYTE       CurrRasterPtr;         /* The current position within */
                                       /* the raster                  */
    PBYTE       LastSetRasterPtr;      /* The last position in the    */
                                       /* raster with a non-zero bit  */
    PBYTE       RasterEndPtr;          /* Marks the end of the raster */
    BYTE        RasterMask;            /* Mask used to insert bits    */
                                       /* into the raster bytes       */
    BYTE        ScanMask;              /* Mask to use to extract bits */
                                       /* from scanline byte          */
    ULONG       BitWidth;       /* Length of scan line in bits        */
    ULONG       ScanWidth;      /* Length of scan line in bytes       */

/* CON3201 ************************************************************/
/* Don't need HugeInc                                                 */
//    USHORT      HugeInc;        /* Huge increment (or 0 if no huge    */
//                                /* increment)                         */


    TRACE4(TFUNC, "GroupCount", &GroupCount, 1);

    /******************************************************************/
    /* Get bitmap info from ListEntry                                 */
    /******************************************************************/
    ScanWidth = ListEntry->Parms.BytesPerRow;

/*  HugeInc = ListEntry->Huge;                               CON3201  */

    /******************************************************************/
    /* There are two possible orientations of paper, portrait and     */
    /* landscape. These require different strategies for converting   */
    /* the bitmap into appropriate rasters.                           */
    /******************************************************************/
    if ( (PDBInst->Orientation == PORTRAIT) ||
         (PDBInst->DDT.DDTInitFlags & DDT_INIT_ORIENTATION) )
    {

        /******************************************************************/
        /* PORTRAIT MODE:                                                 */
        /*                                                                */
        /* The strategy in this routine is to work along each scanline    */
        /* in turn, looking at bits, and putting bits that are set into   */
        /* the same position in successive bytes of the raster.           */
        /*                                                                */
        /*   Scanlines:                                                   */
        /*                                                                */
        /*            Byte  ..1st... ..2nd... ..3rd... ..4th...           */
        /*            Bits  01234567 01234567 01234567 01234567           */
        /*                 ___________________________________            */
        /*      Lines  0   |abcdefgh ijklmnop qrstuvwx yz...              */
        /*             1   |ABCDEFGH IJKL                                 */
        /*             2   |MNOPQRST                                      */
        /*             3   |UVWX            Bitmap format (1,1)           */
        /*             4   |Y                                             */
        /*             5   |Z                                             */
        /*             6   |                                              */
        /*                                                                */
        /*   Raster scan:                                                 */
        /*                                                                */
        /*     Bytes:                                                     */
        /*                              1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2   */
        /*          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5   */
        /*          ___________________________________________________   */
        /*  Bits 7| a b c d e f g h i j k l m n o p q r s t u v w x y z   */
        /*       6| A B C D E F G H I J K L                               */
        /*       5| M N O P Q R S T                                       */
        /*       4| U V W X                                               */
        /*       3| Y                     Scanline format                 */
        /*       2| Z                                                     */
        /*       1|                                                       */
        /*       0|                                                       */
        /*                                                                */
        /******************************************************************/

        /**************************************************************/
        /* We do this with two loops. The outer loop works down the   */
        /* scanlines adjusting the raster mask for each line. The     */
        /* inner loop works along each scanline, and sets a bit in the*/
        /* raster if the correstponding bit in the scanline is set. It*/
        /* also keeps a record of the last position in the raster     */
        /* where a bit is set, so that we don't output lots of blank  */
        /* raster at the end of a line. This record keeping is done   */
        /* by LastSetRasterPtr.                                       */
        /**************************************************************/
        TRACE4(TFUNC, "Portrait mode", FNULL, 0);

        /**************************************************************/
        /* Note the RasterMask normally starts at 0x80 when the group */
        /* count is 8.  However we need to handle the special case    */
        /* when we have got to the bottom of the band and so          */
        /* group count is less than 8.  In this case we must put the  */
        /* few lines of the band into the bottom of the raster buffer */
        /* not the top - this is because we position the base of      */
        /* the printer head at the bottom of the band.                */
        /**************************************************************/
        BitWidth = ListEntry->Parms.Width;

        SaveScanPtr = ScanLinePtr;
        CurrScanPtr = ScanLinePtr;
        LastSetRasterPtr = NULL;

        for ( RasterMask = (BYTE) (0x01 << (SHORT)(GroupCount - 1));
              RasterMask;
              RasterMask >>= 1 )
        {
            /**********************************************************/
            /* The inner loop works along each scanline using ScanMask*/
            /* to check for set bits in the scanline and RasterMask   */
            /* to insert any set bits into the raster scan.           */
            /**********************************************************/
            ScanMask = 0x80;
            RasterEndPtr = RasterPtr + BitWidth;

            for ( CurrRasterPtr = RasterPtr;
                  CurrRasterPtr < RasterEndPtr;
                  CurrRasterPtr++ )
            {
                /******************************************************/
                /* The bitmap is now stored internally with 1 for     */
                /* white and 0 for black, so we must reverse the bits */
                /* as we copy them since the printer wants 0 for      */
                /* white and 1 for black.                             */
                /******************************************************/
                if ( !( (*CurrScanPtr) & ScanMask ) )
                {
                    /**************************************************/
                    /* The bit indicates black so set the             */
                    /* corresponding bit in the raster scan.          */
                    /**************************************************/
                    (*CurrRasterPtr) |= RasterMask;

                    /**************************************************/
                    /* If we have not previously set bits this far    */
                    /* along the raster then record the new non-zero  */
                    /* position.                                      */
                    /**************************************************/
            /* CON3201 *****************************************************/
            /*      if ( OFFSETOF(CurrRasterPtr)                           */
            /*                    > OFFSETOF(LastSetRasterPtr) )           */
            /***************************************************************/
                    if (CurrRasterPtr > LastSetRasterPtr)
                         LastSetRasterPtr = CurrRasterPtr;
                }
                /***********************************************************/
                /* PD00629:                                                */
                /* For bytes that are FF, zero when inverted skip them this*/
                /* can be done because the whole buffer is cleared out with*/
                /* zeros.                                                  */
                /***********************************************************/
                else
                {
                   if ((*CurrScanPtr) == 0xFF)
                   {
                      CurrRasterPtr += 7;
                    /* CON3201 ******************************/
                    /*if ( !(++OFFSETOF(CurrScanPtr)) )     */
                    /*   SELECTOROF(CurrScanPtr) += HugeInc;*/
                    /****************************************/
                      ++CurrScanPtr;
                      continue;
                   }
                }
                /******************************************************/
                /* Update the ScanMask and if we have reached the end */
                /* of a byte in the scanline then move to the next    */
                /* byte (allowing for a huge increment if required).  */
                /******************************************************/
                ScanMask >>=1;

                if ( !ScanMask )
                {
                    ScanMask = 0x80;
                 /* CON3201 ************************************/
                 /* if ( !(++OFFSETOF(CurrScanPtr)) )          */
                 /*       SELECTOROF(CurrScanPtr) += HugeInc;  */
                 /**********************************************/
                     ++CurrScanPtr;
                }
            }

            /**********************************************************/
            /* Update the scanline pointer and the saved scanline     */
            /* pointer. Note the update is SaveScanPtr - ScanWidth    */
            /* because the bitmap origin is bottom left and we are    */
            /* moving down through the bitmap.                        */
            /**********************************************************/
          /* CON3201 ****************************************************/
          /*if ( !HugeInc )                                             */
          /*    CurrScanPtr = SaveScanPtr - ScanWidth;                  */
          /*else                                                        */
          /*    CurrScanPtr = prdb_HugeDecrement ( SaveScanPtr,         */
          /*                                       (USHORT)ScanWidth);  */
          /**************************************************************/
            CurrScanPtr = SaveScanPtr - ScanWidth;          /* CON3201 */
            SaveScanPtr = CurrScanPtr;
        }
    }
    /* .... Portrait mode............................................ */
    else
    {
        /******************************************************************/
        /* LANDSCAPE MODE:                                                */
        /*                                                                */
        /*   Note:                                                        */
        /*                                                                */
        /*       Bitmap orientation  ->  Raster output in landscape       */
        /*           _________           ____________________             */
        /*           |+     *|           |#                +|             */
        /*           |       |           |                  |             */
        /*           |       |           |                  |             */
        /*           |       |           |.                *|             */
        /*           |       |           ~~~~~~~~~~~~~~~~~~~~             */
        /*           |       |                                            */
        /*           |#     .|                                            */
        /*           ~~~~~~~~~                                            */
        /*         (0,0)                                                  */
        /*                                                                */
        /*   Scanlines:                                                   */
        /*                                                                */
        /*                               1 1 1 1 1 1 1 1 1 1 2 2 2 2 2    */
        /*   Lines:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4    */
        /*           _________________________________________________    */
        /* . Bits: 7|a b c d e f g h i j k l m n o p q r s t u v w x      */
        /* .       6|A B C D E F G H I J K L                              */
        /* .       5|M N O P Q R                                          */
        /* Byte 1  4|S T U V                                              */
        /* .       3|W X                   Bitmap format (1,1)            */
        /* .       2|Y                                                    */
        /* .       1|Z                                                    */
        /* .       0|                                                     */
        /*                                                                */
        /*                                                                */
        /*   Raster scan:                                                 */
        /*                                                                */
        /*     Bytes:                                                     */
        /*                              1 1 1 1 1 1 1 1 1 1 2 2 2 2 2     */
        /*          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4     */
        /*          ___________________________________________________   */
        /*  Bits 7| a b c d e f g h i j k l m n o p q r s t u v w x       */
        /*       6| A B C D E F G H I J K L                               */
        /*       5| M N O P Q R                                           */
        /*       4| S T U V                                               */
        /*       3| W X                   Scanline format                 */
        /*       2| Y                                                     */
        /*       1| Z                                                     */
        /*       0|                                                       */
        /*                                                                */
        /******************************************************************/

        /******************************************************************/
        /* In this mode we can copy bytes from the bitmap to the raster   */
        /* directly when the GroupCount is 8, and with a shift otherwise. */
        /* Consecutive bytes in the raster are taken from consecutive     */
        /* lines in the bitmap.                                           */
        /******************************************************************/
        TRACE4(TFUNC, "Landscape mode", FNULL, 0);

        BitWidth = ListEntry->Parms.Height;

        CurrScanPtr = ScanLinePtr;
        LastSetRasterPtr = NULL;

        /******************************************************************/
        /* We make a special case of GroupCount = 8, to increase speed    */
        /******************************************************************/
        if (GroupCount == 8)
        {
            for ( CurrRasterPtr = RasterPtr;
                  CurrRasterPtr < RasterPtr + BitWidth;
                  CurrRasterPtr++ )
            {
                /******************************************************/
                /* The bitmap is now stored internally with 1 for     */
                /* white and 0 for black, so we must reverse the bits */
                /* as we copy them since the printer wants 0 for      */
                /* white and 1 for black.                             */
                /******************************************************/

                /**********************************************************/
                /* Copy the byte at CurrScanPtr to CurrRasterPtr reversed */
                /* and adjust LastSetRasterPtr if necessary.              */
                /**********************************************************/
                if ( *CurrRasterPtr = ~(*CurrScanPtr ) )
                     LastSetRasterPtr = CurrRasterPtr;

                /**********************************************************/
                /* Move the CurrScanPtr to the next scanline up the bitmap*/
                /* allowing for huge increment if necessary.              */
                /**********************************************************/
             /* CON3201 ***************************************************/
             /* if ( !HugeInc )                                           */
             /* {                                                         */
             /*     CurrScanPtr += ScanWidth;                             */
             /* }                                                         */
             /* else                                                      */
             /* {                                                         */
             /*     CurrScanPtr = prdb_HugeIncrement( CurrScanPtr,        */
             /*                                       (USHORT)ScanWidth); */
             /* }                                                         */
             /*************************************************************/
                CurrScanPtr += ScanWidth;                      /* CON3201 */

            }
        }
        else        /*  GroupCount < 8  */
        {
            for ( CurrRasterPtr = RasterPtr;
                  CurrRasterPtr < RasterPtr + BitWidth;
                  CurrRasterPtr++ )
            {
                /******************************************************/
                /* The bitmap is now stored internally with 1 for     */
                /* white and 0 for black, so we must reverse the bits */
                /* as we copy them since the printer wants 0 for      */
                /* white and 1 for black.                             */
                /******************************************************/

                /**********************************************************/
                /* Copy the byte at CurrScanPtr to CurrRasterPtr reversed */
                /* and adjust LastSetRasterPtr if necessary.              */
                /**********************************************************/
                if ( *CurrRasterPtr = (BYTE)( (((USHORT)~(*CurrScanPtr))
                                             >> (8 - (SHORT)GroupCount) )
                                             & ( 0xFF >> (8-GroupCount))) )
                     LastSetRasterPtr = CurrRasterPtr;

                /******************************************************/
                /* Move the CurrScanPtr to the next scanline up the   */
                /* bitmap allowing for huge increment if necessary.   */
                /******************************************************/
            /* CON3201 ***************************************************/
            /*  if ( !HugeInc )                                          */
            /*  {                                                        */
            /*      CurrScanPtr += ScanWidth;                            */
            /*  }                                                        */
            /*  else                                                     */
            /*  {                                                        */
            /*      CurrScanPtr = prdb_HugeIncrement(CurrScanPtr,        */
            /*                                       (USHORT)ScanWidth); */
            /*  }                                                        */
            /*************************************************************/
                    CurrScanPtr += ScanWidth;                 /* CON3201 */
            }
        }
    }
    /* .... Landscape mode........................................... */


    /******************************************************************/
    /* Return the length of the raster scan to the last non-zero byte.*/
    /******************************************************************/
    if (!LastSetRasterPtr)
    {
        /**************************************************************/
        /* The raster is empty so return a raster length of 0.        */
        /**************************************************************/
        return(0);
    }
    return(LastSetRasterPtr - RasterPtr + 1);

}
#undef TFUNC






/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdp_PrintMakeRaster24                                 */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpPDBI          PDBInst;      Pointer to the PDB Instance data   */
/*   PBYTE           ScanLinePtr;  Pointer to the start of the first  */
/*                                 scanline of the group to print     */
/*   PBYTE           RasterPtr;    Pointer to buffer for forming      */
/*                                 raster output in                   */
/*   USHORT          GroupCount;   Number of scan lines to do         */
/*   BitmapListEntry far *ListEntry; Contains bitmap info             */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function converts the scanlines passed to it into raster    */
/*   scans which are compatible with the printer (ie horizontal       */
/*   scanlines to vertical printer rastor bytes).  It returns with    */
/*   the buffer indicated by RasterPtr containing the raster data     */
/*   for the printer and it returns the number of bytes until the     */
/*   last non-zero byte in the buffer.  See in line commenting for    */
/*   different approaches to portrait and landscape mode.             */
/*                                                                    */
/*   This function is used for 24-wire raster output.                 */
/*                                                                    */
/**********************************************************************/
/*CON3201
USHORT pascal prdp_PrintMakeRaster24 ( PDBInst,
                                     ScanLinePtr,
                                     RasterPtr,
                                     GroupCount,
                                     ListEntry
                                   )

lpPDBI               PDBInst;
PBYTE                ScanLinePtr;
PBYTE                RasterPtr;
USHORT               GroupCount;
BitmapListEntry far *ListEntry;
                                 */
USHORT prdp_PrintMakeRaster24 (lpPDBI               PDBInst,
                               PBYTE                ScanLinePtr,
                               PBYTE                RasterPtr,
                               USHORT               GroupCount,
                               BitmapListEntry     *ListEntry)

{
#define TFUNC "prdp_PrMkeRst24"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    PBYTE       CurrScanPtr;           /* The current position within */
                                       /* the scanline                */
    PBYTE       SaveScanPtr;           /* The position of the start   */
                                       /* of the scanline (used for   */
                                       /* updating position to start  */
                                       /* of next line)               */
    PBYTE       CurrRasterPtr;         /* The current position within */
                                       /* the raster                  */
    PBYTE       LastSetRasterPtr;      /* The last position in the    */
                                       /* raster with a non-zero bit  */
    PBYTE       InitRasterPtr;         /* position in raster at start */
                                       /* of current scanline         */
    BYTE        RasterMask;            /* Mask used to insert bits    */
                                       /* into the raster bytes       */
    BYTE        ScanMask;              /* Mask to use to extract bits */
                                       /* from scanline byte          */
    USHORT      RasterLength;          /* length of the non-zero bit  */
                                       /* of the raster               */
    ULONG       BitWidth;       /* Length of scan line in bits        */
    ULONG       ScanWidth;      /* Length of scan line in bytes       */

/* CON3201 ***************************************************************/
//    USHORT      HugeInc;        /* Huge increment (or 0 if no huge    */
                                /* increment)                         */
    PBYTE       TestRasterPtr;


    /******************************************************************/
    /* Get bitmap info from ListEntry                                 */
    /******************************************************************/
    ScanWidth = ListEntry->Parms.BytesPerRow;
/*  HugeInc = ListEntry->Huge;                                CON3201 */

    TRACE4(TFUNC, "Entry", FNULL, 0);
    TRACE4(TFUNC, "RasterPtr", &RasterPtr, 1);
    TRACE4(TFUNC, "GroupCount", &GroupCount, 1);
    TRACE4(TFUNC, "ScanWidth", &ScanWidth, 1);

    CurrScanPtr = ScanLinePtr;
    LastSetRasterPtr = NULL;

    /******************************************************************/
    /* There are two possible orientations of paper, portrait and     */
    /* landscape. These require different strategies for converting   */
    /* the bitmap into appropriate rasters.                           */
    /******************************************************************/
    if ( (PDBInst->Orientation == PORTRAIT) ||
         (PDBInst->DDT.DDTInitFlags & DDT_INIT_ORIENTATION) )
    {
        /**********************************************************/
        /* PORTRAIT :                                             */
        /**********************************************************/
        /**********************************************************/
        /* In high resolution mode printing is done using 24 pins.*/
        /* The data has three bytes per slice with the most       */
        /* significant bit of the first byte mapping to the top   */
        /* wire.                                                  */
        /**********************************************************/
        /**********************************************************/
        /* The raster mask will normally be 0x80 except for       */
        /* perhaps the bottom of the band. Similarly InitRasterPtr*/
        /* will normally be RasterPtr. These two together         */
        /* determine where we will start writing in the raster    */
        /* when we start the current scanline. As we go along the */
        /* scanline, all we need to do is to shift the            */
        /* CurrRasterPtr by 3. If GroupCount < 24, we need to     */
        /* start RasterMask and InitRasterPtr so that the lines in*/
        /* the band are placed in the bottom of the raster buffer.*/
        /* RasterMask and InitRasterPtr are updated at the end of */
        /* each scanline in the band.                             */
        /**********************************************************/
        BitWidth = ListEntry->Parms.Width;

        SaveScanPtr = ScanLinePtr;

        InitRasterPtr = RasterPtr;
        RasterMask = 0x80;

        if ( GroupCount < 24 )
        {
            InitRasterPtr += ((24 - GroupCount) / 8);
            RasterMask >>= ((24 - GroupCount) % 8);
        }

        TRACE6(TFUNC, "RasterMask", &RasterMask, 1);

        while (InitRasterPtr < RasterPtr + 3)
        {
            /**********************************************************/
            /* Do each scanline in turn, starting from the top.       */
            /**********************************************************/
            ScanMask = 0x80;

            TestRasterPtr = InitRasterPtr + (3 * BitWidth);

            /**********************************************************/
            /* PD00629: Call a new assembler routine.                 */
            /**********************************************************/
         /* CON3201 ********************************************************/
         /* HugeInc is no longer used will have to change to assembler     */
         /* routine to reflect this change                                 */
         /* prdu_createraster ( InitRasterPtr, TestRasterPtr, &CurrScanPtr,*/
         /*                     &LastSetRasterPtr, ScanMask, RasterMask,   */
         /*                     HugeInc);                                  */
         /******************************************************************/

            prdu_createraster ( InitRasterPtr, TestRasterPtr, &CurrScanPtr,
                                &LastSetRasterPtr, ScanMask, RasterMask);

            /******************************************************/
            /* Update the scanline pointer and the saved scanline */
            /* pointer.                                           */
            /******************************************************/
        /* CON3201 *******************************************************/
        /*  if ( !HugeInc )                                              */
        /*  {                                                            */
        /*      CurrScanPtr = SaveScanPtr - ScanWidth;                   */
        /*  }                                                            */
        /*  else                                                         */
        /*  {                                                            */
        /*      CurrScanPtr = prdb_HugeDecrement ( SaveScanPtr,          */
        /*                                         (USHORT)ScanWidth);   */
        /*  }                                                            */
        /*****************************************************************/
            CurrScanPtr = SaveScanPtr - ScanWidth;            /* CON3201 */
            SaveScanPtr = CurrScanPtr;

            /******************************************************/
            /* Update the raster mask - watch out for the case    */
            /* when it shifts past a byte boundary.               */
            /******************************************************/
            RasterMask >>= 1;
            if ( !RasterMask )
            {
                RasterMask = 0x80;
                InitRasterPtr++;
            }
        }
    }
    /* .... Portrait mode ........................................... */
    else
    {
        /**************************************************************/
        /* LANDSCAPE :                                                */
        /**************************************************************/
        TRACE4(TFUNC, "Landscape mode", FNULL, 0);

        BitWidth = ListEntry->Parms.Height;

        /**********************************************************************/
        /* Group Count will be 24 for all except perhaps the last             */
        /* bit on the band so do it as "faster" special case.                 */
        /**********************************************************************/
        if ( GroupCount == 24 )
        {
            for ( CurrRasterPtr = RasterPtr;
                  CurrRasterPtr < RasterPtr + (3 * BitWidth);
                  CurrRasterPtr += 3 )
            {
                /******************************************************/
                /* Check three adjacent bytes to build up data for    */
                /* twenty four wires.                                 */
                /******************************************************/
                *CurrRasterPtr = ~(*CurrScanPtr);
                *(CurrRasterPtr + 1) = ~(*(CurrScanPtr + 1));
                *(CurrRasterPtr + 2) = ~(*(CurrScanPtr + 2));

                /**********************************************/
                /* Record the position of non blank pel       */
                /**********************************************/
                if ( *CurrRasterPtr
                     | *( CurrRasterPtr + 1 )
                     | *( CurrRasterPtr + 2 ) )
                         LastSetRasterPtr = CurrRasterPtr;

            /* CON3201 ******************************************************/
            /*  if ( !HugeInc )                                             */
            /*  {                                                           */
            /*      CurrScanPtr += ScanWidth;                               */
            /*  }                                                           */
            /*  else                                                        */
            /*  {                                                           */
            /*      CurrScanPtr = prdb_HugeIncrement( CurrScanPtr,          */
            /*                                        (USHORT)ScanWidth );  */
            /*  }                                                           */
            /****************************************************************/
                CurrScanPtr += ScanWidth;                        /* CON3201 */
            }
        }
        /* ..... if ( GroupCount == 24 ) ............................ */
        else        /* GroupCount != 24 */
        {
            for ( CurrRasterPtr = RasterPtr;
                  CurrRasterPtr < RasterPtr + (3 * BitWidth);
                  CurrRasterPtr += 3 )
            {
                /******************************************************/
                /* We make several cases depending on how many bytes  */
                /* GroupCount covers. This looks horrible but works.  */
                /******************************************************/
                switch ((GroupCount - 1) / 8)
                {
                    case 0:
                        *(CurrRasterPtr + 2) = (~( *CurrScanPtr )
                                                       >> (8-GroupCount))
                                               & (0xFF >> (8-GroupCount));
                        break;
                    case 1:
                        *(CurrRasterPtr + 1) = ( (~*CurrScanPtr
                                                       >> 16-GroupCount)
                                               & (0xFF >> 16-GroupCount) );
                        *(CurrRasterPtr + 2) = ( (~*CurrScanPtr
                                                       << GroupCount-8)
                                               & (0xFF << GroupCount-8) )
                                             | ( (~*(CurrScanPtr + 1)
                                                       >> 16-GroupCount)
                                               & (0xFF >> 16-GroupCount) );
                        break;
                    case 2:
                        *CurrRasterPtr       = ( (~*CurrScanPtr
                                                       >> 24-GroupCount)
                                               & (0xFF >> 24-GroupCount) );
                        *(CurrRasterPtr + 1) = ( (~*CurrScanPtr
                                                       << GroupCount-16)
                                               & (0xFF << GroupCount-16) )
                                             | ( (~*(CurrScanPtr + 1)
                                                       >> 24-GroupCount)
                                               & (0xFF >> 24-GroupCount) );
                        *(CurrRasterPtr + 2) = ( (~*(CurrScanPtr + 1)
                                                       << GroupCount-16)
                                               & (0xFF << GroupCount-16) )
                                             | ( (~*(CurrScanPtr + 2)
                                                       >> 24-GroupCount)
                                               & (0xFF >> 24-GroupCount) );
                        break;
                }
                /**********************************************/
                /* Record the position of non blank pel       */
                /**********************************************/
                if ( *CurrRasterPtr
                     | *( CurrRasterPtr + 1 )
                     | *( CurrRasterPtr + 2 ) )
                         LastSetRasterPtr = CurrRasterPtr;
             /* CON3201 ******************************************************/
             /* if ( !HugeInc )                                              */
             /* {                                                            */
             /*     CurrScanPtr += ScanWidth;                                */
             /* }                                                            */
             /* else                                                         */
             /* {                                                            */
             /*     CurrScanPtr = prdb_HugeIncrement( CurrScanPtr,           */
             /*                                       (USHORT)ScanWidth );   */
             /* }                                                            */
             /****************************************************************/
                CurrScanPtr += ScanWidth;                         /* CON3201 */
            }
        }
        /* .... if ( GroupCount != 24 ) ............................. */
    }
    /* .... Landscape mode .......................................... */

    if ( !LastSetRasterPtr )
    {
        /**************************************************************/
        /* The raster was empty so return a raster length of 0.       */
        /**************************************************************/
        return(0);
    }

    /******************************************************************/
    /* Adjust raster length to multiple of three.                     */
    /******************************************************************/
    RasterLength = LastSetRasterPtr - RasterPtr + 1;

    if ( RasterLength % 3 )
        RasterLength += 3 - ( RasterLength % 3);

    return(RasterLength);

}
#undef TFUNC







/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdp_PrintMakeRasterColor                              */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpPDBI          PDBInst;      Pointer to the PDB Instance data   */
/*   PBYTE           ScanLinePtr;  Pointer to the start of the first  */
/*                                 scanline of the group to print     */
/*   lpColOutputType ColOutputPtr; Pointer to structure for forming   */
/*                                 output in                          */
/*   USHORT          GroupCount;   Number of scan lines to do. We can */
/*                                 assume this is 8 or less.          */
/*   BitmapListEntry far *ListEntry; contains bitmap info             */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*  This function has been written for the 4224 colour printer.  It   */
/*  scans through 8 lines of a (1,4) bitmap reading the colour from   */
/*  each nybble and producing vertical raster bytes for sending to    */
/*  the printer.  It outputs to eight blocks of memory - one for      */
/*  each colour including white.  Each block of memory has a byte     */
/*  for each vertical set of eight pels.  Each bit is set if the      */
/*  corresponding pel is that colour.  Later these lines can be sent  */
/*  in turn to the printer, setting the printer to the appropriate    */
/*  colour before sending each line.  The block for white is          */
/*  discarded.  This ensures that accented as well as subtractive     */
/*  ribbons can be handled without the driver having to know which    */
/*  one is being used.  ( The printer will print black instead of     */
/*  the colour requested if the accent ribbon is installed and the    */
/*  colour requested is not black, blue, red, or green.  ) The        */
/*  absolute maximum amount of memory required for all the output     */
/*  blocks is: 240dpi x 13.2 inches / (8 bits/byte) x 8 lines x 8     */
/*  colours = 25,344 bytes                                            */
/*                                                                    */
/**********************************************************************/
/* CON3201
void pascal prdp_PrintMakeRasterColor ( PDBInst,
                                        ScanLinePtr,
                                        ColOutputPtr,
                                        GroupCount,
                                        ListEntry
                                      )

lpPDBI               PDBInst;
PBYTE                ScanLinePtr;
lpColOutputType      ColOutputPtr;
USHORT               GroupCount;
BitmapListEntry far *ListEntry;
                              */
void prdp_PrintMakeRasterColor (lpPDBI               PDBInst,
                                PBYTE                ScanLinePtr,
                                lpColOutputType      ColOutputPtr,
                                USHORT               GroupCount,
                                BitmapListEntry     *ListEntry)


{
#define TFUNC "prdp_PrintMakeRasterColor"

    /*******************************************************************/
    /* Local Variables                                                 */
    /*******************************************************************/
    PBYTE       CurrScanPtr;           /* The current position within  */
                                       /* the scanline                 */
    PBYTE       SaveScanPtr;           /* The position of the start    */
                                       /* of the scanline (used for    */
                                       /* updating position to start   */
                                       /* of next line)                */
    BYTE        OutputMask;            /* Mask used to insert bits     */
                                       /* into the output bytes        */
    USHORT      i;                     /* Loop index                   */
    USHORT      OutputIndex;           /* Index into output blocks     */
    BYTE        OutputMask1;           /* Masks for landscape mode     */
    BYTE        OutputMask2;           /*                              */
    PBYTE       OutputPtr[8];          /* Local copies of output block */
                                       /* pointers                     */
    BYTE        CurrByte;              /* Current byte at CurrScanPtr  */
    ULONG       BitWidth;              /* bitmap width                 */
    ULONG       ScanWidth;             /* Width of bitmap to dword     */
                                       /* boundary (in bytes)          */
/* CON3201 *************************************************************/
//    USHORT      HugeInc;               /* says whether bitmap is huge  */
//                                       /* (> 64K). 0 if not.           */

    TRACE4(TFUNC, "ColOutputPtr", &ColOutputPtr, 1);
    TRACE4(TFUNC, "GroupCount", &GroupCount, 1);

    /******************************************************************/
    /* Clear output memory blocks prior to putting bits into it.      */
    /* And copy starts of output blocks into local store for speed in */
    /* main loop                                                      */
    /******************************************************************/
    for ( i = 0 ; i < 8; i++ )
    {
        OutputPtr[i] = ColOutputPtr->Output[i];
        (VOID) prdu_memset ( (PBYTE) OutputPtr[i] ,
                             '\0',
                             ColOutputPtr->OutputSize );
    }

    /******************************************************************/
    /* Get bitmap info from ListEntry                                 */
    /******************************************************************/
    ScanWidth = ListEntry->Parms.BytesPerRow;
/*  HugeInc   = ListEntry->Huge;                              CON3201 */

    /******************************************************************/
    /* There are two possible orientations of paper, portrait and     */
    /* landscape. These require different strategies for converting   */
    /* the bitmap into appropriate rasters.                           */
    /******************************************************************/
    if ( (PDBInst->Orientation == PORTRAIT) ||
         (PDBInst->DDT.DDTInitFlags & DDT_INIT_ORIENTATION) )
    {
        /******************************************************************/
        /* PORTRAIT MODE:                                                 */
        /*                                                                */
        /* The strategy in this routine is to work along each scanline    */
        /* in turn, looking at nybbles, and setting the bit in the        */
        /* output block corresponding to the colour of the pel.           */
        /*                                                                */
        /*   Scanlines:                                                   */
        /*                                                                */
        /*            Byte  ...1st... ...2nd... ...3rd...                 */
        /*            Bits  0123 4567 0123 4567 0123 4567                 */
        /*                 ___________________________________            */
        /*      Lines  0   | Red|Red | Wht| Wht|Yel |Blk |....            */
        /*             1   | Red|Grn | Grn| Grn|Grn |Red |                */
        /*             2   | Red|                                         */
        /*             3   | Grn|           Bitmap format (1,4)           */
        /*             4   | Grn                                          */
        /*             5   |                                              */
        /*             6   |                                              */
        /*                                                                */
        /*   Output block for Red:                                        */
        /*                                                                */
        /*                            Bytes                               */
        /*                         0 1 2 3 4 5 6 7 8                      */
        /*                         _________________                      */
        /*                 Bits 7| 1 1 0 0 0 0 ...                        */
        /*                      6| 1 0 0 0 0 1 ...                        */
        /*                      5| 1                                      */
        /*                      4| 0                                      */
        /*                      3| 0                                      */
        /*                      2|                                        */
        /*                      1|                                        */
        /*                      0|                                        */
        /*                                                                */
        /******************************************************************/

        /******************************************************************/
        /* The outer loop handles one scanline at a time.  The local scan */
        /* count is used to control this loop so that we do GroupCount    */
        /* scanlines.  SaveScanPtr is set up as the pointer to the first  */
        /* scan line, the OutputMask is set to 0x80 because the first     */
        /* scanline corresponds to bit 7 of the bytes in the raster scan. */
        /* CurrScanPtr is set up initially to point to the first scanline.*/
        /* At the end of each loop CurrScanPtr is updated to the start of */
        /* the next scan line by using ScanWidth as an offset to          */
        /* SaveScanPtr and SaveScanPtr is itself updated to the start of  */
        /* the next scan line.                                            */
        /*                                                                */
        /******************************************************************/
        TRACE4(TFUNC, "Portrait mode", FNULL, 0);

        /**************************************************************/
        /* Set up OutputMask.  Normally this is 0x80 when the group   */
        /* count is 8.  However we need to handle the special case    */
        /* when we have got to the bottom of the band and so          */
        /* group count is less than 8.  In this case we must put the  */
        /* few lines of the band into the bottom of the raster buffer */
        /* not the top - this is because we position the base of      */
        /* the printer head at the bottom of the band.                */
        /**************************************************************/
        BitWidth = ListEntry->Parms.Width;

        SaveScanPtr = ScanLinePtr;
        CurrScanPtr = ScanLinePtr;

        for ( OutputMask = (BYTE) (0x01 << (GroupCount - 1));
              OutputMask;
              OutputMask >>= 1 )
        {
            /**********************************************************/
            /* The inner loop works along each scanline               */
            /**********************************************************/
            OutputIndex = 0;

            while (OutputIndex < (USHORT)BitWidth)
            {
                CurrByte = *CurrScanPtr;

                /*******************************************************/
                /* Set the bit given by OutputMask in byte number      */
                /* OutputIndex in Output block given by colour in high */
                /* nybble. Then increment OutputIndex for next pel     */
                /*******************************************************/
                OutputPtr[(CurrByte>>4) & 0x07][OutputIndex++] |=
                                                            OutputMask;

                /*******************************************************/
                /* Repeat for low nibble                               */
                /*******************************************************/

                OutputPtr[CurrByte & 0x07][OutputIndex++] |= OutputMask;
           /*CON3201***********************************************************/
           /*   if ( !(++OFFSETOF(CurrScanPtr)) )                             */
           /*        SELECTOROF(CurrScanPtr) += HugeInc;                      */
           /*******************************************************************/
                ++CurrScanPtr;
                } /* CON3201 - replacement for } below */

                /******************************************************/
                /* Move to the next                                   */
                /* byte in the scanline (allowing for a huge          */
                /* increment if required).                            */
                /******************************************************/
           /* CON3201 *********************************************************/
           /*   }                                                             */
           /*                                                                 */
           /*       if ( !HugeInc )                                           */
           /*       {                                                         */
           /*           CurrScanPtr = SaveScanPtr - ScanWidth;                */
           /*       }                                                         */
           /*       else                                                      */
           /*       {                                                         */
           /*           CurrScanPtr = prdb_HugeDecrement ( SaveScanPtr,       */
           /*                                            (USHORT) ScanWidth );*/
           /*       }                                                         */
           /*******************************************************************/
            CurrScanPtr = SaveScanPtr - ScanWidth;
            SaveScanPtr = CurrScanPtr;
            }
    }
    else
    {
        /******************************************************************/
        /* LANDSCAPE MODE:                                                */
        /*                                                                */
        /*   Note:                                                        */
        /*                                                                */
        /*       Bitmap orientation  ->  Raster output in landscape       */
        /*           _________           ____________________             */
        /*           |+     *|           |#                +|             */
        /*           |       |           |                  |             */
        /*           |       |           |                  |             */
        /*           |       |           |.                *|             */
        /*           |       |           ~~~~~~~~~~~~~~~~~~~~             */
        /*           |       |                                            */
        /*           |#     .|                                            */
        /*           ~~~~~~~~~                                            */
        /*         (0,0)                                                  */
        /*                                                                */
        /*                                                                */
        /******************************************************************/
        TRACE4(TFUNC, "Landscape mode", FNULL, 0);

        BitWidth = ListEntry->Parms.Height;

        /**************************************************************/
        /* Set up the Output Masks.  Normally these are 0x80 and 0x40 */
        /* when group count is 8.  But we need to handle the case     */
        /* when we have got to the bottom of the band and so          */
        /* group count is less than 8.  In this case we must put the  */
        /* few lines of the band into the bottom of the raster buffer */
        /* not the top - this is because we position the base of      */
        /* the printer head at the bottom of the band.                */
        /**************************************************************/
        for ( i = 1, OutputMask1 = 0x01;
              i < GroupCount;
              i++ )
        {
            OutputMask1 *= 2;
        }

        OutputMask2 = OutputMask1 >> 1;

        TRACE6(TFUNC, "Output mask 1", &OutputMask1, 1);
        TRACE6(TFUNC, "Output mask 2", &OutputMask2, 1);

        /**************************************************************/
        /* Do 2 vertical lines at a time. Hence we need two           */
        /* OutputMasks.                                               */
        /**************************************************************/
        for ( i = 0,
                CurrScanPtr = ScanLinePtr;
             i < GroupCount;
             i += 2,
               OutputMask1 >>= 2,
               OutputMask2 >>= 2 )

        {
            SaveScanPtr = CurrScanPtr;

            /**********************************************************/
            /* This loop is passed through 4 times, once for each pair*/
            /* of adjacent vertical lines on the screen aligned on    */
            /* byte boundaries. We assume that the first line is      */
            /* aligned on a byte boundary, and the number of lines is */
            /* even.                                                  */
            /**********************************************************/
            for ( OutputIndex = 0;
                  OutputIndex < (USHORT)BitWidth;
                  OutputIndex++ )
            {
                CurrByte = *CurrScanPtr;

                /*******************************************************/
                /* Set the bit given by OutputMask1 in byte number     */
                /* OutputIndex in Output block given by colour in high */
                /* nibble.                                             */
                /*******************************************************/
                OutputPtr[(CurrByte>>4) & 0x07][OutputIndex] |=
                                                            OutputMask1;

                /******************************************************/
                /* Repeat for low nibble and increment OutputIndex.   */
                /* Beware of the case where group count is odd (which */
                /* may happen at the right edge of the page in        */
                /* landscape mode) - here the contents of the low     */
                /* nibble is undefined so we want to avoid looking    */
                /* at it.  If we are in this case then OutputMask2    */
                /* will have been shifted out of existance to zero.   */
                /******************************************************/
                if ( OutputMask2 != 0x00 )
                    OutputPtr[CurrByte & 0x07][OutputIndex] |=
                                                            OutputMask2;

                /******************************************************/
                /* Move the CurrScanPtr to the next scanline up the   */
                /* bitmap allowing for huge increment if necessary.   */
                /******************************************************/
             /* CON3201 *****************************************************/
             /* if ( !HugeInc )                                             */
             /* {                                                           */
             /*     CurrScanPtr += ScanWidth;                               */
             /* }                                                           */
             /* else                                                        */
             /* {                                                           */
             /*     CurrScanPtr = prdb_HugeIncrement( CurrScanPtr,          */
             /*                                      (USHORT) ScanWidth );  */
             /* }                                                           */
             /***************************************************************/
                CurrScanPtr += ScanWidth;
            }

            /**********************************************************/
            /* Set CurrScanPtr to bottom of current line and then     */
            /* increment to set it to bottom of next two lines        */
            /**********************************************************/
            CurrScanPtr = SaveScanPtr;

/* CON3201 ************************************************************/
/*          if ( !(++OFFSETOF(CurrScanPtr)) )                         */
/*               SELECTOROF(CurrScanPtr) += HugeInc;                  */
/**********************************************************************/
            ++CurrScanPtr;
        }
    }
    /* .... Landscape mode ........................................., */

    /*********************************************************************/
    /* For each memory block move back through bytes from end to find    */
    /* first non-zero byte. Make OutputLength set to this. No need to do */
    /* this for white as this block is to be discarded anyway.           */
    /*********************************************************************/
    for ( i = 0; i < 8; i++ )
    {
        if (i == PRD_8_PRINTER_WHITE)
        {
            /**********************************************************/
            /* Skip the white block.                                  */
            /**********************************************************/
            continue;
        }
        for( OutputIndex = (USHORT)BitWidth - 1;
             ((OutputIndex > 0) && (OutputPtr[i][OutputIndex] == 0));
             OutputIndex-- )
           ;

       ColOutputPtr->OutputLength[i] = OutputIndex + 1 -
                ((OutputPtr[i][OutputIndex] == 0) && (OutputIndex == 0) );
    }

    TRACE4(TFUNC, "Exit OK", FNULL, 0);

}
#undef TFUNC



/*CON3201
USHORT pascal prdp_PrintRaster ( DCIData,
                               RasterLength,
                               RasterPtr )

lpDCI           DCIData;
USHORT          RasterLength;
PBYTE           RasterPtr;
                            */
SHORT prdp_PrintRaster (lpDCI           DCIData,
                        USHORT          RasterLength,
                        PBYTE           RasterPtr)

{
#define TFUNC "prdp_PrintRaster"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    SHORT       Result;                /* CON3203 CHANGED USHORT TO SHORT */
    lpPDBI      PDBInst;               /* pointer to PDB instance     */
    USHORT      BytesWritten;          /* number of bytes prtwritten  */
    lpDDTType   pDDT;                  /* Pointer to DDT in PDB       */


    TRACE4(TFUNC, "Entry", FNULL, 0);
    TRACE4(TFUNC, "RasterPtr", &RasterPtr, 1);
    TRACE4(TFUNC, "RasterLength", &RasterLength, 1);

    PDBInst = DCIData->DCIPdbInstance;
    pDDT = &PDBInst->DDT;

    /**************************************************************************/
    /* The code takes advantage of the fact that the number of                */
    /* bytes is supplied as two parameters, with the low byte first.          */
    /*                                                                        */
    /* Length of data to be passed to the printer is length+1 for             */
    /* high density                                                           */
    /*  INKJET : Include the 360 x 360 of the IBM4070 and IBM4072             */
    /**************************************************************************/
    if (( pDDT->DDTRasterMode->VertLinePels == 24 ) ||
        ( pDDT->DDTRasterMode->VertLinePels == 48 ))
    {
        RasterLength++;

        if ( (Result = prdp_PrintSimple( DCIData,
                                         USE_PRINTER_TABLE,
                                         PDBInst->RasterMode,
                                         (PBYTE)&RasterLength )) != OK )
        {
            return( Result );
        }

        RasterLength--;
    }
    else if ( (Result = prdp_PrintSimple(
                              DCIData,
                              USE_PRINTER_TABLE,
                              PDBInst->RasterMode,
                              (PBYTE)&RasterLength )) != OK )
    {
        OutputString("PrintSimple in pRaster failed\n");
        return( Result );
    }

    /******************************************************************/
    /* If this is an Indirect RAW DC then ouput string to spool       */
    /* file rather than to printer.                                   */
    /******************************************************************/
    if ( DCIData->Flags & QUEUED_RAW )
    {
        Result = SplQmWrite ((HSPL)DCIData->DCISplHandle,
                             (ULONG) RasterLength,
                             (PBYTE) RasterPtr);

        if ( Result != OK )
        {
            OutputString("Spool write in pRaster failed\n");
            return (ERROR_NEG);
        }

        return (OK);
    }

    /******************************************************************/
    /* Now output the raster to the printer.  If Write produced an    */
    /* error, then handle it                                          */
    /******************************************************************/
    OutputString("before PrtWrite\n");

    Result = prdn_PrtWrite( DCIData,
                            RasterPtr,
                            RasterLength,
                            PDBInst,
                            BytesWritten );

    OutputString("after PrtWrite\n");

    if ( Result != OK )
    {
        /******************************************************/
        /* ERROR, ERR_ABORT or ERR_PURGE                      */
        /******************************************************/
        return( Result );
    }

    return(OK);
}
#undef TFUNC




/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdp_PrintRasterColor                                  */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpDCI           DCIData;      Guess what.                        */
/*   lpColOutputType ColOutputPtr; Pointer to structure with output   */
/*                                 blocks in                          */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*   Send colour output blocks to printer.                            */
/**********************************************************************/

/*CON3201
USHORT pascal prdp_PrintRasterColor ( DCIData,
                                    ColOutputPtr
                                  )

lpDCI           DCIData;
lpColOutputType ColOutputPtr;
                             */
SHORT prdp_PrintRasterColor (lpDCI           DCIData,
                             lpColOutputType ColOutputPtr)

{
#define TFUNC "prdp_PrintRasterColour"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    SHORT       Result;                /* CON3203 CHANGED USHORT TO SHORT */
    lpPDBI      PDBInst;               /* pointer to PDB instance     */
    USHORT      BytesWritten;          /* number of bytes prtwritten  */
    lpDDTType   pDDT;                  /* Pointer to DDT in PDB       */
    BYTE        Color;                 /* Current bitmap colour       */
    BYTE        HardwareColor;         /* Current hardware colour     */

    TRACE4(TFUNC, "Entry", FNULL, 0);
    TRACE4(TFUNC, "ColOutputPtr", &ColOutputPtr, 1);

    PDBInst = DCIData->DCIPdbInstance;
    pDDT = &PDBInst->DDT;

    /******************************************************************/
    /* Repeat for each color, except white.                           */
    /******************************************************************/
    for ( Color = 0; Color < 8; Color++ )
    {
        if ( Color == PRD_8_PRINTER_WHITE )
        {
            /**********************************************************/
            /* Skip as we don't want to make the printer print in     */
            /* white.                                                 */
            /**********************************************************/
            continue;
        }

       if ( ColOutputPtr->OutputLength[Color] )
       {
          /************************************************************/
          /* Output a Carriage Return before doing the Raster.        */
          /************************************************************/
          if ( (Result = prdp_PrintSimple( DCIData,
                                           USE_GLOBAL_TABLE,
                                           EST_CARRIAGE_RETURN,
                                           FNULL )) != OK )
          {
              return (Result);
          }

          /************************************************************/
          /* Get the hardware color from the bitmap color             */
          /************************************************************/
          HardwareColor = (BYTE) Color;

          /************************************************************/
          /* Output the Set Foreground Color code                     */
          /************************************************************/
          if ( (Result = prdp_PrintSimple( DCIData,
                                        USE_GLOBAL_TABLE,
                                        EST_SET_FORE_COLOR,
                                        (PBYTE)&HardwareColor )) != OK )
          {
              return (Result);
          }


          /************************************************************/
          /* Output the leading Raster Mode control sequence to the   */
          /* printer using asynchronous i/o.                          */
          /* The code takes advantage of the fact that the number of  */
          /* bytes is supplied as two parameters, with the low        */
          /* byte first.                                              */
          /************************************************************/

          /************************************************************/
          /* length of data to be passed to the printer is length+1   */
          /* for high density                                         */
          /************************************************************/
          if ( (Result = prdp_PrintSimple(
                  DCIData,
                  USE_PRINTER_TABLE,
                  PDBInst->RasterMode,
                  (PBYTE)&(ColOutputPtr->OutputLength[Color]) )) != OK )
          {
              return (Result);
          }

          /************************************************************/
          /* If this is an Indirect RAW DC then ouput string to spool */
          /* file rather than to printer.                             */
          /************************************************************/
          if ((DCIData->DCIDCType == OD_QUEUED) &&
              (DCIData->DCIPdbInstance->PDBOutputType == IBMQRAW))
          {
              Result = SplQmWrite (
                              (HSPL)DCIData->DCISplHandle,
                              (ULONG) ColOutputPtr->OutputLength[Color],
                              (PBYTE) ColOutputPtr->Output[Color]);

              TRACE4(TFUNC, "SplQmWrite Result", &Result, 1);
              if (Result != OK)
              {
                  TRACE4(TFUNC, "Spool write failed",&Result,1);
                  return (ERROR_NEG);
              }
              continue;
          }

          /************************************************************/
          /* Now output the raster to the printer.                    */
          /* If Write produced an error, then handle it               */
          /************************************************************/
          Result = prdn_PrtWrite( DCIData,
                                  ColOutputPtr->Output[Color],
                                  ColOutputPtr->OutputLength[Color],
                                  PDBInst,
                                  BytesWritten );

          if ( Result != OK )
          {
              /********************************************************/
              /* ERROR, ERR_ABORT or ERR_PURGE                        */
              /********************************************************/
              return( Result );
          }
       }
    }         /* next colour */

    return(OK);
}

#undef TFUNC

