/*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 = PRDEFPDB
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prde_FillPdb
 *             prde_GetPrinterInfo
 *             prde_SetPageAtts
 *             prde_ChooseForms
 *             prde_GetFormDimensions
 *             prde_GetOutputType
 *             prde_FindDrvDataFormNo
 *             prde_FindDfltFormNo
 *             prde_SetMachineType
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

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

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

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

#include <prdconse.h>

#include <prddcone.h>

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

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

#include <prdmtypt.h>

#include <prdeextf.h>
#include <prdgextf.h>
#include <prdyextf.h>
#include <prduextf.h>

/**********************************************************************/
/* Set up access to external data structures.                         */
/**********************************************************************/
extern lpDDTType            DDT [];
extern HMODULE              prdd_ModHandle;
extern USHORT               DRIVER_TYPE;
extern CHAR                 szIBMQSTD[];
extern CHAR                 szIBMQESC[];
extern CHAR                 szIBMQRAW[];
extern PCHAR                OS2_DD_MAGIC_NUMBER;
extern PCHAR                OS2_DD_MAGIC_NUMBER2;   /* PD00587 */
extern PCHAR                OS2_DD_MAGIC_NUMBER3;   /* PD00651 */
extern PCHAR                OS2_DD_MAGIC_NUMBER4;   /* PD00769 - 600DPI */
extern PCHAR                OS2_INI_THRESHOLD;
extern PCHAR                OS2_INI_MAGIC_NUMBER1;
extern USHORT               NO_OF_PRINTERS;
extern USHORT               DEFAULT_PRINTER;
extern PCHAR                DriverNameString;
extern PCHAR                InternalDriverName;
extern lpDMSettings         DVTDfltDMSettings [];
extern lpFontListType       DVTFontList9Wire [];
extern lpFontListType       DVTFontList9WireNLS [];
extern lpFontListType       DVTFontList24Wire [];
extern lpFontListType       DVTFontList24WireNLS [];

/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_FillPdb                                           */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   See "OS/2 Technical Reference: I/O Subsytems and Device Drivers" */
/*   FillPhysicalDeviceBlock                                          */
/*                                                                    */
/*   FPParamsLst far   *param1;                                       */
/*   Dword              param2;                                       */
/*                                                                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*   ------------                                                     */
/*                                                                    */
/* Param1 has fields:   DcType;    QUEUED, DIRECT, INFO or MEMORY     */
/*                      DO;        a structure of type DEVOPENSTRUCT  */
/*                                                                    */
/* The structure DO has fields:                                       */
/*                      pszLogAddress;          e.g. LPT1 or LPT1Q    */
/*                      pszDriverName;          e.g. IBM42XX          */
/*                      pdriv;                                        */
/*                      pszDataType;            STD or RAW            */
/*                      pszComment;                                   */
/*                      pszQueueProcName;                             */
/*                      pszQueueProcParams;                           */
/*                      pszSpoolerParams;                             */
/*                      pszNetworkParams;                             */
/*                                                                    */
/* pdriv is a structure of type DRIVDATA that contains info from      */
/* the Job Setup dialog box. We call this information DriverData.     */
/*                                                                    */
/* The main jobs of FillPDB are to                                    */
/*              - work out what device we are outputting to and       */
/*                open it if necessary                                */
/*              - initialise PDB with e.g. orientation and            */
/*                page size                                           */
/*              - keep track of the state of the printer as to        */
/*                cards, download fonts etc. and update it            */
/*                                                                    */
/* For the first of these we have various sources of info:            */
/* pszLogAddress passed in in param1, SpoolerIniInfo and              */
/* AppDefaultIniInfo (discussed below) and we do complicated things   */
/* to get a valid output name (see prde_GetLogAddress). We use        */
/* this to open a device in prde_OpenSpooler and prde_OpenPort.       */
/*                                                                    */
/* For the second we need to know which type of printer (e.g. Pro II) */
/* we're using; to find this we use the PrinterName (which we have    */
/* found by now from prde_GetLogAddress ) to find the right entry     */
/* in PrinterIniInfo (our driver info which comes from the Printer    */
/* Setpu dialog), and we use the printer type selected there. If this */
/* doesn't work we might use the printer type passed in in DriverData,*/
/* the printer type associated with the first pinter listed in        */
/* PrinterIniInfo, or the default printer type. This is worked out in */
/* prde_GetPrinterType. We set up info in the PDB with                */
/* prde_GetPrinterInfo.                                               */
/*                                                                    */
/* For the last job we set up a structure called PrinterStateData     */
/* which records the previous state of each printer we've printed on  */
/* since boot-up. We re-initialise this if necessary and fill in info */
/* DataChange flags. This saves us having to initialise the printer   */
/* for every print job.                                               */
/*                                                                    */
/* A note about terminology:                                          */
/* _________________________                                          */
/* Printer name, logical printer name, device name are used           */
/*     interchangeably to mean the logical printer, e.g. PRINTER1.    */
/* PrinterType means e.g. ProIII.                                     */
/* Driver name means e.g. IBM42XX.                                    */
/* LogAddress means either a port, e.g. LPT1, or a queue, e.g. LPT1Q. */
/* OutputType or DataType means STD or RAW.                           */
/*                                                                    */
/* We use information stored in os2.ini and os2sys.ini. We use        */
/* three different entries, which I call AppDefaultIniInfo,           */
/* SpoolerIniInfo and PrinterIniInfo. The AppDefaultIniInfo is stored */
/* from the App Defaults dialog - we only use the default Printer.    */
/* SpoolerIniInfo records which printer is associated with which      */
/* queue with which driver, and is set up by the spooler. Finally     */
/* PrinterIniInfo is stored by our driver from the Printer Setup      */
/* dialog.                                                            */
/*                                                                    */
/* The contents of SpoolerIniInfo and of PrinterIniInfo are described */
/* at the tops of prde_GetLogAddress and prde_GetPrinterType          */
/* respectively.                                                      */
/*                                                                    */
/* PS INFO: 08/04/91 : probably don't use Appdefaultnfo any more      */
/**********************************************************************/
#if 0
ULONG pascal prde_FillPdb( param1,
                           param2 )

FPParamsLst far *  param1;
ULONG              param2;
#endif

ULONG prde_FillPdb( FPParamsLst *param1,                   /* CON3201 */
                    ULONG        param2 )                  /* CON3201 */

