/*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 = PRDAPAGE
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prda_SetCodePage
 *             prda_GetCodePage
 *             prda_AlterCodePage
 *             prda_MatchExactCodePage
 *             prda_CheckMetrics
 *             prda_FindDeviceCodePage
 *             prda_MultiCodePageSupported
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/


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

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

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

#include <prdacone.h>
#include <prddcone.h>
#include <prdecone.h>
#include <prdmcone.h>
#include <prdncone.h>
#include <prdtcone.h>

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

#include <prdaextf.h>
#include <prdeextf.h>
#include <prdtextf.h>
#include <prdyextf.h>
#include <prduextf.h>

extern lplpFontCPListType    DVTFontCPList [];
extern DVTCPListType         DVTCodePageList [];
extern lpDVTCPSource         DVTCodePageCaps [];
extern CPTUseTableEntry      CPTUseTable [];
extern USHORT                DRIVER_TYPE;
extern USHORT               OutlineCodepageEntries;
extern lpOutlineCodepages   OutlineCodepages;
extern USHORT               HeritageResidentCodePageCount;
extern USHORT               HeritageResidentCodePages[];
extern CHAR                 szQualityString1[];               /* PD00465 */
extern CHAR                 szQualityString2[];               /* PD00465 */
extern CHAR                 szQualityString3[];               /* PD00465 */
extern CHAR                 szQualityString2a[];              /* PD00731 */


/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prda_SetCodePage                                       */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   See "OS/2 Technical Reference: I/O Subsytems and Device Drivers" */
/*                                                                    */
/*   HDC             DcH;                                             */
/*   ULONG           ArgCodePage;                                     */
/*   lpDCI           DCIData;                                         */
/*   ULONG           FunN;                                            */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   Sets the code page to the value passed in ArgCodePage.           */
/*                                                                    */
/**********************************************************************/
/*   CON3201  Convert to C/SET2                                       */
ULONG EXPENTRY prda_SetCodePage ( HDC    DcH,
                                  ULONG  ArgCodePage,
                                  lpDCI  DCIData,
                                  ULONG  FunN )

{
#define TFUNC "prda_SetCodePge"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    ULONG                Command;
    USHORT               Result;

    /******************************************************************/
    /* Do entry processing                                            */
    /******************************************************************/
    GetCommand(DCIData);
    prdm_ValidateArea;
    prdm_EnterDriver(DCIData);

    /******************************************************************/
    /* Look for a font with the new code page which "matches" the     */
    /* current default font.                                          */
    /******************************************************************/
    Result = prda_AlterCodePage( (USHORT)ArgCodePage, DCIData );

    /******************************************************************/
    /* Code here is structured so that we can log a warning rather    */
    /* than an error "if needs dictate" (aye verily).                 */
    /******************************************************************/
    if ( Result == ERROR_ZERO )
        goto LOGERR_EXIT;

SETCP_OK_FAST_EXIT:
    prdm_LeaveDriver(DCIData);
    return (OK);

LOGWARN_EXIT:
    /******************************************************************/
    /* After logging a warning return OK not an error.                */
    /******************************************************************/
    prdm_LeaveDriver(DCIData);
    LOGWARNING(TFUNC, "Invalid code page", FNULL, 0, PMERR_INV_CODEPAGE);
    return (OK);

LOGERR_EXIT:
    prdm_LeaveDriver(DCIData);
    LOGERR(TFUNC, "Invalid code page", FNULL, 0, PMERR_INV_CODEPAGE);
    return (ERROR_ZERO);

} /* prda_SetCodePage */

#undef TFUNC






/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prda_GetCodePage                                       */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   See "OS/2 Technical Reference: I/O Subsytems and Device Drivers" */
/*                                                                    */
/*   HDC             DcH;                                             */
/*   lpDCI           DCIData;                                         */
/*   ULONG           FunN;                                            */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   Returns the current code page.                                   */
/*                                                                    */
/**********************************************************************/
/*   CON3201  Convert to C/SET2                                       */
ULONG prda_GetCodePage ( HDC    DcH,
                         lpDCI  DCIData,
                         ULONG  FunN )

