/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Microsoft 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 = querybox.c
 *
 * DESCRIPTIVE NAME = Printer dialog box utilities
 *
 *
 * VERSION = V2.0
 *
 * DATE        : 02/--/89
 *
 * DESCRIPTION : This Module contains support routines for raising Printer
 *               configuration dialog box .
 *
 *               Opens a print set dialog box and prompts user to perform
 *               print settings.The following characteristics can be set:-
 *               Paper type,
 *               Paper placement in input trays,
 *               The type of output paper placement.
 *               Contains routines to read from os2.ini ;
 *               to write onto os2.ini ;
 *
 * FUNCTIONS - cvi
 *           - FillPaperNames
 *           - FillEffects
 *           - b2a
 *           - Fraction2A
 *           - NameWithSC
 *           - ShowCursor
 *           - CheckProfileName
 *           - ReadProfile
 *           - ListUserForms
 *           - FillPaperList
 *           - FillJobList
 *           - ScanCustomset
 *           - EA_GetVersion
 *           - DisplayTranslationString
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define  INCL_WININPUT
#define  INCL_WIN
#define  INCL_PM
#define  INCL_DOSFILEMGR     
#define  INCL_DOSSEMAPHORES
#include <os2.h>
#include <bseerr.h>
#include <string.h>
#include <stdlib.h>                   /*              */
#include "inc\ppdialog.h"
#include "inc\fileext.h"
#include "inc\config.h"
#include "inc\dlgproc.h"
#include "inc\pspagtun.h"             /* V2.174057  Page Tuning */
#define  INCL_GENPLIB_MEMORY
#include <genplib.h>


#if      DEBUG
extern VOID PerformRip(PSZ pszErrorText);

   #define  RIP(Text) PerformRip((PSZ) Text)

#else
   #define  RIP(Text)
#endif
#define  MAX_PATH_SIZE 256   
#define  EA_NAME_VERSION ".VERSION" 
#define  SIZE_EA_NAME_VERSION (sizeof(EA_NAME_VERSION) - 1) 
#define  MAX_VERNAME_SIZE 128 

#pragma pack (4)
typedef struct _GLIST
{
   ULONG   cbList;
   ULONG   NextEntryOffset;
   BYTE    cbName;
   CHAR    szName[128];
} GLIST;

#pragma pack()
typedef struct _FLIST
{
   ULONG   cbList;
   ULONG   oNextEntryOffset;
   BYTE    fEA;
   BYTE    cbName;
   USHORT  cbValue;
   CHAR    szversion[8+1];
   SHORT   usEAT_Type;         /* Type of the EA                        */
   SHORT   usCodePage;         /* code page field                       */
   SHORT   usValueCount;       /* total fileds                          */
   SHORT   usVerASCIIType;     /* type of EAT assume ANSI               */
   SHORT   usSizeVerName;      /* name of version name                  */
   CHAR    szName[100];
} FLIST;

extern CHAR szDefPrinter[MAX_FNAMESIZE];/* config.c                         */
extern PBYTE StringTable[MAX_STRINGS];/* devmode.c                          */
extern PVOID pProcessHeap;
extern LONG DefaultFontCount( PDESPPD );  /*            */
ULONG PostMsgBox(HMODULE,SHORT,SHORT,SHORT);
BOOL ScanCustomset(PSZ,PSZ);

/*
**  LOCAL ROUTINE TO RETREIVE THE DRIVER'S EA VERSION  DCR1399
*/

VOID EA_GetVersion(PSZ);     

/*            */
VOID DisplayTranslationString( HWND, PSZ, UINT );
INT  _Optlink CompareRealNames( PSZ, PSZ );

/*
**           
*/
INT _Optlink CopyStr( PSZ pszDst, PSZ pszSrc );

/*****************************************************************************\
**
** FUNCTION:    GetDefaultPageSize
**
** DESCRIPTION: Simple function to get a pointer to Default Page size
**              For foreign country codes, override the default and set to
**              A4.  This is so that the Printer Properties will match with the
**              Job Properties, since the Job Properties is initially set to
**              A4 for foreign codes.
**
**
** RETURNS:     Pointer to DefaultPageSize
**
\*****************************************************************************/

PSZ GetDefaultPageSize(
      PDESPPD  pdesPpd,     /* pointer to printer descriptor    */
      PBYTE    pResBuf )    /* Pointer to Resource buffer       */
{
  PSZ   *ppFormIndex;
  INT    iCountry;

  /*
  ** @V3.098113
  ** Retrieve the current country code from the INI file.
  */
  iCountry = PrfQueryProfileInt( HINI_USERPROFILE, "PM_National",
                                 "iCountry", 1 );

  /*
  **  If the country is USA(1), Canada(2), or Brazil (55) set the
  **  default paper to Letter else set the default paper size to A4
  */
  if (iCountry == 1 || iCountry == 2 || iCountry == 55)
  {
    /* Point to form index table */
    ppFormIndex = (PSZ *)(pResBuf + pdesPpd->desForms.ofsFormIndex);

    return ( ppFormIndex[ pdesPpd->desPage.ofsDfpgsz ] );
  }
  else
  {
    /*
    ** Override, set to A4.
    */
    return( (PSZ) StringTable[ IDS_A4-STRING_BASE ] );
  }

}


/*****************************************************************************\
**
** FUNCTION: GetImageableArea
**
** DESCRIPTION:
**
** RETURNS:
**
** PROTOTYPE:
**  PFORMSTRUCT GetImageableArea( SHORT, PFORMSTRUCT, PDESPPD, PBYTE )
**
\*****************************************************************************/

PFORMSTRUCT GetImageableArea(
              SHORT    FormNum,         /* Index of form (0 - limit-1 )     */
              PFORMSTRUCT pFormStruct,  /* Pointer to form structure        */
              PDESPPD  pdesPpd,         /* pointer to printer descriptor    */
              PBYTE    pResBuf )        /* Pointer to Resource buffer       */
{
  PSZ   *ppFormIndex;
  PBYTE p;
  SHORT i;

  p = pResBuf + pdesPpd->desPage.ofsImgblPgsz;

  for ( i = 0; i < FormNum; i++ )
  {
    p += sizeof( SHORT );       /* hop over form num */
    p += sizeof( SHORT ) * 4;   /* Hop over the 4 coords */
  }

  /*
  ** Set up form name
  */
  ppFormIndex = (PSZ *)(pResBuf + pdesPpd->desForms.ofsFormIndex);
  pFormStruct->FormName = ppFormIndex[ *((PSHORT)p) ];

  pFormStruct->Data = p + sizeof( SHORT );

  return pFormStruct;
}


/****************************************************************************
 *
 * FUNCTION NAME = cvi
 *
 * DESCRIPTION   = To convert a number into binary
 *
 * INPUT         = PB *pint ;
 *
 * OUTPUT        = SHORT
 *
 * RETURN-NORMAL = i
 * RETURN-ERROR  =
 *
 ****************************************************************************/

SHORT cvi( PB *pint )
{
  PCHAR pchBuf;
  SHORT i;

  pchBuf = *pint;

  while (*pchBuf++ == ' ');
  pchBuf--;
  i = 0;

  if (*pchBuf == '+')
  {
    pchBuf++;
  }

  if (*pchBuf == '-')
  {
    pchBuf++;

    while (*pchBuf >= '0' && *pchBuf <= '9')
    {
      i = i *10-(*pchBuf++-0x30);
    }
  }
  else while (*pchBuf >= '0' && *pchBuf <= '9')
  {
    i = i *10+(*pchBuf++-0x30);
  }
  *pint = pchBuf;
  return (i);
}

/***************************************************************************
 *
 * FUNCTION NAME = FillPaperNames
 *
 * DESCRIPTION   = To store paper names from os2.ini onto pcnfdata structure
 *
 * INPUT         = PCNFDATA pcnfData
 *                 PSZ      pszBuffer
 *
 * OUTPUT        = void
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 ************************************************************************** */

void FillPaperNames( PCNFDATA pcnfData,PSZ pszBuffer )
{
  SHORT i,j;


  for (i = 0; i < INPBINS; i++)
  {
    pcnfData->u.iv.pSourcePaper->szPaperName[i][0] = '\0';/* default name to null  */
  }

  if (*pszBuffer == '\0')
  {
    return ;
  }
  i = 0;

  while (i < INPBINS)
  {
    if (*pszBuffer != ';')
    {
      j = szDlmCopy( (PSZ)&(pcnfData->u.iv.pSourcePaper->szPaperName[i][0]),
                     (PSZ)pszBuffer, MAX_PSIZE );

      if (*(pszBuffer+j) != ';')
      {
        return;
      }
    }
    else
    {
      j = 0;
    }
    pszBuffer += (j+1 );
    i++;
  }
}

/***************************************************************************
 *
 * FUNCTION NAME = FillEffects
 *
 * DESCRIPTION   = To store paper names from os2.ini onto pcnfdata structure
 *
 * INPUT         = PCNFDATA    pcnfData
 *                 PSZ         pszBuffer
 *
 * OUTPUT        = void
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 ************************************************************************** */

