/*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 = PRDPTEXT
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prdp_PrintText
 *             prdp_PrintSetUpFont
 *             prdp_PrintSelectFont
 *             prdp_PrintSelectAttributes
 *             prdp_StrikeOutToBand
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/
#define INCL_32                        /* CON3201 */
#define INCL_DOSPROCESS                /* CON3201 */
#define INCL_DOSSEMAPHORES
#define INCL_DEV
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#define INCL_SPL
#include <os2.h>
#undef INCL_DOSPROCESS                 /* CON3201 */
#undef INCL_DOSSEMAPHORES
#undef INCL_DEV
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS
#undef INCL_SPL

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

#define INCL_WINP_SELECTIVE
#define INCL_WINP_SEI
#include <pmwinx.h>
#undef INCL_WINP_SELECTIVE
#undef INCL_WINP_SEI
#undef INCL_32                      /* CON3201 */

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

#define COCON_INCL
#define PRCON_INCL
#define FOCON_INCL
#define PRDMTYPE_INCL
#define PRDFTYPE_INCL
#define NO_CONSTANT_INCL
#include <prdinclt.h>
#undef NO_CONSTANT_INCL
#undef PRDMTYPE_INCL
#undef PRDFTYPE_INCL
#undef FOCON_INCL
#undef PRCON_INCL
#undef COCON_INCL

#include <prdeextf.h>
#include <prdfextf.h>
#include <prdpextf.h>
#include <prdtextf.h>
#include <prdyextf.h>
#include <prduextf.h>

/******************************************************************************/
/*  A few externals...                                                        */
/******************************************************************************/
extern lpDVTCPSource  DVTCodePageCaps[];
extern DVTCPListType  DVTCodePageList[];
extern USHORT         DRIVER_TYPE;

/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdp_PrintText                                         */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpDCI           DCIData;      Pointer to DC Instance data        */
/*   lpGTBEntry far *TextEntryPtr; Pointer to a pointer to the first  */
/*                                 graphics text band entry to try    */
/*   PBYTE           MemoryPtr;    Pointer to buffer to use for       */
/*                                 output                             */
/*   PUSHORT         pMemoryIndex; ptr to index into buffer           */
/*   USHORT          MemorySize;   Size of buffer available           */
/*   USHORT          ScanLowY;     The position of the bottom scan    */
/*                                 line of this pass                  */
/*   PUSHORT         pHeadPos;     Pointer to current printer head    */
/*                                 position                           */
/*   PUSHORT         pHeadErr;     Pointer to error in current        */
/*                                 printer head position              */
/*                                                                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function outputs all the entries in the text band with      */
/*   origins (bottom left coordinates) inside the group of scan lines */
/*   specified by ScanLowY and GroupCount.  The function uses         */
/*   prdp_AddString to produce a string of characters and control     */
/*   sequences which will produce the required text when output to    */
/*   printer.                                                         */
/*                                                                    */
/**********************************************************************/
/*CON3201
USHORT pascal prdp_PrintText   ( DCIData,
                               TextEntryPtr,
                               MemoryPtr,
                               pMemoryIndex,
                               MemorySize,
                               ScanLowY,
                               pHeadPos,
                               pHeadErr )

lpDCI           DCIData;
lpGTBEntry far *TextEntryPtr;
PBYTE           MemoryPtr;
PUSHORT         pMemoryIndex;
USHORT          MemorySize;
USHORT          ScanLowY;
PUSHORT         pHeadPos;
PUSHORT         pHeadErr;
                         */

USHORT prdp_PrintText   (lpDCI           DCIData,
                         lpGTBEntry     *TextEntryPtr,
                         PBYTE           MemoryPtr,
                         PUSHORT         pMemoryIndex,
                         USHORT          MemorySize,
                         USHORT          ScanLowY,
                         PUSHORT         pHeadPos,
                         PUSHORT         pHeadErr)