{
#define TFUNC "prda_GetCodePge"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    USHORT      CodePage;

    /******************************************************************/
    /* Return the current code page but protect the DCIData as well.  */
    /******************************************************************/
    prdm_EnterDriver(DCIData);
    CodePage = DCIData->DCICodePage;
    prdm_LeaveDriver(DCIData);

    return ((ULONG)CodePage);
}
#undef TFUNC






/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prda_AlterCodePage                                     */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   ULONG           NewCodePage;                                     */
/*   lpDCI           DCIData;                                         */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This implements the change code page function for the default    */
/*   font.                                                            */
/*                                                                    */
/**********************************************************************/
/*   CON3201  Convert to C/SET2                                       */
USHORT prda_AlterCodePage ( USHORT  NewCodePage,
                            lpDCI   DCIData )

{
#define TFUNC "prda_AltCodePge"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    lpDfltFontInfoType   pDfltFont;
    lpDfltFontInfoType   pDfltDeviceFont;
    USHORT               Result;

    /******************************************************************/
    /* If the code pages are the same there is nothing to do          */
    /******************************************************************/
    if (DCIData->DCICodePage == NewCodePage)
        return ( OK );

    /******************************************************************/
    /* Check that the code page is valid (non-zero).                  */
    /******************************************************************/
    if (NewCodePage == 0)
        return( ERROR_ZERO );

    /******************************************************************/
    /* Get some useful pointers.                                      */
    /******************************************************************/
    pDfltFont       = &DCIData->DCIPdbInstance->DfltFont;
    pDfltDeviceFont = &DCIData->DCIPdbInstance->DfltDeviceFont;

    /******************************************************************/
    /* If the default font is an engine font then Check that          */
    /* QueryCodePageVector can pass us a valid table pointer for this */
    /* codepage and thus accept this new code page.                   */
    /******************************************************************/
    if ( DCIData->DCIDefTxtAts->cdef.fFlags & CDEF_GENERIC )
    {
        if ( ! GreQueryCodePageVector( (ULONG)NewCodePage ) )
        {
            goto ERROR_EXIT;
        }
    }
    else
    {
        /**************************************************************/
        /* Currently find device code page always returns OK, but     */
        /* since things in this area change a lot, check for not      */
        /* found any way.                                             */
        /**************************************************************/
        Result = prda_FindDeviceCodePage ( NewCodePage,
                                           DCIData,
                                           pDfltFont );

        if ( Result == CODEPAGE_NOT_FOUND )
        {
            goto ERROR_EXIT;
        }
    }

    /******************************************************************/
    /* Now change the default device font to the new code page just   */
    /* in case we get a raw data call.                                */
    /******************************************************************/
    Result = prda_MatchExactCodePage ( NewCodePage,
                                       DCIData,
                                       pDfltDeviceFont );

    if (Result == CODEPAGE_FOUND)
    {
        /**************************************************************/
        /* Signal to the code below that the default font needs       */
        /* setting up again because it has changed.                   */
        /**************************************************************/
        DCIData->Flags |= RESET_DFLT_FONT;
    }

    /******************************************************************/
    /* Update the code page                                           */
    /******************************************************************/
    DCIData->DCICodePage = NewCodePage;

    /******************************************************************/
    /* Call LocateFont to update FontData if necessary.               */
    /******************************************************************/
//  if (DCIData->DCICurTxtAts->cdef.defSet == 0)
//  {
        /**************************************************************/
        /* PD00048 : Remove if stmt to ALWAYS call LocateFont.        */
        /**************************************************************/
        if ( OK != prdt_LocateFont(&DCIData->DCIFontData, DCIData))
        {
            return (ERROR_ZERO);
        }
        else
        {
            return ( OK );
        }
//  }

ERROR_EXIT:
    /******************************************************************/
    /* Could not change the code page                                 */
    /******************************************************************/
    return (ERROR_ZERO);

}
#undef TFUNC