{
#define TFUNC "prde_FillPdb"
    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    USHORT               DCType;           /* Device context type     */
    USHORT               LogErrCode;       /* Error code to be logged */
    lpPDBI               PDBInstance;      /* Pointer to the PDB      */
    lpDDTType            pDDT;             /* Pointer to DDT in PDB   */
    pDMDriverStruc       DriverData;       /* Pointer to DriverData   */
                                           /* passed in in param1     */
    PBYTE                PrinterIniInfo;
    DMSettingsType       DMSettings;       /* stores PrinterIniInfo   */
    ULONG                MagicNumber;      /* numerical value of      */
    ULONG                MagicNumber2;     /* numerical value of      */
    ULONG                MagicNumber3;     /* numerical value of      */
    ULONG                MagicNumber4;     /* numerical value of      */
    ULONG                LowDDNumber;      /* numerical value of      */
    ULONG                HighDDNumber;     /* numerical value of      */
    PBYTE                pWork;            /* working pointer         */
    USHORT               IniVersionType;   /* current or old .ini     */
    USHORT               Result;           /* result of function call */
    /******************************************************************/
    /*  PD00041 :  Flag to determine when to use driver data.         */
    /******************************************************************/
    /******************************************************************/
    /*  PD00386 : Move this to a local variable to avoid possible     */
    /*            reentrancy problems.                                */
    /******************************************************************/
    /******************************************************************/
    /*  PD00479 : Move DriverDataConvert to PDBInstance.              */
    /******************************************************************/
    pDMDriverStruc       DriverData2;

#ifdef TEST_TYPE_INIT
    OutputString("FillPDB...");
    OutputString("Passed in: " );
    OutputString(param1->DO.pszLogAddress);
#endif

#ifdef DEBUG_FSM
    OutputString("Enter FillPDB...");
    OutputPair("Param1: ", (ULONG)param1, HEX );
    OutputString("LogAddress: " );
    OutputString(param1->DO.pszLogAddress);
#endif
#ifdef PRD_TIMING
    DEKHOOK0(A,7,3A)
#endif

    /******************************************************************/
    /* Set up DCType and exit if it's invalid.                        */
    /******************************************************************/
    DCType = param1->DcType;

    if ( !(   ( DCType == OD_DIRECT )
           || ( DCType == OD_QUEUED )
           || ( DCType == OD_INFO )
           || ( DCType == OD_MEMORY ) ) )
    {
        LogErrCode = PMERR_INV_DC_TYPE;
        goto LOGERR_EXIT;
    }

    /******************************************************************/
    /* Get memory for the PDB instance data.                          */
    /******************************************************************/
    if ( prdg_AllocGlobalHeapItem( sizeof(PDBIType),
                                /* (PBYTE far *)&PDBInstance) != OK ) */
                                   (PBYTE *)&PDBInstance) != OK ) /*CON3201*/
    {
        TRACE6(TFUNC, "Alloc Glob Heap for PDB failed", FNULL, 0);
        LogErrCode = PMERR_NOT_ENOUGH_MEM;
        goto LOGERR_EXIT;
    }


    /******************************************************************/
    /* Get a local pointer to the DDT.                                */
    /******************************************************************/
    pDDT = &(PDBInstance->DDT);

    /******************************************************************/
    /* Set SplData pointer to FNULL          PD00227                  */
    /******************************************************************/
    PDBInstance->lpSplData = FNULL;

    /**************************************************************/
    /* Check that the driver name is the driver we are part of.   */
    /**************************************************************/

    if ( param1->DO.pszDriverName )
    {

        /**************************************************************/
        /* Copy DriverName into DriverNameString and set it to        */
        /* uppercase. PD00175                                         */
        /**************************************************************/
        (VOID) prdu_strcpy( (PBYTE)DriverNameString,
                            (PBYTE)param1->DO.pszDriverName);

        (VOID) prdu_strupr( (PBYTE)DriverNameString );

        /**************************************************************/
        /* A DriverName was passed in. Compare against the string     */
        /* defined in the drivers data segment.                       */
        /**************************************************************/
        if ( prdu_strcmp( (PBYTE)InternalDriverName,
                          (PBYTE)DriverNameString ) )
        {
            /**********************************************************/
            /* The DriverName wasn't our driver. Exit with an error.  */
            /**********************************************************/
            LogErrCode = PMERR_INV_DRIVER_NAME;
            goto LOGERR_EXIT;
        }
        else
        {
            /**************************************************************/
            /* Copy DriverName into DriverNameString and set the case back*/
            /* to its original form.  PD00175                             */
            /**************************************************************/
            (VOID) prdu_strcpy( (PBYTE)DriverNameString,
                                (PBYTE)param1->DO.pszDriverName);

        }

    }
    else
    {
        /**************************************************************/
        /* Copy InternalDriverName into DriverNameString.             */
        /**************************************************************/
        (VOID) prdu_strcpy( (PBYTE)DriverNameString,
                            (PBYTE)InternalDriverName);

    }

    /******************************************************************/
    /* Put the (now validated) DriverName into the instance data.     */
    /* FIX : AK 04/25/91 : allocate strlen(name) + 1 to allow         */
    /* for the terminating null.                                      */
    /******************************************************************/
    if ( OK != prdg_AllocGlobalHeapItem(
                       (USHORT)(prdu_strlen(DriverNameString) + 1),
                    /* (PBYTE far *)&(PDBInstance->PDBDriverName) ) ) */
                       (PBYTE *)&(PDBInstance->PDBDriverName) ) ) /*CON3201*/
    {
        LogErrCode = PMERR_NOT_ENOUGH_MEM;
        goto LOGERR_EXIT;
    }

    PDBInstance->DriverDataConvert = FALSE;            /* Initialize */
    PDBInstance->MinorDriverDataConvert = FALSE;      /* Initialize - PD00665 */

    (VOID) prdu_strcpy( (PBYTE)PDBInstance->PDBDriverName,
                        (PBYTE)DriverNameString );

    /******************************************************************/
    /* Initial checks on the driver data. It fails if:                */
    /* - there was none there                                         */
    /* - the size is not as expected                                  */
    /* - the version number is earlier than we support                */
    /******************************************************************/
    /******************************************************************/
    /* First calculate the numerical value of the version number      */
    /* string.                                                        */
    /******************************************************************/
    pWork = OS2_DD_MAGIC_NUMBER;
    MagicNumber = 0;
    while (*pWork)
    {
       MagicNumber = (MagicNumber << 4) + (*pWork++ - '0');
    }

    /**************************************************************************/
    /* PD00587: we have a new magic number for DRIVERDATA as we have had to   */
    /*  add a new field.                                                      */
    /**************************************************************************/
    pWork = OS2_DD_MAGIC_NUMBER2;
    MagicNumber2 = 0;
    while (*pWork)
    {
       MagicNumber2 = (MagicNumber2 << 4) + (*pWork++ - '0');
    }

    /**************************************************************************/
    /* PD00651: we have a new magic number for DRIVERDATA as we have had to   */
    /*  add a new field.                                                      */
    /**************************************************************************/
    pWork = OS2_DD_MAGIC_NUMBER3;
    MagicNumber3 = 0;
    while (*pWork)
    {
       MagicNumber3 = (MagicNumber3 << 4) + (*pWork++ - '0');      /* PD00664 */
    }

    /**************************************************************************/
    /* PD00769 : Have a new magic number for DRIVERDATA as we have had to     */
    /*  add a new fields. 600DPI also.                                        */
    /**************************************************************************/
    pWork = OS2_DD_MAGIC_NUMBER4;
    MagicNumber4 = 0;
    while (*pWork)
    {
       MagicNumber4 = (MagicNumber4 << 4) + (*pWork++ - '0');
    }

    pWork = OS2_INI_THRESHOLD;
    LowDDNumber = 0;
    while (*pWork)
    {
       LowDDNumber = (LowDDNumber << 4) + (*pWork++ - '0');
    }

    pWork = OS2_INI_MAGIC_NUMBER1;
    HighDDNumber = 0;
    while (*pWork)
    {
       HighDDNumber = (HighDDNumber << 4) + (*pWork++ - '0');
    }

    /******************************************************************/
    /*  PD00041 : Convert old driver data.                            */
    /******************************************************************/

    /******************************************************************/
    /* Now start checking.                                            */
    /******************************************************************/
    if ( (param1->DO.pdriv == FNULL) ||
         ( (param1->DO.pdriv->lVersion < MagicNumber) &&
           ( (param1->DO.pdriv->lVersion < LowDDNumber) ||
             (param1->DO.pdriv->lVersion > HighDDNumber) ) ) )
    {
        /**************************************************************/
        /* DriverData invalid.                                        */
        /**************************************************************/
        DriverData = NULL;
    }
    else
    {
        /**************************************************************/
        /* DriverData looks valid, unless of course the driver name   */
        /* that we ourselves have stored is incorect.                 */
        /**************************************************************/
        /**************************************************************/
        /*  If it is the old type get some memory to hold the new     */
        /*  driver data.                                              */
        /*                                                            */
        /*  PD00587 : we now have a bigger DriverData as we had to    */
        /*  add a new resolution field to do 360x360. So we need to   */
        /*  check for MagicNumber2.                                   */
        /*  PD00651 : Change MagicNumber2 to MagicNumber3             */
        /*  600DPI  :                                                 */
        /*  PD00769 : Changed MagicNumber3 to MagicNumber4            */
        /**************************************************************/

        if ( ( (param1->DO.pdriv->lVersion >= LowDDNumber) &&
               (param1->DO.pdriv->lVersion < HighDDNumber) ) ||
             ( (param1->DO.pdriv->lVersion >= MagicNumber) &&
               (param1->DO.pdriv->lVersion <  MagicNumber4) ) )
        {
        /* Result = SSALLOCSEG ( sizeof(DMDriverStruc),   */
        /*                       &SELECTOROF(DriverData), */
        /*                       0);                      */
           Result = SafeSSALLOCMEM ( &DriverData,          /* CON3201 */
                                 sizeof(DMDriverStruc),    /* CON3201 */
                                 0);                       /* CON3201 */

           if (Result != DOS_OK)
           {
#ifdef PRD_TIMING
    DEKHOOK0(A,7,BA)
#endif
              return ((ULONG)ERROR_ZERO);
           }

/*         OFFSETOF(DriverData) = 0;                                  CON3201 */
           prdu_memset((PBYTE)DriverData, 0, sizeof(DMDriverStruc));

           /***********************************************************/
           /*  Translate the old driver data.                         */
           /***********************************************************/
           if ((USHORT)param1->DO.pdriv->cb >= 99)
           {
              /****************************************************************/
              /*  PD00587 : if it is a migratable version prior to 200        */
              /****************************************************************/
              if ( (param1->DO.pdriv->lVersion >= LowDDNumber) &&
                   (param1->DO.pdriv->lVersion < HighDDNumber) )
              {
                  Result = prde_TranslateOldDriverData ( DriverData,
                                                     param1->DO.pdriv);
              }

              /****************************************************************/
              /*  PD00587 : if it is a migratable version between 250 and     */
              /*  275 just copy the old version and add in the new resolution */
              /*  field.  Set the value of the new resolution to the old      */
              /*  resolution.                                                 */
              /*  PD00651 : Change MagicNumber2 to MagicNumber3 and process   */
              /*  600DPI  :                                                   */
              /*  PD00769 : Change MagicNumber3 to MagicNumber4 and process   */
              /****************************************************************/
              if ( (param1->DO.pdriv->lVersion >= MagicNumber) &&
                 (param1->DO.pdriv->lVersion <  MagicNumber4) )
              {
                  if ( (param1->DO.pdriv->lVersion >= MagicNumber3) )
                  {
                       prdu_memcpy( (PBYTE)DriverData,
                                    (PBYTE)param1->DO.pdriv->abGeneralData,
                                     sizeof(DMDriverStruc) -
                                     (sizeof(USHORT) + sizeof(ULONG)) );
/*                     DriverData->PrinterPatterns = 0;                      */
                       DriverData->Resolution3 = DriverData->Resolution2;
                  }
                  else if ( (param1->DO.pdriv->lVersion >= MagicNumber2) )
                  {
                      /********************************************************/
                      /*  PD00651 : If it is a migratable version between 275 */
                      /*  and 278 just copy everything up to MachineType.     */
                      /*  MachineMachineType was set to zero when we cleared  */
                      /*  the allocated memory.  It will be set to a valid    */
                      /*  value when we have access to INI information.       */
                      /*                                                      */
                      /********************************************************/

                      /********************************************************/
                      /*  PD00769 Update for PrinterPatterns added field      */
                      /*  600DPI Update  for Resolution3 added field          */
                      /********************************************************/
                       prdu_memcpy((PBYTE)DriverData,
                                   (PBYTE)param1->DO.pdriv->abGeneralData,
                                   (sizeof(DMDriverStruc) -
                                   (2*sizeof(USHORT) + sizeof(ULONG)) ) );
/*                     DriverData->PrinterPatterns = 0;                       */
                       DriverData->Resolution3 = DriverData->Resolution;
                  }
                  else
                  {
                      /********************************************************/
                      /*  PD00651 : If it is a migratable version prior to    */
                      /*  275, copy everything up to Resolution2, then set    */
                      /*  Resolution2 to match Resolution.  MachineType was   */
                      /*  set to zero when we cleared the allocated memory.   */
                      /*  It will be set to a valid value when we have access */
                      /*  to INI information.                                 */
                      /********************************************************/

                      /********************************************************/
                      /*  PD00769 Update for PrinterPatterns added field      */
                      /*  600DPI : Update for Resolution3 added field         */
                      /********************************************************/
                       prdu_memcpy( (PBYTE)DriverData,
                                    (PBYTE)param1->DO.pdriv->abGeneralData,
                                    (sizeof(DMDriverStruc) - (2*sizeof(LONG)+
                                          2*sizeof(USHORT)) ) );

                       DriverData->Resolution2 = DriverData->Resolution;
/*                     DriverData->PrinterPatterns = 0;                       */
                       DriverData->Resolution3 = DriverData->Resolution;
                  }

                  PDBInstance->MinorDriverDataConvert = TRUE;     /* PD00665 */
                  Result = OK;

              }


              if (Result == OK)
              {
                 PDBInstance->DriverDataConvert = TRUE;
              }
              else
              {
              /* SSFREESEG ( SELECTOROF(DriverData) ); */
                 SSFREEMEM ( DriverData );                 /* CON3201 */
                 DriverData = NULL;
              }
           }
           else
           {
           /* SSFREESEG ( SELECTOROF(DriverData) ); */
              SSFREEMEM ( DriverData );                    /* CON3201 */
              DriverData = NULL;
           }
        }
        else
        {
           if (param1->DO.pdriv->cb >= sizeof(DRIVDATA)+sizeof(DMDriverStruc)-1)
           {
              DriverData = (pDMDriverStruc)param1->DO.pdriv->abGeneralData;
           }
           else
           {
              DriverData = NULL;
           }
        }

        /**************************************************************/
        /* DriverData looks valid, unless of course the driver name   */
        /* that we ourselves have stored is incorect.                 */
        /**************************************************************/

        /* PD00358 */
        if (DriverData != NULL)
        {
           if ( DriverData->DriverType != DRIVER_TYPE )
           {
               DriverData = NULL;
           }
        }
    }

    /******************************************************************/
    /* Work out which LogAddress we will be printing to, and which    */
    /* PrinterName (e.g. PRINTER1) we will be using. LogAddress       */
    /* will be a port (e.g. LPT1) if we're printing DIRECT and a      */
    /* queue (e.g. LPT1Q) otherwise.                                  */
    /******************************************************************/
    if (prde_GetPrinterName( PDBInstance, param1, DriverData ) != OK)
    {
        goto ERR_EXIT;
    }

#ifdef TEST_TYPE_INIT
#if (TEST_TYPE_INIT == 1)
    OutputString("Found: ");
    OutputString(PDBInstance->PDBDriverName);
    OutputString(PDBInstance->PDBLogAddress);
    OutputString(PDBInstance->LPName);
#endif
#endif

    /******************************************************************/
    /* Work out printer type (PDBInstance->PDBDeviceName and          */
    /* PDBInstance->PrinterType, both being different forms of the    */
    /* same information - string and index) from:                     */
    /*                                                                */
    /*  - the driver data first. if this does not contain anything    */
    /*    sensible then the driver data will be ignored. Pass in      */
    /*    the address so that it can be nulled.                       */
    /*                                                                */
    /*  - the first printer type that we come across in the ini       */
    /*    file (PM_SPOOLER_DD)                                        */
    /*                                                                */
    /*  - the default printer type. In which case a flag tells us     */
    /*    that this is the default printer type.                      */
    /*                                                                */
    /* Work out the PrinterType (e.g. ProIII), from the szDeviceName  */
    /* in DriverData and the INI file "PM_SPOOLER_PRINTER".           */
    /*                                                                */
    /******************************************************************/
    if (PDBInstance->DriverDataConvert)
    {
       DriverData2 = DriverData;
    }

    if (prde_GetDeviceName( param1, &DriverData, PDBInstance ) != OK)
    {
        goto ERR_EXIT;
    }

    if ( DriverData == NULL )
    {
       if (PDBInstance->DriverDataConvert)
       {
       /* SSFREESEG(SELECTOROF(DriverData2)); */
          SSFREEMEM(DriverData2);                          /* CON3201 */
       }
       PDBInstance->DriverDataConvert = FALSE;
    }
#ifdef TEST_TYPE_INIT
#if (TEST_TYPE_INIT == 1)
    OutputString("Found: ");
/*  OutputString(PDBInstance->PrinterType); */
    OutputString(PDBInstance->PDBDeviceName);
#endif
#endif

    /******************************************************************/
    /* Read in the initialisation file information for this device    */
    /******************************************************************/
/*  if (prde_GetPrinterIniInfo( PDBInstance,                          */
/*                              DriverData,                           */
/*                              (PUSHORT) &IniVersionType,            */
/*                              &PrinterIniInfo ) != OK)              */
/*  {                                                                 */
/*      goto ERR_EXIT;                                                */
/*  }                                                                 */

#ifdef TEST_TYPE_INIT
#if (TEST_TYPE_INIT == 1)
    OutputString("Found after GetPrinterType: ");
    OutputString( PDBInstance->LPName);
    OutputPair("PrinterType found: ", (ULONG)PDBInstance->PrinterType, DECIMAL);
    OutputString("Exiting...");
    return ((ULONG)((LONG)ERROR_NEG));
#endif
#endif
    /******************************************************************/
    /* If IniVersionType is INI_VERSION_PREVIOUS then this Ini entry  */
    /* is for old driver format. We must find printer type and        */
    /* translate data to new format.                                  */
    /******************************************************************/
/*  if ( IniVersionType == INI_VERSION_PREVIOUS)                      */
/*  {                                                                 */
/*      if ( prde_GetPrinterTypeEntry(PDBInstance,                    */
/*                                    &PrinterIniInfo ) != OK)        */
/*      {                                                             */
/*          goto ERR_EXIT;                                            */
/*      }                                                             */
/*  }                                                                 */

    /******************************************************************/
    /* If no printer has been found so far then get the first selected*/
    /* device for any printer.                                        */
    /******************************************************************/
    if (PDBInstance->DfltPrtType)
    {
       prde_GetDefaultPrinter(PDBInstance->LPName,
                              PDBInstance->PDBDeviceName,
                              &PDBInstance->PrinterType,
                              &PDBInstance->DfltPrtType);
    }

    /******************************************************************/
    /* Read data from OS2.INI and a pointer to a buffer is returned.  */
    /* PD00441                                                        */
    /******************************************************************/
    PrinterIniInfo = prde_ReadPrinterProperties(PDBInstance->LPName,
                                                PDBInstance->PDBDeviceName,
                                                &PDBInstance->PrinterType);

    /******************************************************************/
    /* This should never occur. This is just a safety check.          */
    /******************************************************************/
    if ( PDBInstance->PrinterType >= NO_OF_PRINTERS )
    {
        PDBInstance->DfltPrtType = TRUE;  /* This flag will be used to */
                                          /* get dflt setting          */
        PDBInstance->PrinterType = DEFAULT_PRINTER;

        PrinterIniInfo = FNULL;

        prdu_strcpy(PDBInstance->PDBDeviceName,DriverNameString);

        *(PDBInstance->PDBDeviceName+DRIVER_NAME_LEN) = '.';

        WinLoadString( hab,
                       prdd_ModHandle,
                       IDS_FIRST_PRINTER + DEFAULT_PRINTER,
                       MAX_PRNTR_NAME,
                       (PSZ)PDBInstance->PDBDeviceName + DRIVER_NAME_LEN + 1 );
    }

    PDBInstance->pStartPtr = PrinterIniInfo;

    /******************************************************************/
    /*  PD00384 : Make sure that the devicename in the driver data is */
    /*  valid if the DriverData exists.  If there is a DeviceName that*/
    /*  is not reported on a query of the devices, the spooler open   */
    /*  will fail.  If there is no DriverData do nothing.             */
    /******************************************************************/

    if ( param1->DO.pdriv )
    {
       prdu_strcpyN( param1->DO.pdriv->szDeviceName, PDBInstance->PDBDeviceName
                     + DRIVER_NAME_LEN + 1, 32);
    }

    /******************************************************************/
    /* Get printer info: DDT for the PrinterType, DMSettings read     */
    /* from PrinterIniInfo or taken from defaults, forms, orientation,*/
    /* resolution, output type.                                       */
    /******************************************************************/
    if (prde_GetPrinterInfo( param1,
                             &PrinterIniInfo,
                             IniVersionType,
                             PDBInstance,
                             DriverData,
                             &DMSettings) != OK)
    {
        goto ERR_EXIT;
    }

#ifdef DEBUG_FSM
    switch (DCType)
    {
    case OD_DIRECT:
        OutputString("DCType : Direct");
        break;
    case OD_QUEUED:
        if ( PDBInstance->PDBOutputType== IBMQRAW )
        {
            OutputString("DCType : Q_RAW");
        }
        else
        {
            OutputString("DCType : Q_STD");
        }

        break;
    case OD_MEMORY:
        OutputString("DCType : Memory");
        break;
    case OD_INFO:
        OutputString("DCType : Info");
        break;
    }
#endif

#ifdef TEST_TYPE_INIT
#if (TEST_TYPE_INIT == 1)
    OutputString("After GetPrinterInfo: ");
    OutputPair("OutputType    ",PDBInstance->PDBOutputType,DECIMAL);
    OutputPair("RasterMode    ",PDBInstance->RasterMode,DECIMAL);
    OutputPair("Orientation   ",PDBInstance->Orientation,DECIMAL);
    OutputPair("Version       ",PDBInstance->Version,DECIMAL);
    OutputPair("PageWidthPels ",PDBInstance->PageWidthPels,DECIMAL);
    OutputPair("PageDepthPels ",PDBInstance->PageDepthPels,DECIMAL);
    OutputPair("FormXOffset   ",PDBInstance->FormXOffset,DECIMAL);
    OutputPair("FormYOffset   ",PDBInstance->FormYOffset,DECIMAL);
    OutputPair("FormClip[0].X ",PDBInstance->FormClipRegion[0].X,DECIMAL);
    OutputPair("FormClip[0].Y ",PDBInstance->FormClipRegion[0].Y,DECIMAL);
    OutputPair("FormClip[1].X ",PDBInstance->FormClipRegion[1].X,DECIMAL);
    OutputPair("FormClip[1].Y ",PDBInstance->FormClipRegion[1].Y,DECIMAL);
    OutputPair("FontCount      ",PDBInstance->FontCount,DECIMAL);
#endif
#endif

    /******************************************************************/
    /* Initialise the printer open flag.  PD00636                    */
    /******************************************************************/
    PDBInstance->PDBPrtOpen = FALSE;
    /******************************************************************/
    /* Open spooler if necessary, or get the semaphore to allow       */
    /* printing on the right port.                                    */
    /******************************************************************/
    switch (DCType)
    {
        case OD_QUEUED:
            /**********************************************************/
            /* Make SetupSplData call.           PD00227              */
            /**********************************************************/
            if (prde_SetupSplData( PDBInstance, param1 ) != OK)
            {
                goto ERR_EXIT;
            }
            break;

        case OD_DIRECT:
            /**********************************************************/
            /* Get semaphore.    PD00636                              */
            /**********************************************************/
              if (prde_OpenPort( PDBInstance ) != OK)
              {
                  goto ERR_EXIT;
              }

            break;

        case OD_INFO:
        case OD_MEMORY:
            /**********************************************************/
            /* No printing.                                           */
            /**********************************************************/
#ifdef PORT_SEMAPHORE
            PDBInstance->PDBDevice = FNULL;
#endif
            break;
    }

    /******************************************************************/
    /* PD00178 : EnableDC traps when a memory DC is created because   */
    /* we need a font to set up the text attributes. So we are going  */
    /* to set up all the fonts for a memory DC as well as other DCs.  */
    /* This will cause no performance hit because the fonts are only  */
    /* set up first time for this logical printer name and afterwards */
    /* only when the font information changes.                        */
    /******************************************************************/
#if 0
//  /******************************************************************/
//  /* For a memory device context the printer is not going to be     */
//  /* accessed, therefore do not set up the Printer State Data.      */
//  /******************************************************************/
//  if (DCType == OD_MEMORY)
//  {
//      /**************************************************************/
//      /* But ...  There are no device fonts thus the default font   */
//      /* must be an engine font, and the default device font is not */
//      /* set up.                                                    */
//      /**************************************************************/
//      PDBInstance->FontCount          = 0;
//      PDBInstance->DfltFont.Info.Type = FT_ENGINE;
//
//      /**************************************************************/
//      /* Now exit.                                                  */
//      /**************************************************************/
//      goto OK_EXIT;
//  }
#endif

    /******************************************************************/
    /* We need some resources to be used later.                       */
    /******************************************************************/
    prde_GetResources();


    /******************************************************************/
    /* LoadResidentFontMetrics works out whether there are any        */
    /* resident fonts in this job and loads the metrics if there are. */
    /* It sets the FontCount field in the PDB to the number of fonts  */
    /* found if there are resident fonts and to a dummy value (-1)    */
    /* if not.                                                        */
    /******************************************************************/
    if ( prde_LoadResidentFontMetrics ( PDBInstance,
                                        DMSettings.PelAddrFontType,
                                        DCType)
       != OK )

    {
        goto ERR_EXIT;
    }


    /******************************************************************/
    /* The PrinterStateData records info about the previous state     */
    /* of the printers. It is a chain of entries, one for each        */
    /* PrinterName that has been printed on already. It records info  */
    /* about what fonts are available, what codepage has been         */
    /* downloaded etc. It is reinitialised if the printer type has    */
    /* changed since the last print job on this printer, otherwise    */
    /* it is updated.                                                 */
    /******************************************************************/

    /**************************************************************************/
    /*  PD00041 : If it is the old type of driver data use the INI values by  */
    /*  sending NULL for driver data                                          */
    /*                                                                        */
    /*  PD00665 : Don't send null if just minor migration changes.            */
    /**************************************************************************/
    if (!PDBInstance->DriverDataConvert || PDBInstance->MinorDriverDataConvert)
    {
       if (prde_SetUpPrinterStateData( PDBInstance,
                                       &DMSettings,
                                       DriverData,
                                       PrinterIniInfo ) != OK)
       {
          goto ERR_EXIT;
       }
    }
    else
    {
       if (prde_SetUpPrinterStateData( PDBInstance,
                                       &DMSettings,
                                       NULL,
                                       PrinterIniInfo ) != OK)
       {
          goto ERR_EXIT;
       }
    }

#ifdef TEST_TYPE_INIT
#if (TEST_TYPE_INIT == 3)
    OutputString("After StateData code: ");
    OutputPair("FontCount ",PDBInstance->FontCount,DECIMAL);
    OutputPair("Resident fonts ",PDBInstance->TotalResidentFonts,DECIMAL);
    OutputPair("CodePage fonts ",PDBInstance->TotalCodePageFonts,DECIMAL);
    OutputPair("Cartridge fonts ",PDBInstance->TotalCartridgeFonts,DECIMAL);
    OutputPair("Download fonts ",PDBInstance->TotalDownloadFonts,DECIMAL);
#endif
#endif

#ifdef TEST_TYPE_PSD
    OutputString("After StateData code: ");
    OutputPair("FontCount       ",(ULONG)PDBInstance->FontCount,DECIMAL);
    OutputPair("Resident fonts  ",(ULONG)PDBInstance->TotalResidentFonts,DECIMAL);
    OutputPair("CodePage fonts  ",(ULONG)PDBInstance->TotalCodePageFonts,DECIMAL);
    OutputPair("Cartridge fonts ",(ULONG)PDBInstance->TotalCartridgeFonts,DECIMAL);
    OutputPair("Download fonts  ",(ULONG)PDBInstance->TotalDownloadFonts,DECIMAL);
#endif

OK_EXIT:
    /******************************************************************/
    /* Clean up and exit.                                             */
    /******************************************************************/
#ifdef TEST_TYPE_INIT
    OutputString("FillPDB return OK");
#endif

    /******************************************************************/
    /*  PD00041 : Free memory obtained for the new driver data.       */
    /******************************************************************/

    if (PDBInstance->DriverDataConvert)
    {
    /* SSFREESEG(SELECTOROF(DriverData)); */
       SSFREEMEM(DriverData);                              /* CON3201 */
    }
    /******************************************************************/
    /* Return the PDB data address.                                   */
    /******************************************************************/
#ifdef PRD_TIMING
    DEKHOOK0(A,7,BA)
#endif
    return ((ULONG)PDBInstance);

LOGERR_EXIT:
    TRACE6(TFUNC, "LogErr_Exit", &LogErrCode, 1);
    LOGERR(TFUNC, "Invalid device", FNULL, 0, LogErrCode);

ERR_EXIT:
    /******************************************************************/
    /*  PD00385 : Free PDBInstance from the global heap instead of    */
    /*            trying to free the whole segment.                   */
    /******************************************************************/
    if (PDBInstance)
    {
        /**************************************************************/
        /* Clear the semaphore. PD00636                               */
        /**************************************************************/
        if (PDBInstance->PDBPrtOpen)
        {
            (VOID) prdg_ClearSemaphore(
                              PDBInstance->PDBDevice->ControlSemaphore);
        }
        prdg_FreeGlobalHeapItem( sizeof(PDBIType),
                                (PUSHORT*)&PDBInstance);
    }

    TRACE6(TFUNC, "Err_Exit", FNULL, 0);
#ifdef TEST_TYPE_INIT
    OutputString("FillPDB return ERROR");
#endif

#ifdef PRD_TIMING
    DEKHOOK0(A,7,BA)
#endif
    return ((ULONG)((LONG)ERROR_NEG));
}
#undef TFUNC