void FillEffects( PCNFDATA pcnfData,PSZ pszBuffer )
{
  SHORT uPrinterPropFlags;

  /*
  ** Boolean flag flip top to bottom
  */
  pcnfData->effOutput.fIsFliptb = FALSE;

  /*
  ** Boolean flag draw inverted
  */
  pcnfData->effOutput.fIsDrawInverted = FALSE;

  /*
  ** Boolean flag flip left to right
  */
  pcnfData->effOutput.fIsFliplr = FALSE;

  /*
  ** default value of job timeout in seconds
  */
  pcnfData->effOutput.iJobTimeout = 0;

  /*
  ** default value of wait timeout is zero
  */
  pcnfData->effOutput.iWaitTimeout = 0;

  /*
  ** default value of scale factor is 100% i.e. unity
  */
  pcnfData->jobProperties.uScale = 100;

  /*
  ** default value of manual feed is false
  */
  pcnfData->jobProperties.iManualfeed = 0;

  /*
  ** default value of color device is false
  */
  pcnfData->jobProperties.fIsColorDevice = NONE;

  /*
  **  DCR 1462 DEFAULT DUPLEX MODE
  */
  pcnfData->sDuplexMode = DUPLEX_NONE;

  /*
  **  Default mode switching is on (if available - turn off in
  **  readprofile if not
  */
  pcnfData->uPrinterPropFlags |= MODESWITCH;

  /*
  **            init to zero will fix in readprofile if needed
  */
  pcnfData->uResolution = 0;

  /*           
  ** Use all fonts by default
  */
  pcnfData->sUseDLFonts = 1;

  /* D74609
  ** Set usPSLevel1 to false
  */
  pcnfData->usPSLevel1 = 0;

  /*
  ** @V3.0GAMMA1
  ** Set initial gamma value to 10.
  */
  pcnfData->lGammaValue = NO_GAMMA;

  if (*pszBuffer == '\0')
  {
    return;
  }

  if (*pszBuffer != ';')
  {
    if (*pszBuffer++ != '0')
    {
      pcnfData->effOutput.fIsFliptb = TRUE;
    }
  }
  pszBuffer++;

  if (*pszBuffer != ';')
  {
    if (*pszBuffer++ != '0')
    {
      pcnfData->effOutput.fIsDrawInverted = TRUE;
    }
  }
  pszBuffer++;

  if (*pszBuffer != ';')
  {
    if (*pszBuffer++ != '0')
    {
      pcnfData->effOutput.fIsFliplr = TRUE;
    }
  }
  pszBuffer++;

  if (*pszBuffer != ';')
  {
    pcnfData->effOutput.iJobTimeout = cvi((PB *)&pszBuffer );
  }
  pszBuffer++;

  if (*pszBuffer != ';')
  {
    pcnfData->effOutput.iWaitTimeout = cvi((PB *)&pszBuffer );
  }
  pszBuffer++;

  if (*pszBuffer != ';')
  {
    pcnfData->jobProperties.uScale = cvi((PB *)&pszBuffer );
  }
  pszBuffer++;

  if (*pszBuffer != ';')
    pcnfData->jobProperties.iManualfeed = cvi((PB *)&pszBuffer );
  pszBuffer++;

  if (*pszBuffer != ';')
  {
    pcnfData->jobProperties.fIsColorDevice = cvi((PB *)&pszBuffer );
  }

  /*
  **  NOTE... If you add new job properties make sure you check for zero
  **  since the semicolon check will pass (it's not a semicolon is it?)
  **  on drivers with existing data
  */
  pszBuffer++;               

  if (*pszBuffer && *pszBuffer != ';')
  {
    pcnfData->sDuplexMode = cvi((PB *)&pszBuffer );
  }

  /*
  **  We now have Printer properties
  */
  pszBuffer++;

  if (*pszBuffer && *pszBuffer != ';')
  {
    pcnfData->uPrinterPropFlags = cvi( (PB *)&pszBuffer );
  }

  /*
  **            Get the resolution
  */
  pszBuffer++;

  if (*pszBuffer && *pszBuffer != ';')
  {
    pcnfData->uResolution = cvi( (PB *)&pszBuffer );
  }

  /*
  **            Get the devfonts
  */
  pszBuffer++;

  if (*pszBuffer && *pszBuffer != ';')
  {
    pcnfData->sUseDLFonts = cvi( (PB *)&pszBuffer );
  }

  /*
  ** D74609
  */
  pszBuffer++;

  if (*pszBuffer && *pszBuffer != ';')
  {
    pcnfData->usPSLevel1 = cvi( (PB *)&pszBuffer );
  }

  /*
  ** @V3.0GAMMA1
  ** Read in the gamma value.
  */
  if (*(++pszBuffer) && *pszBuffer != ';')
  {
    pcnfData->lGammaValue = cvi( &pszBuffer );
  }
}

/***************************************************************************
 *
 * FUNCTION NAME = b2a
 *
 * DESCRIPTION   = Convert a binary no to ascii ,store it in the pointer
 *                 and return the length of string stored .
 *
 * INPUT         = CHAR * pb
 *                 SHORT      i
 *
 * OUTPUT        = SHORT
 *
 * RETURN-NORMAL = j
 * RETURN-ERROR  =
 *
 ************************************************************************** */

SHORT b2a(CHAR *pb,SHORT i)
{
  SHORT j, k, l;

  if (!i)
  {
    *pb = '0';
    return ( 1 );
  }
  j = 0;

  if (i < 0)
  {
    i = -i;
    *pb++ = '-';
    j++;
  }
  k = i;
  l = 0;

  while (k)
  {
    k = k/10;
    l++;
  }
  j += l;
  pb += ( l - 1 );

  while (i)
  {
    k = i/10;
    *pb-- = (char) (i - (k * 10)) + 0x30;
    i = k;
  }
  return( j );
}

/***************************************************************************
 *
 * FUNCTION NAME = Fraction2A
 *
 * DESCRIPTION   = Covert the number i/j into Fractional Ascii form
 *
 * INPUT         = CHAR *pb;
 *                 SHORT idiv;
 *                 SHORT idivsor;
 *
 * OUTPUT        = SHORT
 *
 * RETURN-NORMAL = i
 * RETURN-ERROR  =
 *
 ************************************************************************** */

SHORT Fraction2A( CHAR *pb, SHORT idiv, SHORT idivsor )
{
  SHORT i;

  i = b2a( (PSZ) pb, (int)idiv/idivsor );

  if (idivsor > 1)
  {
    *(pb+i++) = '.';
    i += b2a((PSZ) (pb + i), ((idiv % idivsor) * 10) / idivsor );
  }
  return( i );
}

/***************************************************************************
 *
 * FUNCTION NAME = NameWithSC
 *
 * DESCRIPTION   = Transfer the null terminated string to destination
 *                 buffer and return the length of string (plus the
 *                 delimiting semicolon) copied.
 *
 * INPUT         = PB      pbBuffer
 *                 PSZ     pszString
 *
 * OUTPUT        = SHORT
 *
 * RETURN-NORMAL = int
 * RETURN-ERROR  =
 *
 ************************************************************************** */

SHORT NameWithSC( PB pbBuffer, PSZ pszString )
{
  PSZ psz;

  psz = pbBuffer;

  while (*pszString)
  {
    *psz++ = *pszString++;
  }
  *psz++ = ';';
  return( (int)(psz - pbBuffer) );
}

/***************************************************************************
 *
 * FUNCTION NAME = ShowCursor
 *
 * DESCRIPTION   = show cursor in the window specified by handle hWnd .
 *
 * INPUT         = HWND    hWnd
 *
 * OUTPUT        = BOOL
 *
 * RETURN-NORMAL = WinSetFocus(HWND_DESKTOP,hWnd)
 * RETURN-ERROR  =
 *
 ************************************************************************** */

BOOL ShowCursor( HWND hWnd )
{
  return( WinSetFocus(HWND_DESKTOP, hWnd) );
}

/***************************************************************************
 *
 * FUNCTION NAME = CheckProfileName
 *
 * DESCRIPTION   = Checks for printer profile data in the ini file under
 *                 old appname which was the printer name (eg. QMS PS-810).
 *                 If found will move it to new name format and delete the
 *                 old one.  DCR1399.8
 *
 * INPUT         = pcnfData - Pointer to cnf data
 *
 * OUTPUT        = VOID
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 ************************************************************************** */