{
#define TFUNC "prdp_PrintText"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    BOOL        FirstTime;     /* Flag to indicate whether this is the*/
                               /* first text entry in this scanline   */
                               /* group                               */
    POINTS      CurrPos;       /* Current pos - x in font coords; y   */
                               /* in device coords (the coords in the */
                               /* GTB structure are held likewise)    */
    SHORT       ReqdPosX;      /* Required x coord - in font coords   */
    lpPDBI      PDBInst;       /* Pointer to the PDB Instance data    */
    lpDDTType   pDDT;          /* Pointer to the DDT in the PDB       */
    USHORT      LoopCount;     /* Number of times round main print    */
                               /* loop - 1 if no char positions       */
    USHORT      NoOfChars;     /* Number of chars for this time       */
                               /* round main loop 1 if char positions */
    USHORT      i;             /* Loop variable                       */
    USHORT      Depth;
    USHORT      Width;         /* PD00073                             */
    USHORT      XOffset;
    USHORT      YOffset;
    USHORT      Result;
    BYTE        DCTParms[4];
    BYTE        EngAttrs;

    BOOL                SkipFontCodes;
    BOOL                TurnOffUnderscore;
    lpGTBEntry          NextEntry;
    USHORT              CodePageNo;      /* Variables used to set up  */
    lpPrtDataEntry      PrinterData;     /* Pointer to Printer Data   */
    lpDVTCPSource       CodePageCaps;    /* Code Page capabilities    */
    BYTE                HardwareColor;   /* Used to set foreground    */
                                         /* colour on 4224            */
    lpFontSettingsType  pFontSettings;   /* "Description" of font     */
                                         /* selected on printer -     */
                                         /* used to avoid unnecessary */
                                         /* escape sequences          */
    USHORT      PrevAngle;               /* PD00532                   */

    /******************************************************************/
    /* Set up local pointers.                                         */
    /******************************************************************/
    PDBInst = DCIData->DCIPdbInstance;
    pDDT    = &PDBInst->DDT;

    pFontSettings = &PDBInst->FontSettings;
    PrinterData   = PDBInst->PrinterData;
    CodePageCaps  = DVTCodePageCaps[PrinterData->PrinterType];

    /******************************************************************/
    /* Depth used for calculation of coords for Set Cursor Position   */
    /* command sequence.  Xform value from pels to font coords since  */
    /* this is the coord system used by the SCP command.              */
    /******************************************************************/
    if ( pDDT->DDTHorizMoveType & DDT_MOVE_ABS_SCP )
    {
        if ( PDBInst->Orientation == PORTRAIT )
        {
            Depth = PDBInst->PageDepthPels;
            Width = PDBInst->PageWidthPels;        /*  PD00073         */
        }
        else
        {
            Depth = PDBInst->PageWidthPels;
            Width = PDBInst->PageDepthPels;        /*  PD00073         */
        }

        Depth = prdt_XformFontValue( Depth,
                                     DEVICE_TO_FONT | CONV_Y_VALUE,
                                     &DCIData->DCIFontData );

        Width = prdt_XformFontValue( Width,
                                     DEVICE_TO_FONT | CONV_X_VALUE,
                                     &DCIData->DCIFontData );
    }

    /******************************************************************/
    /* Initialise the FirstTime flag to TRUE.                         */
    /******************************************************************/
    FirstTime = TRUE;

    /******************************************************************/
    /* Initialise the PrevAngle - the char angle to be sent to printer*/
    /* PD00532                                                        */
    /******************************************************************/
    PrevAngle = 361;

    /******************************************************************/
    /* SkipFontCodes is used to avoid escape codes which set and      */
    /* reset the font in the middle of text entries which where drawn */
    /* with position vectors.                                         */
    /******************************************************************/
    SkipFontCodes = FALSE;

    /******************************************************************/
    /* Step through the entries in the text band until the end of the */
    /* text band or we find an entry which does not fit in this       */
    /* scanline group (ie it is below it).                            */
    /******************************************************************/
    while ( *TextEntryPtr )
    {
        TRACE4(TFUNC, "Text pos.", &(*TextEntryPtr)->GTBTxtPos, 1);

        /**************************************************************/
        /* See if this text entry is in this scanline group.  If it   */
        /* is not then break to the end of the function and return    */
        /* (after outputting any data still in the buffer).  ScanLowY */
        /* is set to 0 for a laser printer so the following is always */
        /* true for a laser printer.                                  */
        /**************************************************************/
        if ( (*TextEntryPtr)->GTBTxtPos.y < ScanLowY )
        {
            TRACE4(TFUNC, "Text not in Group", FNULL, 0);
            break;
        }

        /**************************************************************/
        /* Check if the print head needs to be moved in order         */
        /* to get to the required y position from current y.          */
        /*                                                            */
        /* Since CurrPos.y is not adjusted and the entries in the     */
        /* text chain are ordered with descending Y coordinates       */
        /* this branch is always entered except for text drawn at the */
        /* top pel of this scanline group.                            */
        /*                                                            */
        /* The 4019 printers have the Set Cursor Position command     */
        /* sequence so we dont have to shift the printer head down    */
        /* bit by bit.                                                */
        /**************************************************************/
        if ( (!(pDDT->DDTHorizMoveType & DDT_MOVE_ABS_SCP)) &&
             (*pHeadPos > (*TextEntryPtr)->GTBTxtPos.y) )
        {
            /**********************************************************/
            /* Move the print head to the required position.          */
            /* prdp_PrintMoveDown allows for previous errors and      */
            /* the vertical step size when doing this.                */
            /**********************************************************/
            if ( (Result = prdp_PrintMoveDown (
                                      pHeadPos,
                                      pHeadErr,
                                      (*TextEntryPtr)->GTBTxtPos.y,
                                      MemoryPtr,
                                      pMemoryIndex,
                                      MemorySize,
                                      DCIData )) != OK )
                return (Result);
        }

        /**************************************************************/
        /* PD00560: Quick and dirty fix for now.                      */
        /**************************************************************/
        if ( ((*TextEntryPtr)->GTBInfo.Type == FT_ENGINE) )
        {
             SkipFontCodes = FALSE;
        }

        /**************************************************************/
        /* Check if first text in loop                                */
        /**************************************************************/
        if ( FirstTime == TRUE )
        {
            /**********************************************************/
            /* Output a Carriage Return before doing the Text to      */
            /* ensure the printer head position corresponds to        */
            /* CurrPos.x (0 for FirstTime == TRUE).                   */
            /*                                                        */
            /* The 4019 printers have the Set Cursor Position command */
            /* sequence so we dont have to jam the printer head       */
            /* against the left edge.                                 */
            /**********************************************************/
            if ( !(pDDT->DDTHorizMoveType & DDT_MOVE_ABS_SCP) )
            {
                if ( (Result = prdp_AddString(
                                      EST_CARRIAGE_RETURN,
                                      USE_GLOBAL_TABLE,
                                      FNULL,
                                      MemoryPtr,
                                      pMemoryIndex,
                                      MemorySize,
                                      DCIData )) != OK )
                {
                    return (Result);
                }
                /***************************************************************/
                /*  PD00547 : Clear out the accumulating errors.               */
                /***************************************************************/
                DCIData->Remainder = 0;

                /******************************************************/
                /* Allow for form offset (held in device coords)      */
                /* after the carriage return - CurrPos.x is held in   */
                /* font coords.                                       */
                /******************************************************/
                CurrPos.x =
                    - prdt_XformFontValue( PDBInst->FormXOffset,
                                           DEVICE_TO_FONT | CONV_X_VALUE,
                                           &DCIData->DCIFontData );
            }

            /**********************************************************/
            /* Reset the font settings value for colour (for the      */
            /* 4224); this must be done at the start of each call to  */
            /* prdp_PrintText since the colour could be altered when  */
            /* printing the raster data.                              */
            /**********************************************************/
            pFontSettings->LastColour = (USHORT)VALUE_NOT_SET;

            FirstTime = FALSE;
        }

        /**************************************************************/
        /* If colour printer then set foreground colour before        */
        /* printing text.                                             */
        /**************************************************************/
        TRACE4(TFUNC, "Fore Color", &(*TextEntryPtr)->GTBFgClr, 1);

        if ( pDDT->DDTMaxColors == DDT_EIGHT_COLORS )
        {
            /**********************************************************/
            /* If color printer: don't print out white text.          */
            /**********************************************************/
            if ( (*TextEntryPtr)->GTBFgClr == PRD_8_PRINTER_WHITE )
            {
                TRACE4(TFUNC, "White color text", FNULL, 0);
                *TextEntryPtr = (*TextEntryPtr)->GTBNextEntry;
                continue;
            }
            else
            {
                HardwareColor = (BYTE) (*TextEntryPtr)->GTBFgClr;

                /******************************************************/
                /* Check for repeated colour value. N.B. spelling     */
                /******************************************************/
                if (pFontSettings->LastColour != (USHORT)HardwareColor)
                {
                    pFontSettings->LastColour = (USHORT)HardwareColor;

                    if ( (Result = prdp_AddString(
                                         EST_SET_FORE_COLOR,
                                         USE_GLOBAL_TABLE,
                                         (PBYTE)&HardwareColor,
                                         MemoryPtr,
                                         pMemoryIndex,
                                         MemorySize,
                                         DCIData )) != OK)
                    {
                        return (Result);
                    }
                }
            }
        }

#ifdef OMIT_OLD_CODE
        else
        {
            /**********************************************************/
            /* Commented Out  (SMP 10/12/90)  Text bundle colors are  */
            /* ignored for device text for monochrome printers.       */
            /*                                                        */
            /* Only output text if foreground colour (black);         */
            /* if text foreground color is not black get next entry.  */
            /**********************************************************/
            if ( (*TextEntryPtr)->GTBFgClr != PRD_FOREGROUND )
            {
                TRACE4(TFUNC, "White Text", FNULL, 0);
                *TextEntryPtr = (*TextEntryPtr)->GTBNextEntry;
                continue;
            }
        }
#endif

        /**************************************************************/
        /* If this is a code page font we may need to download        */
        /* the code page.  The driver keeps track of the code page    */
        /* - with CPJob in PDBInstance for a Queued Raw job           */
        /* - with CPCurrent in PrinterData for a Direct job.          */
        /* These are updated within prde_DownloadCodePage.            */
        /**************************************************************/
        CodePageNo = (*TextEntryPtr)->GTBInfo.CodePageNo;

        TRACE4(TFUNC, "Download CP no.", &CodePageNo, 1);
        TRACE4(TFUNC, "CPCurrent.", &(PrinterData->CPCurrent), 1);
        TRACE4(TFUNC, "CPJob", &(PDBInst->CPJob), 1);

        if ( (*TextEntryPtr)->GTBInfo.Type == FT_CODE_PAGE )
        {
            if ( ((DCIData->DCIDCType == OD_QUEUED) &&
                  (PDBInst->PDBOutputType == IBMQRAW) &&
                  (CodePageNo != PDBInst->CPJob))        ||
                 ((DCIData->DCIDCType == OD_DIRECT) &&
                  (CodePageNo != PrinterData->CPCurrent)) )
            {
                /******************************************************/
                /* DIAL/NILE : prde_DownloadCodePage does not add the */
                /* output to the buffer so we must first ensure the   */
                /* buffer is cleared.                                 */
                /******************************************************/
                if ( *pMemoryIndex != 0 )
                {
                    if ( (Result = prdp_PrintMemory( MemoryPtr,
                                                     *pMemoryIndex,
                                                     DCIData )) != OK )
                        return ( Result );

                    *pMemoryIndex = 0;
                }

                if ( (Result = prde_DownloadCodePage( CodePageNo,
                                                       DCIData) ) != OK )
                    return ( Result );
            }

        } /* .. if ( (*TextEntryPtr)->GTBInfo.Type == FT_CODE_PAGE ).. */

        /**************************************************************/
        /* The method used to output the string depends on whether    */
        /* the driver needs to individually position each character.  */
        /* If it does we go through the loop n times and print a      */
        /* single character each time; if not we go through the loop  */
        /* once and print n characters.                               */
        /**************************************************************/

        if ( (*TextEntryPtr)->GTBCharStartPos )
        {
            TRACE4(TFUNC, "Char positions", FNULL, 0);

            LoopCount = (*TextEntryPtr)->GTBNumCdPts;
            NoOfChars = 1;
        }
        else
        {
           TRACE4(TFUNC, "No char positions", FNULL, 0);

            LoopCount = 1;
            NoOfChars = (*TextEntryPtr)->GTBNumCdPts;
        }


        TRACE4(TFUNC, "Loop count", &LoopCount, 1);
        TRACE4(TFUNC, "No of chars", &NoOfChars, 1);

        /**************************************************************/
        /* Start looping...                                           */
        /**************************************************************/
        for ( i = 0; i < LoopCount; i++ )
        {
            /**********************************************************/
            /* Position the printer head as accurately as possible    */
            /* for this text entry.  We are already at the correct y  */
            /* position so now we must move to the correct x          */
            /* position.  ReqdPosX is held in font coords.            */
            /**********************************************************/
            /**********************************************************/
            /* PD00076: GTBCharStartPos is PLONG                      */
            /**********************************************************/
            if ( (*TextEntryPtr)->GTBCharStartPos )
                ReqdPosX = (SHORT)( (*TextEntryPtr)->GTBCharStartPos[i] );
            else
                ReqdPosX = (*TextEntryPtr)->GTBTxtPos.x;

            /**********************************************************/
            /* Note: if SkipFontCodes is TRUE and the current font    */
            /* is underscored and if horizontal movement is by        */
            /* DDT_FINE_MOVEMENT or by DDT_FINE_MOVEMENT_RIGHT,       */
            /* then whenever we move by fine movement, we will        */
            /* underscore the space moved over.  To stop this, we     */
            /* deselect the attribute before doing horizontal         */
            /* movement and reselect it afterwards.                   */
            /**********************************************************/
            if ( !((*TextEntryPtr)->GTBInfo.Type == FT_ENGINE) )
            {
              EngAttrs = prdm_GetLCIDEngineAttrs( (*TextEntryPtr)->GTBInfo.LCID );

              TurnOffUnderscore = ( (SkipFontCodes) &&
                                  (CurrPos.x != ReqdPosX) &&
                                  (EngAttrs & FATTR_SEL_UNDERSCORE) );


              if ( TurnOffUnderscore )
              {
                /******************************************************/
                /* Note - all printers use the same underscore off    */
                /* command. If this changes, move to DCT table.       */
                /******************************************************/
                if ( (Result = prdp_AddString(
                           EST_UNDERSCORE_OFF,
                           USE_GLOBAL_TABLE,
                           FNULL,
                           MemoryPtr,
                           pMemoryIndex,
                           MemorySize,
                           DCIData )) != OK )
                {
                    return (Result);
                }
              }
            }

            if ( pDDT->DDTInitFlags & DDT_PRINT_ANGLE_SUPPORT )
            {
              /**********************************************************/
              /* PD00073       : Add Print Angle to string              */
              /**********************************************************/
              /**********************************************************/
              /* PD00532       : Send Print angle only if different     */
              /**********************************************************/
              if ( (*TextEntryPtr)->GTBAngle != PrevAngle )
              {
                 /**********************************************************/
                 /* Note the order of the bytes is hi lo                   */
                 /**********************************************************/
                 DCTParms[0] = (BYTE)((*TextEntryPtr)->GTBAngle / 256);
                 DCTParms[1] = (BYTE)((*TextEntryPtr)->GTBAngle % 256);

                 if ( (Result = prdp_AddString(
                                               EST_SELECT_PRINT_ANGLE,
                                               USE_GLOBAL_TABLE,
                                               (PBYTE)DCTParms,
                                               MemoryPtr,
                                               pMemoryIndex,
                                               MemorySize,
                                               DCIData )) != OK )
                 {
                     return (Result);
                 }
                 PrevAngle = (*TextEntryPtr)->GTBAngle;
              }
            }

            if ( pDDT->DDTHorizMoveType & DDT_MOVE_ABS_SCP )
            {
                /******************************************************/
                /* Absolute movement (as used on 4019s) - all the     */
                /* values used here are in font coords - y coord does */
                /* not change.                                        */
                /******************************************************/
                /******************************************************/
                /* PD00073 Add switch stmt to support four angles     */
                /* supported by Heritage 4029 laser printer.          */
                /******************************************************/
                switch ((*TextEntryPtr)->GTBAngle)
                {
                   case 0:                    /*   0 degree   */
                     XOffset = ReqdPosX;
                     YOffset = Depth - (*TextEntryPtr)->GTBTxtPos.y;
                     break;
                                              /*   90 degrees */
                   case 0x1680:
                     XOffset = (*TextEntryPtr)->GTBTxtPos.y;
                     YOffset = ReqdPosX;
                     break;
                                              /*  180 degrees */
                   case 0x2D00:
                     XOffset = Width - ReqdPosX;
                     YOffset = (*TextEntryPtr)->GTBTxtPos.y;
                     break;
                                              /*  270 degrees */
                   case 0x4380:
                     XOffset = Depth - (*TextEntryPtr)->GTBTxtPos.y;
                     YOffset = Width - ReqdPosX;
                     break;
                }

                XOffset += PDBInst->FormXOffset;
                YOffset += PDBInst->FormYOffset;

                DCTParms[0] = (BYTE)(XOffset / 256);
                DCTParms[1] = (BYTE)(XOffset % 256);
                DCTParms[2] = (BYTE)(YOffset / 256);
                DCTParms[3] = (BYTE)(YOffset % 256);

                if ( (Result = prdp_AddString(
                                            EST_MOVE_SCP,
                                            USE_GLOBAL_TABLE,
                                            (PBYTE)DCTParms,
                                            MemoryPtr,
                                            pMemoryIndex,
                                            MemorySize,
                                            DCIData )) != OK )
                {
                    return (Result);
                }
              }
              else
              {
                /******************************************************/
                /* Function returns immediately if the printer head   */
                /* already at the correct x position.                 */
                /******************************************************/
                if ( (Result = prdp_AddHorizMoveString(
                                            ReqdPosX,
                                            CurrPos.x,
                                            MemoryPtr,
                                            pMemoryIndex,
                                            MemorySize,
                                            DCIData )) != OK )
                {
                    return (Result);
                }
              }

              if ( !((*TextEntryPtr)->GTBInfo.Type == FT_ENGINE) )
              {
                if ( TurnOffUnderscore )
                {
                  /******************************************************/
                  /* Note - all printers use the same underscore on     */
                  /* command. If this changes, move to DCT table.       */
                  /******************************************************/
                  if ( (Result = prdp_AddString(
                                                 EST_UNDERSCORE_ON,
                                                 USE_GLOBAL_TABLE,
                                                 FNULL,
                                                 MemoryPtr,
                                                 pMemoryIndex,
                                                 MemorySize,
                                                 DCIData )) != OK )
                  {
                    return (Result);
                  }
                }
              }

            /**********************************************************/
            /* Update current position to allow for printer head      */
            /* movement - this will be reset later if we print        */
            /* the string successfully.                               */
            /**********************************************************/
            CurrPos.x = ReqdPosX;

            /******************************************************************/
            /* PD00769 : Added code to support using a text chain as a string */
            /* of printer control codes to support using printer patterns via */
            /* the rule and fill printer command.                             */
            /******************************************************************/
            if ( (*TextEntryPtr)->GTBInfo.Type == FT_PRINTER_CODES )
            {
                if ( (Result = prdp_AddString(
                                      NoOfChars,
                                      USE_NOTABLE,
                                      (*TextEntryPtr)->GTBCdPts + i,
                                      MemoryPtr,
                                      pMemoryIndex,
                                      MemorySize,
                                      DCIData )) != OK )
                {
                    return (Result);
                }
                /**************************************************************/
                /* Exit loop since this entry contains only control codes for */
                /* the printer and no text.                                   */
                /**************************************************************/
                break;
            }

            /**********************************************************/
            /* Select the font stage 1 - i.e. SFG or Esc I n.         */
            /**********************************************************/
            if ( (Result = prdp_SetUpFont (
                                  (*TextEntryPtr),
                                  MemoryPtr,
                                  pMemoryIndex,
                                  MemorySize,
                                  DCIData )) != OK )
                return (Result);


            if ( !((*TextEntryPtr)->GTBInfo.Type == FT_ENGINE) )
            {
              if ( !SkipFontCodes )
              {
                /******************************************************/
                /* Select the font (condensed etc)                    */
                /******************************************************/
                if ( (Result = prdp_SelectFont( DCIData,
                                                TextEntryPtr,
                                                PRE_DCT,
                                                MemoryPtr,
                                                pMemoryIndex,
                                                MemorySize )) != OK )
                {
                    return( Result );
                }

                /******************************************************/
                /* Setup the device and engine attributes             */
                /******************************************************/
                if ( (Result = prdp_SelectAttributes( DCIData,
                                                TextEntryPtr,
                                                PRE_DCT,
                                                MemoryPtr,
                                                pMemoryIndex,
                                                MemorySize )) != OK )
                {
                    return( Result );
                }
              }
            /* .... if ( !SkipFontCodes ) ........................... */
            }

            /**********************************************************/
            /* Select print all character mode for the following      */
            /* code points.                                           */
            /**********************************************************/
            if ( (Result = prdp_AddString(
                                  EST_PRINT_TEXT,
                                  USE_GLOBAL_TABLE,
                                  (PBYTE)&NoOfChars,
                                  MemoryPtr,
                                  pMemoryIndex,
                                  MemorySize,
                                  DCIData )) != OK )
            {
                return (Result);
            }

            /**********************************************************/
            /* Add the codepoints to the memory array as a simple     */
            /* string.                                                */
            /**********************************************************/
            TRACE4(TFUNC, "Add codepoints",
                                  ((*TextEntryPtr)->GTBCdPts + i), 2);

            if ( (Result = prdp_AddString(
                                  NoOfChars,
                                  USE_NOTABLE,
                                  (*TextEntryPtr)->GTBCdPts + i,
                                  MemoryPtr,
                                  pMemoryIndex,
                                  MemorySize,
                                  DCIData )) != OK )
            {
                return (Result);
            }

            /**********************************************************/
            /* Update CurrPos since we've now printed the text.       */
            /**********************************************************/
            if ( (*TextEntryPtr)->GTBCharStartPos )
                CurrPos.x = (*TextEntryPtr)->GTBCharEndPos[i];
            else
                CurrPos.x = (*TextEntryPtr)->GTBTxtEnd.x;

            TRACE4(TFUNC, "CurrPos after text", &CurrPos, 1);

            if ( !((*TextEntryPtr)->GTBInfo.Type == FT_ENGINE) )
            {
              /**********************************************************/
              /* If we are in the middle of a position vector text      */
              /* chain entry and we do not need spaces to position the  */
              /* next character then we skip the deselection of the     */
              /* font (stage 2) and the attribute.                      */
              /*                                                        */
              /* This is for a performance enhancement and avoids the   */
              /* printer head juddering when drawing position vectored  */
              /* text which is spaced as it would be if drawn as raw    */
              /* data.                                                  */
              /*                                                        */
              /* If spaces are used to position the next character we   */
              /* must return the printer to a 10 cpi font as this is    */
              /* assumed in prdp_AddHorizMoveString.                    */
              /*                                                        */
              /* The deselection font codes are skipped :               */
              /*   IF text drawn with position vectors AND              */
              /*      the string is at least two characters long AND    */
              /*      this isnt the last character AND                  */
              /*      we dont need any (10 cpi) spaces to position the  */
              /*        printer head for the next character             */
              /*                                                        */
              /**********************************************************/
              /* We add another case in which we might skip font code   */
              /* selection/deselection (the 'else if' bit below):       */
              /*                                                        */
              /*   IF there is a next entry AND                         */
              /*      we've drawn all of this TextEntry AND             */
              /*      the next entry is at the same Y position AND      */
              /*      the next entry uses the same font and atts AND    */
              /*      we dont need any (10 cpi) spaces to position the  */
              /*        printer head for the start of the next entry    */
              /*                                                        */
              /**********************************************************/
              /*  PD00537 : Add a parameter to prdp_NeedSpacesForMove   */
              /**********************************************************/
              /**********************************************************/
              /* PD00076: GTBCharStartPos is PLONG                      */
              /**********************************************************/
              if ( ((*TextEntryPtr)->GTBCharStartPos) &&
                 (LoopCount > 1) &&
                 (i < LoopCount - 1) &&
                 ( !prdp_NeedSpacesForMove(
                               (SHORT)((*TextEntryPtr)->GTBCharStartPos[i+1]),
                               CurrPos.x,
                               TextEntryPtr,
                               DCIData) ) )
              {
                SkipFontCodes = TRUE;
              }
              else if ( ( NextEntry = (*TextEntryPtr)->GTBNextEntry ) &&
                      ( i == LoopCount - 1 ) &&
                      ( ((*TextEntryPtr)->GTBTxtPos.y) ==
                                            (NextEntry->GTBTxtPos.y) ) )
              {
                /******************************************************/
                /* To work out whether spaces are needed, we need the */
                /* X position at the end of the current TextEntry     */
                /* (CurrPos.x gives us this) and we need the X        */
                /* position at the start of the next entry - we call  */
                /* this ReqdPosX.                                     */
                /*      To check that the fonts are the same we       */
                /* check the match number.                            */
                /******************************************************/
                /******************************************************/
                /* PD00076: GTBCharStartPos is PLONG                  */
                /******************************************************/
                if ( NextEntry->GTBCharStartPos )
                    ReqdPosX = (SHORT)NextEntry->GTBCharStartPos[0];
                else
                    ReqdPosX = NextEntry->GTBTxtPos.x;

                /**********************************************************/
                /*  PD00537 : Add a parameter to prdp_NeedSpacesForMove   */
                /**********************************************************/
                if ( (LCIDTOUL( ((*TextEntryPtr)->GTBInfo.LCID) ) ==
                      LCIDTOUL( NextEntry->GTBInfo.LCID) ) &&
                    (!prdp_NeedSpacesForMove( ReqdPosX,
                                              CurrPos.x,
                                              TextEntryPtr,
                                              DCIData )) )
                    SkipFontCodes = TRUE;
                else
                {
                    SkipFontCodes = FALSE;

                    /**************************************************/
                    /* PD00333 : reset the match number so we will    */
                    /* switch back out of 10 pitch (other printers    */
                    /* use a PreDCTcmd but Nile/Tiber/Dakota can't)   */
                    /**************************************************/
                    if (( pDDT->DDTDriverType == DDT_IBM42XX_DRV ) &&
                        (PrinterData->PrinterType > IBM_4224_MONO))
                        pFontSettings->LastMatchNo = VALUE_NOT_SET;
                }
              }
              else
              {
                /******************************************************/
                /* PD00333 : reset the match number so we will switch */
                /* back out of 10 pitch (other printers use a         */
                /* PreDCTcmd but Nile/Tiber/Dakota can't)             */
                /******************************************************/
                SkipFontCodes = FALSE;
                if (( pDDT->DDTDriverType == DDT_IBM42XX_DRV ) &&
                    (PrinterData->PrinterType > IBM_4224_MONO))
                    pFontSettings->LastMatchNo = VALUE_NOT_SET;
              }

              if ( !SkipFontCodes )
              {
                /******************************************************/
                /* DeSelect the font.                                 */
                /******************************************************/
                if ( (Result = prdp_SelectFont( DCIData,
                                                TextEntryPtr,
                                                POST_DCT,
                                                MemoryPtr,
                                                pMemoryIndex,
                                                MemorySize )) != OK )
                {
                    return( Result );
                }

                /******************************************************/
                /* Deselect the device and engine attributes          */
                /******************************************************/
                if ( (Result = prdp_SelectAttributes( DCIData,
                                                TextEntryPtr,
                                                POST_DCT,
                                                MemoryPtr,
                                                pMemoryIndex,
                                                MemorySize )) != OK )
                {
                    return( Result );
                }

              }
              /* .... if ( !SkipFontCodes ) ........................... */
            } /* .... if ( !FT_ENGINE )................................ */

        }
        /* ...... for ( i = 0; i < LoopCount; i++ ) ................. */

        /**************************************************************/
        /* Move the pointer to text band entries to the next          */
        /* one then loop back to try printing it.                     */
        /**************************************************************/
        TRACE4(TFUNC, "Move to new Entry", FNULL, 0);

        *TextEntryPtr = (*TextEntryPtr)->GTBNextEntry;
    }
    /* ... while ( *TextEntryPtr ) .................................. */

    /**************************************************************************/
    /* PD00073 :                                                              */
    /* On the 4029 laser printer printing a string at a non zero angle causes */
    /* any following bitmap graphics to print at the same angle.              */
    /* Reset the angle to zero with the following call to prdp_AddString to   */
    /* make sure that the bitmap graphics prints at the desired angle.        */
    /**************************************************************************/
    if ( pDDT->DDTInitFlags & DDT_PRINT_ANGLE_SUPPORT )
    {
        DCTParms[0] = 0;
        DCTParms[1] = 0;
        if ( (Result = prdp_AddString(
                                       EST_SELECT_PRINT_ANGLE,
                                       USE_GLOBAL_TABLE,
                                       (PBYTE)DCTParms,
                                       MemoryPtr,
                                       pMemoryIndex,
                                       MemorySize,
                                       DCIData )) != OK )
        {
            return (Result);
        }
    }

    /******************************************************************/
    /* If the buffer is non-empty then output it before returning.    */
    /******************************************************************/
    if ( *pMemoryIndex != 0 )
    {
        if ( (Result = prdp_PrintMemory ( MemoryPtr,
                                          *pMemoryIndex,
                                          DCIData )) != OK )
            return (Result);
    }

    *pMemoryIndex = 0;

    TRACE4(TFUNC, "Exit OK", FNULL, 0);
    return (OK);
}
#undef TFUNC