/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_GetPrinterInfo                                    */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*                                                                    */
/*   FPParamsLst far *  param1;                                       */
/*   PBYTE far *        pStartPtr;                                    */
/*   USHORT             IniVersionType;  says whether the ini entry   */
/*                                       is current, previous version,*/
/*                                       or so old we can't use it.   */
/*   lpPDBI             PDBInstance;                                  */
/*   pDMDriverStruc     DriverData;                                   */
/*   DMSettingsType far *pDMSettings;                                 */
/*                                                                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*   ------------                                                     */
/*                                                                    */
/* This function fills the PDB with info for the PrinterType that     */
/* we have chosen. It gets info such as orientation, output type      */
/* and forms.                                                         */
/*                                                                    */
/* From now on, PrinterIniInfo refers to the info for the specific    */
/* type of printer we're using (not to all of the info stored by our  */
/* driver). A pointer to this was returned from prde_GetPrinterType   */
/* (if it was found).                                                 */
/**********************************************************************/
#if 0
ULONG pascal prde_GetPrinterInfo( param1,
                                  pStartPtr,
                                  IniVersionType,
                                  PDBInstance,
                                  DriverData,
                                  pDMSettings)

FPParamsLst far *  param1;
PBYTE far *        pStartPtr;
USHORT             IniVersionType;
lpPDBI             PDBInstance;
pDMDriverStruc     DriverData;
lpDMSettings       pDMSettings;
#endif