VOID CheckProfileName( PCNFDATA pcnfData )
{
  ULONG ulCb;                /* Count of bytes                              */
  PSZ   pszOldApp;
  PSZ   pszNewApp;
  PSZ   pszBuffer;
  SEL   sel;

  #define  BUFSIZE       256

  /*
  **  Just get the size of entry - an error or size of 0 means old style
  **  is not there
  */
  if (PrfQueryProfileSize( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szSegName, (PSZ)
                           NULL, &ulCb) != TRUE || ulCb == 0)
  {
    return;
  }

  /*
  ** Make local copies of appNames
  */
  pszOldApp = (PSZ) pcnfData->szSegName;
  pszNewApp = (PSZ) pcnfData->szKeyApp;

  /*
  ** Allocate buffer - The stack is getting to small to put buffer on it
  */
  if (!(pszBuffer = GplMemoryAlloc( pProcessHeap, BUFSIZE )))
  {
    return;
  }

  /*
  ** Move EFFECTS
  */
  PrfQueryProfileString( HINI_SYSTEMPROFILE, pszOldApp, (PSZ) szKeyEffects,
                         (PSZ)"", pszBuffer, (ULONG)BUFSIZE );
  PrfWriteProfileString( HINI_SYSTEMPROFILE, pszNewApp, (PSZ) szKeyEffects,
                         pszBuffer );

  /*
  ** Move FONTNAME
  */
  PrfQueryProfileString( HINI_SYSTEMPROFILE, pszOldApp, (PSZ) szKeyFontName,
                         (PSZ) "", pszBuffer, (ULONG)BUFSIZE );
  PrfWriteProfileString( HINI_SYSTEMPROFILE, pszNewApp, (PSZ) szKeyFontName,
                         pszBuffer );

  /*
  ** Move ORIENTATION
  */
  PrfQueryProfileString( HINI_SYSTEMPROFILE, pszOldApp, (PSZ) szKeyOrientName,
                         (PSZ) "", pszBuffer, (ULONG)BUFSIZE );
  PrfWriteProfileString( HINI_SYSTEMPROFILE, pszNewApp, (PSZ) szKeyOrientName,
                         pszBuffer );

  /*
  ** Move OUTPUTORDER
  */
  PrfQueryProfileString( HINI_SYSTEMPROFILE, pszOldApp, (PSZ) szKeyOrder, (PSZ)
                         "", pszBuffer, (ULONG)BUFSIZE );
  PrfWriteProfileString( HINI_SYSTEMPROFILE, pszNewApp, (PSZ) szKeyOrder,
                         pszBuffer );

  /*
  Move PAPERSOURCE
  */
  PrfQueryProfileString( HINI_SYSTEMPROFILE, pszOldApp, (PSZ) szKeyFormName,
                         (PSZ) "", pszBuffer, (ULONG)BUFSIZE );
  PrfWriteProfileString( HINI_SYSTEMPROFILE, pszNewApp, (PSZ) szKeyFormName,
                         pszBuffer );

  /*
  ** Move PAPERTYPE
  */
  PrfQueryProfileString( HINI_SYSTEMPROFILE, pszOldApp, (PSZ) szKeyPaperName,
                         (PSZ) "", pszBuffer, (ULONG)BUFSIZE );
  PrfWriteProfileString( HINI_SYSTEMPROFILE, pszNewApp, (PSZ) szKeyPaperName,
                         pszBuffer );

  /*
  ** Move PRINTER
  */
  PrfQueryProfileString( HINI_SYSTEMPROFILE, pszOldApp, (PSZ) szKeyPrintName,
                         (PSZ) "", pszBuffer, (ULONG)BUFSIZE );
  PrfWriteProfileString( HINI_SYSTEMPROFILE, pszNewApp, (PSZ) szKeyPrintName,
                         pszBuffer );

  /*
  ** Move USERFORMS
  */
  PrfQueryProfileString( HINI_SYSTEMPROFILE, pszOldApp, (PSZ) szKeyUserformName,
                         (PSZ) "", pszBuffer, (ULONG)BUFSIZE );
  PrfWriteProfileString( HINI_SYSTEMPROFILE, pszNewApp, (PSZ) szKeyUserformName,
                         pszBuffer );

  /*
  ** Remove the old app entry
  */
  PrfWriteProfileString( HINI_SYSTEMPROFILE, pszOldApp, (PSZ) NULL, (PSZ) NULL );

  GplMemoryFree( pszBuffer );

  return;
}

/***************************************************************************
 *
 * FUNCTION NAME = ReadProfile
 *
 * DESCRIPTION   = Read the textual values of orientation,Paper name,
 *                 Paper Input tray ,Paper output tray and default Font.
 *                 and save the retrieved values in the respective globals.
 *
 * INPUT         = PB *apResources
 *
 * OUTPUT        = void
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *          
 *                                                                    
 *
 **************************************************************************/

void ReadProfile(PB *apResources)
{
#define  LP_SIZE       256   /*                                             */
  PCNFDATA pcnfData;         /* pointer to printer configuration data       */
  PDESPPD  pdesPpd;          /* pointer to printer resource                 */
  PCHAR    pszRes;           /*                                             */
  CHAR     szBuffer[LP_SIZE];  /* buffer to read string from os2.ini          */
  PSZ      pszb;
  SHORT    i, j, k, l;
  CHAR     szLogicalPrinter[LP_SIZE];
  PCHAR    pchSN;
  ULONG    ulFontDataSize;      /*            */
  LONG     lEffectsAvail;

  pcnfData = (PCNFDATA)apResources[CNFRES];
  pdesPpd = (PDESPPD)apResources[PPDRES];

  /*
  **  DCR1399.8 SEE IF THE PROFILE DATA NEEDS TO BE MOVED TO NEW NAME
  */
  CheckProfileName( pcnfData );

  /*
  ** read the paper orientation to be used for printing
  */
  pcnfData->jobProperties.iOrient = PORTRAIT;
  PrfQueryProfileString( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp, (PSZ)
                         szKeyOrientName, (PSZ) "", (PSZ) szBuffer,
                         (ULONG)sizeof(szBuffer) );

  if (*szBuffer != '\0')
  {
    if (sznIsEqual((CHAR *)StringTable[IDS_Portrait-STRING_BASE], (CHAR *)
                   szBuffer))
    {
      pcnfData->jobProperties.iOrient = PORTRAIT;
    }
    else
    {
      pcnfData->jobProperties.iOrient = LANDSCAPE;
    }
  }

  /*
  ** read the output order setting from os2sys.ini. it is stored as
  ** output placement, # of copies, type of dest, name of dest file.
  */
  pcnfData->jobProperties.iOutPlace = NORMAL;
  pcnfData->iDestnType = SYSTEM;
  pcnfData->iCntCopies = 1;

  /*
  ** @V3.0GAMMA1
  ** The default gamma value for this driver is '1.0'.  Since the gamma
  ** function takes in values multiplied by 10, assign the default value
  ** to 10 so that it is compatible with the gamma function.
  */
  pcnfData->lGammaValue = NO_GAMMA;

  /*
  **  if a string stored in os2sys.ini defining the above parameters then
  **  read those values else they have already been initialised
  */
  if (PrfQueryProfileString( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp, (PSZ)
       szKeyOrder, (PSZ) "", (PSZ) szBuffer, (ULONG)sizeof(szBuffer)) &&
       (*szBuffer != '\0'))
  {
    pszb = szBuffer;

    if (*pszb != ';')
    {
      if (*pszb++ != '0')
      {
        pcnfData->jobProperties.iOutPlace = REVERSE;
      }
    }
    pszb++;

    /*
    ** make default initialisations of postscript output parameters
    */
    pcnfData->szDestnFile[0] = '\0';     /* default null name          */

    if (*pszb != ';')
    {
      pcnfData->iCntCopies = cvi((PB *)&pszb );
    }
    pszb++;

    if (*pszb != ';' && *pszb > '0')
    {
      if (*pszb == '1')
      {
        pcnfData->iDestnType = RAW;
      }
      else if (*pszb == '2')
      {
        pcnfData->iDestnType = ENCAPS;
      }
      pszb++;

      if (*pszb++ == ';')
      {
        szDlmCopy( (PSZ) pcnfData->szDestnFile, (PSZ) pszb, sizeof
           (pcnfData->szDestnFile) );
      }
    }
  }

  /*
  ** Read the Job form name from os2sys.ini
  */
  if (PrfQueryProfileString( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp, (PSZ)
     szKeyFormName, (PSZ) "", (PSZ) pcnfData->jobProperties.szFormName, (ULONG)
     sizeof(pcnfData->jobProperties.szFormName)))
  {
    /*
    ** if no information available in os2.ini then
    */
    if (pcnfData->jobProperties.szFormName[0] == '\0')
    {
      INT iCountry;
      PSZ pszDefString;
      PSZ pszDefPageSize;

      /*
      **  Get the current country code set in the INI file.
      **  If the country is USA(1), Canada(2), or Brazil (55) set the
      **  default paper to Letter else set the default paper size to A4
      */
      iCountry = PrfQueryProfileInt( HINI_USERPROFILE, "PM_National",
                                     "iCountry", 1 );

      if (iCountry == 1 || iCountry == 2 || iCountry == 55)
      {
        pszDefString = (PSZ) StringTable[IDS_Letter-STRING_BASE];
      }
      else
      {
        pszDefString = (PSZ) StringTable[IDS_A4-STRING_BASE];
      }

      /*
      **           
      */
      if ( pdesPpd )  /* make sure pointer is OK */
      {
        pszDefPageSize = GetDefaultPageSize( pdesPpd, apResources[RESBUF] );

        /*
        ** If default real name is same as the string table name ( letter or A4
        ** Then use the offical name in case of xlate names
        */
        if ( ! CompareRealNames( pszDefPageSize, pszDefString ) )
        {
          pszDefString = pszDefPageSize;
        }
      }

      szNewCopy( (PSZ) pcnfData->jobProperties.szFormName, (PSZ) pszDefString,
                 MAX_PSIZE );
    }
  }

  QueryUserForm( (PCNFDATA) pcnfData );/* fill up the form size name           */

  /*
  ** scan for custom and if found then
  */
  if (ScanCustomset( (PSZ) pcnfData->jobProperties.szFormSize, (PSZ) StringTable
                     [IDS_Custom-STRING_BASE]))
  {
    pszb = (PSZ) pcnfData->jobProperties.szFormSize;
    *(pszb+6) = '\0';        /* retain only the name custom                 */
    pszb += 7;               /* so that numbers can be scanned              */
    pcnfData->u.iv.pSourcePaper->shCustomWidth = cvi((PB *)&pszb );
    pszb++;
    pcnfData->u.iv.pSourcePaper->shCustomHeight = cvi((PB *)&pszb );
  }

  /*
  ** Read the Default paper name setting from os2.ini
  */

  PrfQueryProfileString( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp, (PSZ)
     szKeyPaperName, (PSZ) "", (PSZ) szBuffer, (ULONG)sizeof(szBuffer) );
  FillPaperNames( (PCNFDATA) pcnfData, (PSZ) szBuffer );

  /*
  ** Read the Default Effects setting from os2.ini
  */
  PrfQueryProfileString( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp, (PSZ)
                         szKeyEffects, (PSZ) "", (PSZ) szBuffer,
                         (ULONG)sizeof(szBuffer) );
  lEffectsAvail = szBuffer[0];  /*            record if buffer avail */
  FillEffects( (PCNFDATA)pcnfData, (PSZ) szBuffer );

  /*           
  ** Get the number of downloaded font limit
  */
  ulFontDataSize = sizeof(ULONG );
  if ( !PrfQueryProfileData( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp,
      (PSZ) "FONTCOUNT",(PLONG)&pcnfData->lFontCount, &ulFontDataSize ) )
  {
    pcnfData->lFontCount = -1L;
  }

  /*
  ** If called from prde_fillPdb this will be NULL
  */
  if (pdesPpd)
  {
    /*
    **  DCR 1462 IF PRINTER SUPPORTS DUPLEX AND THE DEFAULT FROM FILLEFFECTS
    **  INDICATES IT DOESN'T, CHANGE THE PCNFDATA TO SHOW IT REALLY DOES
    */
    if ((pdesPpd->desItems.sDefaultDuplex == DUPLEX_FALSE) &&
       (pcnfData->sDuplexMode == DUPLEX_NONE))
    {
      pcnfData->sDuplexMode = DUPLEX_FALSE;
    }

    /*
    ** Default mode switching is on turn off if not available
    */

    /*
    ** If no init string
    */
    if (pdesPpd->desItems.ofsInitString == -1)
    {
      pcnfData->uPrinterPropFlags &= ~MODESWITCH;   /* Turn off           */
    }
    else  /*            */
    { /*
      ** The default for 4019s should be off until turned on
      */
      if ( ! lEffectsAvail )  /* if no ini data */
      {
        if ( strncmp( pcnfData->szSegName, "IBM 4019", 8 ) == 0 )
        {
          pcnfData->uPrinterPropFlags &= ~MODESWITCH;   /* Turn off           */
        }
      }
    }

    /*           
    ** Retrieve the default resolution.
    */
    if (pcnfData->uResolution == 0)
    {
      pcnfData->uResolution = pdesPpd->desItems.iResDpi;
    }

    /*           
    ** Set initial amount
    */
    if ( pcnfData->lFontCount == -1L )
    {
      pcnfData->lFontCount =  DefaultFontCount( pdesPpd  );
    }
  }
  else /*            */
  /*
  ** No ppd info use defaults
  */
  {
    if ( pcnfData->uResolution == 0 )
      pcnfData->uResolution = 0;    /* indicates unknown */
  }

  /*
  ** Read the Default Font name setting from os2.ini
  */
  PrfQueryProfileString( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp, (PSZ)
     szKeyFontName, (PSZ) "", (PSZ) pcnfData->szFontName, (ULONG)sizeof
     (pcnfData->szFontName) );
}