/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prda_FindDeviceCodePage                                */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   USHORT               NewCodePage;                                */
/*   lpDCI                DCIData;                                    */
/*   lpDfltFontInfoType   pDfltFontInfo;                              */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   Changes the default font to the requested code page if one is    */
/*   available or a font to be used to simulate the requested code    */
/*   page.  If there is no font matches or can be used to simulate    */
/*   the requested code page, the default font will not be changed.   */
/*   We will return CODEPAGE_FOUND in all cases, so that applications */
/*   will not fail.                                                   */
/*                                                                    */
/**********************************************************************/
/*   CON3201  Convert to C/SET2                                       */
USHORT prda_FindDeviceCodePage ( USHORT               NewCodePage,
                                 lpDCI                DCIData,
                                 lpDfltFontInfoType   pDfltFontInfo )

{
#define TFUNC "prda_FndDevCP"
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    CPTUseTableEntry     TableEntry;       /* Use table entry         */
    SHORT                UseTableIndex;    /* Use table entry index   */
    USHORT               i;                /* index for looping       */
    USHORT               RetVal;           /* return value            */

    /******************************************************************/
    /* PD00083 :                                                      */
    /* Initialize the simulate flag to OFF.  This flag will be        */
    /* turned ON when there is not exact match for a code page.       */
    /******************************************************************/
    pDfltFontInfo->Info.Type &= ~SIMULATE_DFLT_FONT;

    /******************************************************************/
    /* First see if we can get an exact match on a device code page.  */
    /******************************************************************/
    RetVal = prda_MatchExactCodePage( NewCodePage,
                                      DCIData,
                                      pDfltFontInfo );

    /******************************************************************/
    /* If we don't have an exact match on the code page, and the new  */
    /* codepage is supported by OS/2 set up for a simulation.         */
    /* First, we search the Code Page Use Table to find the code      */
    /* page to use for the simulation.                                */
    /******************************************************************/
    if ( ( RetVal == CODEPAGE_NOT_FOUND ) &&
         ( GreQueryCodePageVector( (ULONG)NewCodePage ) ) )
    {
        /**************************************************************/
        /* There is may or may not be an entry in this table for the  */
        /* target codepage. If there is not then later on the default */
        /* entry is used.                                             */
        /**************************************************************/
        UseTableIndex = -1;

        for (i = 0; i < CPT_USE_TABLE ; i++ )
        {
            if (CPTUseTable[i].usTargetCP == NewCodePage)
            {
                UseTableIndex = i;
                break;
            }
        }

        /**************************************************************/
        /* Now search for a font in one of the potential root code    */
        /* pages for this font.                                       */
        /**************************************************************/
        if (UseTableIndex >= 0)
        {
            TableEntry = CPTUseTable[UseTableIndex];

            for (i = 0; i < 2; i++ )
            {
                if (TableEntry.RootCPList[i] != 0)
                {
                    RetVal = prda_MatchExactCodePage(
                                        TableEntry.RootCPList[i],
                                        DCIData,
                                        pDfltFontInfo );

                    if (RetVal == CODEPAGE_FOUND)
                        break;
                }
            }
        }

        /**************************************************************/
        /* No entry found in the Use Codepage Table, or no font that  */
        /* matches a root code page in the Use Codepage Table entry   */
        /* so check the default entry.                                */
        /**************************************************************/
        if (RetVal == CODEPAGE_NOT_FOUND)
        {
            TableEntry = CPTUseTable[0];

            for (i = 0; i < 2 ; i++ )
            {
                if (TableEntry.RootCPList[i] != 0)
                {
                    RetVal = prda_MatchExactCodePage(
                                    TableEntry.RootCPList[i],
                                    DCIData,
                                    pDfltFontInfo );

                    if (RetVal == CODEPAGE_FOUND)
                        break;
                }
            }
        }

        /**************************************************************/
        /* If we've found a font in a root code page to use for       */
        /* simulation, turn on the SIMULATE_DFLT_FONT bit in          */
        /* DfltFontInfo.  Otherwise we should return CODEPAGE_FOUND   */
        /* so apps don't fail.                                        */
        /**************************************************************/
        if (RetVal == CODEPAGE_FOUND)
        {
            pDfltFontInfo->Info.Type |= SIMULATE_DFLT_FONT;
        }
        else
        {
            RetVal == CODEPAGE_FOUND;
        }

    } /* ...... if (RetVal == CODEPAGE_NOT_FOUND) .................. */

    return (RetVal);

}
#undef TFUNC