ULONG prde_GetPrinterInfo( FPParamsLst    *param1,                 /* CON3201 */
                           PBYTE          *pStartPtr,              /* CON3201 */
                           USHORT          IniVersionType,         /* CON3201 */
                           lpPDBI          PDBInstance,            /* CON3201 */
                           pDMDriverStruc  DriverData,             /* CON3201 */
                           lpDMSettings    pDMSettings)            /* CON3201 */

{
#define TFUNC "prde_GetPrinterInfo"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    ULONG                Result;           /* Result of function      */
                                           /* calls                   */
    BOOL                 ConvertForm1;
    BOOL                 ConvertForm2;
    BYTE                 CountryCode[4];   /* Country code            */

    /******************************************************************/
    /* Pick up the correct DDT for the printer type.                  */
    /******************************************************************/
    prdu_memcpy( (PBYTE)&(PDBInstance->DDT),
                 (PBYTE)DDT[PDBInstance->PrinterType],
                 sizeof(DDTType) );

    /******************************************************************/
    /* Read the header part of PrinterIniInfo into DMSettings, or     */
    /* get default DMSettings.                                        */
    /******************************************************************/
    if ( *pStartPtr )
    {
        /**********************************************************/
        /* Normal case - read the header.                         */
        /**********************************************************/
        prde_ReadHeaderData( pDMSettings, *pStartPtr, IniVersionType );

        *pStartPtr += HEADER_LENGTH;
    }

    if ( !*pStartPtr )
    {
        /**************************************************************/
        /* Could have got to here as a result of error in             */
        /* ReadOld4019Entry, which is why this isn't if-else.         */
        /**************************************************************/
        prdu_memcpy( (PBYTE)pDMSettings,
                     (PBYTE)DVTDfltDMSettings[PDBInstance->PrinterType],
                     sizeof(DMSettingsType) );

        /**********************************************************************/
        /* PD00676 :  Update printer type since it is zero in default settings*/
        /**********************************************************************/
        pDMSettings->PrinterType = PDBInstance->PrinterType;

        /**********************************************************************/
        /* PD00676 : Update printer memory available field to handle the case */
        /* when there is no driverdata available for all US Pro I and for US  */
        /* Pro II/III when default font is not Draft.                         */
        /*                                                                    */
        /* Put in the correct download code page memory availability          */
        /* information.                                                       */
        /* Note : 1. For Pro Printer (IBM42XX driver), if country is US       */
        /*           or Canada then "Memory Not Available"                    */
        /*        2. Pro Printer XL has memory in machines world-wide.        */
        /*           So, it always has memory available.                      */
        /**********************************************************************/
        if ( DDT[PDBInstance->PrinterType]->DDTDriverType == DDT_IBM42XX_DRV )
        {
            /**********************************************************/
            /* If we didn't find PrinterIniInfo or if the form        */
            /* associated with the default tray is manual, use        */
            /* the default form (country-dependent).                  */
            /**********************************************************/
/*          (void) WinQueryProfileString( hab,                        CON3201 */
            (void) PrfQueryProfileString( HINI_SYSTEMPROFILE,
                                          "PM_National",
                                          "iCountry",
                                          "1",
                                          CountryCode,
                                          3 );

            if ( (CountryCode[0] == '1') &&
                 (CountryCode[1] == '\0') )
            {
                if ( (PDBInstance->PrinterType != IBM_PRO_PRINTER_XL ) )
                {
                    pDMSettings->DownCPMemAvail = DOWN_CP_MEM_NOT_AVAIL;
                }
            }
        }

    }

    /******************************************************************/
    /* Set form feed control from DMSettings.                         */
    /******************************************************************/
    switch ( pDMSettings->FFSet )
    {
        case FF_NONE_MODE:
            PDBInstance->FFcontrol = prdg_FFnever;
            break;
        case FF_COMPULSORY_MODE:
            PDBInstance->FFcontrol = prdg_FFcompulsory;
            break;
        case FF_CONDITIONAL_MODE:
            PDBInstance->FFcontrol = prdg_FFconditional;
            break;
    }

    /******************************************************************/
    /* Set duplex control from DMSettings. Note:                      */
    /*   - bits 0 and 1 if SimDup indicate duplex type.               */
    /*   - DUPLEX flag set if DuplexEnabled set                       */
    /******************************************************************/
    PDBInstance->DuplexControl = (pDMSettings->SimDup & 0x03);
    if (pDMSettings->DuplexEnabled)
    {
        PDBInstance->DuplexControl |= DUPLEX_FLAG;
    }

    /******************************************************************/
    /* Save the compression state from DMSettings.                    */
    /******************************************************************/
    PDBInstance->BandCompression = pDMSettings->BandCompression;

     /*************************************************************************/
    /* Save the Fast System Fonts option.                                     */
    /* PD00136 : Save the Disable Outline Fonts option.                       */
    /* Save the Default outline font pointsize        PD00137                 */
     /*************************************************************************/
    /**************************************************************************/
    /*  PD00665 : If DriverData is valid...                                   */
    /**************************************************************************/

    if (DriverData)
    {
        /**********************************************************************/
        /*  ... and we haven't converted the driver data or we have but it was*/
        /*      only a couple of fields.                                      */
        /**********************************************************************/
        if (!PDBInstance->DriverDataConvert ||
                                           PDBInstance->MinorDriverDataConvert)
        {
           PDBInstance->DisableOutlineFonts = DriverData->DisableOutlineFonts;
           PDBInstance->DfltFontPointSz     = DriverData->DfltFontPointSz;
           PDBInstance->DownSysFonts        = DriverData->DLoadSysFonts;
           /*******************************************************************/
           /* PD00769 : Added printer patterns field in ver 1.310             */
           /*******************************************************************/
           PDBInstance->PrinterPatterns     = DriverData->PrinterPatterns;
        }
        else
        /**********************************************************************/
        /*  ... or we have done a full conversion, and these fields aren't    */
        /*  in the converted driverdata, so get them from DMSettings.         */
        /**********************************************************************/
        {
           PDBInstance->DisableOutlineFonts = pDMSettings->DisableOutlineFonts;
           PDBInstance->DfltFontPointSz     = pDMSettings->DfltFontPointSz;
           PDBInstance->DownSysFonts        = pDMSettings->DownSysFonts;
           /*******************************************************************/
           /* PD00769 : Added following stmt                                  */
           /*******************************************************************/
           PDBInstance->PrinterPatterns     = pDMSettings->PrinterPatterns;
        }
    }
    else
    /**************************************************************************/
    /*  Driver Data is invalid, so we have to get the stuff from DMSettings   */
    /**************************************************************************/
    {
        PDBInstance->DisableOutlineFonts = pDMSettings->DisableOutlineFonts;
        PDBInstance->DfltFontPointSz     = pDMSettings->DfltFontPointSz;
        PDBInstance->DownSysFonts        = pDMSettings->DownSysFonts;
        /**********************************************************************/
        /* PD00769 : Added following stmt                                     */
        /**********************************************************************/
        PDBInstance->PrinterPatterns     = pDMSettings->PrinterPatterns;
    }


    /******************************************************************/
    /* Set the correct orientation and raster mode.                   */
    /******************************************************************/
    (void)prde_SetPageAtts( param1,
                            PDBInstance,
                            DriverData,
                            pDMSettings );

    /******************************************************************/
    /* DIAL/NILE :
    /* For Pro II's and III's fill DDTFontsInCodePage according to    */
    /* Memory available setting.                                      */
    /******************************************************************/
    if (PDBInstance->DDT.DDTFontFlags & DDT_DOWN_CP_MEM_SUBSET_AVAIL)
    {
        if (pDMSettings->DownCPMemAvail == DOWN_CP_MEM_NOT_AVAIL)
        {
           if ( (PDBInstance->PrinterType == IBM_PRO_PRINTER_II) ||
                (PDBInstance->PrinterType == IBM_PRO_PRINTER_II_XL) )
           {
               PDBInstance->DDT.DDTFontsInCodePage = PRO_II_NO_MEM;
           }
           else /* it's a Pro III or Pro III XL */
           {
               PDBInstance->DDT.DDTFontsInCodePage = PRO_III_NO_MEM;
           }

        }
        else /* Memory is available */
        {
           if ( (PDBInstance->PrinterType == IBM_PRO_PRINTER_II) ||
                (PDBInstance->PrinterType == IBM_PRO_PRINTER_II_XL) )
           {
               PDBInstance->DDT.DDTFontsInCodePage = PRO_II_MEM;
           }
           else /* it's a Pro III or Pro III XL */
           {
               PDBInstance->DDT.DDTFontsInCodePage = PRO_III_MEM;
           }

        }  /* if memory not available button selected */

    } /* if subset of memory available at all times */

    /******************************************************************/
    /* DIAL/NILE :                                                    */
    /* Need to set the Resident font list pointers for Niles & Tibers */
    /* depending on whether it's an NLS machine or not.               */
    /******************************************************************/
    if (PDBInstance->DDT.DDTFontFlags & DDT_NLS_FONTS_OPTIONAL)
    {
        (void)prde_SetMachineType( PDBInstance,
                                   pDMSettings );
    }

    /**************************************************************************/
    /*  PD00604 : Need to save the Printer Fonts setting as we are adding     */
    /*  a new value.                                                          */
    /**************************************************************************/
    PDBInstance->DDT.DDTPrinterFonts = pDMSettings->PelAddrFontType;

    /******************************************************************/
    /* PD00041 : If the form number is in the valid range then put    */
    /*           the name in the driverdata, otherwise ChooseForms    */
    /*           will throw away the forms in the DD is not converted */
    /******************************************************************/

    if (PDBInstance->DriverDataConvert)
    {
       if (DriverData->FormNumber1 >= pDMSettings->NumberOfForms)
       {
          ConvertForm1 = FALSE;
       }
       else
       {
          ConvertForm1 = TRUE;
       }
       if (DriverData->FormNumber2 >= pDMSettings->NumberOfForms)
       {
          ConvertForm2 = FALSE;
       }
       else
       {
          ConvertForm2 = TRUE;
       }
       if ( *pStartPtr )                     /* PD0041                */
       {
           prde_TranslateOldDriverDataFrm ( DriverData,
                                            *pStartPtr,
                                            ConvertForm1,
                                            ConvertForm2 );
       }
    }
    /******************************************************************/
    /* Work out which form(s) and paper source(s) to use.             */
    /******************************************************************/
    Result = prde_ChooseForms( PDBInstance,
                               pDMSettings,
                               *pStartPtr,
                               DriverData,
                               param1->DO.pszSpoolerParams );
    if ( Result != OK )
    {
        return ERROR_ZERO;
    }

    /******************************************************************/
    /* Set up the form dimensions of the first form in the PDB. If    */
    /* there are two forms, the second form dimensions will be set    */
    /* up after the first page has printed.                           */
    /******************************************************************/
    prde_GetFormDimensions( PDBInstance, 0 );

#ifdef TEST_TYPE_INIT
#if (TEST_TYPE_INIT == 2)
    OutputString("Found - first form: ");
    OutputValue(PDBInstance->PPMInfo[0].FormNumber, 10);
    OutputValue(PDBInstance->PPMInfo[0].FeedTechnique, 10);
    OutputValue(PDBInstance->PPMInfo[0].FormControl, 10);
    OutputValue(PDBInstance->PPMInfo[0].SourceDrawer, 10);
    OutputString(PDBInstance->PPMInfo[0].FormName);
    if (PDBInstance->NumberOfForms == 2)
    {
        OutputString("      - second form: ");
        OutputValue(PDBInstance->PPMInfo[1].FormNumber, 10);
        OutputValue(PDBInstance->PPMInfo[1].FeedTechnique, 10);
        OutputValue(PDBInstance->PPMInfo[1].FormControl, 10);
        OutputValue(PDBInstance->PPMInfo[1].SourceDrawer, 10);
        OutputString(PDBInstance->PPMInfo[1].FormName);
    }
#endif
#endif
    /******************************************************************/
    /* Work out the output type (STD or RAW).                         */
    /******************************************************************/
    Result = prde_GetOutputType( param1,
                                 PDBInstance,
                                 pDMSettings );
    if ( Result != OK )
    {
        return ERROR_ZERO;
    }

    /******************************************************************/
    /* Move *pStartPtr up to point to the bit after the list of forms.*/
    /******************************************************************/
    if ( *pStartPtr )
        *pStartPtr += (pDMSettings->NumberOfForms *
                                                (FORM_DATA_LENGTH + 2));

    /******************************************************************/
    /* Return.                                                        */
    /******************************************************************/
    return OK;
}
#undef TFUNC






