/*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 = PRDEFONT
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prde_ReadFontResource
 *             prde_LoadCodePageMetrics
 *             prde_DownloadFile
 *             prde_DownloadCodePage
 *             prde_LoadResidentFontMetrics
 *             prde_InitialiseDownFonts
 *
 * 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_DOSRESOURCES
#define INCL_DOSSEMAPHORES
#define INCL_DOSERRORS
#define INCL_GREALL
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#define INCL_SPL
#define INCL_WINSHELLDATA
#define INCL_GPIERRORS
#define INCL_DOSMODULEMGR
#define INCL_WINPOINTERS
#include <os2.h>
#undef INCL_DOSPROCESS                  /* Convert to C/SET2    CON3201       */
#undef INCL_DOSRESOURCES
#undef INCL_DOSSEMAPHORES
#undef INCL_DOSERRORS
#undef INCL_GREALL
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS
#undef INCL_SPL
#undef INCL_WINSHELLDATA
#undef INCL_GPIERRORS
#undef INCL_DOSMODULEMGR
#undef INCL_WINPOINTERS

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

#define INCL_WINP_SELSERVER
#define INCL_WINP_SELECTIVE
#define INCL_WINP_SEI
#define INCL_WINP_FSRS
#define INCL_WINP_MISC
#include <pmwinx.h>
#undef INCL_WINP_SELSERVER
#undef INCL_WINP_SELECTIVE
#undef INCL_WINP_SEI
#undef INCL_WINP_FSRS
#undef INCL_WINP_MISC

#define INCL_DOSINFOSEG
#define INCL_NOCOMMON
#include <bsedos.h>
#undef INCL_DOSINFOSEG
#define INCL_NOCOMMON
#undef INCL_32                          /* Convert to C/SET2    CON3201       */

#include <prdconty.h>
#include <prdconse.h>
#include <prdecone.h>
#include <prdttypt.h>
#include <prddtypt.h>
#include <prdetypt.h>
#include <prdtypet.h>
#include <prddcone.h>
#include <prdmcone.h>
#include <prdqcone.h>
#include <prdtcone.h>
#include <prdpcone.h>
#include <prdecone.h>                                              /* PD00651 */
#include <prdptypt.h>
#include <prdmtypt.h>
#include <prdjtypt.h>
#include <prdctypt.h>
#include <prdatypt.h>

#include <prdgpart.h>
#include <prddct.h>
#include <prdbtypt.h>

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

#include <prdmacro.h>
#include <prderre.h>
#include <prdztrcf.h>

extern CHAR                 *UGL4029[];
extern HMODULE              prdd_ModHandle;
extern lplpFontCPListType   DVTFontCPList [];
extern lpDVTCPSource        DVTCodePageCaps [];
extern DVTCPListType        DVTCodePageList [];
extern USHORT               DRIVER_TYPE;
extern USHORT               OutlineCodepageEntries;
extern lpOutlineCodepages   OutlineCodepages;
extern USHORT               NonOS2HeritageCodePageCount;
extern NonOS2CodePageType   NonOS2HeritageCodePages[];
extern USHORT               HeritageResidentCodePageCount;
extern USHORT               HeritageResidentCodePages[];
extern char                 szQualityString1[];
extern char                 szQualityString2[];


/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_ReadFontResource                                  */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpFMFFileStruc far * ppFMFData;                                  */
/*   USHORT              ResourceId;                                  */
/*   PBOOL               pUseFlag;           Not used.                */
/*   USHORT              NoDefinedFonts;     Total number of          */
/*                                             resident fonts.        */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* This routine accesses an font metrics resource, copies that to     */
/* global heap memory, then releases that resource. In the process    */
/* of the copy it handles different Font Metric File formats:         */
/*                                                                    */
/*     - IBM4019 Old style                                            */
/*     - Multi-codepage font metric files (byte 0 = FD)               */
/*     - dummy font metrics files (byte 0 = FE)                       */
/*     - dummy font metrics files (byte 0 = FF)                       */
/*                                                                    */
/* Dummy font metric files contain a resource identifier that links   */
/* them to a base font metric file. This index must refer to a font   */
/* in the resident font list that appears logical earlier in the list */
/*                                                                    */
/* This code used to leave the resource pointer in the font list for  */
/* full FMFs and only allocate memory for dummy FMFs. This was slow   */
/* and used up a lot of segments.                                     */
/*                                                                    */
/* The reason why this change was made concerned the IBM3816 which    */
/* writes into the font list metrics to add the correct RegistryID    */
/* because the metrics are incorrect. The correct value is in the     */
/* font list. If all printers that select fonts using the SFG command */
/* have the registryID correct in the metrics then there is no need   */
/* of special case code in SetUpFont.                                 */
/*                                                                    */
/*                                                                    */
/* D. Howell:       PD00053 - Changed usByteOffset from BYTE to       */
/*                            USHORT                                  */
/*                                                                    */
/* Phill Springett: PD00009 - Re-wrote to allocate memory for each    */
/*                            font.                                   */
/*                                                                    */
/* Toni Czajkowski: CON3201 - Convert to C/SET2                       */
/*                                                                    */
/**********************************************************************/
#if 0
USHORT pascal prde_ReadFontResource( ppFMFData,
                                     ResourceId,
                                     pUseFlag,
                                     NoDefinedFonts,
                                     PDBInstance )
lpFMFFileStruc far *ppFMFData;
USHORT              ResourceId;
PBOOL               pUseFlag;
USHORT              NoDefinedFonts;
lpPDBI              PDBInstance;
#endif

SHORT prde_ReadFontResource( lpFMFFileStruc *ppFMFData,            /* CON3201 */
                             USHORT          ResourceId,           /* CON3201 */
                             PBOOL           pUseFlag,             /* CON3201 */
                             USHORT          NoDefinedFonts,       /* CON3201 */
                             lpPDBI          PDBInstance )         /* CON3201 */