/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdp_SetUpFont                                         */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpGTBEntry     TextEntryPtr;   Pointer to a pointer to the first */
/*                                  text band entry to try            */
/*   PCHAR          MemoryPtr;      Pointer to buffer to write to     */
/*   PUSHORT        pMemoryIndex;   Number of characters in buffer    */
/*                                  already                           */
/*   USHORT         MemorySize;     Maximum size of buffer            */
/*   lpDCI          DCIData;        Pointer to DC Instance data       */
/*                                                                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function outputs the escape sequences used in the first     */
/*   stage of selecting the font.                                     */
/*                                                                    */
/* Note that we cannot use pFont in the FontInfo to get metrics for   */
/* the font we need since pFont might have become invalid if          */
/* MultiCp fonts are used.                                            */
/*                                                                    */
/* Any metrics fields needed are passed as params of the text chain   */
/* entry.                                                             */
/**********************************************************************/
/* CON3201
USHORT pascal prdp_SetUpFont ( TextEntryPtr,
                               MemoryPtr,
                               pMemoryIndex,
                               MemorySize,
                               DCIData )

lpGTBEntry     TextEntryPtr;
PCHAR          MemoryPtr;
PUSHORT        pMemoryIndex;
USHORT         MemorySize;
lpDCI          DCIData;
                        */

