/*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 = PRDECOPN
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prde_CompleteOpen
 *             prde_OutputDefaultFontCodes
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define INCL_32                         /* Convert to C/SET2    CON3201       */
#define INCL_DOSPROCESS                 /* Convert to C/SET2    CON3201       */
#define INCL_DOSSEMAPHORES
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#define INCL_DOSDEVICES
#define INCL_DOSERRORS
#define INCL_SPL
#define INCL_GPIERRORS
#include <os2.h>
#undef INCL_DOSPROCESS                  /* Convert to C/SET2    CON3201       */
#undef INCL_DOSSEMAPHORES
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS
#undef INCL_DOSDEVICES
#undef INCL_DOSERRORS
#undef INCL_SPL
#undef INCL_GPIERRORS

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

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

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

#include <prdconse.h>

#include <prddcone.h>

#include <prdpcone.h>
#include <prdecone.h>
#include <prdtcone.h>

#include <prdmtypt.h>

#include <prdeextf.h>
#include <prdgextf.h>
#include <prdpextf.h>
#include <prdtextf.h>
#include <prdyextf.h>
#include <prduextf.h>
#include <prdnextf.h>
#include <prdncone.h>

/******************************************************************************/
/* Set up external accesses.                                                  */
/******************************************************************************/
extern DVTCPListType        DVTCodePageList [];
extern lpDVTCPSource        DVTCodePageCaps [];
extern lpOutlineCodepages   OutlineCodepages;
extern USHORT               usCurrentScan;