/***************************************************************************
 *
 * FUNCTION NAME = PostWriteError
 *
 * DESCRIPTION   =
 *
 * INPUT         = NONE
 *
 * OUTPUT        = void
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 ************************************************************************** */
VOID PostWriteError( PCNFDATA pcnfData )
{
  PostMsgBox( (HMODULE)pcnfData->hmod, (USHORT)0, IDM_CantWriteToIni,
              MB_OK | MB_ICONEXCLAMATION );
}

/***************************************************************************
 *
 * FUNCTION NAME =WrtQueryProfile
 *
 * DESCRIPTION   = To Write the various values of Printer characteristics
 *                 obtained to os2.ini.
 *
 * INPUT         = HWND    hWnd
 *                 PB *apResources - printer configuration list of pointers
 *
 * OUTPUT        = void
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *          
 *
 ****************************************************************************/

#define  BUF_LEN       256   /*                                             */
void WrtQueryProfile(HWND hWnd,PB *apResources)
  /*  PB  *apResources - printer configuration list of pointers */
{
  PCNFDATA pcnfData;           /* pointer to printer configuration data       */
  CHAR     szBuffer[BUF_LEN];
  CHAR     szBuffer2[BUF_LEN]; /* a temporary buffer                          */
  SHORT    uSemError;          /* error code returned by sem calls            */
  SHORT    i,iTrayIndex;
  PSZ      pszb;               /* a scratch pointer                           */
  ULONG    cb;
  PCHAR    pch;

  /*
  ** USESTAGGEDLOCK(CRDRIVER );   ** ALLOCATE SEMAPHORE SPACE
  */
  /*
  **  Enter write profile code restricted by a semaphore so that at a time
  **  only one process writes to os2.ini
  */
  /*
  **  PROCURETAGGEDLOCK(TSEMDRIVER, CRDRIVER );
  ** GRAB SEMAPHORE AFTER WE ARE
  */
  pcnfData = (PCNFDATA)apResources[CNFRES];

  /*
  **  DCR 1399.8 DON'T WRITE OUT PRINTER WITHOUT OFFICAL NAMES
  */
  if (*pcnfData->szKeyApp != 'P')
  {
    return;
  }

  /*
  ** write the printer product name to file os2.ini
  */
  if (!PrfWriteProfileString( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp, (PSZ)
      szKeyPrintName, (PSZ) pcnfData->szSegName))
  {
    PostWriteError( pcnfData );
  }

  /*
  ** write the default paper names for all four trays to file os2.ini
  */
  i = 0;

  for (iTrayIndex = 0; iTrayIndex < INPBINS; iTrayIndex++)
  {
    i += NameWithSC((PSZ) (szBuffer+i),
              (PSZ) &pcnfData->u.iv.pSourcePaper->szPaperName[iTrayIndex][0] );
  }
  *(szBuffer+i) = '\0';

  if (!PrfWriteProfileString( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp, (PSZ
     )szKeyPaperName, (PSZ) szBuffer))
  {
    PostWriteError( pcnfData );
  }

  /*
  ** write the default font name to file os2.ini
  */
  if (!PrfWriteProfileString( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp, (PSZ)
      szKeyFontName, (PSZ) pcnfData->szFontName))
  {
    PostWriteError( pcnfData );
  }

  /*
  ** write the orientation name into os2.ini
  */
  if (pcnfData->jobProperties.iOrient == PORTRAIT)
  {
    szNewCopy( (CHAR *)szBuffer, (CHAR *)StringTable[IDS_Portrait-
       STRING_BASE], sizeof(szBuffer) );
  }
  else
  {
    szNewCopy( (CHAR *)szBuffer, (CHAR *)StringTable[IDS_Landscape-
       STRING_BASE], sizeof(szBuffer) );
  }

  if (!PrfWriteProfileString( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp, (PSZ)
      szKeyOrientName, (PSZ) szBuffer))
  {
    PostWriteError( pcnfData );
  }

  /*
  **  binary values are converted into string since that is the form in
  **  which they are stored in os2.ini
  */
  if (pcnfData->jobProperties.iOutPlace == NORMAL)
  {
    i = NameWithSC((CHAR *)szBuffer, (CHAR *)"0" );
  }
  else
  {
    /*
    this is the reverse placement
    */
    i = NameWithSC((CHAR *)szBuffer, (CHAR *)"1" );
  }
  pszb = szBuffer+i;

  /*
  ** write the number of copies onto output
  */
  pszb += b2a((PSZ) pszb, pcnfData->iCntCopies );/* convert binary into ascii */
  *pszb++ = ';';             /* delimiter                                   */
  i = 0;

  switch (pcnfData->iDestnType)     /* The destination medium type        */
  {
  case SYSTEM:
       *pszb++ = '0';
       break;

  case RAW:
       *pszb++ = '1';
       break;

  case ENCAPS:
       *pszb++ = '2';
  }
  *pszb++ = ';';

  if (pcnfData->iDestnType != SYSTEM)
  {
    i = NameWithSC((PSZ) pszb, (PSZ) pcnfData->szDestnFile );
  }
  *(pszb+i) = '\0';          /* make it null terminated                     */

  /*
  ** write the outputOrder value into os2.ini file
  */
  if (!PrfWriteProfileString( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp, (PSZ)
      szKeyOrder, (PSZ) szBuffer))
  {
    PostWriteError( pcnfData );
  }

  /*
  ** write the input form name profile string to os2.ini
  */
  if (!PrfWriteProfileString( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp, (PSZ)
      szKeyFormName, (PSZ) pcnfData->jobProperties.szFormName))
  {
    PostWriteError( pcnfData );
  }

  /*
  ** convert all the printer effect values and some job property values
  ** into ascii and store them in szBuffer
  ** 1. fIsFliptb ,
  ** 2. fIsDrawInverted ,
  ** 3. fIsFliplr ,
  ** 4. iJobTimeout ,
  ** 5. uScale ,
  ** 6. fIsColorDevice
  */
  pszb = szBuffer;

  if (pcnfData->effOutput.fIsFliptb)
  {
    *pszb++ = '1';
  }
  else
  {
    *pszb++ = '0';
  }
  *pszb++ = ';';

  if (pcnfData->effOutput.fIsDrawInverted)
  {
    *pszb++ = '1';
  }
  else
  {
    *pszb++ = '0';
  }
  *pszb++ = ';';

  if (pcnfData->effOutput.fIsFliplr)
  {
    *pszb++ = '1';
  }
  else
  {
    *pszb++ = '0';
  }
  *pszb++ = ';';
  pszb += b2a( (PSZ) pszb, pcnfData->effOutput.iJobTimeout );
  *pszb++ = ';';
  pszb += b2a( (PSZ) pszb, pcnfData->effOutput.iWaitTimeout );
  *pszb++ = ';';
  pszb += b2a( (PSZ) pszb, pcnfData->jobProperties.uScale );
  *pszb++ = ';';
  pszb += b2a( (PSZ) pszb, pcnfData->jobProperties.iManualfeed );
  *pszb++ = ';';
  pszb += b2a( (PSZ) pszb, pcnfData->jobProperties.fIsColorDevice );
  *pszb++ = ';';
  pszb += b2a( (PSZ) pszb, pcnfData->sDuplexMode ); /* DCR 1462 */
  *pszb++ = ';';
  pszb += b2a( (PSZ) pszb, pcnfData->uPrinterPropFlags );
  *pszb++ = ';';
  pszb += b2a( (PSZ) pszb, pcnfData->uResolution );  /*            */
  *pszb++ = ';';                                  /*            */
  pszb += b2a( (PSZ) pszb, pcnfData->sUseDLFonts );
  *pszb++ = ';';
  pszb += b2a( (PSZ) pszb, pcnfData->usPSLevel1 );  /* D74609 */
  *pszb++ = ';';

  /*
  ** @V3.0GAMMA1
  ** Add the gamma value to the INI file.
  */
  pszb += b2a( (PSZ) pszb, pcnfData->lGammaValue );
  *pszb++ = ';';
  *pszb++ = '\0';

  /*
  ** write the output profile string to os2.ini
  */
  if (!PrfWriteProfileString( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp, (PSZ)
      szKeyEffects, (PSZ) szBuffer))
  {
    PostWriteError( pcnfData );
  }

  /*           
  ** Write out font count
  */
  if ( !PrfWriteProfileData( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp,
                       (PSZ) "FONTCOUNT",(PULONG)&pcnfData->lFontCount,
                       (ULONG)sizeof(ULONG) ) )
  {
    PostWriteError( pcnfData );
  }

  /*
  **  clear the semaphore so that another process can configure the printer
  */
  /*
  **  RELEASETAGGEDLOCK(TSEMDRIVER );              ** RELEASE SEMAPHORE
  */
  /*
  ** Wake the spooler up and notify it that a form change may have
  ** occurred; this is done by writing a valid entry to PM_SPOOLER_DD.
  ** to get a valid entry we just read a current entry.
  */
  /*
  **  get szBuffer2 to be PSCRIPT.printertype
  */
  pch = "PSCRIPT.";

  for (i = 0; *pch; szBuffer2[i++] = *pch++);

  /*
  **  DCR 1399
  */
  pch = pcnfData->szSegName; 

  for (; *pch; szBuffer2[i++] = *pch++);
  szBuffer2[i] = 0;
  cb = BUF_LEN;

  if (PrfQueryProfileData(HINI_SYSTEMPROFILE, "PM_SPOOLER_DD", (PSZ) szBuffer2,
     (PSZ) szBuffer, &cb) == TRUE)
  {
    PrfWriteProfileData( HINI_SYSTEMPROFILE, "PM_SPOOLER_DD", (PSZ) szBuffer2,
                         (PSZ) szBuffer, cb );
  }
}