USHORT  prdp_SetUpFont (lpGTBEntry     TextEntryPtr,
                        PCHAR          MemoryPtr,
                        PUSHORT        pMemoryIndex,
                        USHORT         MemorySize,
                        lpDCI          DCIData)

{
#define TFUNC "prdp_SetUpFont"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    lpPDBI              PDBInst;       /* Pointer to the PDB data     */
    lpFontSettingsType  pFontSettings; /* "Description" of font       */
                                       /* selected on printer -       */
                                       /* used to avoid unnecessary   */
                                       /* escape sequences            */
    lpPrtDataEntry      PrinterData;   /* Pointer to Printer Data     */
    lpDDTType           pDDT;          /* Pointer to the DDT PDB      */
    lpDVTCPSource       CodePageCaps;  /* Code Page capabilities      */
    USHORT              FontType;
    USHORT              FontIndex;
    USHORT              CodePageNo;
    USHORT              FontId;        /* n for Esc I n               */
    BYTE                DCTParms[9];
    USHORT              GlobalId;
    USHORT              UserFont;
    USHORT              CodePage;      /* the required code page      */
    USHORT              Result;        /* the required code page      */
    PEDFH               pedfh;

    BYTE        OutlineBuffer[200];
    USHORT      OutlineBufferSize = 200;
    USHORT      OutlineIndex;
    USHORT      NameLength;
    PFOCAMETRICS pMetrics;


    /******************************************************************/
    /* Set up local pointers and bits and bobs.                       */
    /******************************************************************/
    PDBInst       = DCIData->DCIPdbInstance;
    pFontSettings = &PDBInst->FontSettings;
    PrinterData   = PDBInst->PrinterData;
    pDDT          = &PDBInst->DDT;
    CodePageCaps  = DVTCodePageCaps[PrinterData->PrinterType];

    FontType   = TextEntryPtr->GTBInfo.Type;
    FontIndex  = TextEntryPtr->GTBInfo.Index;
    CodePageNo = TextEntryPtr->GTBInfo.CodePageNo;



      /******************************************************************/
      /* The font is selected by a Set Font Global command (on          */
      /* the 3816) or by an Esc I n (with a Set Code Page as well on    */
      /* some printers); pick up this "n" called the font id.           */
      /******************************************************************/
      if ( (FontType == FT_RESIDENT) || (FontType == FT_CODE_PAGE) )
      {
        FontId = PDBInst->FontList[FontIndex]->SelectionId;

        /**************************************************************/
        /* DIAL/NILE : Removed check for CP_RESIDENT.                 */
        /*                                                            */
        /* Adjust the n if this a download code page font.            */
        /* This "gap" of 4 between the code page font ids             */
        /* and the corresponding resident fonts ids is                */
        /* common across all the supported printers.                  */
        /**************************************************************/
        if ( FontType == FT_CODE_PAGE )
        {
            FontId += 4;
        }
      }

      TRACE6(TFUNC, "Select font id", &FontId, 1);

      /******************************************************************/
      /* Select the font and the code page (if relevant).  This is done */
      /* by one of 5 possible paths:                                    */
      /*                                                                */
      /* - SFG for the 3816 printer                                     */
      /* - SCP_4224 for the color & mono 4224                           */
      /* - SCP + Esc I n for printers with the Set Code Page command    */
      /* - ESC I n for any other printers                               */
      /* - Font Selection Command for outline fonts on Heritage         */
      /*                                                                */
      /* For each individual method we check the relevant last settings */
      /* to see if we need to change the font.  These last settings are */
      /* updated at the end of each branch if the font has changed.     */
      /* They are initiated in prdp_PrintBand.                          */
      /******************************************************************/
      /******************************************************************/
      /* If the font we want is an outline font, we use the Font        */
      /* Selection Command. We detect this condition by examining the   */
      /* NVFS and NHFS fields in the text chain entry: if both are      */
      /* non-null then the font is outline.                             */
      /*                                                                */
      /* These fields are set up in EstablishFont if the font is        */
      /* outline and are put onto the text chain in TextOutDevFont.     */
      /******************************************************************/
      /****************************************************************/
      /* PD00155 : Corrected if stmt to check both NVFS and NHFS even */
      /* though this had nothing to do with this PTR.                 */
      /****************************************************************/
      if (TextEntryPtr->GTBNVFS || TextEntryPtr->GTBNHFS)
      {
        /**************************************************************/
        /* Outline font. Use FSC command. Because this command is so  */
        /* long, we chop it into 3 chunks.                            */
        /*                                                            */
        /* Test whether font is same as last time.                    */
        /**************************************************************/
        if ( (pFontSettings->LastMatchNo !=
                               LCIDTOUL(TextEntryPtr->GTBInfo.LCID)) ||
             (pFontSettings->LastHeight != TextEntryPtr->GTBNVFS) ||
             (pFontSettings->LastWidth  != TextEntryPtr->GTBNHFS)
             || (pFontSettings->LastShear  != TextEntryPtr->GTBShear)
             )
        {
            /**********************************************************/
            /* Use the FGID method of selection - and do not include  */
            /* any shear angle, as this de-italisizes Italic fonts.   */
            /**********************************************************/
            /**********************************************************/
            /* PD00155 : Heritage now supports Posture angle with     */
            /* a FGID so use this method even when the shear angle    */
            /* is zero.                                               */
            /**********************************************************/
            /******************************************************/
            /* use FGID selection method                          */
            /******************************************************/

            /**********************************************************/
            /* Different font from last time. Construct FSC commands. */
            /*                                                        */
            /* First codepage and escapement type (1 = fixed pitch,   */
            /* 0 = proportional).                                     */
            /**********************************************************/
            DCTParms[0] = (BYTE)(TextEntryPtr->GTBCodePage / 256);
            DCTParms[1] = (BYTE)(TextEntryPtr->GTBCodePage % 256);
            DCTParms[2] = (BYTE)(BOOL)
                         (TextEntryPtr->GTBFontSizeType == FIXED_PITCH);

            if ( (Result = prdp_AddString(
                                  EST_FSC_FGID_PART_1,
                                  USE_GLOBAL_TABLE,
                                  (PBYTE)DCTParms,
                                  MemoryPtr,
                                  pMemoryIndex,
                                  MemorySize,
                                  DCIData )) != OK )
            {
                return (Result);
            }

            /**********************************************************/
            /* Then font global Id and vertical size (a string of 7   */
            /* chars).                                                */
            /*                                                        */
            /* Get the vertical size string from GTBNVFS.             */
            /**********************************************************/
            DCTParms[0] = (BYTE)(TextEntryPtr->GTBRegistryId / 256);
            DCTParms[1] = (BYTE)(TextEntryPtr->GTBRegistryId % 256);

            prdp_OutlineFontSizeString( (PBYTE) &DCTParms[2],
                                        TextEntryPtr->GTBNVFS );

            if ( (Result = prdp_AddString(
                                  EST_FSC_FGID_PART_2,
                                  USE_GLOBAL_TABLE,
                                  (PBYTE)DCTParms,
                                  MemoryPtr,
                                  pMemoryIndex,
                                  MemorySize,
                                  DCIData )) != OK )
            {
                return (Result);
            }

            /**********************************************************/
            /* Finally NHFS (a string of 7 chars).                    */
            /*                                                        */
            /* Get the size string from GTBNHFS.                      */
            /**********************************************************/
            prdp_OutlineFontSizeString( (PBYTE) &DCTParms[0],
                                        TextEntryPtr->GTBNHFS );
            /**********************************************************/
            /* PD00155 : Add Shear (posture angle) to string          */
            /**********************************************************/
            /**********************************************************/
            /* And also the shear. Note the order of the bytes is     */
            /* hi lo.                                                 */
            /* Note that italic+shear = shear - so a small shear will */
            /* actually decrease the apparent slope.                  */
            /**********************************************************/
            DCTParms[7] = (BYTE)(TextEntryPtr->GTBShear / 256);
            DCTParms[8] = (BYTE)(TextEntryPtr->GTBShear % 256);

            if ( (Result = prdp_AddString(
                                  EST_FSC_FGID_PART_3,
                                  USE_GLOBAL_TABLE,
                                  (PBYTE)DCTParms,
                                  MemoryPtr,
                                  pMemoryIndex,
                                  MemorySize,
                                  DCIData )) != OK )
            {
                return (Result);
            }

            /**********************************************************/
            /* Record updated settings.                               */
            /**********************************************************/
            pFontSettings->LastMatchNo =
                                   LCIDTOUL(TextEntryPtr->GTBInfo.LCID);
            pFontSettings->LastHeight = TextEntryPtr->GTBNVFS;
            pFontSettings->LastWidth  = TextEntryPtr->GTBNHFS;
            pFontSettings->LastShear  = TextEntryPtr->GTBShear;

            /*************************************************/
            /* LastFontId field is not used for laser printer*/
            /* fonts. Therefore it is being used for Fast Sys*/
            /* fonts for laser printers. Since for 42xx      */
            /* printers this block of code is not executed,  */
            /* this field can be safely used for FSF         */
            /*************************************************/
            pFontSettings->LastFontId = VALUE_NOT_SET;
        }

      } /* .................. if outline font ..................... */

      else if ( pDDT->DDTInitFlags & DDT_SFG_SUPPORT )
      {
        /**************************************************************/
        /* To test whether the font we need is the same as the one    */
        /* we used last, compare the ptr to the metrics for this      */
        /* font and the last.                                         */
        /**************************************************************/
        if ( pFontSettings->LastMatchNo !=
                               LCIDTOUL(TextEntryPtr->GTBInfo.LCID) )
        {
            /**********************************************************/
            /* Set up the parameter block for the Set Font Global     */
            /* command.  This is 7 bytes long and is made up as       */
            /* follows:                                               */
            /*                                                        */
            /*   FGID high, FGID low,          0,1,                   */
            /*   FS high, FS low, SM,          2,3,4,                 */
            /*   CPGID high, CPGID low.        5,6                    */
            /*                                                        */
            /* FGID ... is the global registry id identifying         */
            /*          the type style                                */
            /* FS ..... is the font size in 1/1440" increments -      */
            /*          the value it specifies depends on SM          */
            /* SM ..... is the size modifier and depends on           */
            /*          whether the font is fixed pitch,              */
            /*          proportional or typographic.                  */
            /* CPGID .. is the code page number.                      */
            /*                                                        */
            /* If SM is 1 (fixed pitch font) or 2 (proportional       */
            /* font) FS gives the width of the space                  */
            /* character; if SM is 3 (typographical font) then        */
            /* FS gives the height of the space character.            */
            /*                                                        */
            /* If a 4019 printer pick up the global id from the       */
            /* metrics; otherwise (3816) from the Font List.          */
            /*                                                        */
            /* While RegistryId has a prefix "us" it is in fact a     */
            /* SHORT - hence the cast.                                */
            /*                                                        */
            /* DIAL/NILE : Nile/Tibers use SFG as well                */
            /*                                                        */
            /* PD00295:  So does the 4226                             */
            /**********************************************************/
            GlobalId = (USHORT)TextEntryPtr->GTBRegistryId;

            /**********************************************************/
            /* The FontSize and FontSizeType have already been worked */
            /* out in prdt_TextOutDevFont.                            */
            /**********************************************************/

            DCTParms[0] = (BYTE)(GlobalId / 256);
            DCTParms[1] = (BYTE)(GlobalId % 256);

            DCTParms[2] = (BYTE)(TextEntryPtr->GTBFontSize / 256 );
            DCTParms[3] = (BYTE)(TextEntryPtr->GTBFontSize % 256 );

            DCTParms[4] = (BYTE)TextEntryPtr->GTBFontSizeType;

            DCTParms[5] = (BYTE)(TextEntryPtr->GTBCodePage / 256);
            DCTParms[6] = (BYTE)(TextEntryPtr->GTBCodePage % 256);

            if ( (Result = prdp_AddString(
                                  DCT_SELECT_FONT,
                                  USE_PRINTER_TABLE,
                                  (PBYTE)DCTParms,
                                  MemoryPtr,
                                  pMemoryIndex,
                                  MemorySize,
                                  DCIData )) != OK )
            {
                return (Result);
            }

            /******************************************************************/
            /*  PD00648 : Add a set code page command to the 2391 so we can   */
            /*  tell 4072 customers to use the 2391 driver.  4072 ignores the */
            /*  code page selected by the set font global command.            */
            /******************************************************************/
            if ( (pDDT->DDTDriverType == DDT_IBM42XX_DRV   ) &&
                 (PrinterData->PrinterType == IBM_TIBER_24 )    )
            {
                DCTParms[0] = (BYTE)(TextEntryPtr->GTBCodePage / 256);
                DCTParms[1] = (BYTE)(TextEntryPtr->GTBCodePage % 256);

                if ( (Result = prdp_AddString(
                                      EST_SET_CODE_PAGE,
                                      USE_GLOBAL_TABLE,
                                      (PBYTE)DCTParms,
                                      MemoryPtr,
                                      pMemoryIndex,
                                      MemorySize,
                                      DCIData )) != OK )
                    {
                        return (Result);
                    }

            }

            /**********************************************************/
            /* Record updated settings.                               */
            /**********************************************************/
            pFontSettings->LastMatchNo =
                                   LCIDTOUL(TextEntryPtr->GTBInfo.LCID);

        }

      } /* .... if ( pDDT->DDTInitFlags & DDT_SFG_SUPPORT ......... */

      else if ( pDDT->DDTInitFlags & DDT_SCP_4224_SUPPORT )
      {
        /**********************************************************************/
        /*  PD00402 : Grab code page from TextEntry instead of using the code */
        /*  page index as 4224 no longer uses the download code page          */
        /*  structures.                                                       */
        /**********************************************************************/
            CodePage = TextEntryPtr->GTBCodePage;                  /* PD00402 */

        /**************************************************************/
        /* For 4224 printer must use ESC I, ILF, SLCS, etc.           */
        /* Check the font id and the code page number (which will     */
        /* be for 437 or 850).                                        */
        /**************************************************************/
        if ( (pFontSettings->LastFontId != FontId) ||
             (pFontSettings->LastCodePageNo != CodePage) )         /* PD00402 */
        {

            if ( CodePage != 850 )
            {
                /******************************************************/
                /* Just use normal printer fonts.                     */
                /******************************************************/
                if ( (Result = prdp_AddString(
                                      DCT_SELECT_FONT,
                                      USE_PRINTER_TABLE,
                                      (PBYTE)&FontId,
                                      MemoryPtr,
                                      pMemoryIndex,
                                      MemorySize,
                                      DCIData )) != OK )
                {
                    return (Result);
                }
            }
            else /* CodePage == 850 */
            {
                if ( (Result = prdp_AddString(
                                      EST_DEL_LOCAL_FONTS,
                                      USE_GLOBAL_TABLE,
                                      FNULL,
                                      MemoryPtr,
                                      pMemoryIndex,
                                      MemorySize,
                                      DCIData )) != OK )
                {
                    return (Result);
                }

                if ( (Result = prdp_AddString(
                                      DCT_SELECT_FONT,
                                      USE_PRINTER_TABLE,
                                      (PBYTE)&FontId,
                                      MemoryPtr,
                                      pMemoryIndex,
                                      MemorySize,
                                      DCIData )) != OK )
                {
                    return (Result);
                }
                UserFont = 32 + ( FontId % 96 );

                DCTParms[0] = (BYTE)UserFont;
                DCTParms[1] = 0;
                DCTParms[2] = (BYTE)FontId;

                if ( (Result = prdp_AddString(
                                      EST_INIT_LOCAL_FONT,
                                      USE_GLOBAL_TABLE,
                                      (PBYTE)DCTParms,
                                      MemoryPtr,
                                      pMemoryIndex,
                                      MemorySize,
                                      DCIData )) != OK )
                {
                    return (Result);
                }

                /******************************************************/
                /* The two bytes of the code page need to be          */
                /* flipped round.                                     */
                /******************************************************/
                DCTParms[0] = ((PBYTE)&CodePage)[1];
                DCTParms[1] = ((PBYTE)&CodePage)[0];
                DCTParms[2] = (BYTE)UserFont;

                TRACE4(TFUNC, "Flipped CP", DCTParms, 1);

                if ( (Result = prdp_AddString(
                                     EST_SET_CODE_PAGE_4224,
                                     USE_GLOBAL_TABLE,
                                     (PBYTE)DCTParms,
                                     MemoryPtr,
                                     pMemoryIndex,
                                     MemorySize,
                                     DCIData )) != OK )
                {
                    return (Result);
                }

                if ( (Result = prdp_AddString(
                                      DCT_SELECT_FONT,
                                      USE_PRINTER_TABLE,
                                      (PBYTE)&UserFont,
                                      MemoryPtr,
                                      pMemoryIndex,
                                      MemorySize,
                                      DCIData )) != OK )
                {
                    return (Result);
                }
            } /* .... if ( CodePage != 850 ) ........................ */

            /**********************************************************/
            /* Record updated settings.                               */
            /**********************************************************/
            pFontSettings->LastFontId     = FontId;
            pFontSettings->LastCodePageNo = CodePage;              /* PD00402 */
        }

      } /* .... if ( pDDT->DDTInitFlags & DDT_SCP_4224_SUPPORT ..... */

      else
      {
        /**************************************************************/
        /* Not SFG or SCP_4224 - do an ESC I n.  If the printer       */
        /* supports the Set Code Page command (X24E or XL24E) then do */
        /* one if necessary.                                          */
        /**************************************************************/
        if ( pDDT->DDTInitFlags & DDT_SCP_SUPPORT )
        {
            /******************************************************************/
            /*  PD00435: Code page number not set up for resident 850 font.   */
            /******************************************************************/
            if ( TextEntryPtr->GTBCodePage == 850)
                CodePageNo =  CP_850_INDEX;

            /**********************************************************/
            /* Only issue SCP if code page is different from the      */
            /* previous one.                                          */
            /**********************************************************/
            if ( pFontSettings->LastCodePageNo != CodePageNo )
            {
                CodePage = DVTCodePageList[CodePageNo].Number;

                /******************************************************/
                /* The two bytes of the code page need to be          */
                /* flipped round.                                     */
                /******************************************************/
                DCTParms[0] = ((PBYTE)&CodePage)[1];
                DCTParms[1] = ((PBYTE)&CodePage)[0];

                TRACE4(TFUNC, "Flipped CP", DCTParms, 1);

                if ( (Result = prdp_AddString(
                                      EST_SET_CODE_PAGE,
                                      USE_GLOBAL_TABLE,
                                      (PBYTE)DCTParms,
                                      MemoryPtr,
                                      pMemoryIndex,
                                      MemorySize,
                                      DCIData )) != OK )
                {
                    return (Result);
                }

                /******************************************************/
                /* Record updated settings.                           */
                /******************************************************/
                pFontSettings->LastCodePageNo = CodePageNo;
            }

        } /* ... if ( pDDT->DDTInitFlags & DDT_SCP_SUPPORT ) .... */

        /**************************************************************/
        /* Now, finally, select the font if necessary.  Watch out for */
        /* the special case of FastFont where we need to reset before */
        /* each string.                                               */
        /**************************************************************/
        if ( (pFontSettings->LastFontId != FontId) ||
             (FontId == SEL_FASTFONT) ||
             (FontId == SEL_FASTFONT + 4) )
        {
            /**********************************************************/
            /* Special code to send a select font command for         */
            /* resident before download.  This will allow Ohio to use */
            /* the X24E selection, and correctly select its resident  */
            /* fonts that are downloaded on the X24E.                 */
            /* Also changed PRDECOPN.C for default font selection.    */
            /*                                                        */
            /* DIAL/NILE : Remove check for CP_RESIDENT.              */
            /**********************************************************/
            if ( (pDDT->DDTDriverType == DDT_IBM42XX_DRV) &&
                 (PrinterData->PrinterType == IBM_PRO_PRINTER_X24E) &&
                 (FontType == FT_CODE_PAGE) )
            {
                FontId -= 4;

                if ( (Result = prdp_AddString(
                                      DCT_SELECT_FONT,
                                      USE_PRINTER_TABLE,
                                      (PBYTE)&FontId,
                                      MemoryPtr,
                                      pMemoryIndex,
                                      MemorySize,
                                      DCIData )) != OK )
                {
                    return (Result);
                }

                FontId += 4;
            }

            /**********************************************************/
            /* This is the original call.                             */
            /**********************************************************/
            if ( (Result = prdp_AddString(
                                  DCT_SELECT_FONT,
                                  USE_PRINTER_TABLE,
                                  (PBYTE)&FontId,
                                  MemoryPtr,
                                  pMemoryIndex,
                                  MemorySize,
                                  DCIData )) != OK )
            {
                return (Result);
            }

            /**********************************************************/
            /* Record updated settings.                               */
            /**********************************************************/
            pFontSettings->LastFontId = FontId;
        }
      }
    TRACE4(TFUNC, "Exit OK", FNULL, 0);
    return (OK);
}
#undef TFUNC