{
#define TFUNC "prde_ReadFontResource"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    lpDDTType         pDDT;
    USHORT            Result;
    USHORT            j;
    PBYTE             pResourceFMF;   /* Resource pointer             */
    PBYTE             pDummyFMF;      /* Pointer into dummy resource  */
    lpFMFFileStruc    pValidFMF;      /* Base FMF (for dummy resource */
    USHORT            FMFFileSize;    /* Size full FMF                */
    USHORT            NoOfChangeBytes;
    USHORT            usByteOffset;                        /* PD00053 */
    BYTE              ByteValue;
    BYTE              DummyByte;      /* FMF byte for full or dummy   */
    PBYTE             FilePtr;
    BOOL              Found;


    /******************************************************************/
    /* Process is to read the resource, allocate some global heap     */
    /* memory and copy the resource then free the resource. But if    */
    /* anyhting was set up before then do nothing.                    */
    /******************************************************************/
    if (!*ppFMFData)
    {
        /**************************************************************/
        /* Useful pointers.                                           */
        /**************************************************************/
        pDDT = &PDBInstance->DDT;

        /**************************************************************/
        /* Nothing set up. So get the resource                        */
        /**************************************************************/
        Result = DosGetResource( (HMODULE)prdd_ModHandle,
                              /* (USHORT)1000,                      */
                              /* (USHORT)ResourceId,                */
                              /* (PSEL)&SELECTOROF(pResourceFMF) ); */
                                 (ULONG)1000,             /* CON3201 */
                                 (ULONG)ResourceId,       /* CON3201 */
                                 (PVOID)&pResourceFMF );  /* CON3201 */

        if ( Result != DOS_OK )
        {
            TRACE6(TFUNC, "DosGetRes failed", FNULL, 0);
            return (ERROR_NEG);
        }

        /**************************************************************/
        /* Set offset to zero.                                        */
        /**************************************************************/
/*      OFFSETOF (pResourceFMF) = 0;                                 CON3201 */

        /**************************************************************/
        /* Get the dummy check byte for ease of use later.            */
        /**************************************************************/
        DummyByte = pResourceFMF[DUMMY_FMF_CHECK_BYTE];

        /**************************************************************/
        /* Four cases:                                                */
        /*    - 0xFF : dummy FMF with byte index into base FMF        */
        /*    - 0xFE : dummy FMF with word index into base FMF        */
        /*    - 0xFC : dummy FMF, same as 0xFE except resourceID      */
        /*             (index) into other resident FMF.               */
        /*    - 0xFD : Multi-code page FMF                            */
        /*    - None of these : normal Font Metric File               */
        /**************************************************************/
        if ( DummyByte == MULTICP_FMF_VALUE )
        {
            /**********************************************************/
            /* Length of the font metric file is the second and third */
            /* byte. This length includes the length fields and the   */
            /* first byte which are not required in the copy.         */
            /**********************************************************/
            FMFFileSize = pResourceFMF[2] * 256 + pResourceFMF[1] - 3;

            /**********************************************************/
            /* Get memory for the font metric file                    */
            /**********************************************************/
            if ( prdg_AllocGlobalHeapItem(
                         FMFFileSize,
                      /* (PBYTE far *)ppFMFData ) != OK ) */
                         (PBYTE *)ppFMFData ) != OK )     /* CON3201 */
            {
                TRACE6(TFUNC, "Heap alloc error", FNULL, 0);
                return (ERROR_NEG);
            }

            /**********************************************************/
            /* Now copy the bytes. Ignore the first three bytes.      */
            /**********************************************************/
            prdu_memcpy( (PBYTE) *ppFMFData,
                         (PBYTE) pResourceFMF+3,
                         FMFFileSize );

        }

        else if ( DummyByte == DUMMY_FMF_CHECK_VALUE_FF ||
                  DummyByte == DUMMY_FMF_CHECK_VALUE_FE ||
                  DummyByte == DUMMY_FMF_CHECK_VALUE_FC  )
        {
            /**********************************************************/
            /* Dummy font metric file. Interpret dummy file to get a  */
            /* font metric file to start from. FMF indices start from */
            /* 1 (since zero is invalid) hence the factor of one.     */
            /**********************************************************/
            if ( DummyByte == DUMMY_FMF_CHECK_VALUE_FC )
                ResourceId =
                *( (PUSHORT)(pResourceFMF + DUMMY_FMF_RES_INDEX) ) + 1;
            else
                ResourceId = *(pResourceFMF + DUMMY_FMF_RES_INDEX) + 1;

            /**********************************************************/
            /* Search through previous entries in the font list to    */
            /* find the one whose metrics we will use as a base.      */
            /**********************************************************/
            Found = FALSE;

            for ( j = 0; j < NoDefinedFonts; j++ )
            {
                if ( pDDT->DDTFontList[j]->ResourceId == ResourceId )
                {
                    /**************************************************/
                    /* Matched resource identifiers                   */
                    /**************************************************/
                    Found     = TRUE;
                    pValidFMF = pDDT->DDTFontList[j]->pFMFData;
                    break;
                }
            }

            /**********************************************************/
            /* Could not find the resource identifier. Let the        */
            /* calling function ignore this font.                     */
            /**********************************************************/
            if (!Found)
            {
                TRACE8(TFUNC, "Bad ResourceId", FNULL, 0);
                return (ERROR_NEG);
            }

            /**********************************************************/
            /* Allocate space for the valid font metric file          */
            /**********************************************************/
            if ( (pValidFMF->WidthFlag & FMF_WIDTH_MASK) == 0 )
            {
                FMFFileSize = FMF_SIZE_PROP_SPACED;
            }
            else
            {
                FMFFileSize = FMF_SIZE_FIXED_PITCH;
            }

            if ( prdg_AllocGlobalHeapItem(
                      FMFFileSize,
                   /* (PBYTE far *)ppFMFData ) != OK ) */
                      (PBYTE *)ppFMFData ) != OK )         /* CON3201 */
            {
                TRACE6(TFUNC, "Heap alloc error", FNULL, 0);
                return (ERROR_NEG);
            }

            /**********************************************************/
            /* Copy across the FMF data we use as a base.             */
            /**********************************************************/
            prdu_memcpy( (PBYTE) *ppFMFData,
                         (PBYTE) pValidFMF,
                         FMFFileSize );

            /**********************************************************/
            /* Position pDummyFMFData to point to the start of the    */
            /* change info.  Find out the number of bytes we need to  */
            /* change.                                                */
            /**********************************************************/
            if ( DummyByte == DUMMY_FMF_CHECK_VALUE_FC )
                pDummyFMF = pResourceFMF + DUMMY_FMF_NO_OF_PAIRS_FC;
            else
                pDummyFMF = pResourceFMF + DUMMY_FMF_NO_OF_PAIRS;

            NoOfChangeBytes = *pDummyFMF++;

            /**********************************************************/
            /* Change the Code Page metrics according to the data in  */
            /* the dummy FMF file.                                    */
            /**********************************************************/
            if (DummyByte == DUMMY_FMF_CHECK_VALUE_FE ||
                DummyByte == DUMMY_FMF_CHECK_VALUE_FC )
            {
                /******************************************************/
                /* Get two byte index/offset                          */
                /******************************************************/
                for ( j = 0; j < NoOfChangeBytes; j++ )
                {
                    usByteOffset  = pDummyFMF[0] + 256 * pDummyFMF[1];

                    /**********************************************************/
                    /* PD00595 : Add if stmt to check for Multi Codepage FMF  */
                    /**********************************************************/
                    if ( pValidFMF->Metrics.usCodePage == 0 )
                    {
                        /******************************************************/
                        /* This is a Multi codepage FMF type 0xFD that has    */
                        /* been compressed.  The index is 3 too large due to  */
                        /* the 3 bytes at the beginning of a 0xFD FMF that are*/
                        /* ignored, so subtract 3 from the index to get the   */
                        /* memory offset that needs to be updated.            */
                        /******************************************************/
                        usByteOffset -= 3;
                    }

                    ByteValue     = pDummyFMF[2];
                    pDummyFMF    += 3;

                    ((PBYTE)*ppFMFData)[usByteOffset] = ByteValue;
                }
            }
            else
            {
                /******************************************************/
                /* Get one byte index                                 */
                /******************************************************/
                for ( j = 0; j < NoOfChangeBytes; j++ )
                {
                    usByteOffset = pDummyFMF[0];
                    ByteValue    = pDummyFMF[1];
                    pDummyFMF    += 2;

                    ((PBYTE)*ppFMFData)[usByteOffset] = ByteValue;
                }
            }
        }
        else
        {
            /**********************************************************/
            /* Full font metric file. But could be the old style 4019 */
            /* which needs conversion.                                */
            /**********************************************************/
            DummyByte = pResourceFMF[ FMF_STYLE_CHECK_BYTE ];

            /**********************************************************/
            /* There is some initial processing that is common to     */
            /* both arms Thus calculate the target length ...         */
            /**********************************************************/
            if ( (((lpFMFFileStruc)pResourceFMF)->WidthFlag
                                                & FMF_WIDTH_MASK) == 0 )
                FMFFileSize = FMF_SIZE_PROP_SPACED;
            else
                FMFFileSize = FMF_SIZE_FIXED_PITCH;

            /**********************************************************/
            /* ... and get the memory for the target metric.          */
            /**********************************************************/
            if ( prdg_AllocGlobalHeapItem(
                         FMFFileSize,
                      /* (PBYTE far *)ppFMFData ) != OK ) */
                         (PBYTE *)ppFMFData ) != OK )      /* CON3201 */
            {
                TRACE6(TFUNC, "Heap alloc error", FNULL, 0);
                return (ERROR_NEG);
            }


            if (DummyByte == FILE_NOT_OLD_STYLE_CARSON)
            {
                /******************************************************/
                /* For a normal Font Metric File just copy the bytes. */
                /******************************************************/
                prdu_memcpy( (PBYTE) *ppFMFData,
                             (PBYTE) pResourceFMF,
                             FMFFileSize );
            }
            else
            {
                /******************************************************/
                /* For an old style IBM4019 Font metric File, copy by */
                /* hand and add some extra fields. So first copy the  */
                /* indentical bytes.                                  */
                /******************************************************/
                prdu_memcpy( (PBYTE) *ppFMFData,
                             (PBYTE) pResourceFMF,
                             FMF_SIZE_4019_COMMON );

                FilePtr = (PBYTE)*ppFMFData + FMF_SIZE_4019_COMMON;

                /******************************************************/
                /* Write the correct values into the next 2 bytes     */
                /* (PrinterType and DriverType), and reset the style  */
                /* flag.  The PrinterType value takes advantage of    */
                /* the fact that there are only 2 possible values of  */
                /* it in the new style 4019 files: 0 for the          */
                /* Laserprinters and 1 for the Heritage printers.     */
                /******************************************************/
                *(FilePtr - 1) |= FILE_NOT_OLD_STYLE_CARSON;

                *FilePtr++ = FILE_FOR_4019;
                *FilePtr++ = (BYTE)(PDBInstance->PrinterType >
                                                      IBM_4019_LASER_E);

                if ( FMFFileSize == FMF_SIZE_PROP_SPACED )
                {
                    /**************************************************/
                    /* Write the rest of the FMF (width table for PS  */
                    /* fonts).                                        */
                    /**************************************************/
                    prdu_memcpy( (PBYTE)FilePtr,
                                 (PBYTE)(pResourceFMF + FMF_SIZE_4019_COMMON),
                                 FMF_SIZE_4019_RESIDUE );
                }
            }
        }

        /**************************************************************/
        /* Free the resource.                                         */
        /**************************************************************/
        DosFreeResource ( pResourceFMF );
    }

    /******************************************************************/
    /* Finished with no problems.                                     */
    /******************************************************************/
    return OK;
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prde_LoadCodePageMetrics                                        */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  USHORT        CodePageNo;                                                 */
/*  lpPDBI        PDBInstance;                                                */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/******************************************************************************/
#if 0
USHORT pascal prde_LoadCodePageMetrics( CodePageNo,
                                        PDBInstance )

USHORT        CodePageNo;
lpPDBI        PDBInstance;
#endif

SHORT prde_LoadCodePageMetrics( USHORT CodePageNo,                 /* CON3201 */
                                lpPDBI PDBInstance )               /* CON3201 */

{
#define TFUNC "prde_LoadCPMtrc"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    USHORT             i;                /* Loop variables            */
    lplpFontCPListType FontCodePageList;
    lpFontCPListType   CodePageList;
    lpFontCPListType   pCodePageData;
    lpDDTType          pDDT;             /* Pointer to DDT in PDB     */


    TRACE4(TFUNC, "Entry", FNULL, 0);

    /******************************************************************/
    /* SEt up local pointers.                                         */
    /******************************************************************/
    pDDT = &PDBInstance->DDT;
    FontCodePageList = DVTFontCPList[PDBInstance->PrinterType];

    /******************************************************************/
    /* For each resident font get the metrics for the corresponding   */
    /* Code Page font. Note that there mey be fewer fonts in the code */
    /* page e.g. in the case of the 4224 printers.                    */
    /******************************************************************/
    for ( i = 0; i < pDDT->DDTFontsInCodePage; i++ )
    {
        /**************************************************************/
        /* Get the Code Page structure for this resident font and     */
        /* this code page.                                            */
        /**************************************************************/
        CodePageList  = FontCodePageList[i];
        pCodePageData = &CodePageList[CodePageNo - 1];

        TRACE6(TFUNC, "CodePageData", pCodePageData, 2);

        /**************************************************************/
        /* If the FMF file for the code page is a dummy and the       */
        /* metrics pointer has been set already then we dont need to  */
        /* reset it.  If the FMF file is not a dummy and the metrics  */
        /* pointer has been set already then we do need to reset the  */
        /* pointer since the segment previously returned from         */
        /* DosGetResource could have become invalid.                  */
        /*                                                            */
        /* PD00009 : FMFUseFlag is no longer needed because all font  */
        /*           metrics are allocated as memory not left as      */
        /*           resources. Prde_ReadFontResource controls the    */
        /*           allocation (or non-allocation) if necessary so   */
        /*           resources are never read twice. So remove the    */
        /*           code that follows.                               */
        /*                                                            */
        /**************************************************************/
/*      if ( (pCodePageData->FMFUseFlag == DUMMY_FMF) &&              */
/*           (pCodePageData->pFMFData != FNULL) )                     */
/*      {                                                             */
/*          TRACE6(TFUNC, "Ptr set already", FNULL, 0);               */
/*          continue;                                                 */
/*      }                                                             */

        /**************************************************************/
        /* Get the FMF from resources. The routine gets a valid FMF   */
        /* from a dummy, and also reads 4019 FMFs correctly.          */
        /**************************************************************/
        if (prde_ReadFontResource( &pCodePageData->pFMFData,
                                   pCodePageData->ResourceId,
                                /* &pCodePageData->FMFUseFlag, */
                                   (PBOOL)&pCodePageData->FMFUseFlag,/*CON3201*/
                                   pDDT->DDTNoOfResidentFonts,
                                   PDBInstance ) != OK )
            return ERROR_NEG;

        /**********************************************************************/
        /*  PD00220 : Copy the correct code page number into the metrics.     */
        /**********************************************************************/
        pCodePageData->pFMFData->Metrics.usCodePage =
                                   DVTCodePageList[CodePageNo].Number;


    }
    /* .... for ( i = 0; i < pDDT->DDTFontsInCodePage; i++) ......... */

    TRACE6(TFUNC, "Exit", FNULL, 0);
    return(OK);

}
#undef TFUNC





/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_DownloadFile                                      */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   PSZ           Path;                                              */
/*   PSZ           Filename;                                          */
/*   PSZ           Extension;                                         */
/*   USHORT        FontId;                                            */
/*   USHORT        FontLife;                                          */
/*   lpDCI         DCIData;                                           */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   Path, Filename and Extension are null terminated strings.        */
/*   Path and Extension can be empty; Filename must not be empty.     */
/*   Any value in extension overides an extension already included in */
/*   Filename.  Extension must include the initial point ('.').       */
/*                                                                    */
/*   The contents of the given file are downloaded to the printer.    */
/*                                                                    */
/*   The routine returns 1 (OK) or an error as follows:               */
/*     0      .. SSALLOCSEG, PrtWrite or SplQmWrite fail or           */
/*                 not all bytes read in DosRead                      */
/*     other  .. Dos error code                                       */
/*                                                                    */
/**********************************************************************/
#if 0
USHORT pascal prde_DownloadFile( Path,
                                 Filename,
                                 Extension,
                                 FontId,
                                 FontLife,
                                 DCIData )

PSZ              Path;
PSZ              Filename;
PSZ              Extension;
USHORT           FontId;
USHORT           FontLife;
lpDCI            DCIData;
#endif

SHORT prde_DownloadFile( PSZ    Path,                     /* CON3201 */
                         PSZ    Filename,                 /* CON3201 */
                         PSZ    Extension,                /* CON3201 */
                         USHORT FontId,                   /* CON3201 */
                         USHORT FontLife,                 /* CON3201 */
                         lpDCI  DCIData )                 /* CON3201 */

{
#define TFUNC "prde_DownLoadFl"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    lpPDBI       PDBInstance;        /* Pointer to the PDB            */
 /* USHORT       Result; */          /* Function call return values   */
                                                           /* CON3201 */
    SHORT        Result;             /* Function call return values   */
    BYTE         FullPathName[80];
    PBYTE        pDest;              /* Working pointers...           */
    PBYTE        pSource;            /*                    ...        */
    PBYTE        pExt;               /*                       ...     */
    HFILE        FileHandle;         /* File handle                   */
 /* USHORT       ActionTaken; */     /* Parameter for DosOpen         */
    ULONG        ActionTaken;        /* Parameter for DosOpen CON3201 */
    BYTE         FileInfoBuf[36];    /* Buffer for file info          */
    ULONG        FileSize;           /* Size of the font file         */
    USHORT       FileBufferSize;     /* Size of the font file buffer  */
    PBYTE        FileBuffer = FNULL; /* Buffer for font file data     */
                                     /* PD00607                       */
    ULONG        BytesRead;          /* returned from DosRead         */
    ULONG        BytesWritten;       /* In the PrtWrite macro         */
 /* USHORT       RetVal; */          /* The value to return at end    */
                                                           /* CON3201 */
    SHORT        RetVal;             /* The value to return at end    */
    DLFType      DLFData;


    TRACE8(TFUNC, "Entry", FNULL, 0);

    PDBInstance = DCIData->DCIPdbInstance;

    /******************************************************************/
    /* Build the full pathname for the file.                          */
    /******************************************************************/
    pDest = FullPathName;

    /******************************************************************/
    /* Start with the path if this not empty - add a backslash to     */
    /* the end if there isn't one already.                            */
    /******************************************************************/
    if ( Path )
    {
        for ( pSource = Path; *pSource != (BYTE)'\0'; )
            *pDest++ = *pSource++;

        if ( *(pDest - 1) != '\\' )
            *pDest++ = (BYTE)'\\';
    }

    TRACE4(TFUNC, "Path", FullPathName, 10);

    /******************************************************************/
    /* Add on the filename - this should never be empty.              */
    /* Record the position of the extension if there is one.          */
    /******************************************************************/
    pExt = FNULL;

    for ( pSource = Filename; *pSource != (BYTE)'\0'; )
    {
        if ( *pSource == (BYTE)'.' )
            pExt = pDest;
        *pDest++ = *pSource++;
    }

    /******************************************************************/
    /* Add the extension if this not empty.  Start at the end of the  */
    /* filename if there is no extension already.                     */
    /******************************************************************/
    if ( Extension )
    {
        if ( pExt )
            pDest = pExt;

        for ( pSource = Extension; *pSource != (BYTE)'\0'; )
            *pDest++ = *pSource++;
    }

    /******************************************************************/
    /* Finish off with a null terminator.                             */
    /******************************************************************/
    *pDest = (BYTE)'\0';

    TRACE4(TFUNC, "Full pathname", FullPathName, 10);

    /******************************************************************/
    /* Open the file.                                                 */
    /******************************************************************/
    Result = DosOpen( FullPathName,
                      &FileHandle,
                      &ActionTaken,
                      0L,
                      0x1,           /* File attribute - read only    */
                      1,             /* open flag - open if exists    */
                      0x42,          /* open mode                     */
                      0L);           /* reserved                      */

    if ( Result != DOS_OK )
    {
        TRACE4(TFUNC, "DosOpen failed", FNULL, 0);
        return (ERROR_NEG);
    }

    /******************************************************************/
    /* Errors from here on are sent to ERROR_EXIT - set up the        */
    /* default return code to OK.                                     */
    /******************************************************************/
    RetVal = OK;

    /******************************************************************/
    /* Get the file size.                                             */
    /******************************************************************/
    Result = DosQueryFileInfo( FileHandle,
                               1,
                               (PBYTE)FileInfoBuf,
                               36 );

    if ( Result != DOS_OK )
    {
        TRACE4(TFUNC, "DosQFileInfo failed", FNULL, 0);
        RetVal = ERROR_NEG;
        goto ERROR_EXIT;
    }

    /******************************************************************/
    /* Allocate memory for the file contents; allow for the           */
    /* possibility of the file being 64K or more.                     */
    /******************************************************************/
    FileSize       = *((PULONG)(FileInfoBuf + 12));
    FileBufferSize = (USHORT)min( FileSize,
                                  (ULONG)MAX_FILE_READ_LENGTH );

    TRACE4(TFUNC, "FileSize", &FileSize, 1);
    TRACE4(TFUNC, "FileBufferSize", &FileBufferSize, 1);

 /* Result = SSALLOCSEG ( FileBufferSize,          */
 /*                       &SELECTOROF(FileBuffer), */
 /*                       0 );                     */
    Result = SafeSSALLOCMEM ( &FileBuffer,                     /* CON3201 */
                              FileBufferSize, 0 );             /* CON3201 */

    if ( Result != DOS_OK )
    {
     /* LOGDOSERR(TFUNC, "SSALLOCSEG failed", &Result, 1, Result); */
        LOGDOSERR(TFUNC, "SSALLOCMEM failed", &Result, 1, Result); /* CON3201 */
        RetVal = ERROR_NEG;
        goto ERROR_EXIT;
    }

 /* OFFSETOF(FileBuffer) = 0;                                 CON3201 */

    /******************************************************************/
    /* Read in a chunk of the file and send it to the printer.        */
    /* Repeat this until all the file has been copied to the printer. */
    /******************************************************************/
    while ( (LONG)FileSize > 0 )
    {
        Result = DosRead( FileHandle,
                          (PVOID)FileBuffer,
                          FileBufferSize,
                       /* (PUSHORT)&BytesRead ); */
                          (PULONG)&BytesRead );            /* CON3201 */

        TRACE4(TFUNC, "Bytes read", &BytesRead, 1);

        if ( (Result != DOS_OK) || (BytesRead != FileBufferSize) )
        {
            RetVal = ERROR_NEG;
            goto ERROR_EXIT;
        }

        /**************************************************************/
        /* If this is an Queued RAW DC then output string to the      */
        /* spool file rather than to printer and return an error if   */
        /* this fails.                                                */
        /**************************************************************/
        TRACE4(TFUNC, "Send download data", FNULL, 0);

        if ( DCIData->DCIDCType != OD_QUEUED )
        {
            Result = prdn_PrtWrite( DCIData,
                                    FileBuffer,
                                    FileBufferSize,
                                    PDBInstance,
                                    BytesWritten );
            if ( Result != OK )
            {
                /******************************************************/
                /* ERR_ABORT, ERR_PURGE                               */
                /******************************************************/
                return( Result );
            }
        }
        else
        {
            if ( PDBInstance->PDBOutputType == IBMQRAW )
            {
                if ( SplQmWrite( (HSPL)DCIData->DCISplHandle,
                                 (ULONG)FileBufferSize,
                                 FileBuffer ) != OK )
                    return (ERROR_NEG);
            }
        }

        FileSize      -= MAX_FILE_READ_LENGTH;
        FileBufferSize = (USHORT)min( FileSize,
                                      (ULONG)MAX_FILE_READ_LENGTH );

        TRACE4(TFUNC, "FileSize", &FileSize, 1);
        TRACE4(TFUNC, "FileBuffer size", &FileBufferSize, 1);
    }


ERROR_EXIT:
    /******************************************************************/
    /* Free any segment used.                                         */
    /******************************************************************/
    if ( FileBuffer )
     /* SSFREESEG( SELECTOROF(FileBuffer) ); */
        SSFREEMEM( FileBuffer );                           /* CON3201 */

    /******************************************************************/
    /* Close the file.                                                */
    /******************************************************************/
    (void) DosClose(FileHandle);

    return (RetVal);

}
#undef TFUNC


/******************************************************************************/
/*  FUNCTION: prde_prde_DownloadCodePage                                      */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  USHORT        CodePageNo;                                                 */
/*  lpDCI         DCIData;                                                    */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/******************************************************************************/

#if 0
USHORT pascal prde_DownloadCodePage( CodePageNo,
                                     DCIData )

USHORT          CodePageNo;
lpDCI           DCIData;
#endif

SHORT prde_DownloadCodePage( USHORT CodePageNo,            /* CON3201 */
                             lpDCI  DCIData )              /* CON3201 */

{
#define TFUNC "prde_DownCdePge"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    lpPDBI             PDBInstance;      /* Pointer to the PDB        */
    lpPrtDataEntry     PrinterData;      /* Pointer to Printer Data   */
    USHORT             PrinterType;      /* Current printer type      */
    lpDVTCPSource      CodePageCaps;     /* Code Page capabilities    */
                                         /* array for this printer    */
    lpDVTCPSource      pCodePageInfo;    /* Code Page info for this   */
                                         /* code page                 */
 /* USHORT             Result;  */       /* Result of function call   */
                                                           /* CON3201 */
    SHORT              Result;           /* Result of function call   */
    USHORT             ResourceId;
    USHORT             FileSize;
    PBYTE              FileBuffer;
    USHORT             BytesWritten;     /* in PrtWrite macro         */
    BYTE               Dstname[13];   /* Code page bin file dst name  */
    PSZ                pDstname;      /* temp pointer to dst name     */
    PSZ                pSrcname;      /* temp pointer to src name     */
    USHORT             i;              /* Loop variable               */
    BYTE               bCount = 1;

    TRACE8(TFUNC, "Entry", FNULL, 0);

    /******************************************************************/
    /* First set up some pointers.                                    */
    /******************************************************************/
    PDBInstance   = DCIData->DCIPdbInstance;
    PrinterData   = PDBInstance->PrinterData;
    PrinterType   = PrinterData->PrinterType;

    CodePageCaps  = DVTCodePageCaps[PrinterType];
    pCodePageInfo = &CodePageCaps[CodePageNo];

    if ( ! (PDBInstance->DDT.DDTFontFlags & DDT_ADD_CODE_PAGE_SUPPORT) )
    {
        /**************************************************************/
        /* We shouldn't be here. Exit with error.                     */
        /**************************************************************/
        return (ERROR_NEG);
    }

    if ( (DCIData->DCIDCType == OD_QUEUED) &&
         (PDBInstance->PDBOutputType == IBMQSTD) )
    {
        TRACE8(TFUNC, "Qd Std:Exit", FNULL, 0);
        return (OK);
    }

    /******************************************************************/
    /* The download method depends on the code page source for this   */
    /* printer.                                                       */
    /******************************************************************/
    if ( pCodePageInfo->CPSource == CP_DOWNLOAD )
    {
        /**************************************************************/
        /* The Codepage binary filename is not the one in the data    */
        /* structure. When the binary files are copied they are re-   */
        /* named because there are some clashes of source names.      */
        /*                                                            */
        /* The new name is:                                           */
        /* - the first four characters of the source name             */
        /* - the codepage number in decimal.                          */
        /**************************************************************/
        pDstname = (PSZ)Dstname;
        pSrcname = pCodePageInfo->BINFileName;

        for ( i = 0; i < 4; i++ )
        {
            *pDstname++ = *pSrcname++;
        }

        prdm_WriteTextFromWord( DVTCodePageList[CodePageNo].Number,
                                3,
                                pDstname);

        *pDstname = (BYTE)'\0';

        TRACE6(TFUNC, "Code page path",
                            PrinterData->CPPathList[CodePageNo - 1], 1);
        TRACE6(TFUNC, "Code page BIN name", Dstname, 2);

        Result = prde_DownloadFile(
                              PrinterData->CPPathList[CodePageNo - 1],
                              Dstname,
                              BIN_EXTENSION,
                              0,                  /* not used for CPs */
                              0,                  /* not used for CPs */
                              DCIData );

        if ( Result != OK )
            return (Result);
    }
    else if ( pCodePageInfo->CPSource == CP_RESOURCE )
    {

        /**************************************************************/
        /* If it is a ProIII or a ProIIIXL, download the BIN file     */
        /* associated with ProII first and then follow it up with a   */
        /* download of the ProIII BIN file.  The PROII BIN file       */
        /* initializes the download areas and down loads codepoints   */
        /* to DRAFT/NLQ and NLQII Courier areas.  The PROIII BIN file */
        /* down loads codepoints to the NLQII Italic download area.   */
        /**************************************************************/

        if( (PrinterData->PrinterType == IBM_PRO_PRINTER_III)    ||
            (PrinterData->PrinterType == IBM_PRO_PRINTER_III_XL) )
        {
            PrinterType = IBM_PRO_PRINTER_II;
            bCount = 2;
        }

        for( i=1; i <= bCount; i++ )
        {
            if ( i==2 )
            {
                PrinterType = PrinterData->PrinterType;
            }

            CodePageCaps  = DVTCodePageCaps[PrinterType];
            pCodePageInfo = &CodePageCaps[CodePageNo];

            ResourceId = (USHORT)
                          ((lpDVTCPSourceRes)pCodePageInfo)->ResourceId;

            TRACE8(TFUNC, "ResourceId", &ResourceId, 1);

            /**********************************************************/
            /* Pick up the BIN file from resources.                   */
            /**********************************************************/
            Result = DosGetResource( (HMODULE)prdd_ModHandle,
                                  /* (USHORT)1000,        */
                                  /* (USHORT)ResourceId,  */
                                  /* (PSEL)&SelFontRes ); */
                                     (ULONG)1000,          /* CON3201 */
                                     (ULONG)ResourceId,    /* CON3201 */
                                     (PPVOID)&FileBuffer); /* CON3201 */

            TRACE4(TFUNC, "Selector", &SelFontRes, 1);

            if ( Result != DOS_OK )
            {
                TRACE6(TFUNC, "DosGetRes failed", FNULL, 0);
                return (ERROR_NEG);
            }

            /**********************************************************/
            /* Copy the BIN file contents to the printer.             */
            /**********************************************************/
            FileSize = (USHORT)
                         ((lpDVTCPSourceRes)pCodePageInfo)->BINFileSize;

            TRACE8(TFUNC, "BIN File Size", &FileSize, 1);

            /**********************************************************/
            /* If this is an Queued RAW DC then output data to the    */
            /* spool file rather than to printer and return an error  */
            /* if Do the downlaod of the code page.                   */
            /**********************************************************/
            if ( DCIData->DCIDCType != OD_QUEUED )
            {
                /******************************************************/
                /* For a non-queued job do the download direct to the */
                /* printer.                                           */
                /******************************************************/
                Result = prdn_PrtWrite( DCIData,
                                        FileBuffer,
                                        FileSize,
                                        PDBInstance,
                                        BytesWritten );
                if (Result != OK)
                {
                    /**************************************************/
                    /* ERR_ABORT, ERR_PURGE                           */
                    /**************************************************/
                    return( Result );
                }
            }
            else
            {
                /******************************************************/
                /* For a queued job if it is raw then add the         */
                /* download escape sequences to the spooler file.  If */
                /* it standard then do nothing.                       */
                /******************************************************/
                if ( PDBInstance->PDBOutputType == IBMQRAW )
                {
                    if ( SplQmWrite( (HSPL)DCIData->DCISplHandle,
                                     (ULONG)FileSize,
                                     FileBuffer ) != OK )
                    {
                        TRACE6(TFUNC, "SplQMWrite failed", FNULL, 0);
                        return (ERROR_NEG);
                    }
                }
            }
        }
    }

    /******************************************************************/
    /* PrinterData->CPCurrent is used to keep track of the code page  */
    /* currently in the printer's download area (and so is only       */
    /* affected by Direct jobs).                                      */
    /*                                                                */
    /* PDBInstance->CPJob is used by Queued Raw jobs to keep track    */
    /* of the last code page downloaded (to the spooler file) in      */
    /* order to reduce downloads to a minimum.  CPJob is              */
    /* initialised to NO_CODE_PAGE (in prde_InitialiseDownFonts) at   */
    /* the start of a Queued Raw job since we dont know what will be  */
    /* in the printer's download area when the Queued Raw job comes   */
    /* off the queue.                                                 */
    /*                                                                */
    /* 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 ( DCIData->DCIDCType == OD_DIRECT )
    {
        PrinterData->CPCurrent = CodePageNo;
    }
    else    /* Queued Raw */
    {
        PDBInstance->CPJob = CodePageNo;
    }

    TRACE8(TFUNC, "Exit", FNULL, 0);
    return (OK);

}
#undef TFUNC





/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_LoadResidentFontMetrics                           */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpPDBI            PDBInstance     Instance Data                  */
/*   USHORT            PelAddrFontType                                */
/*   USHORT            DContextType                                   */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function is called from FillPdb.  It sets up the metrics    */
/*   pointer and the base match number for each resident font.  It    */
/*   also calculates the total number of resident fonts including     */
/*   each attribute type.  It can handle dummy FMF files.             */
/*                                                                    */
/*   Return codes:                                                    */
/*      OK          -  Done                                           */
/*      ERROR_NEG  -  An error occurred goto FillPdb ERR_EXIT         */
/*                                                                    */
/**********************************************************************/
#if 0
USHORT pascal prde_LoadResidentFontMetrics( PDBInstance,
                                            PelAddrFontType,
                                            DContextType )

lpPDBI            PDBInstance;
USHORT            PelAddrFontType;
USHORT            DContextType;
#endif

SHORT prde_LoadResidentFontMetrics( lpPDBI PDBInstance,     /* CON3201 */
                                    USHORT PelAddrFontType, /* CON3201 */
                                    USHORT DContextType )   /* CON3201 */

{
#define TFUNC "prde_LoadResFMs"

    /**************************************************************************/
    /*  Local variables                                                       */
    /**************************************************************************/
    lpDDTType         pDDT;            /* Pointer to DDT in PDB       */
    USHORT            i,j;             /* Loop variables              */
 /* USHORT            return_value; */
    SHORT             return_value;                                /* CON3201 */
    ULONG             ItalicResId;
    BOOL              SetItalicFMF;
    SHORT             SystemCodePage;                               /* PD00604*/
    SHORT             FMFCodePage;                                  /* PD00604*/


    /**************************************************************************/
    /*  Set the pointer for the DDT in the PDB.                               */
    /**************************************************************************/
    pDDT = &PDBInstance->DDT;

    /**************************************************************************/
    /*  TotalResidentFonts is calculated (and used to get the match numbers)  */
    /*  regardless of whether device fonts are available or not.  FontList,   */
    /*  off the PDB instance data, is also set up regardless of whether device*/
    /*  fonts are available or not - this may be needed by AlterCodePage for a*/
    /*  RAW job even when there are no device fonts available for a BAND print*/
    /*  job.  FontCount is used to indicate whether device fonts are available*/
    /*  or not.                                                               */
    /**************************************************************************/
    PDBInstance->TotalResidentFonts = 0;
    PDBInstance->FontList           = pDDT->DDTFontList;

    /**************************************************************************/
    /*  Cycle through all the resident fonts to set up the total number of    */
    /*  fonts, and initialise the font fields in the DDT.                     */
    /**************************************************************************/
    for ( i = 0; i < pDDT->DDTNoOfResidentFonts; i++ )
    {
        /**********************************************************************/
        /*  PD00265 : If pFMFData is already set or this font doesn't need a  */
        /*  pointer to the italic metrics, set flag to FALSE otherwise it's   */
        /*  TRUE.                                                             */
        /**********************************************************************/
        if ( (pDDT->DDTFontList[i]->pFMFData != FNULL) ||
             (pDDT->DDTFontList[i]->pItalicFMF == FNULL) )
            SetItalicFMF = FALSE;
        else
            SetItalicFMF = TRUE;

        /**********************************************************************/
        /*  Get the resources.  The metric pointer is only updated if         */
        /*  necessary.  Essentially it needs updating if the metrics are      */
        /*  resources, and don't need updating if the the resoruces were      */
        /*  copied into global heap data.                                     */
        /**********************************************************************/
        if (prde_ReadFontResource(
                          &pDDT->DDTFontList[i]->pFMFData,
                   (USHORT)pDDT->DDTFontList[i]->ResourceId,
                          (PVOID)NULL,
                          i,
                          PDBInstance ) != OK )
        {
            return ERROR_NEG;
        }

        /**********************************************************************/
        /*  PD00265 : If we need to, read in the resources for the PS italic  */
        /*  fonts.                                                            */
        /**********************************************************************/
        if (SetItalicFMF)
        {
            /******************************************************************/
            /*  Initially pItalicFMF contains the resource id of the italic   */
            /*  fmf.  We must copy the id into another variable and clear     */
            /*  pItalicFMF so that ReadFontResource will work.                */
            /******************************************************************/
            ItalicResId = (ULONG)pDDT->DDTFontList[i]->pItalicFMF;
            pDDT->DDTFontList[i]->pItalicFMF = FNULL;

            /******************************************************************/
            /*  PD00375 : add one to number of fonts to check through as      */
            /*  we just added one to the list and i hasn't been incremented   */
            /*  yet                                                           */
            /******************************************************************/
            if (prde_ReadFontResource(
                          &pDDT->DDTFontList[i]->pItalicFMF,
                          (USHORT)ItalicResId,
                          (PVOID)NULL,
                          i+1,
                          PDBInstance ) != OK )
            {
                return ERROR_NEG;
            }
        }

        pDDT->DDTFontList[i]->pMultiCp = NULL;

        /**********************************************************************/
        /* PD00220 : grab the code page from the font structure, not the      */
        /* metrics for the Nile/Tiber/4226.                                   */
        /*                                                                    */
        /* PD00290 : also need it for X24E and XL24E resident fonts.          */
        /**********************************************************************/
        if ( (pDDT->DDTDriverType == DDT_IBM42XX_DRV) &&
             ( (PDBInstance->PrinterType > IBM_4224_MONO) ||
               (PDBInstance->PrinterType == IBM_PRO_PRINTER_X24E) ||
               (PDBInstance->PrinterType == IBM_PRO_PRINTER_XL24E) ) )
        {
            pDDT->DDTFontList[i]->pFMFData->Metrics.usCodePage =
                                         pDDT->DDTFontList[i]->CodePage;
            /******************************************************************/
            /*  Fill in the Inline Direction for the Arabic/Hebrew code pages */
            /******************************************************************/
            if ( (pDDT->DDTFontList[i]->CodePage == 862) ||
                 (pDDT->DDTFontList[i]->CodePage == 864) )
            {
                pDDT->DDTFontList[i]->pFMFData->Metrics.sInlineDir = 180;
            }
        }

        /******************************************************************/
        /*  PD00651 : Must check for the Courier PS fonts on the extended */
        /*  NLS 238x machines and continue out of the loop if it is one   */
        /*  of these fonts in the extended NLS code pages, otherwise we   */
        /*  will continue on inside the loop.                             */
        /******************************************************************/
        if ( (pDDT->DDTDriverType == DDT_IBM42XX_DRV) &&
             ((PDBInstance->PrinterType == IBM_NILE_9) ||
              (PDBInstance->PrinterType == IBM_TIBER_9)) &&
             (pDDT->DDTNoOfResidentFonts == NLS_9WIRE) )
        {
           /***************************************************************/
           /*  Check for a Courier PS font in one of the extended NLS     */
           /*  code pages. 852 = 134, 855 = 135, 857 = 136, 862 = 138,    */
           /*  864 = 140, and 869 = 142.  These are the indexes of these  */
           /*  fonts into the font list.                                  */
           /***************************************************************/
           if ( ((i >= 134) && (i <=136)) ||
                (i == 138) || (i == 140) || (i == 142) )
           {
              continue;
           }
        }

        /**********************************************************************/
        /*  Keep track of the total number of resident fonts, including the   */
        /*  attributed versions.  This is in the instance data not the DDT so */
        /*  needs calculating for each DC.                                    */
        /*                                                                    */
        /* PD00604 : We have added a new button to Printer Fonts for Nile/    */
        /*  Tiber/Dakota to limit the number of fonts returned.   We only     */
        /*  return fonts in the system code page and code pages 437 and 850.  */
        /*  Also for the 24wires we will limit the attributes to normal       */
        /*  and DW DH only.                                                   */
        /*  600DPI : Must use the data structure that all of the drivers use. */
        /**********************************************************************/
        if ( (pDDT->DDTDialogFlags & DDT_LIMIT_FONTS) &&
             (PDBInstance->DDT.DDTPrinterFonts == DEV_FONTS_LIMITED) )
        {
            SystemCodePage = (SHORT)WinQueryProcessCP();
            FMFCodePage = pDDT->DDTFontList[i]->pFMFData->Metrics.usCodePage;

            /******************************************************************/
            /* Check the font's code page (and attributes on 239x) to see     */
            /* if we add to TotalResidentFonts.                               */
            /******************************************************************/
            if ( (FMFCodePage == 437) || (FMFCodePage == 850) ||
                 (FMFCodePage == SystemCodePage) )
            {
                if ( (pDDT->DDTDriverType == DDT_IBM42XX_DRV) &&
                     ( (PDBInstance->PrinterType == IBM_NILE_24 ) ||
                       (PDBInstance->PrinterType == IBM_TIBER_24 ) ||
                       (PDBInstance->PrinterType == IBM_2390_PS1) ) )
                {
                    if ( pDDT->DDTFontList[i]->Attrs & FATT_BOTH )
                        PDBInstance->TotalResidentFonts += 2;
                    else
                        PDBInstance->TotalResidentFonts +=
                                         pDDT->DDTFontList[i]->NumAttrs;
                }
                else
                {
                    PDBInstance->TotalResidentFonts +=
                                         pDDT->DDTFontList[i]->NumAttrs;
                }

            } /* if ( (FMFCodePage == 437) || (FMFCodePage == 850) ...       */
        }
        else
        {
            PDBInstance->TotalResidentFonts +=
                                         pDDT->DDTFontList[i]->NumAttrs;
        }

    }

    /**************************************************************************/
    /*  PD00178 : Switch off device fonts for memory DCs as well as device    */
    /*  fonts not available and landscape mode.                               */
    /*                                                                        */
    /*  Work out whether there are any resident fonts available for this job  */
    /*  (e.g.  none if LANDSCAPE and not a laser printer).                    */
    /**************************************************************************/
    if ( ( PDBInstance->DDT.DDTPrinterFonts == DEV_FONTS_NOT_AVAIL  ) ||
         ( DContextType    == OD_MEMORY            ) ||
         ( (PDBInstance->Orientation == LANDSCAPE) &&
                      (!(pDDT->DDTInitFlags & DDT_INIT_ORIENTATION)) ) )
    {
        /**********************************************************************/
        /*  No resident fonts in this job.                                    */
        /*                                                                    */
        /*  We use a value of FontCount to act as a flag for Dev Fonts not    */
        /*  available.  Its value is 0xFFFF (note that FontCount is a USHORT).*/
        /**********************************************************************/
        PDBInstance->FontCount = NO_RESIDENT_FONTS;
    }
    else
    {
        PDBInstance->FontCount = pDDT->DDTNoOfResidentFonts;
    }


    TRACE6(TFUNC, "TotalResidentFonts",
                                 &(PDBInstance->TotalResidentFonts), 1);
    return (OK);
}
#undef TFUNC


/******************************************************************************/
/*  FUNCTION: prde_InitialiseDownFonts                                        */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  lpDCI       DCIData;                                                      */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/******************************************************************************/

#if 0
USHORT pascal prde_InitialiseDownFonts( DCIData )

lpDCI           DCIData;

{
#define TFUNC "prde_InitDwnFnt"
#endif

SHORT prde_InitialiseDownFonts( lpDCI DCIData )                    /* CON3201 */

{
#define TFUNC "prde_InitDwnFnt"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    lpPDBI             PDBInstance;      /* Pointer to the PDB        */
    lpPrtDataEntry     PrinterData;      /* Pointer to Printer Data   */
    lpDDTType          pDDT;             /* Pointer to DDT in PDB     */
 /* USHORT             Result; */        /* Result of function call   */
                                                           /* CON3201 */
    SHORT              Result;           /* Result of function call   */
    lpDownFontListType pDownFont;        /* font to be downloaded     */
    USHORT             i;                /* Loop variable             */

    /******************************************************************/
    /* Set up pointers.                                               */
    /******************************************************************/
    PDBInstance = DCIData->DCIPdbInstance;
    PrinterData = PDBInstance->PrinterData;
    pDDT        = &PDBInstance->DDT;

    /******************************************************************/
    /* This function sets up initial download fonts and code pages    */
    /* on the printer - IT ONLY SENDS OUT STUFF FOR A DIRECT DC.      */
    /* It is called at the start of the first page for any job.       */
    /*                                                                */
    /* The action taken by the function depends on the DC type as     */
    /* follows:                                                       */
    /*                                                                */
    /* - DIRECT ........ Set up initial download fonts and code pages */
    /*     on the printer and set PrinterData->CPCurrent which keeps  */
    /*     track of the code page in the printer download area.       */
    /*     (CPCurrent is actually set within prde_DownloadCodePage).  */
    /*                                                                */
    /* - QUEUED (RAW) .. We do not want to send anything to the       */
    /*     spooler file.  If we did, and turned off the code page     */
    /*     init reload flag, and then another job was run and came    */
    /*     off the queue first then that job COULD find that the      */
    /*     initial code page was not set up correctly for it when it  */
    /*     got down to the printer.                                   */
    /*                                                                */
    /*     We won't know for sure what will be in the download        */
    /*     area when the Queued Raw job comes off the queue.  We      */
    /*     set PDBInstance->CPJob to either the initial code page or  */
    /*     to NO_CODE_PAGE (if there is no initial code page) as a    */
    /*     reasonable assumption.   This is initialised in            */
    /*     prde_GetCodePageList                                       */
    /*                                                                */
    /*     This is not guaranteed to print text in the initial code   */
    /*     page correctly (the code page in the download area may     */
    /*     have been altered) but:                                    */
    /*     - any other assumption will produce unnecessary downloads  */
    /*     - the user can always use the per-job download flag to     */
    /*       force downloading.                                       */
    /*                                                                */
    /* - QUEUED (STD) .. We shouldn't be here in this case, return    */
    /*     with an error.                                             */
    /*                                                                */
    /* PrinterData->CPCurrent and PDBInstance->CPJob are updated      */
    /* within prde_DownloadCodePage.                                  */
    /*                                                                */
    /******************************************************************/
    if ( DCIData->DCIDCType == OD_QUEUED )
    {
        if ( PDBInstance->PDBOutputType == IBMQSTD )
            return (ERROR_NEG);
        else
            return (OK);
    }

    /******************************************************************/
    /* In order to avoid offline problems on the Pro II & Pro III do  */
    /* a dummy download if this is the first time we write to the     */
    /* printer.  This will destroy any current download code page in  */
    /* the printer.  If we are about to download an initial code page */
    /* doing the dummy download wont do any harm so do it in this     */
    /* case as well for good measure.                                 */
    /*                                                                */
    /* We actually do this download for all the Proprinters but not   */
    /* the 4224 printers; in effect we do the download for all the    */
    /* printers which support downloadable code pages.                */
    /******************************************************************/
    if ( (pDDT->DDTFontFlags & DDT_ADD_CODE_PAGE_SUPPORT) &&
         (PrinterData->DataChange &
                            (FIRST_DIRECT_DC | CODE_PAGE_INIT_RELOAD)) )
    {
        if ( (Result = prdp_PrintSimple( DCIData,
                                         USE_GLOBAL_TABLE,
                                         EST_DUMMY_DOWNLOAD,
                                         FNULL) ) != OK )
        {
            return (Result);
        }

        PrinterData->DataChange &= ~FIRST_DIRECT_DC;
    }

    if ( PrinterData->DataChange & CODE_PAGE_INIT_RELOAD )
    {
        TRACE8(TFUNC, "Download init CP", &PrinterData->CPCurrent, 1);

        /**************************************************************/
        /* Download the initial code page.                            */
        /**************************************************************/
        Result = prde_DownloadCodePage( PrinterData->CPCurrent,
                                        DCIData );

        if ( Result != OK )
            return (Result);

        /**************************************************************/
        /* Turn off the load initial code page bit.                   */
        /**************************************************************/
        PrinterData->DataChange &= ~CODE_PAGE_INIT_RELOAD;
    }

    TRACE8(TFUNC, "Change flag", &PrinterData->DataChange, 1);
    return (OK);

}
#undef TFUNC