/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_SetPageAtts                                       */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   See "OS/2 Technical Reference: I/O Subsytems and Device Drivers" */
/*   FillPhysicalDeviceBlock                                          */
/*                                                                    */
/*   FPParamsLst far   *param1;                                       */
/*   lpPDBI             PDBInstance;                                  */
/*   pDMDriverStruc     DriverData;                                   */
/*   DMSettingsType far * pDMSettings;                                */
/*                                                                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*   ------------                                                     */
/*                                                                    */
/* Set the orientation and raster mode into the PDB.                  */
/**********************************************************************/
#if 0
ULONG pascal prde_SetPageAtts( param1,
                               PDBInstance,
                               DriverData,
                               pDMSettings )

FPParamsLst far *    param1;
lpPDBI               PDBInstance;
pDMDriverStruc       DriverData;
DMSettingsType far * pDMSettings;
#endif

ULONG prde_SetPageAtts( FPParamsLst    *param1,                    /* CON3201 */
                        lpPDBI          PDBInstance,               /* CON3201 */
                        pDMDriverStruc  DriverData,                /* CON3201 */
                        DMSettingsType *pDMSettings )              /* CON3201 */

{
#define TFUNC "prde_SetPageAtts"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    USHORT               PageResolution;
    lpDDTType            pDDT;             /* Pointer to DDT in PDB   */

    /******************************************************************/
    /* Set up pointer to DDT.                                         */
    /******************************************************************/
    pDDT = &(PDBInstance->DDT);

    /******************************************************************/
    /* First get resolution and orientation, from the DriverData if   */
    /* possible, otherwise from DMSettings.                           */
    /*                                                                */
    /* PD00587 : get the resolution from the new field in DriverData. */
    /* 600DPI  :                                                      */
    /******************************************************************/
    if ( DriverData )
    {
        PageResolution           = (USHORT)DriverData->Resolution3; /* 600DPI */
        PDBInstance->Orientation = (USHORT)DriverData->Orientation;
    }
    else
    {
        PageResolution           = pDMSettings->Resolution;
        PDBInstance->Orientation = pDMSettings->Orientation;
    }

    /**************************************************************************/
    /*  600x600 : Do some error checking. If we have a resolution that        */
    /*  is out of range then we need to set it to the max resolution of the   */
    /*  printer.                                                              */
    /**************************************************************************/
    if (PageResolution >= pDDT->DDTNoOfRasterModes)
        PageResolution = pDDT->DDTNoOfRasterModes - 1;

    /******************************************************************/
    /* Set the pointer to the current raster mode structure.          */
    /******************************************************************/
    pDDT->DDTRasterMode += PageResolution;

    /******************************************************************/
    /* Set up the raster mode - note that we assume DCT_RASTER_MODE_1,*/
    /* DCT_RASTER_MODE_2...etc are contiguous.                        */
    /******************************************************************/
    PDBInstance->RasterMode = DCT_RASTER_MODE_1 + PageResolution;

    return OK;
}
#undef TFUNC







/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_ChooseForms                                       */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   See "OS/2 Technical Reference: I/O Subsytems and Device Drivers" */
/*   FillPhysicalDeviceBlock                                          */
/*                                                                    */
/*   lpPDBI             PDBInstance;                                  */
/*   DMSettingsType     DMSettings;                                   */
/*   PBYTE              pFormData;          Pointer to start of form  */
/*                                          info in PrinterIniInfo    */
/*   pDMDriverStruc     DriverData;                                   */
/*   PSZ                pszSpoolerParams;                             */
/*                                                                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*   ------------                                                     */
/*                                                                    */
/* Choose the form(s) and tray(s) for this job, and fill the PPMInfo  */
/* structure.                                                         */
/*                                                                    */
/* The PPMInfo structure (of which there is one for each form - two   */
/* in a dual-form job) has the following fields:                      */
/*                                                                    */
/* - TopMargin, used when setting up page size in GetFormDimensions   */
/* - FormNumber, which is an index into the list of forms in          */
/*          PrinterIniInfo if found and into the default list in the  */
/*          DDT if not                                                */
/* - FormName, which sometimes gets passed to the spooler             */
/* - FormInfoPtr, used in GetFormDimensions                           */
/* - FeedTechnique, FormControl, SourceDrawer which all record info   */
/*          about the tray being used                                 */
/*                                                                    */
/* We must decide which form or (if this is a dual-form job) forms    */
/* to use, for two reasons. One is to set up the page size correctly  */
/* and the other is to tell the Spooler what forms are being used.    */
/*                                                                    */
/* We must also work out which tray we are using (some printers have  */
/* more than one - you can put        letterheaded notepaper in one   */
/* of them).                                                          */
/*                                                                    */
/* The forms might be given to us in DriverData or in SpoolerParams.  */
/* If they aren't, we assume that this is a single form job and use   */
/* either the form associated with the first (default) tray or the    */
/* default form (which is country-dependent).                         */
/*                                                                    */
/* The bit of PrinterIniInfo that we use in this function (the bit    */
/* that pFormData points to) looks like this:                         */
/*                                                                    */
/* PLetter (8*5 x 11 inches)I 8*50 11*00 0*00 8*00 0*00 11*00       */
/* PLe gal (8*5 x 14 inches)I 8*50 14*00 0*00 8*00  0*00 14*00      */
/* P B5 (18 2 x 257 mm)M 182*0 257*0 0*0 182*0 0*0 257*0             */
/* PA4 (210 x  297 mm)M 210*0 297*0 0*0 203*2 0*0 297*0             */
/* PExec (7*25 x 1 0*5 inches)I 7*25 10*50 0*00 7*25 0*00 10*50     */
/* P A5 (148 x 210 mm) M 148*0 210*0 0*0 148*0 0*0 210*0             */
/* P8 x 12 inchesI 8*00 1 2*00 0*00 8*00 0*00 12*00                 */
/* E7 3/4 (3*875 x 7*5 inches) I 7*50 3*87 0*00 7*50 0*00 3*87      */
/* E9 (3*875 x 8*875 inches)I 8*8 7 3*87 0*00 8*00 0*00 3*87        */
/* E10 (4*125 x 9*5 inches)I 9*50 4*1 2 0*00 8*00 0*00 4*12         */
/* EDL (110 x 220 mm)M 220*0 110*0 0*0 20 3*2 0*0 110*0             */
/* EC5 (162 x 229 mm)M 229*0 162*0 0*0 203*2 0*0 162*0              */
/* EB 5 (176 x 250 mm)M 250*0 176*0 0*0 203*2 0*0  176*0            */
/*                                                                    */
/* How to read this: each form has a fixed length (FORM_DATA_LENGTH,  */
/* currently 84). First is a letter indicating the type (paper or     */
/* envelope) then \x<n>, where n is the number of the form. Then      */
/* comes the form name, followed by \x01. Then I or M to indicate the */
/* units used (inches or mm) then page width, page height, left clip, */
/* right clip, bottom clip and top clip. This is padded with          */
/* blanks.                                                            */
/**********************************************************************/
#if 0
ULONG pascal prde_ChooseForms( PDBInstance,
                               pDMSettings,
                               pFormData,
                               DriverData,
                               pszSpoolerParams )

lpPDBI                PDBInstance;
lpDMSettings          pDMSettings;
PBYTE                 pFormData;
pDMDriverStruc        DriverData;
PSZ                   pszSpoolerParams;
#endif

ULONG prde_ChooseForms( lpPDBI         PDBInstance,                /* CON3201 */
                        lpDMSettings   pDMSettings,                /* CON3201 */
                        PBYTE          pFormData,                  /* CON3201 */
                        pDMDriverStruc DriverData,                 /* CON3201 */
                        PSZ            pszSpoolerParams )          /* CON3201 */