/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prda_MatchExactCodePage                                */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   USHORT               NewCodePage;                                */
/*   lpDCI                DCIData;                                    */
/*   lpDfltFontInfoType   pDfltFontInfo;                              */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   Looks for a default device font with the new code page in the    */
/*   available font sources.                                          */
/*                                                                    */
/*   ASSUMPTIONS:                                                     */
/*                                                                    */
/*   - The function assumes that the font count is non-zero.          */
/*                                                                    */
/**********************************************************************/
/*   CON3201  Convert to C/SET2                                       */
USHORT prda_MatchExactCodePage ( USHORT               NewCodePage,
                                 lpDCI                DCIData,
                                 lpDfltFontInfoType   pDfltFontInfo )

{
#define TFUNC "prda_MatchExtCP"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    lpPDBI               PDBInstance;      /* Pointer to the PDB      */
    lpPrtDataEntry       PrinterData;
    lpDDTType            pDDT;             /* Pointer to DDT in PDB   */
    lpFontInfoType       pFontInfo;        /* Current font info       */
    FontInfoType         CardFontInfo;
    SHORT                CPIndex;
    USHORT               CPSource;
    USHORT               i, j, k;
    SHORT                CardIndex;
    USHORT               FontIndex;
    USHORT               RetVal;
    PBYTE                pCardName;
    PFOCAMETRICS         pOldMetrics;
    PFOCAMETRICS         pNewMetrics;
    lpCardFontListType   pCardList;
    lplpFontCPListType   FontCodePageList;
    lpFontCPListType     CodePageList;
    lpFontCPListType     pCodePageData;
    lpFontListType       pFontList;
    lpDVTCPSource        CodePageCaps;  /* Code Page capabilities     */
    BYTE                 OldFaceName[32];
    BYTE                 NewFaceName[32];
    USHORT               Index;        /* MultiCp index to global tbl */
    BYTE                 GCPIndex;     /* 4-bit global codepage index */

    /******************************************************************/
    /* Set up local pointers and variables.                           */
    /******************************************************************/
    PDBInstance = DCIData->DCIPdbInstance;
    PrinterData = PDBInstance->PrinterData;
    pDDT        = &PDBInstance->DDT;
    pFontInfo   = &pDfltFontInfo->Info;
    CodePageCaps = DVTCodePageCaps[PrinterData->PrinterType];

    /******************************************************************/
    /* Start off pessimistic...                                       */
    /******************************************************************/
    RetVal = CODEPAGE_NOT_FOUND;

    /******************************************************************/
    /* The add code page option is supported on the Proprinters.      */
    /******************************************************************/
    if ( pDDT->DDTFontFlags & DDT_ADD_CODE_PAGE_OPTION )
    {
        /**************************************************************/
        /* Check code page change is to one that is supported.        */
        /*                                                            */
        /* The DVTCodePageList contains all the code page numbers     */
        /* supported.  Look through this array until a match is found */
        /* with the code page number parameter (or not).  If a match  */
        /* is found then the index of the array entry can be adjusted */
        /* and used as the index to the code page path table in the   */
        /* printer data.  (The adjustment is needed since the         */
        /* CodePageList has an 437 as entry 0 while the CPPathList    */
        /* does not).                                                 */
        /*                                                            */
        /* The CodePageList has NO_OF_ADDABLE_CPS+2 entries since it  */
        /* has an entry for each addable code page plus 437 and 850   */
        /**************************************************************/
        for ( CPIndex = NO_OF_ADDABLE_CPS + 2 ;
              ((CPIndex--) &&
               (DVTCodePageList[CPIndex].Number != NewCodePage));  );

        /**************************************************************/
        /* CPIndex is now the index to CodePageList for the entry     */
        /* matching the requested code page.  If it is -ve then no    */
        /* match was found; if it is zero then we have matched on a   */
        /* code page 437 resident font.                               */
        /*                                                            */
        /* DIAL/NILE : made extensive changes in this branch of the   */
        /* code.                                                      */
        /**************************************************************/
        if ( CPIndex >= 0 )
        {
            CodePageCaps = DVTCodePageCaps[PrinterData->PrinterType];
            if ( CodePageCaps[CPIndex].CPSource == CP_RESIDENT )
            {
                /******************************************************/
                /* Must search the font list for the correct font     */
                /* index as we have made 850 resident.                */
                /******************************************************/
                if ( (PrinterData->PrinterType == IBM_PRO_PRINTER_X24E) ||
                     (PrinterData->PrinterType == IBM_PRO_PRINTER_XL24E)
                   )
                {
                    pOldMetrics = &pFontInfo->pFont->Metrics;

                    /**********************************************************/
                    /* PD00290 : forgot to set up OldFaceName                 */
                    /**********************************************************/
                    for ( k = 0; k < 32; k++ )
                    OldFaceName[k] = pOldMetrics->szFacename[k];

                    for ( i = 0;i < pDDT->DDTNoOfResidentFonts; i++ )
                    {
                        pFontList = PDBInstance->FontList[i];
                        pNewMetrics = &pFontList->pFMFData->Metrics;

                        if ( prda_CheckMetrics ( pNewMetrics,
                                                 pOldMetrics,
                                                (PBYTE)pNewMetrics->szFacename,
                                                (PBYTE)OldFaceName,
                                                NewCodePage,
                                                PrinterData) )
                        {
                            pFontInfo->Type  = FT_RESIDENT;
                            pFontInfo->Index = i;
                            pFontInfo->pFont = pFontList->pFMFData;

                            RetVal = CODEPAGE_FOUND;
                            goto EXIT_FUNCTION;
                        }
                    }
                }
                else
                {
                    /**************************************************/
                    /* It isn't X24E, so index is correct.            */
                    /**************************************************/
                    pFontInfo->Type  = FT_RESIDENT;
                    pFontInfo->pFont = PDBInstance->
                               FontList[pFontInfo->Index]->pFMFData;

                    RetVal = CODEPAGE_FOUND;
                    goto EXIT_FUNCTION;
                }
            }
            else
            {
                /******************************************************/
                /* Set up access to the code page caps arrays so that */
                /* we can determine how to set up the default font    */
                /* info                                               */
                /******************************************************/
                CPSource     = CodePageCaps[CPIndex].CPSource;

                /******************************************************/
                /* Careful about processing here. There are three     */
                /* kinds of download code pages.                      */
                /*                                                    */
                /* CP_RESOURCE and CP_PSEU_RES are always available,  */
                /* but real CP_DOWNLOAD are only available if they    */
                /* have been installed - i.e. there is a path for     */
                /* them                                               */
                /*                                                    */
                /* Note that the CPPathList does not have an entry for*/
                /* code page 437. Therefore must be accessed slightly */
                /* differently.                                       */
                /*                                                    */
                /* Must also have Memory Available for CP_RESOURCE,   */
                /* CP_DOWNLOAD and CP_PSEU_RES fonts and since number */
                /* of download fonts in code page can vary for Pro    */
                /* II's and III's make sure that's okay too.          */
                /******************************************************/
                if ( ( (PrinterData->CPMemAvail == DOWN_CP_MEM_AVAIL) ||
                       (pDDT->DDTFontFlags & DDT_DOWN_CP_MEM_SUBSET_AVAIL) ) &&
                     ( (CPSource == CP_PSEU_RES) ||
                       (CPSource == CP_RESOURCE) ||
                       ( (CPSource == CP_DOWNLOAD) &&
                         (PrinterData->CPPathList[CPIndex - 1])
                       )
                     )
                   )
                {
                    /**************************************************/
                    /* Index may be incorrect if it's an X24E and     */
                    /* the current code page is 850.                  */
                    /**************************************************/
                    if ( (PrinterData->PrinterType == IBM_PRO_PRINTER_X24E) ||
                         (PrinterData->PrinterType == IBM_PRO_PRINTER_XL24E)
                       )
                    {
                        pOldMetrics = &pFontInfo->pFont->Metrics;
                        if (pOldMetrics->usCodePage == 850)
                        {
                            pFontInfo->Index = pFontInfo->Index -
                                   pDDT->DDTFontsInCodePage;
                        }
                    }

                    if (pFontInfo->Index < pDDT->DDTFontsInCodePage)
                    {
                        /**************************************************/
                        /* Change the default font source to indicate that*/
                        /* it is a codepage font.  The CodePageNo field   */
                        /* must also be changed to reflect the new        */
                        /* codepage. This has the same base as the        */
                        /* DVTCodePageList so CPIndex is the value to use */
                        /* here.                                          */
                        /**************************************************/
                        pFontInfo->Type       = FT_CODE_PAGE;
                        pFontInfo->CodePageNo = CPIndex;

                        FontCodePageList =
                                        DVTFontCPList[PrinterData->PrinterType];

                        RetVal = CODEPAGE_FOUND;
                        goto EXIT_FUNCTION;
                    }
                    else
                       RetVal = CODEPAGE_NOT_FOUND;
                }
                else
                {
                    /**************************************************/
                    /* No match found (CP not added or no memory      */
                    /* available).                                    */
                    /**************************************************/
                    RetVal = CODEPAGE_NOT_FOUND;
                }
            } /* ... if ( CodePageCaps[CPIndex].CPSource == CP_RES... */
        }
        /* .... if ( CPIndex >= 0 ) ................................. */
    }
    /* .... if ( pDDT->DDTFontFlags & DDT_ADD_CODE_PAGE_OPTION ) .... */


    /******************************************************************/
    /* Cartridge fonts supported by the Quick and the Quiet.  Also    */
    /* use this branch to check other resident fonts on the 3816.     */
    /******************************************************************/
    if ( pDDT->DDTFontFlags & DDT_CARTRIDGE_OPTION )
    {
        /**************************************************************/
        /* Get the pointer to the old metrics.                        */
        /**************************************************************/
        pOldMetrics = &pFontInfo->pFont->Metrics;

        /**************************************************************/
        /* If the old default font is a card font, the face name in   */
        /* the font metrics will not include the quality (draft etc). */
        /* Make a local copy, OldFaceName, that does include quality. */
        /**************************************************************/
        for ( k = 0; k < 32; k++ )
            OldFaceName[k] = pOldMetrics->szFacename[k];

        /**************************************************************/
        /* First look through all the resident fonts for a match.     */
        /**************************************************************/
        for ( i = 0;
              i < pDDT->DDTNoOfResidentFonts;
              i++ )
        {
            pFontList = PDBInstance->FontList[i];
            pNewMetrics = &pFontList->pFMFData->Metrics;

            if ( prda_CheckMetrics ( pNewMetrics,
                                     pOldMetrics,
                                     (PBYTE)pNewMetrics->szFacename,
                                     (PBYTE)OldFaceName,
                                     NewCodePage,
                                     PrinterData) )
            {
                /******************************************************/
                /* Found it .. store the details and return.          */
                /******************************************************/
                pFontInfo->Type  = FT_RESIDENT;
                pFontInfo->Index = i;
                pFontInfo->pFont = pFontList->pFMFData;

                RetVal = CODEPAGE_FOUND;
                goto EXIT_FUNCTION;
            }
        }
        /* .... for all resident fonts............................... */

    }
    /* ... if ( pDDT->DDTFontFlags & DDT_CARTRIDGE_OPTION ) ......... */


EXIT_FUNCTION:
    /******************************************************************/
    /* If we've got a new code page we need to reset the match        */
    /* number.                                                        */
    /******************************************************************/
    if ( RetVal == CODEPAGE_FOUND )
    {
        /**************************************************************/
        /* PS WORRY: is this even needed now?                         */
        /* Construct the new LCID for this font.                      */
        /**************************************************************/
        if ( pFontInfo->Type == FT_CODE_PAGE )
        {
            GCPIndex = (BYTE)pFontInfo->CodePageNo;
            prdm_PutLCIDGCPIndex(pFontInfo->LCID, GCPIndex);
            prdm_PutLCIDCPFontIndex(pFontInfo->LCID, pFontInfo->Index);
        }
        else
        {
            prdm_PutLCIDFontIndex(pFontInfo->LCID, pFontInfo->Index);
        }

        prdm_PutLCIDFontType(pFontInfo->LCID, pFontInfo->Type);
        prdm_PutLCIDEngineAttrs(pFontInfo->LCID, (BYTE)0 );
        prdm_PutLCIDFontDevAttrs(pFontInfo->LCID, (BYTE)0 );
        prdm_PutLCIDCPIndex(pFontInfo->LCID, (BYTE)0xFF );

    }
    return (RetVal);

} /* prda_MatchExactCodePage */
#undef TFUNC