/******************************************************************************/
/*                                                                            */
/*                                                                            */
/*    EXPLANATION OF THE STATE MACHINE FOR THE PRINTER FRAMEWORK              */
/*                                                                            */
/*   All the framework functions (EnableDC, DisableDC, CompleteOpen,          */
/* BeginClose, the DevEscape calls) now use a Finite State Machine            */
/* (FSM) with six states:-                                                    */
/*                                                                            */
/* 1 : WAIT_START       -  waiting for a StartDoc or Begin_Close              */
/* 2 : IMPLICIT         -  initial state after complete_open                  */
/* 3 : EXPLICIT         -  during a 'proper' document                         */
/* 4 : PURGE            -  PrtOpen\PrtWrite failed and CANCEL selected        */
/* 5 : RAW_IMPLICIT     -  implicit state, after RawData issued.              */
/* 6 : RAW_EXPLICIT     -  explicit state, after RawData issued.              */
/*                                                                            */
/* The initial state, after CompleteOpen, is IMPLICIT. The FSM with           */
/* state transitions and actions is given below.                              */
/*                                                                            */
/*            |    1  |    2  |    3  |   4   |   5   |   6   |               */
/* ___________|_______|_______|_______|_______|_______|_______|               */
/*            |       |       |       |       |       |       |               */
/* Cmplt_Open | 2 a   | 2 a   | 2 a   | 2 a   | 2 a   | 2 a   |               */
/* ___________|_______|_______|_______|_______|_______|_______|               */
/*            |       |       |       |       |       |       |               */
/* Begin_Close| - b1  | - b2  | - b3  | - b1  | - b3  | - b3  |               */
/* ___________|_______|_______|_______|_______|_______|_______|               */
/*            |       |       |       |       |       |       |               */
/* StartDoc   | 3 c1  | 3 c2  | - c3  | 3 c1  | 3 c2  | 3 c3  |               */
/* ___________|_______|_______|_______|_______|_______|_______|               */
/*            |       |       |       |       |       |       |               */
/* EndDoc     | -ERR  | 1 d1  | 1 d2  | 1 OK  | 1 d2  | 1 d2  |               */
/* ___________|_______|_______|_______|_______|_______|_______|               */
/*            |       |       |       |       |       |       |               */
/* NewFrame   | -ERR  | - e1  | - e2  | - OK  | 2ERR  | 3 e2  |               */
/* ___________|_______|_______|_______|_______|_______|_______|               */
/*            |       |       |       |       |       |       |               */
/* AbortDoc   | - f   | - f   | - f   | - f   | - f   | - f   |               */
/* ___________|_______|_______|_______|_______|_______|_______|               */
/*            |       |       |       |       |       |       |               */
/* Purge      | -     | 4 g   | 4 g   |       | 4 g   | 4 g   |               */
/* ___________|_______|_______|_______|_______|_______|_______|               */
/*            |       |       |       |       |       |       |               */
/* RawData    | -ERR  | 5 h1  | 6 h1  | - OK  | - h2  | - h3  |               */
/* ___________|_______|_______|_______|_______|_______|_______|               */
/*            |       |       |       |       |       |       |               */
/* Drawing op.| -ERR  | - j   | - j   | - OK  | - j   |   j   |               */
/* ___________|_______|_______|_______|_______|_______|_______|               */
/*                                                                            */
/*                                                                            */
/* -   ERR      return( ERROR )                                               */
/* -    OK       return( OK )                                                 */
/*                                                                            */
/* -    a        setup attributes & default font,                             */
/*               IF Queued THEN SplQmOpen,                                    */
/*               IF Queued_Standard THEN SplSTDOpen,                          */
/*               IF !Q_STD                                                    */
/*                   (enforce StartDoc for Q_STD)                             */
/*                   PrepareNewDocument.                                      */
/*               ENDIF                                                        */
/*                                                                            */
/* -    b1       IF Queued THEN SplQmClose,                                   */
/*               IF Queued_Std THEN SplSTDClose.                              */
/*                                                                            */
/*                                                                            */
/* -    b2       IF !Q_STD THEN ProcessLastPage,                              */
/*               IF Queued THEN SplQmClose,                                   */
/*               IF Q_STD THEN SplSTDClose                                    */
/*                                                                            */
/* -    b3       ProcessLastPage,                                             */
/*               IF Queued THEN SplQmClose,                                   */
/*               IF Q_STD THEN SplSTDClose                                    */
/*                                                                            */
/* -    c1       SetStartDocDCIDefaults                                       */
/*               PrepareNewDocument.                                          */
/*               Setup doc name                                               */
/*               IF QUEUED THEN SplQmStartDoc                                 */
/*                                                                            */
/* -    c2       IF !Q_STD THEN ProcessLastPage                               */
/*               SetStartDocDCIDefaults                                       */
/*               PrepareNewDocument.                                          */
/*               Setup doc name                                               */
/*               IF QUEUED THEN SplQmStartDoc                                 */
/*                                                                            */
/* -    c3       IF aborted THEN                                              */
/*                   write_abort_tidy_up                                      */
/*                   GOTO c1                                                  */
/*               ELSE return ERROR                                            */
/*                                                                            */
/* -    d1       IF Q_STD THEN return ERROR ( enforce StartDoc )              */
/*               ELSE ProcessLastPage                                         */
/*                                                                            */
/* -    d2       ProcessLastPage                                              */
/*                                                                            */
/* -    e1       IF Q_STD return ERROR                                        */
/*               ELSE                                                         */
/*                  ProcessPage                                               */
/*                  Increment PageNumber                                      */
/*                  PrepareNextPage                                           */
/*               ENDIF                                                        */
/*                                                                            */
/* -    e2       ProcessPage                                                  */
/*               Increment PageNumber                                         */
/*               PrepareNextPage                                              */
/*                                                                            */
/* -    f        Set Aborted flag                                             */
/*               IF direct THEN                                               */
/*                   return( OK )                                             */
/*                   ( AbortTidyUp done at next PrtWrite )                    */
/*               ELSE                                                         */
/*                   wait-for_thread                                          */
/*                   AbortTidyUp                                              */
/*                   return( OK )                                             */
/*               ENDIF.                                                       */
/*                                                                            */
/* -    g        PrtAbort,                                                    */
/*               ClosePrinter,                                                */
/*               AbortTidyUp                                                  */
/*                                                                            */
/* -    h1       IF Direct THEN                                               */
/*                   OpenPrinter                                              */
/*               ELSE                                                         */
/*                   SplQmStartDoc                                            */
/*               ENDIF                                                        */
/*               InitialisePrinter                                            */
/*               Establish default font                                       */
/*               Send rawdata to spoolfile or printer.                        */
/*                                                                            */
/* -    h2       InitialisePrinter                                            */
/*               Establish default font                                       */
/*               Send rawdata to spoolfile or printer.                        */
/*                                                                            */
/* -    j        Continue with drawing function                               */
/*                                                                            */
/*                                                                            */
/*                                                                            */
/* CHANGES/NOTES                                                              */
/*                                                                            */
/*  Enforce a StartDoc for a QUEUED_STD document. If we don't then            */
/* metafiling must start at CompleteOpen. But we cannot tell if any           */
/* NewFrame or RawData calls have come in when we get a StartDoc or           */
/* BeginClose, as they are metafiled. So cannot decide whether to             */
/* output the metafile to the spooler or not. Enforce StartDoc; and           */
/* only start metafiling at StartDoc time.                                    */
/*                                                                            */
/*  We will always have to support a DIRECT job without StartDoc, as          */
/* when a Q_STD job comes off the spooler queue, StartDoc and EndDoc          */
/* are not issued. This is a bit of a weakness in the interface.              */
/*                                                                            */
/*                                                                            */
/******************************************************************************/