{
#define TFUNC "prde_ChooseForms"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    USHORT               Result;           /* Result of function      */
                                           /* calls                   */
    lpDVTSourceTray      pTrayInfo;        /* Tray list for the curr. */
                                           /* source configuration    */
    PBYTE                pSourceData;      /* from PrinterIniInfo     */
    CHAR                 pszWord[100];     /* for reading keys in     */
                                           /* SpoolerParams.          */
    PBYTE                pWork;            /* working pointer         */
    CHAR                 Terminator;       /* dummy for subfn         */
    USHORT               PageNo;           /* Loop variable           */
    BYTE                 CountryCode[4];   /* Country code            */
    lpDDTType            pDDT;             /* Pointer to DDT in PDB   */
    lpDVTSourceList      pSourceInfo;      /* Current source config   */
    USHORT               FormNo;
    USHORT               Result1;          /* Result of function call */
    USHORT               Result2;          /* prde_FindDrvDataFormNo  */
    USHORT               DfltFormNo;       /* default form number     */

    /******************************************************************/
    /* Get local pointer to DDT.                                      */
    /******************************************************************/
    pDDT = &(PDBInstance->DDT);

    /******************************************************************/
    /* Fill the TopMargin field in PPMInfo. This is got from the      */
    /* source configuration, which is a constant for the job. The     */
    /* 4224 (b/w), the Quiet and the Quick have four possible         */
    /* configurations; the other printers have just one.              */
    /******************************************************************/
    pSourceInfo  = pDDT->DDTSourceList;
    pSourceInfo += pDMSettings->SourceIndex;

    /******************************************************************/
    /* Allow for added sources. On Quiet/Quick printers and 4019Laser */
    /* this is just the Envelope feed. On the Heritage this may be    */
    /* Envelope or MultiMedia. The pSourceInfo is an index into the   */
    /* DVTSourceList tables defined in prdd????.c                     */
    /******************************************************************/
    /******************************************************************/
    /* PD00355 : Make sure that the SourceIndex for the 52xx is 3     */
    /*           before incrementing for the envelope since the       */
    /*           envelope can only be added for dual bin feed.        */
    /******************************************************************/
    /******************************************************************/
    /* PD00445 : Put brackets around the if check for the envelope so */
    /*           that the else is to the FD_ENVELOPE check.           */
    /******************************************************************/

    if ( pDMSettings->AddedFeed == FD_ENVELOPE )
        pSourceInfo += 1;
    else if ( pDMSettings->AddedFeed == FD_MULTIMEDIA )
        pSourceInfo += 2;
    else if ( pDMSettings->AddedFeed == FD_100_SHEET )
        pSourceInfo += 3;

    PDBInstance->PPMInfo[0].TopMargin = pSourceInfo->TopMargin;
    PDBInstance->PPMInfo[1].TopMargin = pSourceInfo->TopMargin;

    /******************************************************************/
    /* Look for the form number first. This comes from DriverData     */
    /* or from SpoolerParams if possible, otherwise from whatever     */
    /* form is in the default tray or from defaults.                  */
    /*                                                                */
    /* Clear PDBInstance->NumberOfForms.                              */
    /******************************************************************/
    PDBInstance->NumberOfForms = 0;

    /******************************************************************/
    /* First look for FormNumber in DriverData.                       */
    /******************************************************************/
    if ( DriverData )
    {
        if ( DriverData->NumberOfForms )
        {
            /**********************************************************/
            /* There is some form info in DriverData.                 */
            /**********************************************************/
            PDBInstance->NumberOfForms =
                                      (USHORT)DriverData->NumberOfForms;

            /**********************************************************/
            /* Find the default form number, in case the form info in */
            /* the DriverData is not valid.                           */
            /**********************************************************/
            DfltFormNo = prde_FindDfltFormNo( pDMSettings->NumberOfForms,
                                              pFormData,
                                              pSourceInfo );

            /**********************************************************/
            /* Find the form number(s) according to the DriverData    */
            /* form info.                                             */
            /* if the DriverData form info is not valid.              */
            /*    Single form job - use the default form              */
            /*    Dual form job   - 1) if only one of the two forms   */
            /*                         is invalid, use the other one  */
            /*                         that is vaild                  */
            /*                      2) both are invalid, use default  */
            /**********************************************************/
            Result1 = prde_FindDrvDataFormNo( &DriverData->FormInfo1,
                                              pFormData,
                                              pDMSettings->NumberOfForms,
                                              pDDT );

            if ( DriverData->NumberOfForms == 1 )
            {
               if ( Result1 )
                  PDBInstance->PPMInfo[0].FormNumber = Result1 - 1;
               else
                  PDBInstance->PPMInfo[0].FormNumber = DfltFormNo;
            }
            else if ( DriverData->NumberOfForms == 2 )
            {
               Result2 = prde_FindDrvDataFormNo( &DriverData->FormInfo2,
                                                 pFormData,
                                                 pDMSettings->NumberOfForms,
                                                 pDDT );
               if ( Result1 && Result2 )
               {
                  PDBInstance->PPMInfo[0].FormNumber = Result1 - 1;
                  PDBInstance->PPMInfo[1].FormNumber = Result2 - 1;
               }
               else if ( Result1 && !Result2 )
               {
                  PDBInstance->PPMInfo[0].FormNumber = Result1 - 1;
                  PDBInstance->PPMInfo[1].FormNumber = Result1 - 1;
               }
               else if ( !Result1 && Result2 )
               {
                  PDBInstance->PPMInfo[0].FormNumber = Result2 - 1;
                  PDBInstance->PPMInfo[1].FormNumber = Result2 - 1;
               }
               else
               {
                  PDBInstance->PPMInfo[0].FormNumber = DfltFormNo;
                  PDBInstance->PPMInfo[1].FormNumber = DfltFormNo;
               }
            }
        }
    }

    if ( !PDBInstance->NumberOfForms )
    {
        /**************************************************************/
        /* We didn't find form info in DriverData. Look in            */
        /* SpoolerParams.                                             */
        /**************************************************************/
        if (pWork = pszSpoolerParams)
        {
            /**********************************************************/
            /* SpoolerParams contains an optional string of spooler   */
            /* parameters. Each entry consists of <KEY>=<VALUE>, each */
            /* pair separated by an arbitrary number of blanks.       */
            /**********************************************************/
            do
            {
                if ( *pWork != 'F')
                {
                    /**************************************************/
                    /* Not the 'FORM=' keyword.                       */
                    /**************************************************/
                    continue;
                }

                /******************************************************/
                /* See whether we've hit the keyword.                 */
                /******************************************************/
                prde_ReadTerminatedWordFromText ( pszWord,
                                                  &Terminator,
                                                  "=",
                                                  &pWork );

                if ( ( !prde_StringsAreEqual (pszWord, "FORM" ) ) )
                {
                    /**************************************************/
                    /* Not the right keyword.                         */
                    /**************************************************/
                    continue;
                }

                /******************************************************/
                /* We've found the keyword. Read the form name        */
                /* and work out what number form it is.               */
                /* Note that pWork points to just after "FORM=",      */
                /* so it points to the start of the form name.        */
                /******************************************************/
                Result = prde_FindFormNumber(pWork,
                                             pFormData,
                                             pDMSettings->NumberOfForms,
                                             pDDT );

                if ( Result )
                {
                    PDBInstance->NumberOfForms = 1;
                    PDBInstance->PPMInfo[0].FormNumber = Result - 1;
                }

                /******************************************************/
                /* See whether there's a second form name. If         */
                /* there is it will be preceeded by a comma. Stop     */
                /* looking if we hit another keyword or the end       */
                /* of the string.                                     */
                /******************************************************/
                while ( (*pWork != '=' ) &&
                        (*pWork != '\0') &&
                        (*pWork != ',' ) )
                {
                    pWork++;
                }

                if ( *pWork++ != ',')
                {
                    /**************************************************/
                    /* There isn't a second form listed so we've      */
                    /* finished.                                      */
                    /**************************************************/
                    break;
                }

                /******************************************************/
                /* There is a second form. Get its form number.       */
                /******************************************************/
                Result = prde_FindFormNumber(pWork,
                                        pFormData,
                                        pDMSettings->NumberOfForms,
                                        pDDT );

                if ( Result )
                {
                    FormNo = PDBInstance->NumberOfForms;
                    PDBInstance->PPMInfo[FormNo].FormNumber = Result-1;
                    PDBInstance->NumberOfForms += 1;
                }
                break;

            } while (*pWork++);
        }
    }

    if ( PDBInstance->NumberOfForms )
    {
        /**************************************************************/
        /* We found a form passed in in param1. The flag              */
        /* FormSpecifiedOnOpen records this, so that in this case     */
        /* we may pass the form names to the spooler in               */
        /* prde_OpenSpooler.                                          */
        /**************************************************************/
        PDBInstance->FormSpecifiedOnOpen = TRUE;
    }
    else
    {
        /**************************************************************/
        /* The form wasn't passed in in param1. This is a single form */
        /* job, since it wasn't specified otherwise. Work out which   */
        /* form to use.                                               */
        /**************************************************************/
        PDBInstance->FormSpecifiedOnOpen = FALSE;
        PDBInstance->NumberOfForms = 1;

        PDBInstance->PPMInfo[0].FormNumber =
                        prde_FindDfltFormNo( pDMSettings->NumberOfForms,
                                             pFormData,
                                             pSourceInfo );
    }

    /******************************************************************/
    /* Now we've found the FormNumber(s). Fill in the other fields    */
    /* of PPMInfo.                                                    */
    /******************************************************************/

    for (PageNo = 0; PageNo < PDBInstance->NumberOfForms; PageNo++)
    {
        /**************************************************************/
        /* This might be a dual form job. If PrinterIniInfo is        */
        /* present, we do complicated things to find the right tray.  */
        /**************************************************************/
        if ( PDBInstance->FormSpecifiedOnOpen && pFormData )
        {
            /**********************************************************/
            /* We look through the trays to find the right one.       */
            /* FindReqdTray finds the right tray (it might change     */
            /* the FormNumber) and calls ProcessTrayInfo to put the   */
            /* info into PPMInfo.                                     */
            /**********************************************************/
            prde_FindReqdTray( PDBInstance,
                               PageNo,
                               pDMSettings,
                               pFormData,
                               pSourceInfo );
        }
        else
        {
            /**********************************************************/
            /* Use the default (1st) tray.                            */
            /**********************************************************/
            pTrayInfo   = pSourceInfo->SourceTrayList;

            /**********************************************************/
            /* Put tray info into PPMInfo.                            */
            /* Note that this will never be the Heritage multi-media  */
            /* tray, so we do not need to tell ProcessPPMTrayInfo     */
            /* whether the form is paper or envelope.                 */
            /**********************************************************/
            prde_ProcessPPMTrayInfo( PDBInstance,
                                     PageNo,
                                     DDT_PAPER_FORM,
                                     pTrayInfo );
        }

        /**************************************************************/
        /* Fill in the FormName and FormInfoPtr fields in PPMInfo.    */
        /**************************************************************/
        Result = prde_SetUpPPMFormInfo( PDBInstance,
                                        pFormData,
                                        pDMSettings->NumberOfForms,
                                        PageNo );
        if (Result != OK)
            goto ERR_EXIT;
    }
    return OK;

ERR_EXIT:
    return ERROR_ZERO;
}
#undef TFUNC





/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_GetFormDimensions                                 */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpPDBI             PDBInstance;                                  */
/*   USHORT             PageNo;                                       */
/*                                                                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*   ------------                                                     */
/*                                                                    */
/* This function sets up the page width, page depth and clips fields  */
/* of the PDB. It calculates these from the TopMargin and FormInfoPtr */
/* fields of PPMInfo. It is called from FillPDB at the start of the   */
/* job and if this is a dual form job it is called again when setting */
/* up the second page.                                                */
/**********************************************************************/
#if 0
void pascal prde_GetFormDimensions( PDBInstance,
                                    PageNo )

lpPDBI             PDBInstance;
USHORT             PageNo;
#endif

void prde_GetFormDimensions( lpPDBI PDBInstance,           /* CON3201 */
                             USHORT PageNo )               /* CON3201 */