/***************************************************************************
 *
 * FUNCTION NAME = ListUserForms
 *
 * DESCRIPTION   = Inserts all the user defined forms into list handle hWnd
 *
 * INPUT         = HWND    hWnd
 *                 PCNFDATA pcnfData
 *
 * OUTPUT        = void
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *          
 *
 **************************************************************************/

void ListUserForms( HWND hWnd, PCNFDATA pcnfData )
{
  SHORT iIndex;
  ULONG ulCount;
  PSZ   pszUserForms = NULL;
  CHAR  szBuffer[MAX_PSIZE];


  if (!PrfQueryProfileSize(HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp, (PSZ)
     szKeyUserformName, (PULONG)&ulCount))
  {
    return;
  }

  /*
  ** allocate memory so that info can be read from os2.ini
  */

  if ( !(pszUserForms = GplMemoryAlloc ( pProcessHeap, ulCount )))
  {
    RIP( "ListUserForms: AllocMem failed" );
    return;
  }

  PrfQueryProfileString( HINI_SYSTEMPROFILE, (PSZ) pcnfData->szKeyApp, (PSZ)
           szKeyUserformName, (PSZ) "", (PSZ) pszUserForms, (ULONG)ulCount );

  /*
  ** the form name mappings are in the format
  ** <form name>;<form size>;;<form name>;<form size> ...
  */
  iIndex = 0;

  while (iIndex < (SHORT)(ulCount-1))
  {
    szDlmCopy( (PSZ) szBuffer, (PSZ) (pszUserForms+iIndex), MAX_PSIZE );

    /*
    **           
    */
#if 0
//  WinSendMsg( hWnd, LM_INSERTITEM, (MPARAM)LIT_END, (MPARAM)(PSZ) szBuffer );
#endif
    DisplayTranslationString( hWnd, szBuffer, LIT_END );

    /*
    ** skip the form name and size name and compare with next form
    */
    while (*(pszUserForms+iIndex++) != ';');
    while (*(pszUserForms+iIndex++) != ';');
    iIndex++;                /* skip the second semicolon                   */
  }
  GplMemoryFree((PVOID)pszUserForms );
  pszUserForms = NULL;
}

/****************************************************************************
 *
 * FUNCTION NAME = FillPaperList
 *
 * DESCRIPTION   = This routine retrieves the paper list and font list
 *                 from PPB Resources and inserts them into the respective
 *                 list boxes. This routine also selectively enables the
 *                 radio buttons for which bins are provided in the printer
 *                 selected .
 *
 * INPUT         = HWND    hWnd - handle of the dialog box
 *                 PB *apResources
 *
 * OUTPUT        = void
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *          
 *
 **************************************************************************/