/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prda_CheckMetrics                                      */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   PFOCAMETRICS    pNewMetrics                                      */
/*   PFOCAMETRICS    pOldMetrics                                      */
/*   PBYTE           NewFaceName                                      */
/*   PBYTE           OldFaceName                                      */
/*   USHORT          NewCodePage                                      */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   Looks for a default font with the new code page.                 */
/*                                                                    */
/**********************************************************************/
/*   CON3201  Convert to C/SET2                                       */
BOOL prda_CheckMetrics ( PFOCAMETRICS      pNewMetrics,
                         PFOCAMETRICS      pOldMetrics,
                         PBYTE             NewFaceName,
                         PBYTE             OldFaceName,
                         USHORT            NewCodePage,
                         lpPrtDataEntry    PrinterData )

{
#define TFUNC "prda_CheckMtrcs"

    /******************************************************************/
    /* Compare code page, facename, registry id and point size.       */
    /******************************************************************/
    if ( ( pNewMetrics->usCodePage == NewCodePage )         &&
         ( !prdu_strcmp( (PBYTE)NewFaceName,(PBYTE)OldFaceName) ) &&
         ( pNewMetrics->usRegistryId == pOldMetrics->usRegistryId ) &&
         ( pNewMetrics->usNominalPointSize ==
                                    pOldMetrics->usNominalPointSize ) )
    {
       return (TRUE);
    }
    else
    {
       return (FALSE);
    }
}
#undef TFUNC