{
#define TFUNC "prde_GetFormDims"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    lpDDTType   pDDT;                      /* Pointer to DDT in PDB   */
    ULONG       ConvFact;                  /* Conversion factor       */
                                           /* depends on the units the*/
                                           /* form is stored in       */
    ULONG       PageDepth;                 /* Page depth in pels      */
    ULONG       PageWidth;                 /* Page width in pels      */
    WcsRect     PDBFormClip;               /* First stab at clip      */
                                           /* region for form         */
    ULONG       TopMargin;                 /* used by 4224            */
    PBYTE       FormPtr;                   /* ptr to form dimensions  */
    BYTE        Units;
    ULONG       ResWidth;
    ULONG       ResDepth;
    ULONG       PageDepthPels;
    ULONG       LeftClip;
    ULONG       LeftMargin;
    ULONG       RightClip;
    ULONG       TopClip;
    ULONG       BottomClip;

    ULONG       MinDifference;
    ULONG       NewMin;
    ULONG       i, j;
    ULONG       MinI, MinJ;
    ULONG       tempPageDepth;             /* PD00758                 */
    ULONG       tempTopMargin;             /* PD00726                 */

    USHORT      SCPMultFactor;             /* 600DPI                  */

    /******************************************************************/
    /* Get local ptr to DDT.                                          */
    /******************************************************************/
    pDDT = &PDBInstance->DDT;

    /******************************************************************/
    /* FormPtr points to the start of the form dimensions info for    */
    /* the form on the current page. The info starts with I or M, for */
    /* inches or mm, then lists the PageWidth, PageDepth              */
    /* and the four clips. See the comment at the top of              */
    /* prde_GetPrinterType for an example.                            */
    /******************************************************************/
    FormPtr = PDBInstance->PPMInfo[PageNo].FormInfoPtr;

    /******************************************************************/
    /* If FormPtr is NULL, can't set up the page. This could happen   */
    /* for the second page if AllocGlobalHeapItem didn't work. Just   */
    /* return, so we'll retain the form dimensions of the first page. */
    /******************************************************************/
    if ( !FormPtr )
        return;

    /******************************************************************/
    /* Read the units and work out the conversion factor - get the    */
    /* TopMargin from the PDB (units are hundredths of inches).       */
    /******************************************************************/
    Units = *FormPtr++;
    FormPtr++;

    TopMargin = PDBInstance->PPMInfo[PageNo].TopMargin;

    if ( Units == INCHES )
    {
        ConvFact = 100;
    }
    else
    {
        ConvFact = 254;
        TopMargin = (TopMargin * 254) / 100;
    }


    /******************************************************************/
    /* Convert the text of the entry to numbers then apply            */
    /* the conversion factor.                                         */
    /******************************************************************/
    PageWidth = prde_GetValFromText( &FormPtr );
    FormPtr++;

    PageDepth = prde_GetValFromText( &FormPtr );
    FormPtr++;

    /******************************************************************/
    /* Get the values for the clip region from the text of            */
    /* the entry.  Note these will be converted later.                */
    /******************************************************************/
    PDBFormClip[0].X = (LONG)(prde_GetValFromText( &FormPtr ));
    FormPtr++;

    PDBFormClip[1].X = (LONG)(prde_GetValFromText( &FormPtr ));
    FormPtr++;

    PDBFormClip[0].Y = (LONG)(prde_GetValFromText( &FormPtr ));
    FormPtr++;

    PDBFormClip[1].Y = (LONG)(prde_GetValFromText( &FormPtr ));
    FormPtr++;

    LeftMargin = 64L;

    /******************************************************************/
    /* We've finished with FormPtr. If this is the second page, then  */
    /* memory was allocated specially for it. Get rid of this here.   */
    /*                                                                */
    /* FIX : AK 04/26/91 : this function not called for OD_INFO or    */
    /* Q_STD dc types: so do this in DisablePdb.                      */
    /******************************************************************/
#if 0
//  if ( PageNo )
//  {
//       (void)prdg_FreeGlobalHeapItem(
//                      FORM_DIMS_LENGTH,
//                      (PUSHORT)&(PDBInstance->PPMInfo[PageNo]
//                                                      .FormInfoPtr) );
//  }
#endif

    /******************************************************************/
    /* Start converting these values.                                 */
    /******************************************************************/
    ResWidth = pDDT->DDTRasterMode->ResWidth;
    ResDepth = pDDT->DDTRasterMode->ResDepth;

    /******************************************************************/
    /* Working in 72ths of inches - as this is the units used for     */
    /* the physical printer page length.  PageDepthPels is used to    */
    /* set up the form offsets only if the SCP command is not         */
    /* available.                                                     */
    /******************************************************************/
    if ( !(pDDT->DDTHorizMoveType & DDT_MOVE_ABS_SCP) )
    {
        PageDepthPels = (PageDepth * 72) / ConvFact;
        PageDepthPels = (PageDepthPels * ResDepth) / 72;
    }

    /******************************************************************/
    /* If the form units are in cm x 100 then first convert the       */
    /* dimensions passed in to inches x 100 - all values are          */
    /* rounded down.                                                  */
    /*                                                                */
    /* Allow for the top margin on 4224 printers                      */
    /******************************************************************/
    LeftClip = PDBFormClip[0].X;
    PDBFormClip[0].X = (PDBFormClip[0].X * ResWidth) / ConvFact;

    RightClip = PDBFormClip[1].X;
    PDBFormClip[1].X = (PDBFormClip[1].X * ResWidth) / ConvFact;

    if (pDDT->DDTFormFlags & DDT_VAR_BOTTOM_CLIP)
    {
       /***********************************************************************/
       /*  INKJET : The Bottom Clip limit varies with the paper source.       */
       /***********************************************************************/
       if ( PDBFormClip[0].Y < TopMargin)
           PDBFormClip[0].Y = TopMargin;

       BottomClip = PDBFormClip[0].Y;
       PDBFormClip[0].Y = (PDBFormClip[0].Y * ResDepth) / ConvFact;

       TopClip = PDBFormClip[1].Y;
       PDBFormClip[1].Y = (PDBFormClip[1].Y * ResDepth) / ConvFact;
    }
    else
    {
       BottomClip = PDBFormClip[0].Y;
       PDBFormClip[0].Y = (PDBFormClip[0].Y * ResDepth) / ConvFact;

       if ( PDBFormClip[1].Y > PageDepth - TopMargin )
           PDBFormClip[1].Y = PageDepth - TopMargin;

       TopClip = PDBFormClip[1].Y;
       PDBFormClip[1].Y = (PDBFormClip[1].Y * ResDepth) / ConvFact;
    }


    /******************************************************************/
    /* Calculate the values used to set the page length on the        */
    /* printer.                                                       */
    /*                                                                */
    /* New pagelength algorithm :                                     */
    /*                                                                */
    /* Want to find a pair of integers whose product is as close as   */
    /* possible to the PageDepth (in 72ths of inches), constrained    */
    /* by the one-byte limit (ie 1-255).                              */
    /*                                                                */
    /* Should mostly be within 2/72 inches: as worst case (in normal  */
    /* range?) is: ..., x, P1, 2*P2, P3, x, ...   (P are primes >255) */
    /* where 2*P2 is required length. In most cases will be within    */
    /* 1/72 inch.                                                     */
    /******************************************************************/
    if ( pDDT->DDTInitFlags & DDT_INIT_PAGE_LENGTH )
    {
        tempPageDepth = PageDepth;
        MinI = 1;
        MinJ = (USHORT)((tempPageDepth * 72 + ConvFact/2) / ConvFact);


        MinDifference = 99999999L; /* A large number */

        if ( MinJ > 255)
        {
            /**********************************************************/
            /* Note for best accuracy, stay in correct PageDepth      */
            /* units (mm/10 or inches/100)                            */
            /**********************************************************/
            for ( j = 255; j > 0; j-- )
            {
                i = (USHORT)((tempPageDepth*72 + j*ConvFact/2)/(j * ConvFact));

                if (i > 255)
                    break;

                NewMin = (ULONG)prdu_abs( (tempPageDepth*72)-(i*j*ConvFact) );

                if ( NewMin < MinDifference )
                {
                    MinDifference = NewMin;
                    MinI = i;
                    MinJ = j;

                    if ( MinDifference <= ConvFact/2 )
                    {
                        /**********************************************/
                        /* Match to within half a 72th of an inch.    */
                        /**********************************************/
                        break;
                    }
                }
            }
        }

        PDBInstance->TextSpacing = MinI;
        PDBInstance->LengthLines = MinJ;
    }


    /******************************************************************/
    /* Calculate the offset from the top-left corner of the physical  */
    /* paper to the top-left corner of the form (in pels).            */
    /*                                                                */
    /* Note: still allow for TopMargin in clips; not in PageLength.   */
    /******************************************************************/
    if ( !(pDDT->DDTHorizMoveType & DDT_MOVE_ABS_SCP) )
    {
        /**************************************************************/
        /* PD00476: FormXOffset and FormYOffset is same for both      */
        /* potrait and landscape mode.                                */
        /**************************************************************/
        PDBInstance->FormXOffset = (USHORT)( PDBFormClip[0].X );
        PDBInstance->FormYOffset = (USHORT)
                                   ( PageDepthPels - PDBFormClip[1].Y );

#if 0
//      if ( PDBInstance->Orientation == PORTRAIT )
//      {
//          PDBInstance->FormXOffset = (USHORT)( PDBFormClip[0].X );
//          PDBInstance->FormYOffset = (USHORT)
//                     ( PageDepthPels - PDBFormClip[1].Y  );
//      }
//      else
//      {
//          PDBInstance->FormXOffset = (USHORT) ( PDBFormClip[0].Y );
//          PDBInstance->FormYOffset = (USHORT) ( PDBFormClip[0].X );
//      }
#endif
    }

    /******************************************************************/
    /* For the printers with the SCP command we also take out the     */
    /* non-printable margins and store the offsets in the highest     */
    /* resolution.  Note that top-left in landscape mode is           */
    /* equivalent to bottom-left in portrait mode.                    */
    /*                                                                */
    /* Assumptions used in hard coding:                               */
    /* - only the 4019 printers have the SCP command                  */
    /*     (so highest resolution is always 300x300)                  */
    /* - all forms have the same minimum margins                      */
    /*     (0.25 inches left and right, 0.17 inches top and bottom)   */
    /*                                                                */
    /* Code here uses same rounding method as above so that forms     */
    /* defined with the minimum margins end up with offset values of  */
    /* 0.                                                             */
    /*                                                                */
    /* Cannot use the prdt_XformFontValue function here as the        */
    /* ResAdj structure used in that function will not have been set  */
    /* up yet.                                                        */
    /******************************************************************/
    if ( pDDT->DDTHorizMoveType & DDT_MOVE_ABS_SCP )
    {
        if ( Units == INCHES )
        {
            SCPMultFactor = 3;

            if ( PDBInstance->Orientation == PORTRAIT )
            {
                PDBInstance->FormXOffset = (USHORT)
                                    (SCPMultFactor * (LeftClip - 25L));
                PDBInstance->FormYOffset  = (USHORT)
                                    (SCPMultFactor * (PageDepth - TopClip - 17L));
            }
            else
            {
                PDBInstance->FormXOffset = (USHORT)
                                    (SCPMultFactor * (BottomClip - 17L));
                PDBInstance->FormYOffset  = (USHORT)
                                    (SCPMultFactor * (LeftClip - 25L));
            }
        }
        else
        {
            /**********************************************************/
            /* ... note LeftMargin, set above. 64L for all but        */
            /* 4019 A4 form, when it is 34L.                          */
            /**********************************************************/
            SCPMultFactor = 300;

            if ( PDBInstance->Orientation == PORTRAIT )
            {
                PDBInstance->FormXOffset = (USHORT)
                            ((SCPMultFactor * (LeftClip - LeftMargin)) / 254);
                PDBInstance->FormYOffset  = (USHORT)
                            ((SCPMultFactor * (PageDepth - TopClip - 44L)) / 254);
            }
            else
            {
                PDBInstance->FormXOffset = (USHORT)
                            ((SCPMultFactor * (BottomClip - 44L)) / 254);
                PDBInstance->FormYOffset  = (USHORT)
                            ((SCPMultFactor * (LeftClip - LeftMargin)) / 254);
            }
        }
    }

    /******************************************************************/
    /* OK now we can set up the form limits and dimensions in pels.   */
    /* Different methods are used depending on how we set the page    */
    /* depth - work in 72ths of inches vertically if not using the    */
    /* PPM command to set the form size.                              */
    /******************************************************************/
    PageWidth = ( RightClip - LeftClip ) * ResWidth / ConvFact;

    if ( pDDT->DDTInitFlags & DDT_INIT_PAGE_LENGTH )
    {
        PageDepth = (( TopClip - BottomClip ) * 72) / ConvFact;
        PageDepth = ( PageDepth * ResDepth ) / 72;
    }
    else
    {
        PageDepth = ( TopClip - BottomClip ) * ResDepth / ConvFact;
    }

    /******************************************************************/
    /* ... and store the values in the instance data.  The top and    */
    /* right edge form clip limits are set up according to the        */
    /* orientation; the page dimensions are not (the orientation is   */
    /* checked when these are used, e.g., to create the band).        */
    /******************************************************************/
    PDBInstance->PageWidthPels = (USHORT)PageWidth;
    PDBInstance->PageDepthPels = (USHORT)PageDepth;

    PDBInstance->FormClipRegion[0].X = 0;
    PDBInstance->FormClipRegion[0].Y = 0;

    if ( PDBInstance->Orientation == PORTRAIT )
    {
        PDBInstance->FormClipRegion[1].X = (INT)PageWidth;
        PDBInstance->FormClipRegion[1].Y = (INT)PageDepth;
    }
    else
    {
        PDBInstance->FormClipRegion[1].X = (INT)PageDepth;
        PDBInstance->FormClipRegion[1].Y = (INT)PageWidth;
    }

    OutputPair("PageWidth = ", PageWidth, DECIMAL);
    OutputPair("PageDepth = ", PageDepth, DECIMAL);

    return;
}
#undef TFUNC





/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_GetOutputType                                     */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   See "OS/2 Technical Reference: I/O Subsytems and Device Drivers" */
/*   FillPhysicalDeviceBlock                                          */
/*                                                                    */
/*   FPParamsLst far   *param1;                                       */
/*   lpPDBI             PDBInstance;                                  */
/*   lpDMSettingsType   pDMSettings;                                  */
/*                                                                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*   ------------                                                     */
/*                                                                    */
/* This function decides whether we're printing STD or RAW.           */
/**********************************************************************/
#if 0
ULONG pascal prde_GetOutputType( param1,
                                 PDBInstance,
                                 pDMSettings )

FPParamsLst far *    param1;
lpPDBI               PDBInstance;
DMSettingsType far * pDMSettings;
#endif

ULONG prde_GetOutputType( FPParamsLst    *param1,          /* CON3201 */
                          lpPDBI          PDBInstance,     /* CON3201 */
                          DMSettingsType *pDMSettings )    /* CON3201 */

{
#define TFUNC "prde_GetOutputType"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    PBYTE                DataType;         /* OutputType from param1  */
    USHORT               LogErrCode;       /* Error code to be logged */

    /******************************************************************/
    /* Get the DataType from param1.                                  */
    /******************************************************************/
    DataType = param1->DO.pszDataType;

    if ( !DataType || !(*DataType) )
    {
        /**************************************************************/
        /* No data type is supplied in param1 so use DMSettings.      */
        /**************************************************************/
        /**************************************************************/
        /* Get the datatype - in the list box displayed in            */
        /* Device Modes IBMQSTD has index 0, IBMQRAW has index 1.     */
        /* IBMQSTD = 0 and IBMQRAW = 2;  (IBMQESC is no more)         */
        /* hence factor of 2.                                         */
        /**************************************************************/
        PDBInstance->PDBOutputType = 2*pDMSettings->DefaultSpoolIndex;
    }
    else
    {
        /**************************************************************/
        /* The data type was supplied in param1. Interpret it.        */
        /**************************************************************/
        if ( prde_StringsAreEqual(DataType, szIBMQRAW) )
            PDBInstance->PDBOutputType = IBMQRAW;
        else if ( prde_StringsAreEqual(DataType, szIBMQSTD) )
            PDBInstance->PDBOutputType = IBMQSTD;
        else
        {
            LogErrCode = PMERR_SPL_INV_DATATYPE;
            goto LOGERR_EXIT;
        }
    }
    return OK;

LOGERR_EXIT:
    TRACE6(TFUNC, "LogErr_Exit", &LogErrCode, 1);
    LOGERR(TFUNC, "Invalid device", FNULL, 0, LogErrCode);

    return ERROR_ZERO;
}
#undef TFUNC