/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdp_SelectFont                                        */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*        As for Prdp_AddString                                       */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function sends the escape sequences to select a font on     */
/* the printer.                                                       */
/*                                                                    */
/**********************************************************************/
/*CON3201
USHORT pascal prdp_SelectFont ( DCIData,
                                TextEntryPtr,
                                Select,
                                MemoryPtr,
                                pMemoryIndex,
                                MemorySize )

lpDCI           DCIData;
lpGTBEntry far *TextEntryPtr;
USHORT          Select;
PBYTE           MemoryPtr;
PUSHORT         pMemoryIndex;
USHORT          MemorySize;
                           */

USHORT prdp_SelectFont (lpDCI           DCIData,
                        lpGTBEntry     *TextEntryPtr,
                        USHORT          Select,
                        PBYTE           MemoryPtr,
                        PUSHORT         pMemoryIndex,
                        USHORT          MemorySize)

{
    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    lpPDBI          PDBInst;
    USHORT          Cmd;
    USHORT          QualityId;
    USHORT          Result;
    lpDDTType       pDDT;
    USHORT          PrinterType;
    USHORT          DriverType;
    BYTE            DCTParms[9];

    /******************************************************************/
    /* Useful pointers & variables                      PD00565       */
    /******************************************************************/
    PDBInst = DCIData->DCIPdbInstance;
    pDDT    = &PDBInst->DDT;
    PrinterType = DCIData->DCIPdbInstance->PrinterType;    /* PD00565 */
    DriverType = pDDT->DDTDriverType;                      /* PD00565 */

    /******************************************************************/
    /* Select the font stage 2 - i.e. condensed, 12 cpi,              */
    /* enhanced/quality/draft etc.                                    */
    /******************************************************************/
    if ( (*TextEntryPtr)->GTBInfo.Type == FT_RESIDENT ||
         (*TextEntryPtr)->GTBInfo.Type == FT_CODE_PAGE )
    {
        if (Select == PRE_DCT)
        {
            Cmd = PDBInst->FontList[(*TextEntryPtr)->
                                              GTBInfo.Index]->PreDCTCmd;
        }
        else
        {
            Cmd = PDBInst->FontList[(*TextEntryPtr)->
                                             GTBInfo.Index]->PostDCTCmd;
        }

        if ( (Result = prdp_AddString( Cmd,
                                       USE_GLOBAL_TABLE,
                                       FNULL,
                                       MemoryPtr,
                                       pMemoryIndex,
                                       MemorySize,
                                       DCIData )) != OK )
        {
            return (Result);
        }

        /**********************************************************************/
        /*  PD00565 : Output a set code page command for 238X's as we have    */
        /*  a hardware bug.                                                   */
        /**********************************************************************/
        if ( (Select == PRE_DCT) &&
             ( (DriverType == DDT_IBM42XX_DRV) &&
               ( (PrinterType == IBM_NILE_9) ||
                 (PrinterType == IBM_TIBER_9) ) ) )
        {
            DCTParms[0] = (BYTE)(PDBInst->
                          FontList[(*TextEntryPtr)->GTBInfo.Index]
                          ->CodePage / 256);

            DCTParms[1] = (BYTE)(PDBInst->
                          FontList[(*TextEntryPtr)->GTBInfo.Index]
                          ->CodePage % 256);

            if ( (Result = prdp_AddString( EST_SET_CODE_PAGE,
                                           USE_GLOBAL_TABLE,
                                           DCTParms,
                                           MemoryPtr,
                                           pMemoryIndex,
                                           MemorySize,
                                           DCIData )) != OK )
            {
                return (Result);
            }


        }
    }
    else if ((*TextEntryPtr)->GTBInfo.Type == FT_CARD  &&
             (pDDT->DDTFontFlags & DDT_ADD_QUALITY_TO_FACE))
    {
        if (Select == PRE_DCT)
        {
            QualityId = PDBInst->PrinterData->
                  CardData[(*TextEntryPtr)->GTBInfo.Index].QualityLevel;

            if (pDDT->DDTDriverType == DDT_IBM42XX_DRV)
            {
                DCTParms[0] = (BYTE)((USHORT)(*TextEntryPtr)->
                                                        GTBRegistryId / 256);
                DCTParms[1] = (BYTE)((USHORT)(*TextEntryPtr)->
                                                        GTBRegistryId % 256);

                DCTParms[2] = (BYTE)((*TextEntryPtr)->GTBFontSize / 256 );
                DCTParms[3] = (BYTE)((*TextEntryPtr)->GTBFontSize % 256 );

                DCTParms[4] = (BYTE)(*TextEntryPtr)->GTBFontSizeType;

                DCTParms[5] = (BYTE)((*TextEntryPtr)->GTBCodePage / 256);
                DCTParms[6] = (BYTE)((*TextEntryPtr)->GTBCodePage % 256);
            }
        }
        else /* POST_DCT */
        {
            /******************************************************************/
            /*  PD00454: POST_DCT font selection is not supported on the      */
            /*  5202 so just return.                                          */
            /******************************************************************/
//          QualityId = 0;
            return( OK);                                           /* PD00454 */
        }

        /**********************************************************************/
        /*  PD00720 : Check to see which escape sequence to send down.        */
        /**********************************************************************/
        if (pDDT->DDTDriverType == DDT_IBM42XX_DRV)
        {
            switch (QualityId)
            {
                case 1: Cmd = EST_NT_DRAFT;
                        break;
                case 2: Cmd = EST_NT_LQ;
                        break;
            }

            if ( (Result = prdp_AddString(
                                  Cmd,
                                  USE_GLOBAL_TABLE,
                                  FNULL,
                                  MemoryPtr,
                                  pMemoryIndex,
                                  MemorySize,
                                  DCIData )) != OK )
            {
                return (Result);
            }

            if ( (Result = prdp_AddString(
                                  DCT_SELECT_FONT,
                                  USE_PRINTER_TABLE,
                                  (PBYTE)DCTParms,
                                  MemoryPtr,
                                  pMemoryIndex,
                                  MemorySize,
                                  DCIData )) != OK )
            {
                return (Result);
            }
        }
    }

    /******************************************************************/
    /* All done.                                                      */
    /******************************************************************/
    return( OK);
}