void FillPaperList( HWND hWnd, PB *apResources )
  /* HWND hWnd - handle of the dialog box */
{
  SHORT    i, j, k, l, m;
  SHORT    iTrayIndex, iPaperIndex, iPaperofs, iCount, cbSize;
  HWND     hWnd1;            /* a temp variable to receive sub handles      */
  HWND     hWndPaper;
  HWND     hWndTray;
  HWND     hModeSwitch;
  PCNFDATA pcnfData;         /* pointer to printer configuration data       */
  PDESPPD  pdesPpd;          /* pointer to printer descriptor segment       */
  /*
  **  CHAR SZBUFFER[80]; A TEMP BUFFER TO FORMULATE STRINGS FOR INSERT
  **                     INTO LISTS
  */
  CHAR szBuffer[128];
  CHAR szDefPaper[MAX_PSIZE];/* a default paper name as stored in ppd file  */
  SHORT mi;
  FORMSTRUCT FormStruct;

  /*
  **  CHAR *CHPTR ;  DCR1399
  **  LONG LVERSION ;    DCR1399
  */
  /*
  **  printer configuration data pointer
  */
  pcnfData = (PCNFDATA)apResources[CNFRES];
  pdesPpd = (PDESPPD)apResources[PPDRES];/* printer segment info pointer    */

/*
**  ** FOLLOWING CODE IS BEEN REPLACED, DCR1399
**  ** DRIVER'S VERSION NO. IS NOW READ FROM .DRV'S EA
**  **
**  ** DISPLAY VERSION NO WHICH IS HARDCODED IN PPDIALOG.H MODULE
**    LVERSION = DRIVERSION ;
**    CHPTR = ((CHAR *)&LVERSION)+2;
**    I =0 ;
**    I += B2A ((CHAR *)&SZBUFFER[I] , *(SHORT *)CHPTR );
**    SZBUFFER[I++] = '.';
**    CHPTR = (CHAR *)&LVERSION ;
**    I += B2A((CHAR *)&SZBUFFER[I] , *(SHORT *)CHPTR );
**    SZBUFFER [I]='\0';
** DCR1399
*/
  /*
  ** get driver's EA version and display
  */
  EA_GetVersion(&szBuffer[0] );
  WinSetDlgItemText(hWnd, DSPTXT_VERSION, (PSZ) szBuffer );

  /*
  **  save list box handle ,
  **  delete all items
  */
  hWndPaper = WinWindowFromID( hWnd, LIST_PAPER );
  WinSendMsg( hWndPaper, LM_DELETEALL, (MPARAM)NULL, (MPARAM)NULL );

  /*
  ** save text box handle and initialize all to blanks
  */
  hWndTray = WinWindowFromID( hWnd, LIST_TRAY );
  WinSendMsg( hWndTray, LM_DELETEALL, (MPARAM) NULL, (MPARAM)NULL );

  if (pdesPpd->desOutbins.fIsDefoutorder == NORMAL)
  {
    pcnfData->jobProperties.iOutPlace = NORMAL;
  }
  else
  {
    pcnfData->jobProperties.iOutPlace = REVERSE;
  }

  /*
  ** Read the default paper name into a scratch buffer
  */
  strcpy( szDefPaper, GetDefaultPageSize(  pdesPpd, apResources[RESBUF] ) );
#if 0
//if (pdesPpd->desPage.ofsDfpgsz != -1)
//{
//  i = *(apResources[RESBUF]+pdesPpd->desPage.ofsDfpgsz );
//
//  if (i < MAX_PSIZE)       /* papername size limited to 32 bytes          */
//  {
//    cbSize = i;
//  }
//  else
//  {
//    cbSize = MAX_PSIZE-1;
//  }
//  szNewCopy( (PSZ) szDefPaper, (PSZ) (apResources[RESBUF]+
//     pdesPpd->desPage.ofsDfpgsz+1), (cbSize+1) );
//  *(szDefPaper+cbSize) = '\0';
//}
#endif

  /*
  ** whichever bins are provided enable the radio buttons for those bins
  **  a finite no of input tray exists
  */
  if ((m = pdesPpd->desInpbins.iInpbinpairs) > 0)
  {
    j = pdesPpd->desInpbins.ofsCmInpbins;
  }
  else
  {
    m = 1;                   /* just enable the default input tray if
                                provided in ppd file                        */
    j = pdesPpd->desInpbins.ofsDefinputslot;
  }

  for (i = 0; i < m; i++)
  {
    /*
    **           
    */
    CopyStr( szBuffer, apResources[ RESBUF ] + j );
    j += strlen( szBuffer ) + 1;

#if 0
//  k = *(apResources[RESBUF] + j);
//  j++;
//  szNewCopy( (CHAR *)szBuffer, (CHAR *)apResources[RESBUF]+j, (k+1) );
#endif

    /*
    **           
    */
    j += strlen( apResources[ RESBUF ] + j ) + 1;
#if 0
//  *(szBuffer+k) = '\0';    /* make it a proper string                     */
//  j += k;
//  k = *(apResources[RESBUF]+j );
//  j += (1+k );              /* skip the next string which is a command
//                              string                                      */
#endif

    /*
    **  This comparison is because some of the ppd files don't
    **  talk of any trays at all!!!
    */
    if (!sznIsEqual((PSZ) StringTable[IDS_None-STRING_BASE], (PSZ) szBuffer))
    {
      /*
      **           
      */
#if 0
//    WinSendMsg( hWndTray, LM_INSERTITEM, (MPARAM)LIT_END, (MPARAM)(PSZ)
//       szBuffer );          /* put the tray name in display buffer         */
#endif
      DisplayTranslationString( hWndTray, szBuffer, LIT_END );
    }
    else
    {
      /*
      **           
      */
#if 0
//    WinSendMsg(hWndTray, LM_INSERTITEM, (MPARAM)LIT_END, (MPARAM)(PSZ)
//       StringTable[IDS_Upper-STRING_BASE] );
#endif
      DisplayTranslationString( hWndTray, StringTable[IDS_Upper-STRING_BASE],
                                LIT_END );
    }
  }

  WinSendMsg( hWndTray, LM_SELECTITEM, (MPARAM)0, (MPARAM)TRUE );

  /*
  **  Control comes to this routine before the dialog box is loaded
  **  so that paper list box initialisations can be carried out
  **  Insert all the paper types from PPB resource into paper list box
  */
/*iPaperofs = pdesPpd->desPage.ofsImgblPgsz;*/

  for (iPaperIndex = 0; iPaperIndex < pdesPpd->desPage.iImgpgpairs;
     iPaperIndex++)
  {
    GetImageableArea( iPaperIndex, (PFORMSTRUCT)&FormStruct, pdesPpd,
                      (PBYTE)apResources[RESBUF] );
    strcpy( szBuffer, FormStruct.FormName );
#if 0
//  iCount = *(apResources[RESBUF]+iPaperofs );
//  iPaperofs++;
//
//  if (iCount < MAX_PSIZE)  /* papername size limited to 32 bytes          */
//  {
//    cbSize = iCount;
//  }
//  else
//  {
//    cbSize = MAX_PSIZE-1;
//  }
//  szNewCopy( (CHAR *)szBuffer, (CHAR *)apResources[RESBUF]+iPaperofs,
//             (cbSize+1) );
//  iPaperofs += iCount;
//  *(szBuffer+cbSize) = '\0';/* make it a proper string                    */
//  iPaperofs += 8;          /* skip the next 8 bytes which are dimensions  */
#endif
    /*
    ** The WinSendMsg line was changed to be executed conditionally.
    ** Instead we will only insert the item in the list box if it's not
    ** already there.
    **                                                                     
    */
    if ((SHORT)WinSendMsg(hWndPaper, LM_SEARCHSTRING, (MPARAM)(MPFROM2SHORT(0,
       (SHORT)LIT_FIRST)), (MPARAM)szBuffer) == LIT_NONE)
    {
      /*
      **           
      */
#if 0
//    WinSendMsg(hWndPaper, LM_INSERTITEM, (MPARAM)LIT_SORTASCENDING, (MPARAM)
//       (PSZ) szBuffer );
#endif
      DisplayTranslationString( hWndPaper, szBuffer, LIT_SORTASCENDING );
    }
  }

  /*
  ** insert this entry to facilitate removal of any paper from tray
  */
  /*
  **           
  */
#if 0
//WinSendMsg( hWndPaper, LM_INSERTITEM, (MPARAM)LIT_END, (MPARAM)(PSZ)
//            StringTable[IDS_None-STRING_BASE] );
#endif
  DisplayTranslationString( hWndPaper, StringTable[IDS_None-STRING_BASE],
                            LIT_END );

  /*
  ** Insert any user defined forms to the list box
  */
  ListUserForms( hWndPaper, (PCNFDATA)pcnfData );

  /*
  **  search the printer seg name and set the filelist entry in selected
  **  state
  */
  mi = LIT_NONE;

  if (pcnfData->u.iv.pSourcePaper->szPaperName[0][0] != '\0')
  {
    /*
    ** Search for paper name.
    */
    mi = (SHORT)WinSendMsg( hWndPaper, LM_SEARCHSTRING, (MPARAM)(MPFROM2SHORT(0,
         (SHORT)LIT_FIRST)),
         (MPARAM)&pcnfData->u.iv.pSourcePaper->szPaperName[0][0]);
  }

  if (mi == LIT_NONE)        /* either paper name is       or null          */
  {
    mi = (SHORT)WinSendMsg(hWndPaper, LM_SEARCHSTRING, (MPARAM)(MPFROM2SHORT(0
       , (SHORT)LIT_FIRST)), (MPARAM)szDefPaper );/* search for default
                                paper name                                  */

        /*
        **  the paper name is changed because either it was null or
        **  wrongly recorded in os2.ini
        */

    szNewCopy( (PSZ) &pcnfData->u.iv.pSourcePaper->szPaperName[0][0],
               (PSZ) szDefPaper, MAX_PSIZE );
  }

  if (mi == LIT_NONE);

  /*
  ** an entry has been clicked so it should be displayed selected
  */
  else
  {
    WinSendMsg( hWndPaper, LM_SELECTITEM, (MPARAM)mi, (MPARAM)TRUE );
  }

  /*
  ** Process Auto Mode Switching
  */
  hModeSwitch = WinWindowFromID( hWnd, CHECK_MODESWITCH );

  if (pdesPpd->desItems.ofsInitString != -1)/* If init string exists        */
  {
    WinEnableWindow( hModeSwitch, TRUE );/* Enable Auto Mode Switch           */

    if (pcnfData->uPrinterPropFlags&MODESWITCH)
    {
      /*
      ** Check it
      */
      WinSendMsg( hModeSwitch, BM_SETCHECK, (MPARAM)1L, (MPARAM)0L );
    }
    else                     /* No                                          */
    {
      /*
      ** Uncheck it
      */
      WinSendMsg( hModeSwitch, BM_SETCHECK, (MPARAM)0L, (MPARAM)0L );
    }
  }
  else
  {
    WinEnableWindow( hModeSwitch, FALSE );/* Disable button                   */
    pcnfData->uPrinterPropFlags &= ~MODESWITCH;
  }
}

/****************************************************************************
 *
 * FUNCTION NAME = FillJobList
 *
 * DESCRIPTION   = This routine retrieves the paper list and font list
 *                 from PPB Resources and inserts them into the respective
 *                 list boxes. This routine also selectively enables the
 *                 radio buttons for which bins are provided in the printer
 *                 selected .
 *
 * INPUT         = HWND    hWnd - handle of the dialog box
 *                 PB *apResources
 *
 * OUTPUT        = void
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ************************************************************************** */