/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prda_MultiCodePageSupported                            */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   USHORT          CodePage                                         */
/*   lpMultiCpType   pMultiCp                                         */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   Looks thru the global outline code page table for a match on     */
/*   CodePage and returns TRUE if found.  When it is not found in     */
/*   the table call GreQueryCodePageVector to see if OS/2 supports    */
/*   this code page.  If it is supported add it to the global table   */
/*   and increment OutlineCodepageEntries and return TRUE else        */
/*   return FALSE when not supported by OS/2.                         */
/*                                                                    */
/**********************************************************************/
/*   CON3201  Convert to C/SET2                                       */
BOOL prda_MultiCodePageSupported( USHORT            CodePage,
                                  lpMultiCpType     pMultiCp )

{
#define TFUNC "prda_MultiCpSupported"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    USHORT               i;
    USHORT               j;

    for ( i = 0 ; i < OutlineCodepageEntries ; i++ )
    {
        if ( CodePage == OutlineCodepages[i].cp )
            return( TRUE );
    }

    if (OutlineCodepageEntries > MAX_OUTLINE_CODEPAGE_ENTRIES )
    {
        /**************************************************************/
        /* The Global outline codepage table is Full!                 */
        /**************************************************************/
        return( FALSE );
    }

    if ( (PUSHORT)GreQueryCodePageVector( CodePage ) != GPI_ERROR )
    {
        /**********************************************************/
        /* This code page is supported by OS/2 so add it to the   */
        /* global outline code page table                         */
        /**********************************************************/
        OutlineCodepages[OutlineCodepageEntries].cp = CodePage;
        OutlineCodepages[OutlineCodepageEntries].CPVResId = OS2SUPPORTED;

        /**************************************************************/
        /* Check to see if this code page is resident in the Heritage */
        /* printer.  Set the CpType field to indicate code page is    */
        /* resident or non resident.  Non resident code pages are     */
        /* supported by downloading a BIN file to the printer.        */
        /**************************************************************/
        OutlineCodepages[OutlineCodepageEntries].CpType = NON_RESIDENT;

        for ( j = 0; j < HeritageResidentCodePageCount; j++)
        {
            if ( OutlineCodepages[OutlineCodepageEntries].cp ==
                                      HeritageResidentCodePages[j] )
            {
                /******************************************************/
                /* This codepage is printer resident, set a flag in   */
                /* global table and quit this loop.                   */
                /******************************************************/
                OutlineCodepages[OutlineCodepageEntries].CpType =
                                                               RESIDENT;
                break;
            }
        }
        /**************************************************************/
        /* Increment the count for the number of entries in the       */
        /* global outline table.                                      */
        /**************************************************************/
        OutlineCodepageEntries++;

        return( TRUE );
    }

    else
    {
        /**************************************************************/
        /* This code page is not in the global table and is not       */
        /* supported by OS/2 so return FALSE.                         */
        /**************************************************************/
        return( FALSE );
    }
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prda_AdjustFaceName2                                PD00465     */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  PBYTE         FaceName;     Facename buffer                               */
/*  FontInfoType  CardFontInfo;                                               */
/*  lpPDBI        PDBInstance;                                                */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function adds a description of the font quality and then the font    */
/*  attribute of the facename.                                                */
/*  This is needed because we may not have an LCID in all cases and we        */
/*  don't want to bother creating one.                                        */
/*  ASSUMPTIONS:                                                              */
/*  The total facename length will not exceed 32 characters (including the  */
/*  null terminator) after quality and attribute descriptions have been added.*/
/******************************************************************************/
/*   CON3201  Convert to C/SET2                                               */
VOID prda_AdjustFaceName2( PBYTE         FaceName,
                           FontInfoType  CardFontInfo,
                           lpPDBI        PDBInstance )

{
#define TFUNC "prda_AdjFaceNme2"

    /**************************************************************************/
    /*  Local variables                                                       */
    /**************************************************************************/
    PBYTE   pSource, pDest;            /* Working pointers                    */
    USHORT  fsAttrs;                   /* The font attribute in terms of bit  */
                                       /* flags                               */
    USHORT  FontIndex;

    /**************************************************************************/
    /*  Move our working pointer to the end of the facename.                  */
    /**************************************************************************/
    for (pDest = FaceName; *pDest != '\0'; pDest++);

    /**************************************************************************/
    /*  Finish off, not with a bang but with a whimper.                       */
    /**************************************************************************/
    *pDest = '\0';

    /**************************************************************************/
    /*  hmmm-mmm, all done.                                                   */
    /**************************************************************************/
    return;
}
#undef TFUNC