/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdp_SelectAttributes                                  */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*        As for Prdp_AddString                                       */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function sends the device attribute and engine attribute    */
/* escape sequences. Parameters as for Prdp_AddString.                */
/*                                                                    */
/**********************************************************************/
/*CON3201
USHORT pascal prdp_SelectAttributes ( DCIData,
                                      TextEntryPtr,
                                      Select,
                                      MemoryPtr,
                                      pMemoryIndex,
                                      MemorySize )

lpDCI           DCIData;
lpGTBEntry far *TextEntryPtr;
USHORT          Select;
PBYTE           MemoryPtr;
PUSHORT         pMemoryIndex;
USHORT          MemorySize;
                          */

USHORT prdp_SelectAttributes (lpDCI           DCIData,
                              lpGTBEntry     *TextEntryPtr,
                              USHORT          Select,
                              PBYTE           MemoryPtr,
                              PUSHORT         pMemoryIndex,
                              USHORT          MemorySize)

{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    USHORT      Cmd;
    BYTE        DevAttrs;
    BYTE        EngAttrs;
    BYTE        FontType;
    BYTE        CPIndex;
    USHORT      FontIx;
    ULONG       AttControl;
    USHORT      Result;
    lpPDBI      PDBInst;

    /******************************************************************/
    /* Useful pointers                                                */
    /******************************************************************/
    PDBInst     = DCIData->DCIPdbInstance;

    /******************************************************************/
    /* Get the attributes from the new match number.                  */
    /******************************************************************/
    DevAttrs = prdm_GetLCIDFontDevAttrs((*TextEntryPtr)->GTBInfo.LCID );
    EngAttrs = prdm_GetLCIDEngineAttrs( (*TextEntryPtr)->GTBInfo.LCID );
    CPIndex  = prdm_GetLCIDCPIndex(     (*TextEntryPtr)->GTBInfo.LCID );
    FontType = prdm_GetLCIDFontType(    (*TextEntryPtr)->GTBInfo.LCID );

    /******************************************************************/
    /* PD00134 : For FT_CODE_PAGE fonts get the CPFontIndex not the   */
    /* CPIndex as the font index. We were getting the incorrect font  */
    /* index (7F probably) therefore not getting the attribute        */
    /* control correctly below and therefore thinking that FT_CODE_   */
    /* PAGE fonts do not support BOLD.                                */
    /******************************************************************/
    if (FontType == FT_CODE_PAGE)
    {
        FontIx = prdm_GetLCIDCPFontIndex( (*TextEntryPtr)->GTBInfo.LCID );
    }
    else
    {
        FontIx = prdm_GetLCIDFontIndex( (*TextEntryPtr)->GTBInfo.LCID );
    }

    /******************************************************************/
    /* Get the attribute control flag from the font list for resident */
    /* fonts, otherwise just use a default value.                     */
    /******************************************************************/
    if ( (FontType == FT_RESIDENT) ||
         (FontType == FT_CODE_PAGE ) )
    {
        AttControl = PDBInst->FontList[FontIx]->Attrs;
    }
    else
    {
        /**************************************************************/
        /* Different default for outline fonts and image fonts.       */
        /**************************************************************/
        if (CPIndex == 0x7f)
        {
            /**********************************************************/
            /* For a non-outline fonts the default is bold is         */
            /* supported by using the emphasize escape sequence.      */
            /**********************************************************/
            AttControl = FATT_BOLD | FATT_BOLD_EMP;
        }
        else
        {
            /**********************************************************/
            /* For outline fonts the default is bold is unsupported   */
            /**********************************************************/
            AttControl = 0;
        }
    }

    /******************************************************************/
    /* DEVICE ATTRIBUTE - double wide                                 */
    /******************************************************************/
    if (DevAttrs & FATT_DOUBLE_WIDE)
    {
        /**************************************************************/
        /* Either switch it on or switch it off                       */
        /**************************************************************/
        Cmd = (Select == PRE_DCT) ? EST_D_WIDE_ON : EST_D_WIDE_OFF;

        if ( (Result = prdp_AddString(
                              Cmd,
                              USE_GLOBAL_TABLE,
                              FNULL,
                              MemoryPtr,
                              pMemoryIndex,
                              MemorySize,
                              DCIData )) != OK )
        {
            return (Result);
        }
    }

    /******************************************************************/
    /* DEVICE ATTRIBUTE - double high                                 */
    /******************************************************************/
    if (DevAttrs & FATT_DOUBLE_HIGH)
    {
        /**************************************************************/
        /* Either switch it on or switch it off                       */
        /**************************************************************/
        Cmd = (Select == PRE_DCT) ? EST_D_HIGH_ON : EST_D_HIGH_OFF;

        if ( (Result = prdp_AddString(
                              Cmd,
                              USE_GLOBAL_TABLE,
                              FNULL,
                              MemoryPtr,
                              pMemoryIndex,
                              MemorySize,
                              DCIData )) != OK )
        {
            return (Result);
        }
    }

    /******************************************************************/
    /* ENGINE ATTRIBUTES - which depend on the attribute control      */
    /* settings. Note that the LCID uses FATTR_SEL flags not CDEF     */
    /* flags.                                                         */
    /******************************************************************/

    /******************************************************************/
    /* ENGINE ATTRIBUTE - italic. Only send escape sequences if the   */
    /* font can be italicised.                                        */
    /******************************************************************/
    if ( (EngAttrs & FATTR_SEL_ITALIC) &&
         (AttControl & FATT_ITALIC) )
    {
        /**************************************************************/
        /* Either switch it on or switch it off                       */
        /**************************************************************/
        Cmd = (Select == PRE_DCT) ? 1 : 3;

        if ( (Result = prdp_AddString(
                              DCT_SELECT_ITALIC,
                              USE_PRINTER_TABLE,
                              (PBYTE)&Cmd,
                              MemoryPtr,
                              pMemoryIndex,
                              MemorySize,
                              DCIData )) != OK )
        {
            return (Result);
        }
    }

    /******************************************************************/
    /* ENGINE ATTRIBUTE - bold.  Only send escape sequences if the    */
    /* font can be emboldened.  Remember that there are two ways to   */
    /* get bold: emphasize or double strike.                          */
    /******************************************************************/
    if ( (EngAttrs & FATTR_SEL_BOLD) &&
         (AttControl & FATT_BOLD) )
    {
        if (AttControl & FATT_BOLD_EMP)
        {
            /**********************************************************/
            /* Either switch it on or switch it off                   */
            /**********************************************************/
            Cmd = (Select == PRE_DCT) ? EST_BOLD_ON : EST_BOLD_OFF;
        }
        else
        {
            /**********************************************************/
            /* Either switch it on or switch it off                   */
            /**********************************************************/
            Cmd = (Select == PRE_DCT) ? EST_D_STRIKE_ON : EST_D_STRIKE_OFF;
        }

        if ( (Result = prdp_AddString(
                              Cmd,
                              USE_GLOBAL_TABLE,
                              FNULL,
                              MemoryPtr,
                              pMemoryIndex,
                              MemorySize,
                              DCIData )) != OK )
        {
            return (Result);
        }
    }

    /******************************************************************/
    /* ENGINE ATTRIBUTE - underscore.  Always send the escape         */
    /* sequences.                                                     */
    /******************************************************************/
    if (EngAttrs & FATTR_SEL_UNDERSCORE)
    {
        /**************************************************************/
        /* Either switch it on or switch it off                       */
        /**************************************************************/
        Cmd = (Select == PRE_DCT) ? EST_UNDERSCORE_ON : EST_UNDERSCORE_OFF;

        if ( (Result = prdp_AddString(
                              Cmd,
                              USE_GLOBAL_TABLE,
                              FNULL,
                              MemoryPtr,
                              pMemoryIndex,
                              MemorySize,
                              DCIData )) != OK )
        {
            return (Result);
        }
    }

    /******************************************************************/
    /* OK done.                                                       */
    /******************************************************************/
    return( OK );
}