void FillJobList( HWND hWnd, PB *apResources )
  /*  HWND hWnds - handle of the dialog box*/
{
  SHORT    i, uIdTemp, iPaperIndex, iPaperofs, iCount, cbSize;
  HWND     hWnd1;            /* a temp variable to receive sub handles      */
  PCNFDATA pcnfData;         /* pointer to printer configuration data       */
  PDESPPD  pdesPpd;          /* pointer to printer descriptor segment       */
  UCHAR    ResString [6];    /*            */
  PUCHAR   pResBuffer;       /*            */
  USHORT   counter;          /*            */
  USHORT   uItemIndex;       /*            */
  USHORT   uResValue;        /*            */
  USHORT   uStringLength;    /*            */
  /*
  **  a temp buffer to formulate strings for insert into lists
  */
  CHAR     szBuffer[80];
  CHAR     szDefPaper[MAX_PSIZE];  /* a default paper name as stored in ppd file */
  SHORT    mi;
  FORMSTRUCT FormStruct;

  /*
  ** printer configuration data pointer
  */
  pcnfData = (PCNFDATA) apResources[CNFRES];
  pdesPpd = (PDESPPD) apResources[PPDRES];   /* printer segment info pointer */

  /*
  **  set Form name
  **  Control comes to this routine before the dialog box is loaded
  **  so that list box initialisations can be carried out
  */
  hWnd1 = WinWindowFromID( hWnd, LIST_FORMS );

  /*
  **  clear the list box first
  */
  WinSendMsg( hWnd1, LM_DELETEALL, (MPARAM)NULL, (MPARAM)NULL );

  /*
  ** Insert all the paper types from PPB resource into paper list box
  */
/*iPaperofs = pdesPpd->desPage.ofsImgblPgsz;*/

  for (iPaperIndex = 0; iPaperIndex < pdesPpd->desPage.iImgpgpairs;
     iPaperIndex++)
  {
    GetImageableArea( iPaperIndex, (PFORMSTRUCT)&FormStruct, pdesPpd,
                      (PBYTE)apResources[RESBUF] );
    strcpy( szBuffer, FormStruct.FormName );
#if 0
//  iCount = *(apResources[RESBUF] + iPaperofs );
//
//  if (iCount < MAX_PSIZE)  /* papername size limited to 32 bytes          */
//  {
//    cbSize = iCount;
//  }
//  else
//  {
//    cbSize = MAX_PSIZE-1;
//  }
//  iPaperofs++;
//  szNewCopy( (PCHAR)szBuffer, (PCHAR)apResources[RESBUF]+iPaperofs,
//             (cbSize+1) );
//  iPaperofs += iCount;
//  *(szBuffer + cbSize) = '\0';    /* make it a proper string              */
//  iPaperofs += 8;          /* skip the next 8 bytes which are dimensions  */
#endif
    /*
    **           
    */
#if 0
//  WinSendMsg( hWnd1, LM_INSERTITEM, (MPARAM)LIT_SORTASCENDING, (MPARAM)(PSZ)
//              szBuffer );
#endif
    DisplayTranslationString( hWnd1, szBuffer, LIT_SORTASCENDING );
  }

  /*
  **  Insert any user defined forms to the list box
  */
  ListUserForms( hWnd1, (PCNFDATA) pcnfData );

  /*
  **  Read the default paper name into a scratch buffer
  */
  strcpy( szDefPaper, GetDefaultPageSize(  pdesPpd, apResources[RESBUF] ) );
#if 0
//if (pdesPpd->desPage.ofsDfpgsz != -1)
//{
//  i = *(apResources[RESBUF] + pdesPpd->desPage.ofsDfpgsz );
//
//  if (i < MAX_PSIZE)       /* papername size limited to 32 bytes          */
//  {
//    cbSize = i;
//  }
//  else
//  {
//    cbSize = MAX_PSIZE - 1;
//  }
//  szNewCopy( (PSZ) szDefPaper, (PSZ) (apResources[RESBUF]+
//             pdesPpd->desPage.ofsDfpgsz+1), (cbSize+1) );
//  *(szDefPaper+cbSize) = '\0';
//}
#endif

  /*
  **  search the form name and set the  entry in selected state
  **  search for the printer name
  */
  mi = (SHORT)WinSendDlgItemMsg( hWnd, LIST_FORMS, LM_SEARCHSTRING, (MPARAM)
                                 (MPFROM2SHORT(0, (SHORT) LIT_FIRST)), (MPARAM)
                                 pcnfData->jobProperties.szFormName );

  if (mi == LIT_NONE)
  {
    /*
    **  search for the printer name
    */
    mi = (SHORT) WinSendDlgItemMsg( hWnd, LIST_FORMS, LM_SEARCHSTRING, (MPARAM)
                                   (MPFROM2SHORT(0, (SHORT)LIT_FIRST)),
                                   (MPARAM)szDefPaper );
  }

  if (mi == LIT_NONE);

  /*
  ** an entry has been clicked so it should be displayed selected
  */
  else
  {
    WinSendDlgItemMsg( hWnd, LIST_FORMS, LM_SELECTITEM, (MPARAM)mi, (MPARAM)
       TRUE );
  }

  /*           
  ** Display the available resolutions in the RESOLUTION listbox.
  ** First, go to the buffer containing the resolutions.
  */
  /*
  **            For single res printers
  */
  if ( pdesPpd->desItems.ResList.uNumOfRes == 0 )
  {
    uResValue = pdesPpd->desItems.iResDpi;

    /*
    **           
    */
    _itoa( uResValue, ResString, 10 );
#if 0
//  uStringLength = b2a( ResString, uResValue );
//  ResString [uStringLength] = 0;
#endif

    uItemIndex = (USHORT) WinSendDlgItemMsg( hWnd, LIST_RESOLUTION,
                          LM_INSERTITEM, (MPARAM) LIT_END,
                         (MPARAM) ResString );
    WinSendDlgItemMsg( hWnd, LIST_RESOLUTION, LM_SETITEMHANDLE,
                      (MPARAM) uItemIndex, (MPARAM) uResValue );
    WinSendDlgItemMsg( hWnd, LIST_RESOLUTION, LM_SELECTITEM,
                       (MPARAM) uItemIndex, (MPARAM) TRUE );

  }
  else
  {
    if ( pcnfData->uResolution == 0 )
    {
      pcnfData->uResolution = pdesPpd->desItems.iResDpi;
    }

    pResBuffer = (PUCHAR) (apResources[RESBUF] + pdesPpd->desItems.ResList.
                 uResOffset );
    for (counter = 0 ; counter < pdesPpd->desItems.ResList.uNumOfRes ;
      counter++)
    {
      /*
      ** Take the first two bytes from the buffer and put their
      ** values to the WORD.
      */
      uResValue = *(PUSHORT)pResBuffer;

      /*
      ** Convert the integer to a NULL-terminated string.
      */
      /*
      **           
      */
#if 0
//    uStringLength = b2a( ResString, uResValue );
//    ResString [uStringLength] = 0;
#endif
      _itoa( uResValue, ResString, 10 );

      /*
      ** Insert the string in the listbox.  Assign a handle to that
      ** string.  The handle will be the resolution value.
      */
      uItemIndex = (USHORT) WinSendDlgItemMsg (hWnd, LIST_RESOLUTION,
                   LM_INSERTITEM, (MPARAM) LIT_END,
                   (MPARAM) ResString );
      WinSendDlgItemMsg( hWnd, LIST_RESOLUTION, LM_SETITEMHANDLE,
        (MPARAM) uItemIndex, (MPARAM) uResValue );

      /*
      ** If the resolution matches the default resolution, display
      ** that resolution in the top of the listbox.
      */
      if (uResValue == pcnfData->uResolution)
      {
        WinSendDlgItemMsg( hWnd, LIST_RESOLUTION, LM_SELECTITEM,
                           (MPARAM) uItemIndex, (MPARAM) TRUE );
      }

      /*
      ** Go to the next string by incrementing the pointer the
      ** length of the buffer plus the buffer length plus 2 extra
      ** bytes.
      */
      /*
      **           
      */
      pResBuffer += strlen( pResBuffer + 2 ) + 3;
    }
  }

    /*  if output eps disable the landscape button. */

  if (pcnfData->iDestnType == ENCAPS)
  {
    /*
    **  disable this particular radio button
    */
    WinEnableWindow( WinWindowFromID( hWnd, RADIO_LAND), FALSE );
    pcnfData->jobProperties.iOrient = PORTRAIT;
  }

  /*
  ** put the portrait or landscape button in proper shape
  */
  if (pcnfData->jobProperties.iOrient == PORTRAIT)
  {
    uIdTemp = RADIO_PORTRAIT;
    WinSendDlgItemMsg( hWnd, RADIO_LAND, BM_SETCHECK, (MPARAM)0L, (MPARAM)0L );
  }
  else
  {
    uIdTemp = RADIO_LAND;
    WinSendDlgItemMsg( hWnd, RADIO_PORTRAIT, BM_SETCHECK, (MPARAM)0L, (MPARAM)
                       0L );
  }
  WinSendDlgItemMsg( hWnd, uIdTemp, BM_SETCHECK, (MPARAM)1L, (MPARAM)0L );

  /*
  **  DCR 1462 ADD SUPPORT FOR DUPLEX OPTIONS
  **  DECIDE WHICH OPTIONS TO ACTIVATE...
  **  IF SUPPORT DUPLEX THEN ENABLE DUPLEX SELECTION
  */
  if (pdesPpd->desItems.ofsDuplexNoTumble > 0)
  {
    WinEnableWindow( WinWindowFromID( hWnd, RADIO_BOOK), TRUE );
  }

  /*
  ** If support duplex and tumble
  */
  if (pdesPpd->desItems.ofsDuplexTumble > 0)
  {
    WinEnableWindow( WinWindowFromID( hWnd, RADIO_FLIP), TRUE );
  }

  /*
  ** Decide which on which option to set...
  */
  if (pcnfData->sDuplexMode == DUPLEX_DUPLEXNOTUMBLE)
  {
    uIdTemp = RADIO_BOOK;
  }
  else if (pcnfData->sDuplexMode == DUPLEX_DUPLEXTUMBLE)
  {
    uIdTemp = RADIO_FLIP;
  }
  else
  {
    uIdTemp = RADIO_ONE_SIDED;
  }
  WinSendDlgItemMsg( hWnd, uIdTemp, BM_SETCHECK, (MPARAM)1L, (MPARAM)0L );

  /*
  ** If manualfeed provided enable the manualfeed button
  */
  hWnd1 = WinWindowFromID( hWnd, CHECK_MANUAL );

  if (pdesPpd->desInpbins.iManualfeed != NONE)
  {
    /*
    ** enable this particular check box button
    */
    WinEnableWindow( hWnd1, TRUE );

    if (pcnfData->jobProperties.iManualfeed == 1)
    {
      /*
      ** check the button
      */
      WinSendMsg( hWnd1, BM_SETCHECK, (MPARAM)1L, (MPARAM)0L );
    }
    else
    {
      /*
      ** uncheck the button
      */
      WinSendMsg( hWnd1, BM_SETCHECK, (MPARAM)0L, (MPARAM)0L );
      pcnfData->jobProperties.iManualfeed = 0;
    }
  }
  else
  {
    /*
    ** disable this particular check box button
    */
    WinEnableWindow( hWnd1, FALSE );
    pcnfData->jobProperties.iManualfeed = NONE;
  }

  /*
  ** If colorsupport provided enable the use color button
  */
  hWnd1 = WinWindowFromID( hWnd, CHECK_COLOR );

  if (pdesPpd->desItems.fIsColorDevice != NONE)
  {
    /*
    ** enable this particular check box button
    */
    WinEnableWindow( hWnd1, TRUE );

    if (pcnfData->jobProperties.fIsColorDevice == NONE)
    {
      pcnfData->jobProperties.fIsColorDevice = TRUE;
    }

    if (pcnfData->jobProperties.fIsColorDevice == TRUE)
    {
      /*
      ** check the button
      */
      WinSendMsg( hWnd1, BM_SETCHECK, (MPARAM) 1L, (MPARAM) 0L );
    }
    else
    {
      /*
      ** uncheck the button
      */
      WinSendMsg( hWnd1, BM_SETCHECK, (MPARAM) 0L, (MPARAM) 0L );
    }
  }
  else
  {
    /*
    ** disable this particular check box button
    */
    WinEnableWindow( hWnd1, FALSE );
    pcnfData->jobProperties.fIsColorDevice = NONE;
  }

  /*
  **  set to display the no of copies and set the maximum no of chars
  **  in the edit field to 3.
  */
  WinSendMsg( WinWindowFromID( hWnd, EDIT_SCALE ), EM_SETTEXTLIMIT, (MPARAM)3L,
              (MPARAM) 0L );
  WinSetDlgItemShort( hWnd, EDIT_SCALE, pcnfData->jobProperties.uScale,
                      (BOOL) FALSE );

  /*
  ** activate the cursor on scale field
  */
  ShowCursor(WinWindowFromID( hWnd, EDIT_SCALE) );
}