/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_FindDrvDataFormNo                                 */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   PBYTE            pFormInfo       Ptr to the form Info we're      */
/*                                    trying to match                 */
/*   PBYTE            pFormData       Start of form data chunk in     */
/*                                    in INI file                     */
/*   USHORT           NumberOfForms   Number of forms listed in       */
/*                                    PrinterIniInfo or in DDT        */
/*   lpDDTType        pDDT            ptr to DDT in PDB               */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* This function is given a form info (that was from DriverData) and  */
/* tries to match it in the list of forms in PrinterIniInfo (if       */
/* found) or the default list in the DDT (if not).                    */
/* It returns the number of the form matched +1 if it found a match   */
/* and 0 if it didn't.                                                */
/**********************************************************************/
#if 0
USHORT pascal prde_FindDrvDataFormNo( pFormInfo,
                                      pFormData,
                                      NumberOfForms,
                                      pDDT )

pFormInfoStruc pFormInfo;
PBYTE          pFormData;
USHORT         NumberOfForms;
lpDDTType      pDDT;
#endif

USHORT prde_FindDrvDataFormNo( pFormInfoStruc pFormInfo,      /* CON3201 */
                               PBYTE          pFormData,      /* CON3201 */
                               USHORT         NumberOfForms,  /* CON3201 */
                               lpDDTType      pDDT )          /* CON3201 */

{
#define TFUNC "prde_FindDrvDataFormNo"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    USHORT NumberBytes;        /* Count of bytes to be compared       */
    USHORT i;                  /* Loop variable                       */
    SHORT  j;                  /* Loop variable                       */
    BYTE   FormNameBuffer[33]; /* Buffer used to get form name from   */
                               /* resources                           */
    PBYTE  pTmpFormData;       /* pointer to step through the form    */
    PBYTE  ItemPtr;            /* data                                */
    PBYTE  FormPtr;
    BYTE   FormUnits;
    SHORT  CompResult;
    BYTE   DecimalPoint[3];    /* Country dependent decimal pt PD00615*/


    /******************************************************************/
    /* pWork points to the form name terminated by a NULL.            */
    /******************************************************************/
    NumberBytes = 0;

    while ( pFormInfo->FormName[NumberBytes] != '\0' &&
            ( NumberBytes < 33 ) )
         NumberBytes++;

    /**************************************************************************/
    /* PD00615 : need to know the decimal point character of the current      */
    /*  country so we can compare correctly.                                  */
    /**************************************************************************/
/*  if ( !WinQueryProfileString( hab,                                 CON3201 */
    if ( !PrfQueryProfileString( HINI_SYSTEMPROFILE,
                             "PM_National",   /* application name */
                             "sDecimal",      /* key name         */
                             ".",             /* default          */
                             DecimalPoint,    /* returned value   */
                             3 ) )            /* maximum length   */
    {
        return(0);
    }

    /******************************************************************/
    /* Now loop through the defined forms and check for a match       */
    /******************************************************************/
    if (pFormData)
    {
        /**************************************************************/
        /* Form data is from PrinterIniInfo.                          */
        /**************************************************************/
        for ( i = 0; i < NumberOfForms; i++ )
        {
            pTmpFormData = pFormData + i * ( FORM_DATA_LENGTH + 2 );

            if ( *pTmpFormData == pFormInfo->FormType )
            {
                pTmpFormData += 2;

                for ( ItemPtr = pTmpFormData;
                     *ItemPtr != '\1'; ItemPtr++ );

                j = -1;
                do {
                   j++;
                   /***********************************************************/
                   /*  PD00615: compare to variable decimal point, not hard   */
                   /*  coded "."                                              */
                   /***********************************************************/
                   FormNameBuffer[j] = (pFormInfo->FormName[j] == *DecimalPoint) ?
                                       ALT_POINT : pFormInfo->FormName[j];
                } while ( FormNameBuffer[j] );

                CompResult = prdu_memcmp( (PBYTE) FormNameBuffer,
                                          (PBYTE) pTmpFormData,
                                          (USHORT) NumberBytes );
                if ( !CompResult )
                {
                    ItemPtr++;

                    if ( *ItemPtr == pFormInfo->FormUnits )
                    {

                        /**********************************************/
                        /* Found match. Return form no. + 1.          */
                        /**********************************************/
                        return( i + 1);
                    }
                }
            }
        }

        /**************************************************************/
        /* No match found. Return.                                    */
        /**************************************************************/
        return( 0);
    }

    else      /*   PrinterIniInfo not found    */
    {
        /**************************************************************/
        /* Look through the default list of form names.               */
        /**************************************************************/
        for ( i = 0; i < NumberOfForms; i++ )
        {
            /**********************************************************/
            /* Get FormName no. i from resources.                     */
            /**********************************************************/
            (void)WinLoadString(
                           hab,
                           prdd_ModHandle,
                           pDDT->DDTDefinedForms[i].FormNameId,
                           33,
                           FormNameBuffer );

            FormPtr = pDDT->DDTDefinedForms[i].FormData;
            FormUnits = *FormPtr++;

            if ( (pDDT->DDTDefinedForms[i].FormType == pFormInfo->FormType) &&
                 (FormUnits == pFormInfo->FormUnits) &&
                 !(prdu_memcmp( (PBYTE) pFormInfo->FormName,
                                (PBYTE) FormNameBuffer,
                                (USHORT) NumberBytes ) ) )
            {
                /******************************************************/
                /* Found match. Return form no. + 1.                  */
                /******************************************************/
                return( i + 1 );
            }
        }
        /**************************************************************/
        /* No match. Return 0.                                        */
        /**************************************************************/
        return (0);
    }
}
#undef TFUNC



/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_FindDfltFormNo                                    */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   USHORT           NumberOfForms   Number of forms listed in       */
/*                                    PrinterIniInfo or in DDT        */
/*   PBYTE            pFormData       Start of form data chunk in     */
/*                                    in INI file                     */
/*   lpDVTSourceList  pSourceInfo;    Current source configuation     */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* This function tries to find the default form to use and return     */
/* the form number.                                                   */
/**********************************************************************/
#if 0
USHORT pascal prde_FindDfltFormNo( NumberOfForms,
                                   pFormData,
                                   pSourceInfo )
USHORT          NumberOfForms;
PBYTE           pFormData;
lpDVTSourceList pSourceInfo;
#endif

USHORT prde_FindDfltFormNo( USHORT          NumberOfForms, /* CON3201 */
                            PBYTE           pFormData,     /* CON3201 */
                            lpDVTSourceList pSourceInfo )  /* CON3201 */

{
#define TFUNC "prde_FindDfltFormNo"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    PBYTE                pWork;            /* working pointer         */
    PBYTE                pSourceData;      /* from PrinterIniInfo     */
    lpDVTSourceTray      pTrayInfo;        /* Tray list for the curr. */
    BYTE                 CountryCode[4];   /* Country code            */
    USHORT               ReturnFormNo;

    /**************************************************************/
    /* The tray used will be the default (1st) tray.              */
    /**************************************************************/
    pTrayInfo = pSourceInfo->SourceTrayList;

    if ( (pTrayInfo->FeedType == DDT_AUTO_FEED) && pFormData )
    {
        /**********************************************************/
        /* Use the form associated with the default tray if it    */
        /* is automatic.                                          */
        /**********************************************************/
        pSourceData = pFormData +
              (NumberOfForms * (FORM_DATA_LENGTH + 2));

        pWork = pSourceData +
             (NO_FORM_CNT_DIGITS * pTrayInfo->DMTrayUsage);

        prdm_ReadWordFromText( ReturnFormNo,
                               NO_FORM_CNT_DIGITS,
                               pWork );
        return(ReturnFormNo);
    }
    else
    {
        /**********************************************************/
        /* If we didn't find PrinterIniInfo or if the form        */
        /* associated with the default tray is manual, use        */
        /* the default form (country-dependent).                  */
        /**********************************************************/
/*      (void) WinQueryProfileString( hab,                           CON3201 */
        (void) PrfQueryProfileString( HINI_SYSTEMPROFILE,
                                      "PM_National",
                                      "iCountry",
                                      "1",
                                      CountryCode,
                                      3 );

        if (( (CountryCode[0] == '1') &&
             (CountryCode[1] == '\0') ) ||
              !prdu_strcmpN(CountryCode,"55",3) )                  /* PD00812 */
        {
            return(DEFAULT_PAPER_FORM_US);
        }
        else
        {
            return(DEFAULT_PAPER_FORM_NONUS);
        }
    }
}
#undef TFUNC

/**********************************************************************/
/* DIAL/NILE : New routine to set up fields in DDT for some printers. */
/**********************************************************************/

/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_SetMachineType                                    */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   See "OS/2 Technical Reference: I/O Subsytems and Device Drivers" */
/*   FillPhysicalDeviceBlock                                          */
/*                                                                    */
/*   lpPDBI             PDBInstance;                                  */
/*   DMSettingsType far * pDMSettings;                                */
/*                                                                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*   ------------                                                     */
/*                                                                    */
/* Set the machine type, resident font list and number of resident    */
/* fonts                                                              */
/**********************************************************************/
#if 0
VOID pascal prde_SetMachineType( PDBInstance,
                                 pDMSettings )

lpPDBI               PDBInstance;
lpDMSettings         pDMSettings;
#endif

VOID prde_SetMachineType( lpPDBI       PDBInstance,        /* CON3201 */
                          lpDMSettings pDMSettings )       /* CON3201 */

{
#define TFUNC "prde_SetMachineType"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
//  BYTE                 CountryCode[4];   /* Country code            */

    /**************************************************************************/
    /*  If the Machine type has not been set up in DMSettings then set it to  */
    /*  a default value depending on the country code.                        */
    /**************************************************************************/

    /**************************************************************************/
    /*  PD00558 : Default to US_MACHINE in all countries as not all non-US    */
    /*  printers will be NLS machines.                                        */
    /**************************************************************************/
    if (!pDMSettings->MachineType)
    {
        pDMSettings->MachineType = US_MACHINE;         /* PD00558 */

//      (void) WinQueryProfileString( hab,
//                                    "PM_National",
//                                    "iCountry",
//                                    "1",
//                                    CountryCode,
//                                    3 );
//
//      if ( (CountryCode[0] == '1') &&
//           (CountryCode[1] == '\0') )
//      {
//          pDMSettings->MachineType = US_MACHINE;
//      }
//      else
//      {
//          pDMSettings->MachineType = NLS_MACHINE;
//      }

    }

    /**************************************************************/
    /* Now that we know that there is a value in DMSettings       */
    /* to check, store the correct values in the DDT.             */
    /**************************************************************/
    if ( (PDBInstance->PrinterType == IBM_NILE_9) ||
         (PDBInstance->PrinterType == IBM_TIBER_9) )
    {
        if (pDMSettings->MachineType == NLS_MACHINE)
        {
            PDBInstance->DDT.DDTNoOfResidentFonts = NLS_9WIRE;
            PDBInstance->DDT.DDTFontList = DVTFontList9WireNLS;
        }
        else
        {
            PDBInstance->DDT.DDTNoOfResidentFonts = US_9WIRE;
            PDBInstance->DDT.DDTFontList = DVTFontList9Wire;

        }
    }
    else /* its a 24-wire */
    {
        if (pDMSettings->MachineType == NLS_MACHINE)
        {
            PDBInstance->DDT.DDTNoOfResidentFonts = NLS_24WIRE;
            PDBInstance->DDT.DDTFontList = DVTFontList24WireNLS;
        }
        else
        {
            PDBInstance->DDT.DDTNoOfResidentFonts = US_24WIRE;
            PDBInstance->DDT.DDTFontList = DVTFontList24Wire;

        }
    }

}
#undef TFUNC