/******************************************************************************/
/*                                                                            */
/*   FUNCTION: prde_CompleteOpen                                              */
/*                                                                            */
/*   PARAMETERS:                                                              */
/*                                                                            */
/*   hanDC      DcH;       Handle to DC                                       */
/*   lpDCI      DCIData;   Pointer to DC Instance data                        */
/*                                                                            */
/*   DESCRIPTION:                                                             */
/*                                                                            */
/*   Finish off preparing the DC (after EnableDC). Prepare for a              */
/* document (allocate band etc) if an IMPLICIT document is allowed.           */
/* Set initial state (IMPLICIT).                                              */
/*                                                                            */
/******************************************************************************/
#if 0
USHORT pascal prde_CompleteOpen ( DcH,
                                  DCIData )


hanDC      DcH;
lpDCI      DCIData;
#endif

SHORT prde_CompleteOpen ( hanDC DcH,                               /* CON3201 */
                          lpDCI DCIData )                          /* CON3201 */

{
#define TFUNC "prde_CompltOpen"
    /**************************************************************************/
    /* Local variables                                                        */
    /**************************************************************************/
 /* USHORT      Result = OK; */
     SHORT      Result = OK;                                       /* CON3201 */

#ifdef DEBUG_FSM
    OutputString("Enter CompleteOpen");
#endif
#ifdef PRD_TIMING
    DEKHOOK0(A,8,47)
#endif

    /**************************************************************************/
    /* The DC was initialised in EnableDC; do some font/GRE setup now.        */
    /**************************************************************************/
    prdn_SetCompleteOpenDCIDefaults( DCIData );

    if ( DCIData->Flags & QUEUED )
    {
        /**********************************************************************/
        /* SplQmOpen done in prde_FillPdb.  But for now open the metafile     */
        /**********************************************************************/
        if ( DCIData->Flags & QUEUED_STD )
        {
            if ( SplStdOpen( (HDC)DCIData->DcH ) != OK )
            {
                Result = ERROR_NEG;
                goto EXIT_FUNCTION;
            }
        }
    }

    /**************************************************************************/
    /* Now prepare a document.  For a memory dc do not do this, as we don't   */
    /* want to allocate a band etc; no StartDoc, EndDoc stuff is received,    */
    /* just drawing.                                                          */
    /*                                                                        */
    /* NOTE: enforce StartDoc for Q_STD                                       */
    /**************************************************************************/
    if ( !(DCIData->Flags & (MEMORY | QUEUED_STD) ) )
    {
        if ( prdn_PrepareNewDocument( DCIData ) != OK )
        {
            /******************************************************************/
            /* error - eg insufficient memory                                 */
            /******************************************************************/
            Result = ERROR_NEG;
            goto EXIT_FUNCTION;
        }
    }

    /**************************************************************************/
    /* PD00474 : Set up some memory for the current pattern to be used by the */
    /* the polyscanline call.                                                 */
    /**************************************************************************/
    if (prdu_AllocPatternMemory ( DCIData ) == ERROR_ZERO )
    {
       Result = ERROR_NEG;
       goto EXIT_FUNCTION;
    }

    /**************************************************************************/
    /* This is the OK return path                                             */
    /**************************************************************************/
    DCIData->State = IMPLICIT;
    Result = OK;

EXIT_FUNCTION:

#ifdef PRD_TIMING
    DEKHOOK0(A,8,C7)
#endif
    return( Result );
}

#undef TFUNC