/******************************************************************************/
/*                                                                            */
/*   FUNCTION: prdp_StrikeOutToBand                                           */
/*                                                                            */
/*   PARAMETERS:                                                              */
/*                                                                            */
/*   lpDCI           DCIData;      Pointer to DC Instance data                */
/*   lpGTBEntry      TextEntryPtr; Pointer to the first text band             */
/*                                 entry.                                     */
/*                                                                            */
/*                                                                            */
/*   DESCRIPTION:                                                             */
/*                                                                            */
/*   This function loops thru all the text chain entries and for any          */
/*   text that needs to be strikeout adds the strikeout lines to the          */
/*   graphics bitmap band.                                                    */
/*                                                                            */
/******************************************************************************/
/*CON3201
USHORT pascal prdp_StrikeOutToBand ( DCIData,
                               TextEntryPtr )

lpDCI           DCIData;
lpGTBEntry      TextEntryPtr;
                            */

USHORT prdp_StrikeOutToBand (lpDCI           DCIData,
                             lpGTBEntry      TextEntryPtr)

{

    /**************************************************************************/
    /* Local variables                                                        */
    /**************************************************************************/

    lpGTBEntry  NextEntry;
    USHORT      NumOfRects;              /* PD00073 - # strikeout rects       */
    DevRect     FillRect;                /* fill rect for strikeout           */
    USHORT      i;
    /**************************************************************************/
    /* PD00632 : Added the following local variables                          */
    /**************************************************************************/
    BYTE        StrikeOutColor;
    lpPDBI      PDBInst;                 /* Pointer to the PDB Instance data  */
    lpDDTType   pDDT;                    /* Pointer to the DDT in the PDB     */

    /**************************************************************************/
    /* PD00632 :    Set up local pointers.                                    */
    /**************************************************************************/
    PDBInst = DCIData->DCIPdbInstance;
    pDDT    = &PDBInst->DDT;

    /**************************************************************************/
    /* Loop thur all text chain entries and check for strikeout text.         */
    /**************************************************************************/
    while ( TextEntryPtr )
    {
        /**********************************************************************/
        /* PD00073                                                            */
        /* At this point, have a text entry that is going to be               */
        /* drawn. So draw strikeout rectangles into the graphics              */
        /* band.                                                              */
        /* GTBpStrike acts as a flag: if NULL then no strikeouts are          */
        /* present, otherwise it points to the rectangles.                    */
        /*                                                                    */
        /* If in future there may be 1 or GTBNumCdPts rectangles,             */
        /* then add a GTBNumStrikeRects field to the GTB type.                */
        /**********************************************************************/
        if ( TextEntryPtr->GTBStrike )
        {
            /******************************************************************/
            /* PD00632 : Here only for device fonts that require strikeout    */
            /******************************************************************/
            /******************************************************************/
            /* PD00076: For bitmap fonts, only one rectangle.                 */
            /* PD00642 : Added TextEntryPtr->GTBCharStartPos to if stmt to    */
            /* handle strikeout of MODE 2 bitmap fonts.                       */
            /* PD00670 : Use new field GTBCharMode instead of GTBCharStartPos */
            /* in or leg of if stmt to handle strikeout of CM_MODE2 device    */
            /* bitmap text strings.                                           */
            /******************************************************************/
            if (TextEntryPtr->GTBNVFS || TextEntryPtr->GTBNHFS ||
                (TextEntryPtr->GTBCharMode == CM_MODE2) )
               NumOfRects = TextEntryPtr->GTBNumCdPts;
            else
               /***************************************************************/
               /* Here for CM_MODE1 device bitmap strikeout text.  Draw one   */
               /* strikeout line for entire string for better accuracy.       */
               /***************************************************************/
               NumOfRects = 1;

            /******************************************************************/
            /*  PD00632 : For color printer use foreground color for strikeout*/
            /*  and always use black for monochrome printers.                 */
            /*                                                                */
            /*  PD00800 : Changed the criteria for determining whether or not */
            /*  this is a color printer as we now report eight color          */
            /*  capability so that we may greyscale source bitmaps.           */
            /******************************************************************/
            if ((DRIVER_TYPE == DDT_IBM42XX_DRV) &&
                (PDBInst->PrinterType == IBM_4224_COLOR))
            {

                /**************************************************************/
                /*  Use foreground color for strikeout lines for color        */
                /*  printers to insure the strikeout is same color as text.   */
                /**************************************************************/
                StrikeOutColor = TextEntryPtr->GTBFgClr;
            }
            else
            {

                /**************************************************************/
                /* PD00632 : Always use black as color for strikeout lines for*/
                /* all device fonts on monochrome printers.                   */
                /* NOTE: PRD_FOREGROUND is used to get a black strikeout since*/
                /* the bitmap has already been inverted such that 0 is black. */
                /**************************************************************/
                StrikeOutColor = PRD_FOREGROUND;
            }
            /******************************************************************/
            /* The strikeout rectangle needs to be added to bitmap band.      */
            /******************************************************************/

            for  (i=0; i < NumOfRects; i++)
            {
                /**************************************************************/
                /* Have the four points to be filled here.                    */
                /**************************************************************/
                FillRect[0].X = (SHORT)TextEntryPtr->GTBStrike[i].BottomLeft.x;
                FillRect[0].Y = (SHORT)TextEntryPtr->GTBStrike[i].BottomLeft.y;
                FillRect[1].X = (SHORT)TextEntryPtr->GTBStrike[i].TopRight.x;
                FillRect[1].Y = (SHORT)TextEntryPtr->GTBStrike[i].TopRight.y;

                /**************************************************************/
                /*               !!!!! Important Note !!!!                    */
                /* NOTE: The fill routine should NOT clip this rectangle - as */
                /* its clipping should be the same as the text clipping!  If a*/
                /* character is drawn, then so should ALL of its strikeout    */
                /* rectangle -as long as it is on the form!                   */
                /**************************************************************/
                prdt_FillRectangle( (HDC)DCIData->DcH,
                                    (DevRect  *)FillRect,
                                    StrikeOutColor,
                                    (ULONG)COM_DRAW, DCIData);
            }
        }
        /**********************************************************************/
        /* Point to next text entry on text chain                             */
        /**********************************************************************/
        TextEntryPtr = TextEntryPtr->GTBNextEntry;
    }
    return( OK );
}