/***************************************************************************
 *
 * FUNCTION NAME = ScanCustomset
 *
 * DESCRIPTION   = scan the presence of string szScan in szSource
 *                 and return TRUE if found.
 *
 * INPUT         = PSZ szSource
 *                 PSZ szScan
 *
 * OUTPUT        = BOOL
 *
 * RETURN-NORMAL = return TRUE if found
 * RETURN-ERROR  = FALSE
 *
 ***************************************************************************/

BOOL ScanCustomset( PSZ szSource, PSZ szScan )
{
  SHORT i, j, k, l;
  PSZ   pszb;

  pszb = szScan;
  i = 0;                     /* compute length of search string             */

  while (*pszb++ != '\0')
  {
    i++;
  }
  pszb = szSource;
  j = 0;

  while (*pszb++ != '\0')
  {
    j++;
  }

  /*
  **  Only search till end - length of search string
  */
  j -= i;

  if (j < i)
  {
    return( FALSE );
  }

  /*
  **  Start searching the hard way from the ist char of scan string.
  */
  for (k = 0 ; k < j ; k++)
  {
    pszb = szSource + k;
    l = 0;

    while (l < i && *(pszb+l) == *(szScan+l))
    {
      l++;
    }

    if (l < i);
    else
    {
      return( TRUE );
    }
  }
  return( FALSE );
}

/***************************************************************************
 *
 * FUNCTION NAME = EA_GetVersion
 *
 * DESCRIPTION   = retreive the EA .VERSION from driver file
 *
 * INPUT         = PSZ pszStrVersion
 *
 * OUTPUT        = VOID
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *                                                                    
 *
 **************************************************************************/

VOID EA_GetVersion( PSZ pszStrVersion )
{

  GLIST geaver;
  FLIST feaver;
  EAOP2 eaop2;
  SHORT usVerNameCount;              /* length of version data             */
  CHAR  szFileName[MAX_PATH_SIZE];   /* pscript driver file name           */
  SHORT rc;                          /* return from DosQPathInfo           */

  szNewCopy( pszStrVersion, "???.???", MAX_VERNAME_SIZE );

  /*
  ** Get driver file's path
  */
  if (PrfQueryProfileString( HINI_USERPROFILE, "PM_DEVICE_DRIVERS",
                             "PSCRIPT", (PSZ) "", (PSZ) szFileName,
                             (ULONG) sizeof( szFileName )))
  {

    szNewCopy( geaver.szName, EA_NAME_VERSION, (SIZE_EA_NAME_VERSION+1) );
    geaver.cbName = SIZE_EA_NAME_VERSION;
    geaver.cbList = sizeof(GLIST );
    geaver.NextEntryOffset = 0L;

    feaver.cbList = sizeof(FLIST );

    eaop2.fpGEA2List = (PGEA2LIST)&geaver;
    eaop2.fpFEA2List = (PFEA2LIST)&feaver;
    eaop2.oError = 0L;
    rc = DosQueryPathInfo((PSZ) szFileName, 3, (PVOID) &eaop2, sizeof(eaop2) );

    if (!rc &&               /* call succeed                                */
       (feaver.cbList > sizeof(feaver.cbList)) && /* has return value       */
       (feaver.cbValue) &&     /* value not zero                            */
       /*
       ** name size must .VERSION
       */
       (feaver.cbName == SIZE_EA_NAME_VERSION))
    {
      szNewCopy( pszStrVersion, feaver.szName,feaver.usSizeVerName + 1 );
    }                        /* end of if DosQPathInfo sucesses             */
  }                          /* end of if DosGetModName                     */
  return;
}


/*
**           
** Added new function
*/
/***************************************************************************
 *
 * FUNCTION NAME = DisplayTranslationString
 *
 * DESCRIPTION   = A PPD line may include a combination of a PPD value and a
 *                 matching translation string in the form "NAME/TRANSLATION
 *                 STRING".  If the translation string exists, display the
 *                 translation string only in the specific window (provided by
 *                 hWnd). This is done by moving pointer to the next character
 *                 after the slash ('/') and displaying the string.  If there
 *                 is no translation string or if there is a terminator (0)
 *                 after the slash, 'NAME' is displayed.
 *
 * INPUT         = HWND hWnd - Listbox handle where string is to be displayed.
 *                 PSZ  pFullName - String that contains name and (optionally),
 *                   the translation string.
 *                 UINT uiInsertType - Once the string is ready to be inserted
 *                  into the listbox, this indicates how the string is to be
 *                  inserted.  This is normally LIT_END or LIT_SORTASCENDING.
 *                  This is used as the third parameter of WinSendMsg.
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 *
 **************************************************************************/
VOID DisplayTranslationString( HWND hWnd, PSZ pFullName, UINT uiInsertType )
{
  PSZ pTransString;

  pTransString = strchr( pFullName, '/' );

  pTransString = 0;  /* Debug REMOVE ME */

  /*
  ** If no slash exists, pTransString is NULL.  Assign a pointer to the
  ** translation string (slash + 1) if not NULL and if there is a non-zero
  ** character following the slash.  Otherwise, assign the pointer to the
  ** beginning of the string.
  */
  if (pTransString != NULL &&
      *(pTransString + 1) != 0 )
  {
    pTransString++;
  }
  else
  {
    pTransString = pFullName;
  }

  /*
  ** Insert the string into the listbox.
  */
  WinSendMsg( hWnd, LM_INSERTITEM, (MPARAM) uiInsertType,
              (MPARAM) pTransString );
  return;
}


/***************************************************************************
 *
 * FUNCTION NAME = CompareRealNames
 *
 * DESCRIPTION   = Compares two strings that *may* each contain a translation
 *                 string.  If a translation string exists for either string,
 *                 the slash that starts the string is temporarily set to 0,
 *                 making the real name NULL-terminated.  Both strings are
 *                 compared using strcmp.  For any string that contains a
 *                 translation string, the slash is reinserted after the
 *                 compare.
 *                 This function returns the return code generated by strcmp.
 *
 * INPUT         = PSZ pString1 - First string to compare.
 *                 PSZ pString2 - Second string to compare.
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = Same as strcmp (0).
 * RETURN-ERROR  = Same as strcmp (non-0).
 *
 *
 **************************************************************************/
INT _Optlink CompareRealNames( PSZ pString1, PSZ pString2 )
{
  INT  iReturnCode;
  PSZ  pStrSlash1;
  PSZ  pStrSlash2;

  /*
  ** A translation string exists if a slash '/' exists.  If so, temporarily
  ** terminate the string at the slash.
  */
  if ((pStrSlash1 = strchr( pString1, '/' )) != NULL)
  {
    *pStrSlash1 = 0;
  }
  if ((pStrSlash2 = strchr( pString2, '/' )) != NULL)
  {
    *pStrSlash2 = 0;
  }

  /*
  ** Compare the strings.  The return value from strcmp will be returned by
  ** this function.
  */
  iReturnCode = (INT) strcmp( pString1, pString2 );

  /*
  ** If a slash exists, pStrSlash1 and 2 are not NULL.  For that case, insert
  ** the slash back into the string.
  */
  if (pStrSlash1 != NULL)
  {
    *pStrSlash1 = '/';
  }
  if (pStrSlash2 != NULL)
  {
    *pStrSlash2 = '/';
  }

  return( iReturnCode );
}