/******************************************************************************/
/*                                                                            */
/*   FUNCTION: prde_OutputDefaultFontCodes                                    */
/*                                                                            */
/*   PARAMETERS:                                                              */
/*                                                                            */
/*   lpDCI      DCIData;   Pointer to DC Instance data                        */
/*                                                                            */
/*   DESCRIPTION:                                                             */
/*                                                                            */
/*   This function sends out the default font escape sequences to the         */
/*   printer.                                                                 */
/*                                                                            */
/******************************************************************************/
#if 0
USHORT pascal prde_OutputDefaultFontCodes ( DCIData )

lpDCI      DCIData;
#endif
SHORT prde_OutputDefaultFontCodes ( lpDCI DCIData )                /* CON3201 */

{
#define TFUNC "prde_OutDfltFntCodes"

    /**************************************************************************/
    /* Local Variables                                                        */
    /**************************************************************************/
    lpPDBI               PDBInstance;   /* Pointer to PDB data                */
    lpDDTType            pDDT;          /* Pointer to DDT in PDB              */
    lpPrtDataEntry       PrinterData;
    USHORT               QualityId;
    lpFMFFileStruc       pDfltFMFData;
    USHORT               FontIndex;
    USHORT               FontType;
    USHORT               MemoryIndex;   /* Index into memory buffer           */
    PBYTE                 MemoryPtr;     /* Pointer to output buffer          */
    USHORT               MemorySize;    /* Size of output buffer              */
    USHORT               CodePage;      /* Unflipped code page                */
    USHORT               FontId;
    USHORT               CodePageNo;
    lpDVTCPSource        CodePageCaps;  /* Code Page capabilities             */
    BYTE                 DCTParms[11];  /* PD00694 : Change from 9 to 11 bytes*/
    PFOCAMETRICS         pMetrics;
    USHORT               FontSizeType;
    USHORT               FontSize;
    ULONG                CharWidth;
    USHORT               GlobalId;
    USHORT               UserFont;
    lpDfltFontInfoType   pDfltFontInfo;
 /* USHORT               return_value; */
    SHORT                return_value;                             /* CON3201 */
    ULONG                NVFSFixed;
    USHORT               CpIndex;
    USHORT               Cmd;           /* PD00720                            */

    /**************************************************************************/
    /* Some useful pointers                                                   */
    /**************************************************************************/
    PDBInstance   = DCIData->DCIPdbInstance;
    PrinterData   = PDBInstance->PrinterData;
    pDfltFontInfo = &PDBInstance->DfltDeviceFont;
    pDDT = &PDBInstance->DDT;

    /**************************************************************************/
    /* Pick up info for the default device font.                              */
    /**************************************************************************/
    FontType     = pDfltFontInfo->Info.Type;
    FontIndex    = pDfltFontInfo->Info.Index;
    pDfltFMFData = pDfltFontInfo->Info.pFont;

    /**************************************************************************/
    /* Set up other variables required for the default font handling.         */
    /**************************************************************************/
    switch ( FontType )
    {
        case FT_RESIDENT:
            /******************************************************************/
            /* DIAL/NILE : Set the Code Page number.                          */
            /******************************************************************/
            /******************************************************************/
            /* PD00850 : Removed if stmt and set CodePageNo to code page index*/
            /* was always being set to 850 index with if stmt.                */
            /******************************************************************/
            CodePageNo   = pDfltFontInfo->Info.CodePageNo;

            break;

        case FT_CODE_PAGE:
            /******************************************************************/
            /* Get the Code Page data.                                        */
            /******************************************************************/
            CodePageNo   = pDfltFontInfo->Info.CodePageNo;
            CodePageCaps = DVTCodePageCaps[PrinterData->PrinterType];

            /******************************************************************/
            /* We may need to download the code page.                         */
            /******************************************************************/
            TRACE8(TFUNC, "CPCurrent", &(PrinterData->CPCurrent), 1);

            if ( DCIData->DCIDCType == OD_QUEUED )
            {
                if ( PDBInstance->PDBOutputType == IBMQRAW )
                {
                    /**********************************************************/
                    /* Queued Raw - use CPJob to track the CodePage; this is  */
                    /* reset within DownloadCodePage.                         */
                    /**********************************************************/
                    if (CodePageNo != PDBInstance->CPJob)
                    {
                        if ( (return_value = prde_DownloadCodePage(
                                                  CodePageNo,
                                                  DCIData)  ) != OK )
                        {
                            return (return_value);
                        }
                    }
                }
            }
            else    /* ... Direct DC ................................ */
            {
                /**************************************************************/
                /* Direct Raw or Std - use CPCurrent to track the CodePage;   */
                /* this is reset within DownloadCodePage.                     */
                /*                                                            */
                /* There is a danger that raw data could destroy the current  */
                /* code page downloaded in the printer ram and so for absolute*/
                /* safety we should re-download the code page after any raw   */
                /* data.  However that would be pitifully slow so we take the */
                /* risk.                                                      */
                /**************************************************************/
                if (CodePageNo != PrinterData->CPCurrent)
                {
                    if ( (return_value = prde_DownloadCodePage(
                                                CodePageNo,
                                                DCIData) ) != OK )
                    {
                        return (return_value);
                    }
                }
            }
            break;

        default:
            break;
    }
    /*.. switch (Default font type) ..........................................*/


    /**************************************************************************/
    /* We now need to select the default device font.  The font is selected by*/
    /* a Set Font Global command (on the 3816) or by an Esc I n followed by a */
    /* command to set the quality level and or pitch.  Allocate some temporary*/
    /* memory to use to build up the escape sequences.                        */
    /**************************************************************************/
    MemorySize = MIN_TEXT_SIZE;

    if ( prdg_AllocHeapItem(DCIData,
                            MemorySize,
                            (PUSHORT *)&MemoryPtr ) != OK )
        return (ERROR);

    MemoryIndex = 0;

    /**************************************************************************/
    /* Get the n for the Esc I n or the size modify parameter for the Set Font*/
    /* Global.                                                                */
    /**************************************************************************/
    switch (FontType)
    {
      case FT_RESIDENT:
        FontId = PDBInstance->FontList[FontIndex]->SelectionId;
        break;
      case FT_CODE_PAGE:
        /**********************************************************************/
        /* 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 IBM printers supported.               */
        /**********************************************************************/
        FontId = PDBInstance->FontList[FontIndex]->SelectionId + 4;
        break;
      default:
        break;
    }  /* end switch */

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

    /**************************************************************************/
    /* Select the font for this Text Entry - i.e.  the initial Esc I n command*/
    /* or the Set Font Global command.                                        */
    /**************************************************************************/
    pMetrics = &pDfltFMFData->Metrics;

    if ( pDDT->DDTInitFlags & DDT_SFG_SUPPORT )
    {
        /**********************************************************************/
        /* 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.                                                    */
        /**********************************************************************/
        pMetrics = &pDfltFMFData->Metrics;

        /**********************************************************************/
        /* DIAL/NILE : Use registry ID for Nile/Tiber.                        */
        /*                                                                    */
        /* PD00295 : And for 4226.                                            */
        /**********************************************************************/
        GlobalId = (USHORT)pMetrics->usRegistryId;

        /**********************************************************************/
        /* If a 4019 printer pick up the font size type (Fixed Pitch,         */
        /* Proportional or Typographic) from the metrics; otherwise (3816)    */
        /* from the Font List.                                                */
        /*                                                                    */
        /* DIAL/NILE : Nile/Tiber also use FontSizeType.                      */
        /*                                                                    */
        /* PD00295: So does 4226.                                             */
        /*                                                                    */
        /* PD00371: FontSizeType for Nile/Tiber/4226 should be PROPORTIONAL   */
        /* not TYPOGRAPHIC.                                                   */
        /**********************************************************************/
        if ( (pDfltFMFData->WidthFlag & FMF_WIDTH_MASK) == 0 )
        {
            FontSizeType = PROPORTIONAL;
        }
        else
        {
            FontSizeType = FIXED_PITCH;
        }

        /**********************************************************************/
        /* Point Size is held in decipoints (1 decipoint = 1/720th of an      */
        /* inch).  The widths are held in the units given by xDeviceRes.  The */
        /* space character is the 0x20th character.  The font size used for   */
        /* the SFG command is in 1/1440th of an inch.                         */
        /**********************************************************************/
        if ( FontSizeType == TYPOGRAPHIC )
        {
            FontSize = 2 * pMetrics->usNominalPointSize;
        }
        else if ( FontSizeType == PROPORTIONAL )
        {
            CharWidth = (ULONG)pDfltFMFData->CharWidth[0x20];

            FontSize = (USHORT)((CharWidth * 1440L) /
                                        (ULONG)pMetrics->xDeviceRes );
        }
        else    /* FIXED_PITCH */
        {
            CharWidth = (ULONG)(pDfltFMFData->WidthFlag &
                                                     FMF_WIDTH_MASK );

            FontSize  = (USHORT)( (CharWidth * 1440L) /
                                        (ULONG)pMetrics->xDeviceRes );
        }

        if ( pMetrics ->usCodePage == 0 )
        {
            /******************************************************************/
            /* Set codepage to the cp whose index is in the MatchNo.          */
            /* Note: Should never get here now since all MultiCp fonts are    */
            /* outline type.  This code is here in case we have a MultiCp font*/
            /* that is NOT outline.                                           */
            /******************************************************************/
            CpIndex  = pDfltFontInfo->Info.LCID.CPIndex & 0x7F;
            CodePage = OutlineCodepages[CpIndex].cp;
        }
        else
        {
            CodePage = pMetrics->usCodePage;
        }

        DCTParms[0] = (BYTE)(GlobalId / 256);
        DCTParms[1] = (BYTE)(GlobalId % 256);
        DCTParms[2] = (BYTE)(FontSize / 256 );
        DCTParms[3] = (BYTE)(FontSize % 256 );
        DCTParms[4] = (BYTE) FontSizeType;
        DCTParms[5] = (BYTE)(CodePage / 256);
        DCTParms[6] = (BYTE)(CodePage % 256);

        if ( (return_value = prdp_AddString ( DCT_SELECT_FONT,
                                              USE_PRINTER_TABLE,
                                              (PBYTE)DCTParms,
                                              MemoryPtr,
                                              &MemoryIndex,
                                              MemorySize,
                                              DCIData) ) != OK )
        {
            return (return_value);
        }

        /**********************************************************************/
        /* 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)(CodePage / 256);
            DCTParms[1] = (BYTE)(CodePage % 256);

            if ( (return_value = prdp_AddString ( EST_SET_CODE_PAGE,
                                                  USE_GLOBAL_TABLE,
                                                  (PBYTE)DCTParms,
                                                  MemoryPtr,
                                                  &MemoryIndex,
                                                  MemorySize,
                                                  DCIData) ) != OK )
            {
                return (return_value);
            }

        }

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

    /**************************************************************************/
    /*  DIAL/NILE : This else arm was restructured.                           */
    /**************************************************************************/
    else  /* ESC I is used to select font */
    {
        /**********************************************************************/
        /*  PD00402: Grab the code page from the metrics, not from the code   */
        /*  page index.                                                       */
        /**********************************************************************/
        CodePage = pMetrics->usCodePage;                        /* PD00402    */

        /**********************************************************************/
        /*  4224 requires setting up a user defined font if you want to get   */
        /*  850.                                                              */
        /**********************************************************************/
        if ( (pDDT->DDTInitFlags & DDT_SCP_4224_SUPPORT) &&
             (CodePage == 850) )
        {
            /******************************************************************/
            /*  Set up a user defined font (>20H) in the 4224.  Set up this   */
            /*  font to be in the relevant code page.                         */
            /******************************************************************/
            if ( (return_value = prdp_AddString (
                                  EST_DEL_LOCAL_FONTS,
                                  USE_GLOBAL_TABLE,
                                  FNULL,
                                  MemoryPtr,
                                  &MemoryIndex,
                                  MemorySize,
                                  DCIData )) != OK )
            {
                return (return_value);
            }

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

            UserFont = 32 + ( FontId % 96 );

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

            if ( (return_value = prdp_AddString (
                                  EST_INIT_LOCAL_FONT,
                                  USE_GLOBAL_TABLE,
                                  (PBYTE)DCTParms,
                                  MemoryPtr,
                                  &MemoryIndex,
                                  MemorySize,
                                  DCIData )) != OK )
            {
                return (return_value);
            }

            /******************************************************************/
            /*  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 ( (return_value = prdp_AddString (
                                 EST_SET_CODE_PAGE_4224,
                                 USE_GLOBAL_TABLE,
                                 (PBYTE)DCTParms,
                                 MemoryPtr,
                                 &MemoryIndex,
                                 MemorySize,
                                 DCIData )) != OK )
            {
                return (return_value);
            }

            if ( (return_value = prdp_AddString (
                                  DCT_SELECT_FONT,
                                  USE_PRINTER_TABLE,
                                  (PBYTE)&UserFont,
                                  MemoryPtr,
                                  &MemoryIndex,
                                  MemorySize,
                                  DCIData )) != OK )
            {
                return (return_value);
            }
        }
        else
        {
            /******************************************************************/
            /*  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 PRDPTEXT.C for other font selection.      */
            /******************************************************************/
            if ( (pDDT->DDTDriverType == DDT_IBM42XX_DRV) &&
                 (PrinterData->PrinterType == IBM_PRO_PRINTER_X24E) &&
                 (FontType == FT_CODE_PAGE) )
            {
                FontId -= 4;

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

                FontId += 4;
            }

            /******************************************************************/
            /*  Select the font.                                              */
            /******************************************************************/
            if ( (return_value = prdp_AddString ( DCT_SELECT_FONT,
                                                  USE_PRINTER_TABLE,
                                                  (PBYTE)&FontId,
                                                  MemoryPtr,
                                                  &MemoryIndex,
                                                  MemorySize,
                                                  DCIData) ) != OK )
            {
                return (return_value);
            }
        } /*.. if 4224 & CodePage == 850.. */
    } /* ..! if ( pDDT->DDTInitFlags & DDT_SFG_SUPPORT ) ...     */

    /**************************************************************************/
    /* Now set the code page if the printer has the Set Code Page command.    */
    /**************************************************************************/
    if ( pDDT->DDTInitFlags & DDT_SCP_SUPPORT )
    {
        /**********************************************************************/
        /* The two bytes of the code page need to be flipped round            */
        /**********************************************************************/
        CodePage = DVTCodePageList[CodePageNo].Number;

        DCTParms[0] = ((PBYTE)&CodePage)[1];
        DCTParms[1] = ((PBYTE)&CodePage)[0];

        /**********************************************************************/
        /* Send the code page to the printer.                                 */
        /**********************************************************************/
        TRACE4(TFUNC, "Flipped CP", DCTParms, 1);

        if ( (return_value = prdp_AddString ( EST_SET_CODE_PAGE,
                                              USE_GLOBAL_TABLE,
                                              (PBYTE)DCTParms,
                                              MemoryPtr,
                                              &MemoryIndex,
                                              MemorySize,
                                              DCIData) ) != OK )
        {
            return (return_value);
        }

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

    /**************************************************************************/
    /* Select the font stage 2 - i.e.  condensed, 12 c.p.i.  enhanced quality */
    /* / draft etc.                                                           */
    /**************************************************************************/
    if ( FontType == FT_RESIDENT ||
         FontType == FT_CODE_PAGE )
    {
        if ( (return_value = prdp_AddString (
                            PDBInstance->FontList[FontIndex]->PreDCTCmd,
                            USE_GLOBAL_TABLE,
                            FNULL,
                            MemoryPtr,
                            &MemoryIndex,
                            MemorySize,
                            DCIData )) != OK )
        {
            return (return_value);
        }

        /**********************************************************************/
        /*  PD00565 : Output a set code page command for 238X's as we have    */
        /*  a hardware bug.                                                   */
        /**********************************************************************/
        if   ( ( pDDT->DDTDriverType == DDT_IBM42XX_DRV) &&
               ( (PrinterData->PrinterType == IBM_NILE_9) ||
                 (PrinterData->PrinterType == IBM_TIBER_9) ) )
        {

            DCTParms[0] = (BYTE)(PDBInstance->FontList[FontIndex]->CodePage / 256);
            DCTParms[1] = (BYTE)(PDBInstance->FontList[FontIndex]->CodePage % 256);

            if ( (return_value = prdp_AddString( EST_SET_CODE_PAGE,
                                           USE_GLOBAL_TABLE,
                                           DCTParms,
                                           MemoryPtr,
                                           &MemoryIndex,
                                           MemorySize,
                                           DCIData )) != OK )
            {
                return (return_value);
            }

        }
    }

    /**************************************************************************/
    /* Send the commands to the printer and then release the memory.          */
    /**************************************************************************/
    if ( (return_value = prdp_PrintMemory (MemoryPtr,
                                           MemoryIndex,
                                           DCIData )) != OK )
    {
        return (return_value);
    }

    TRACE4(TFUNC, "Font selected OK", FNULL, 0);

    (void) prdg_FreeHeapItem(DCIData,
                             MemorySize,
                             (PUSHORT)MemoryPtr );

    return (OK);
}

#undef TFUNC
