/*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 = PRDTESUB
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prdt_LocateFont
 *             prdt_EstablishFont
 *             prdt_NextCodePoint
 *             prdt_OutlineFontSize
 *             prdt_SetUpFMF
 *             prdt_ExpandMultiCpFMF
 *             prdt_TranslateChar
 *             prdt_TranslateWidthTable
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define INCL_32                          /* CON3201 */
#define INCL_DOSPROCESS                  /* CON3201 */
#define INCL_DOSRESOURCES
#define INCL_DOSSEMAPHORES
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#define INCL_GPIERRORS
#define INCL_SHLERRORS
#include <os2.h>
#undef INCL_DOSPROCESS                 /* CON3201 */
#undef INCL_DOSRESOURCES
#undef INCL_DOSSEMAPHORES
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS
#undef INCL_GPIERRORS
#undef INCL_SHLERRORS

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

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

#include <prdconse.h>
#include <prddcone.h>
#include <prdecone.h>
#include <prdmcone.h>

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

#include <prdtextf.h>
#include <prdgextf.h>
#include <prdmtypt.h>
#include <prdeextf.h>
#include <prdaextf.h>
#include <prduextf.h>
#include <prdtcone.h>
#include <prdmacro.h>
#include <prdacone.h>

extern MarkerFontType       MarkerDefaultFont;
extern HMODULE              prdd_ModHandle;
extern USHORT               OutlineCodepageEntries;
extern lpOutlineCodepages   OutlineCodepages;
extern CPTMappingTableEntry CPTMapTable [];

/******************************************************************************/
/* Set up access to external function.                                        */
/******************************************************************************/
extern PFNL            da_ConvertWithMatrix;

/******************************************************************************/
/*                                                                            */
/*   FUNCTION: prdt_LocateFont                                                */
/*                                                                            */
/*   PARAMETERS:                                                              */
/*                                                                            */
/*   lpFontDataType  FontData; Pointer to font data structure                 */
/*   lpDCI           DCIData;  Pointer to DC Instance data                    */
/*                                                                            */
/*   DESCRIPTION:                                                             */
/*                                                                            */
/*   This function sets up the font data structure using the                  */
/*   CHARDEFS values in the text attribute bundle (and, sometimes,            */
/*   DCICodePage).                                                            */
/*                                                                            */
/*   The function uses standard OK / ERROR_ZERO return codes.                 */
/*                                                                            */
/*   The function is designed so that the given font data remains             */
/*   untouched should the function fail.                                      */
/*                                                                            */
/******************************************************************************/
/*
USHORT prdt_LocateFont ( pFontData,
                                DCIData )

lpFontDataType   pFontData;
lpDCI            DCIData;
                         */
USHORT prdt_LocateFont (lpFontDataType pFontData, lpDCI DCIData)
{
#define TFUNC "prdt_LocateFont"

    /**************************************************************************/
    /* Local Variables                                                        */
    /**************************************************************************/
    lpPDBI          PDBInstance;       /* Pointer to the PDB                  */
    lpPrtDataEntry  PrinterData;       /* Pointer to Printer Data             */
    lpFontInfoType  pFontInfo;
    lpFMFFileStruc  pMetrics;          /* Pointer to font metrics             */
    lpMultiCpType   pMultiCP;          /* Pointer to multi cp info            */
    BYTE            DeviceAttrs;       /* Device attributes                   */
    lpEngAttrsType  pEngineAttrs;      /* Pointer to eng attrs struct         */
    LCIDType        lcid;
    ULONG           Font;              /* From the text attr bundle           */
    USHORT          CodePage;          /* Currently selected codepage         */
    lpResAdjType    pResAdj;
    PUSHORT         CodeTable;
    USHORT          i;
    USHORT          Result;
    BOOL            DefaultFont;
    DfltFontInfoType   DfltFont;       /* Normal default font                 */

    /**************************************************************************/
    /* Set up pointers.                                                       */
    /**************************************************************************/
    PDBInstance = DCIData->DCIPdbInstance;
    DfltFont    = PDBInstance->DfltFont;
    PrinterData = PDBInstance->PrinterData;
    pFontInfo   = &pFontData->Info;

    /**************************************************************************/
    /* First, we need to see if the memory for the font is available.  If it  */
    /* isn't, then allocate some memory here before we continue.  This will   */
    /* hold expanded font metrics for the font requested.                     */
    /**************************************************************************/
    if (pFontInfo->pFont == FNULL)
    {
        /**********************************************************************/
        /* This is the first time into this routine, so allocate the font data*/
        /* memory.  Allocate enough memory for the largest font.              */
        /**********************************************************************/
/*      Result = SSALLOCSEG( FMF_SIZE_PROP_SPACED,                CON3201 */
/*                           &SELECTOROF(pFontInfo->pFont), 0);   CON3201 */
        Result = SafeSSALLOCMEM( &pFontInfo->pFont, FMF_SIZE_PROP_SPACED,
                              0);
        if (Result)
        {
            LOGDOSERR(TFUNC, "SSALLOCMEM Fail", &Result, 1, Result);
            return(ERROR_ZERO);
        }
/*     OFFSETOF(pFontInfo->pFont) = 0;                            CON3201*/
    }

    /**************************************************************************/
    /* Font is interpreted according to cdef.fFlags.  It could be:            */
    /* - the default font (device or engine)                                  */
    /* - a value indicating that we've got the default marker set             */
    /* - a (negative) match number indicating a device font                   */
    /* - a pointer to an engine font                                          */
    /**************************************************************************/
    Font = DCIData->DCICurTxtAts->cdef.defSet;

    if ( !(DCIData->DCICurTxtAts->cdef.fFlags & CDEF_GENERIC) )
    {
        /**********************************************************************/
        /* Font is a device font.  But if there are no device fonts then this */
        /* is the first call to LocateFont from Enable before the engine font */
        /* is set up, so just return here.                                    */
        /*                                                                    */
        /* PD00022 : Actually do not return.  let the font data be set up to  */
        /* match the text attributes.  If the default font ends as an engine  */
        /* font, then the engine will call DeviceSet- Attributes between      */
        /* EnableDC and CompleteOpen.                                         */
        /**********************************************************************/
//      if (PDBInstance->FontCount == 0)
//      {
//          return (OK);
//      }

        /**********************************************************************/
        /* The font is not an engine font.                                    */
        /**********************************************************************/
        if ( Font == DFLT_MARKER_FONT )
        {
            /******************************************************************/
            /* The font is the default marker font.                           */
            /******************************************************************/
            pFontData->Genre     = NON_DEVICE_FONT;
            pFontInfo->Type      = FT_MARKER;
            pFontData->CodeTable = FNULL;

            /******************************************************************/
            /* The pFont field is lpFMFFileStruc.  For marker fonts (and      */
            /* engine fonts, see below), store a pointer to the               */
            /* MarkerDefaultFont info - i.e.  double de-reference.            */
            /******************************************************************/
            *((PULONG)pFontInfo->pFont) =
                                     (ULONG)((PVOID)&MarkerDefaultFont);
        }
        else
        {
            /******************************************************************/
            /* PD00022 : The font is a device font.  This may fail, so only   */
            /* update the pFontData structure when we know that it will       */
            /* succeed.  This is after the GetInfoFromMatch- Number call.     */
            /******************************************************************/
            DefaultFont      = FALSE;

            /******************************************************************/
            /* Construct the LCID.  For the default font use the LCID from the*/
            /* default font structure otherwise it is already set up.         */
            /******************************************************************/
            if (Font == 0L)
            {
                /**************************************************************/
                /* Remember that we are dealing with the default font.        */
                /**************************************************************/
                DefaultFont = TRUE;

                /**************************************************************/
                /* When the User has selected a system font or no device fonts*/
                /* are available then when enable DC calls SetTxtAttribute we */
                /* will have no valid LCID.  So...                            */
                /**************************************************************/
                if ( (DfltFont.Info.Type & 0x7F) == FT_ENGINE )
                {
                    /**********************************************************/
                    /* ...  if this is the case then use the default device   */
                    /* font LCID.                                             */
                    /**********************************************************/
                    Font = LCIDTOUL(PDBInstance->DfltDeviceFont.Info.LCID);
                }
                else
                {
                    /**********************************************************/
                    /* ...  otherwise just use the default font LCID.         */
                    /**********************************************************/
                    Font = LCIDTOUL(DfltFont.Info.LCID);
                }
            }

            /******************************************************************/
            /* Combine the fsSelection flags stored in the LCID and the cDef  */
            /* flags supplied to give a final target font.  Note - convert the*/
            /* CDEF_ flags passed in by the engine into the FATTR_SEL_ flags  */
            /* stored in the LCID.                                            */
            /******************************************************************/
            ULTOLCID(Font).EngineAttrs |=
                   prdm_CdefToFattr(DCIData->DCICurTxtAts->cdef.fFlags);

            /******************************************************************/
            /* Now switch the LCID if necessary based on the engine           */
            /* attributes.                                                    */
            /******************************************************************/
            Font = prda_MatchEngineAttributes( DCIData,
                                               ULTOLCID(Font) );

            /******************************************************************/
            /* Now convert the LCID to all the information that is required to*/
            /* create the full FontData.                                      */
            /******************************************************************/
            if (prda_InfoFromMatchNumber(ULTOLCID(Font),
                                         DCIData,
                  (lpFMFFileStruc  *) &pMetrics,
                  (lpMultiCpType   *) &pMultiCP,
                  (PBYTE)                &DeviceAttrs,
                  (lpEngAttrsType  *) &pEngineAttrs) != OK)
            {
                /**************************************************************/
                /* PD00022 : PS used to worry that the FontData would have    */
                /* been half set up at this point.  Now PS has suffled the    */
                /* code around so that up to this point the FontData has not  */
                /* been touched.  The LCID was invalid, so return error.      */
                /**************************************************************/
                return( ERROR_ZERO);
            }

            /******************************************************************/
            /* Now set up the font information from the LCID.                 */
            /******************************************************************/
            pFontData->Genre = DEVICE_FONT;
            pFontInfo->Attr  = prdm_GetLCIDFontDevAttrs(Font);
            pFontInfo->Type  = prdm_GetLCIDFontType(Font);
            pFontInfo->LCID  = ULTOLCID(Font);

            /******************************************************************/
            /* This following code assumes that a download codepage font is   */
            /* never an outline font.  As of version 200 this is true.  Note  */
            /* the dual use of the FontInfo code page field.                  */
            /******************************************************************/
            if ( pFontInfo->Type == FT_CODE_PAGE )
            {
                /**************************************************************/
                /* Get Index from lower 8 bits of FontIndex field and get     */
                /* CodePageNo from upper 4 bits of FontIndex field.           */
                /**************************************************************/
                pFontInfo->Index      = prdm_GetLCIDCPFontIndex( Font );
                pFontInfo->CodePageNo = prdm_GetLCIDGCPIndex( Font );
            }
            else
            {
                /**************************************************************/
                /* Get Index from all 12 bits, and CodePageNo from the CPIndex*/
                /* part (top byte).                                           */
                /**************************************************************/
                pFontInfo->Index      = prdm_GetLCIDFontIndex( Font );
                pFontInfo->CodePageNo = prdm_GetLCIDCPIndex( Font );
            }

            /******************************************************************/
            /* Now using the FMF and MultiCP information create a real font   */
            /* metric structure targetted at the requested code page.         */
            /******************************************************************/
            if (  prdt_SetUpFMF(pFontInfo->LCID.CPIndex & 0x7F,
                                pMetrics,
                                pMultiCP,
                                pFontInfo->pFont ) != OK )
            {
                /**************************************************************/
                /* This can only fail if the global font list structures are  */
                /* set up incorrectly such that they reference am invalid     */
                /* resource ID.  This could only happen in the development    */
                /* environment, but be aware that the Fontdata is now very    */
                /* confused.                                                  */
                /**************************************************************/
                return( ERROR_ZERO);
            }

            /******************************************************************/
            /* May or may not be using these fields, so start of at zero.     */
            /* There are set up in the following block.                       */
            /******************************************************************/
            pFontData->CodeTable = FNULL;
            pFontData->Simulated = FALSE;

            /******************************************************************/
            /* Currently only the default font can be simulated.              */
            /******************************************************************/
            if (DefaultFont)
            {
                if (SIMULATED(DfltFont.Info.Type))
                {
                    /**********************************************************/
                    /* It is simulated so tinker with the metrics.  All that  */
                    /* is necessary is that the width table is shuffled.      */
                    /**********************************************************/
                    (VOID) prdt_SimulateFont (pFontData,
                                              DCIData->DCICodePage);
                }
            }
        } /* .... device font ....................................... */
    } /*..if ( !(DCIData->DCICurTxtAts->cdef.fFlags & CDEF_GENERIC) ).*/

    else    /* engine font */
    {
        /**********************************************************************/
        /* Pick up the code page from the attribute bundle.  If this is zero  */
        /* and we have the default (engine) font then use the code page in the*/
        /* DCIData (as set up by GpiSetCodePage).                             */
        /*                                                                    */
        /* PD00152 : The Q-RAW jobs the engine does not update the codepage   */
        /* field, it always appears as 850.  So if the code- page in the      */
        /* attribute bundle is zero OR 850 then use the DCIData codepage.     */
        /**********************************************************************/
        CodePage = (USHORT)DCIData->DCICurTxtAts->cdef.CodePage;

        /**********************************************************************/
        /* Note: DCIDefTxtAts may be NULL for Memory DC, so check it.         */
        /*                                                                    */
        /* PD00152 : The Q-RAW jobs the engine does not update the codepage   */
        /* field, it always appears as 850.  So if the code- page in the      */
        /* attribute bundle is zero OR 850 then use the DCIData codepage.     */
        /**********************************************************************/
        if ( (DCIData->DCIDefTxtAts) &&
             (Font == DCIData->DCIDefTxtAts->cdef.defSet) &&
             ((CodePage == 850) || (CodePage == 0)) )
        {
            CodePage = DCIData->DCICodePage;
        }

        /**********************************************************************/
        /* If the code page from the attribute bundle (or DCIData ) is        */
        /* non-zero and the metrics code page is 850 (i.e.  this is a         */
        /* multi-codepage font) then we need a code table to use for code page*/
        /* translation.  Otherwise set the code table to FNULL to indicate    */
        /* that the codepoints should be used as direct indices.              */
        /**********************************************************************/
        if ( (CodePage) &&
             (((PFOCAFONT)Font)->fmMetrics.usCodePage == 850) )
        {
            CodeTable= (PUSHORT)GreQueryCodePageVector((ULONG)CodePage);

            if ( !CodeTable )
                return (ERROR_ZERO);

            pFontData->CodeTable = CodeTable;
        }
        else
        {
            pFontData->CodeTable = FNULL;
        }

        /**********************************************************************/
        /* These are set up here to avoid problems with invlaid font data     */
        /* should the QueryCPVector call fail.                                */
        /**********************************************************************/
        pFontData->Genre = NON_DEVICE_FONT;
        pFontInfo->Type  = FT_ENGINE;

        /**********************************************************************/
        /* The pFont field is lpFMFFileStruc.  For engine fonts store a       */
        /* pointer to the font - ie double de-reference.                      */
        /**********************************************************************/
        *((PULONG)pFontInfo->pFont) = (ULONG)Font;

    }
    /*.. else engine font............................................ */


    /**************************************************************************/
    /* Set up the font metrics pointer and (for an engine font) the font      */
    /* header pointer.                                                        */
    /**************************************************************************/
    if ( pFontData->Genre == DEVICE_FONT )
    {
        pFontData->pMetrics = &pFontInfo->pFont->Metrics;
    }
    else
    {
         /*********************************************************************/
         /* Use *(*(pFontInfo->pFont)).                                       */
         /*********************************************************************/
        pFontData->pMetrics = (PFOCAMETRICS)(
          ((PBYTE)*((PULONG)pFontInfo->pFont) + sizeof(FONTSIGNATURE)));

        pFontData->pHeader = (PFONTDEFINITIONHEADER)
                      (((PBYTE)pFontData->pMetrics)
                                        + pFontData->pMetrics->ulSize);
    }

    /**************************************************************************/
    /* Set up the ResAdj structure for use by conversion functions to move    */
    /* between font coords and device coords.  These are used for device fonts*/
    /* only and would normally be used in portrait mode.  For printers which  */
    /* have device fonts in landscape mode the design assumes that both the   */
    /* device and font resolutions are square.                                */
    /*                                                                        */
    /* Once these values have been set up (for the first device font through  */
    /* here) they should remain unchanged till the end of job.                */
    /**************************************************************************/
    if ( pFontData->Genre == DEVICE_FONT )
    {
        pResAdj = &pFontData->ResAdj;

        pResAdj->DeviceResX = PDBInstance->DDT.DDTRasterMode->ResWidth;
        pResAdj->DeviceResY = PDBInstance->DDT.DDTRasterMode->ResDepth;
        /**********************************************************************/
        /* For image fonts, FontRes is stored in the metrics.  For outline    */
        /* fonts it isn't - the fields xDeviceRes and yDeviceRes give info    */
        /* about the precision to which the characters are drawn.             */
        /**********************************************************************/
        pResAdj->FontResX = pFontData->pMetrics->xDeviceRes;
        pResAdj->FontResY = pFontData->pMetrics->yDeviceRes;
    }

    /**************************************************************************/
    /* Set the initial values in the CodePoint structure held in the font     */
    /* data.                                                                  */
    /**************************************************************************/
    if (prdt_EstablishFont(pFontData, DCIData) != OK)
        return (ERROR_ZERO);

    return (OK);
}
#undef TFUNC






/******************************************************************************/
/*                                                                            */
/*   FUNCTION: prdt_EstablishFont                                             */
/*                                                                            */
/*   PARAMETERS:                                                              */
/*                                                                            */
/*   lpFontDataType  FontData; Pointer to font data structure                 */
/*   lpDCI           DCIData;  Pointer to DC Instance data                    */
/*                                                                            */
/*   DESCRIPTION:                                                             */
/*                                                                            */
/*   This function sets up initial values for the fields in the               */
/*   CodePoint structure.                                                     */
/*                                                                            */
/*   It also sets up NVFS and NHFS in FontData for an outline font.           */
/******************************************************************************/
/*CON3201
USHORT prdt_EstablishFont ( pFontData,
                                   DCIData )

lpFontDataType  pFontData;
lpDCI           DCIData;
                         */

USHORT prdt_EstablishFont (lpFontDataType  pFontData,
                           lpDCI           DCIData)

{
#define TFUNC "prdt_EstFont"

    /**************************************************************************/
    /* Local Variables                                                        */
    /**************************************************************************/
    lpCodePointType        pCPtInfo;
    SHORT                  fsAttrs;
    SHORT                  fsFontdef;
    PFONTDEFINITIONHEADER  pHeader;
    lpFontInfoType         pFontInfo;
    XFORM                  xfm;
    POINTL                 Coords;
    LONG                   CharBoxWidth;
    LONG                   CharBoxHeight;
    BYTE                   DfltFontRealized;   /* PD00681             */


    /**************************************************************************/
    /* Set up pointers.                                                       */
    /**************************************************************************/
    pFontInfo = &pFontData->Info;
    pCPtInfo  = &pFontData->CPtInfo;

    /**************************************************************************/
    /* Initiate the CodePoint structure to 0.                                 */
    /**************************************************************************/
    (VOID) prdu_memset( (PBYTE)pCPtInfo,
                        0,
                        (sizeof(CodePointType)) );

    /**************************************************************************/
    /* Set the fields according to the genre (device font or not).            */
    /**************************************************************************/
    if ( pFontData->Genre == DEVICE_FONT )
    {
        /**********************************************************************/
        /* The high bit of the width flags should be set for all Pro and Q    */
        /* fonts.  We don't want it set when the field is used as the width of*/
        /* characters.  If the width is zero the font is proportional, not    */
        /* fixed pitch.                                                       */
        /**********************************************************************/
        pCPtInfo->Width =(pFontInfo->pFont->WidthFlag & FMF_WIDTH_MASK);

        /**********************************************************************/
        /* Get the height and baseline offset from the font metrics.          */
        /**********************************************************************/
        pCPtInfo->Height     = pFontData->pMetrics->yMaxBaselineExt;
        pCPtInfo->BaseOffset = pFontData->pMetrics->yMaxAscender;

        /**********************************************************************/
        /* Double the dimensions if required by the font attribute.           */
        /**********************************************************************/
        if ( pFontInfo->Attr & FATT_DOUBLE_HIGH )
        {
            pCPtInfo->Height     *= 2;
            pCPtInfo->BaseOffset *= 2;
        }

        if ( pFontInfo->Attr & FATT_DOUBLE_WIDE )
        {
            pCPtInfo->Width *= 2;
        }

        /**********************************************************************/
        /* Now set up the WorkCoords fields.  For a raster font at mode 1,    */
        /* WorkCoords are FontCoords, and the WorkCoords fields are the same  */
        /* as the other Width and Height fields.                              */
        /*                                                                    */
        /* For a raster font at mode 2, WorkCoords are WorldCoords and the    */
        /* WorkCoords fields reflect the size of the character box being used */
        /* for positioning, whereas the other Width and Height fields reflect */
        /* the normal size of the character for clipping.                     */
        /*                                                                    */
        /* For an outline font, WorkCoords are WorldCoords, but all the units */
        /* reflect the size of the character box.                             */
        /*                                                                    */
        /* The idea of the WorkCoords fields is that positioning is done in   */
        /* WorkCoords but clipping is always done in FontCoords.  The Width,  */
        /* Height and BaseOffset fields in CPtInfo are held in font coords and*/
        /* are used for clipping; the WorkCoords fields are used for          */
        /* positioning.                                                       */
        /*                                                                    */
        /* Got that ?                                                         */
        /*                                                                    */
        /* Recall the character box fields are in WorldCoords and are of FIXED*/
        /* type.                                                              */
        /**********************************************************************/
        if (DCIData->DCICurTxtAts->cbnd.usPrecision == CM_MODE1)
        {
            /******************************************************************/
            /* When using a raster font at mode 1, positioning is worked out  */
            /* in FontCoords, so the values used for clipping can also be used*/
            /* for positioning.                                               */
            /******************************************************************/
            pCPtInfo->WorkCoords = COORD_FONT;
            pCPtInfo->WidthInWorkCoords = pCPtInfo->Width;
            pCPtInfo->HeightInWorkCoords = pCPtInfo->Height;
            pCPtInfo->BaseOffsetInWorkCoords = pCPtInfo->BaseOffset;
        }
        else
        {
            /******************************************************************/
            /* Our font is either outline or is at mode 2.                    */
            /*                                                                */
            /* Scale the width and height by the CharBox.                     */
            /*                                                                */
            /* The << 16 is to compensate for the CharBox units being of FIXED*/
            /* type.                                                          */
            /******************************************************************/

            pCPtInfo->WorkCoords = COORD_WORLD;

            /******************************************************************/
            /* PD00137 Def outline font pointsize selection                   */
            /******************************************************************/
            /******************************************************************/
            /* IF a font has not been realized and the default font is an     */
            /* outline font and user has selected a pointsize                 */
            /* (PDBInstance->DfltFontPointSz != 0), then set the char box to  */
            /* the pointsize.                                                 */
            /******************************************************************/
            /******************************************************************/
            /* PD00681 : Get the lcid attribute to see if default font was    */
            /* realized.                                                      */
            /******************************************************************/
            DfltFontRealized = prdm_GetLCIDEngineAttrs(pFontInfo->LCID) &
                                                         FATTR_SEL_DEFAULT ;
            if ( (DCIData->DCIPdbInstance->DDT.DDTDialogFlags &
                                             DDT_DEF_OUTLN_FNT_PSZ) &&
                (pFontData->pMetrics->fsDefn & FM_DEFN_OUTLINE) &&
                (DCIData->DCICurTxtAts->cdef.defSet == 0 || DfltFontRealized) &&
                (DCIData->DCIPdbInstance->DfltFontPointSz) )
            {
               CharBoxWidth  = prdg_ScaleValue(
                   (LONG)DCIData->DCIPdbInstance->DfltFontPointSz,
                   (LONG)(DCIData->DCIPdbInstance->DDT.DDTRasterMode->ResWidth),
                    72L);
               CharBoxHeight = CharBoxWidth;

               pCPtInfo->WidthInWorkCoords =
                              prdg_ScaleValue (
                                (LONG)pCPtInfo->Width,
                                (LONG)CharBoxWidth,
                                (LONG)pFontData->pMetrics->xEmInc);

               pCPtInfo->HeightInWorkCoords =
                             prdg_ScaleValue (
                               (LONG)pCPtInfo->Height,
                               (LONG)CharBoxHeight,
                               (LONG)pFontData->pMetrics->yEmHeight);

               pCPtInfo->BaseOffsetInWorkCoords =
                             prdg_ScaleValue (
                               (LONG)pCPtInfo->BaseOffset,
                               (LONG)CharBoxHeight,
                               (LONG)pFontData->pMetrics->yEmHeight);

            }
            else
            {
               CharBoxWidth  = (LONG)DCIData->DCICurTxtAts->cbnd.sizfxCell.cx;
               CharBoxHeight = (LONG)DCIData->DCICurTxtAts->cbnd.sizfxCell.cy;

               pCPtInfo->WidthInWorkCoords =
                              prdg_ScaleValue (
                                (LONG)pCPtInfo->Width,
                                (LONG)CharBoxWidth,
                                (LONG)pFontData->pMetrics->xEmInc << 16);

               pCPtInfo->HeightInWorkCoords =
                             prdg_ScaleValue (
                               (LONG)pCPtInfo->Height,
                               (LONG)CharBoxHeight,
                               (LONG)pFontData->pMetrics->yEmHeight << 16);

               pCPtInfo->BaseOffsetInWorkCoords =
                             prdg_ScaleValue (
                               (LONG)pCPtInfo->BaseOffset,
                               (LONG)CharBoxHeight,
                               (LONG)pFontData->pMetrics->yEmHeight << 16);

            }
            /******************************************************************/
            /* If DW or DH, the Cpt fields were scaled above, but these metric*/
            /* fields are not doubled - so divide by two here.                */
            /******************************************************************/
            if ( pFontInfo->Attr & FATT_DOUBLE_HIGH )
            {
                pCPtInfo->HeightInWorkCoords /= 2;
                pCPtInfo->BaseOffsetInWorkCoords /= 2;
            }
            if ( pFontInfo->Attr & FATT_DOUBLE_WIDE )
            {
                pCPtInfo->WidthInWorkCoords /= 2;
            }

            /******************************************************************/
            /* For an outline font, these scaled widths and heights are the   */
            /* ones we want to use for clipping - so convert them to font     */
            /* coords and store in CPtInfo.                                   */
            /******************************************************************/
            if ( pFontData->pMetrics->fsDefn & FM_DEFN_OUTLINE )
            {
                /**************************************************************/
                /* PD00073 : Use the transform stored in DCIData.             */
                /**************************************************************/
                xfm = DCIData->DCITransform;
                xfm.lM41 = 0;        /* Ignore Origin Shift */
                xfm.lM42 = 0;

                /**************************************************************/
                /* Use prdg_XformPoint to scale the widths and heights - this */
                /* takes a point as input and returns the vector length of the*/
                /* scaled point.                                              */
                /*                                                            */
                /* First width.                                               */
                /**************************************************************/
                Coords.x = pCPtInfo->WidthInWorkCoords;
                Coords.y = 0;

                pCPtInfo->Width = (USHORT) prdg_XformPoint(
                                               (HDC) DCIData->DcH,
                                               (PPOINTL)& Coords,
                                               (PXFORM) &xfm );
                pCPtInfo->Width = prdt_XformFontValue(
                                            pCPtInfo->Width,
                                            DEVICE_TO_FONT | CONV_X_VALUE,
                                            pFontData);

                /**************************************************************/
                /* BaseOffset.                                                */
                /**************************************************************/
                Coords.x = 0;
                Coords.y = pCPtInfo->BaseOffsetInWorkCoords;

                pCPtInfo->BaseOffset = (USHORT) prdg_XformPoint(
                                                    (HDC) DCIData->DcH,
                                                    (PPOINTL) &Coords,
                                                    (PXFORM) &xfm );
                pCPtInfo->BaseOffset = prdt_XformFontValue(
                                            pCPtInfo->BaseOffset,
                                            DEVICE_TO_FONT | CONV_Y_VALUE,
                                            pFontData);

                /**************************************************************/
                /* Height.                                                    */
                /**************************************************************/
                Coords.x = 0;
                Coords.y = pCPtInfo->HeightInWorkCoords;

                pCPtInfo->Height = (USHORT) prdg_XformPoint(
                                                (HDC) DCIData->DcH,
                                                (PPOINTL) &Coords,
                                                (PXFORM) &xfm );
                pCPtInfo->Height = prdt_XformFontValue(
                                            pCPtInfo->Height,
                                            DEVICE_TO_FONT | CONV_Y_VALUE,
                                            pFontData);

                /**************************************************************/
                /* For an outline font, set up the fields NHFS and NVFS in    */
                /* FontData.                                                  */
                /**************************************************************/
                if (prdt_OutlineFontSize( pFontData, DCIData ) != OK)
                    return (ERROR_ZERO);
                /**************************************************************/
                /* PD00073 : Removed call to prdt_OutlineFontShear.  The shear*/
                /* in pfontdata will not be used when building the textchain. */
                /* The shear will be calculated in prdt_TextOutDevOutlineFont */
                /* by calling prdt_GetPrinterParameters.                      */
                /**************************************************************/
                pFontData->Shear = 0;

            }
        }
    }
    else
    {
        /**********************************************************************/
        /* Non-device font.                                                   */
        /**********************************************************************/
        pHeader   = pFontData->pHeader;
        fsFontdef = pHeader->fsFontdef;

        /**********************************************************************/
        /* The hex values below (used to check against fsFontdef) are         */
        /* taken from PMFONT.H                                                */
        /*                                                                    */
        /* FONTDEFFONT1   0x47  set width, height, inc. & base offset         */
        /* FONTDEFFONT2   0x42  set height & base offset                      */
        /* FONTDEFFONT3   0x42  set height & base offset                      */
        /*                                                                    */
        /* FONTDEFCHAR1   0x81  set char offset and width                     */
        /* FONTDEFCHAR2   0x81  set char offset and width                     */
        /* FONTDEFCHAR3   0xB8  set char offset, A, B, and C space            */
        /*                                                                    */
        /* We pick up two very reasonable assumptions from these              */
        /* values:                                                            */
        /* - the height and base offset do not vary from character to         */
        /*   character                                                        */
        /* - A/B/CSpace values are always defined together in a group         */
        /*                                                                    */
        /* We also assume that the character width will be                    */
        /* defined either here in the header data or in the per               */
        /* character definitions.                                             */
        /*                                                                    */
        /* For an ABC-spaced font the width held is set to A+B+C.             */
        /**********************************************************************/
        if ( fsFontdef & 0x01 )
            pCPtInfo->Width = pHeader->xCellWidth;

        if ( fsFontdef & 0x02 )
            pCPtInfo->Height = pHeader->yCellHeight;

        if ( fsFontdef & 0x04 )
            pCPtInfo->Increment = pHeader->xCellIncrement;

        if ( (fsFontdef & 0x38) == 0x38 )
        {
            pCPtInfo->ASpace = pHeader->xCellA;
            pCPtInfo->BSpace = pHeader->xCellB;
            pCPtInfo->CSpace = pHeader->xCellC;

            pCPtInfo->Width = pCPtInfo->ASpace +
                              pCPtInfo->BSpace +
                              pCPtInfo->CSpace;
        }

        if ( fsFontdef & 0x40 )
            pCPtInfo->BaseOffset = pHeader->pCellBaseOffset;

    }
    /* .... non device font ................................................. */

    return (OK);
}
#undef TFUNC





/******************************************************************************/
/*                                                                            */
/*   FUNCTION: prdt_NextCodePoint                                             */
/*                                                                            */
/*   PARAMETERS:                                                              */
/*                                                                            */
/*   USHORT          CodePt;    Code point of character required              */
/*   lpFontDataType  FontData;  Pointer to font data structure                */
/*                                                                            */
/*   DESCRIPTION:                                                             */
/*                                                                            */
/*   This function sets up fields in the code point structure held            */
/*   in font data describing the character specified by CodePt.               */
/*                                                                            */
/******************************************************************************/
/*CON3201
VOID prdt_NextCodePoint ( CodePt,
                                 pFontData,
                                 DCIData )

USHORT           CodePt;
lpFontDataType   pFontData;
lpDCI            DCIData;
                           */

VOID prdt_NextCodePoint (USHORT           CodePt,
                         lpFontDataType   pFontData,
                         lpDCI            DCIData)

{
#define TFUNC "prdt_NextCodePt"

    /**************************************************************************/
    /* Local variables                                                        */
    /**************************************************************************/
    lpFontInfoType    pFontInfo;
    lpCodePointType   pCPtInfo;
    PFOCAMETRICS      pMetrics;
    USHORT            usCharWidth;
    PUSHORT           pusCPtData;   /* Pointer to per character defns */
    USHORT            usPosition;   /* The position of the per char   */
                                    /* definitions for the codepoint  */
                                    /* we want                        */
    SHORT             fsChardef;
    USHORT            fsAttrs;      /* The font attribute in terms    */
                                    /* of bit flags                   */
    XFORM             xfm;
    POINTL            Coords;
    lpFMFFileStruc    pFont;
    lpDfltFontInfoType pDfltFontInfo;
    USHORT            DefaultChar;
    USHORT            RootCodePage;
    USHORT            i;
    LONG              CharBoxWidth;
    BYTE              DfltFontRealized; /* PD00681                    */


    /**************************************************************************/
    /* Set up pointers.                                                       */
    /**************************************************************************/
    pFontInfo = &pFontData->Info;
    pCPtInfo  = &pFontData->CPtInfo;
    pMetrics  = pFontData->pMetrics;

    /**************************************************************************/
    /* If the current font is an engine font and a code table is defined for  */
    /* it, then use CodePt as an index into this to obtain the actual         */
    /* codepoint.                                                             */
    /**************************************************************************/
    if ( pFontData->CodeTable && pFontData->Info.Type == FT_ENGINE)
        CodePt = pFontData->CodeTable[CodePt];

//  if ( pFontData->CodeTable )
//      CodePt = pFontData->CodeTable[CodePt];

    /**************************************************************************/
    /* Check that the codepoint we want is defined for this font; note that   */
    /* the value of usLastChar is relative to usFirstChar.                    */
    /*                                                                        */
    /* The range checking for the default marker font is done when the marker */
    /* symbol attribute is set in prda_SetMarkAttrs.  This avoids any problems*/
    /* with having to set these range values in the marker font metrics and   */
    /* allowing for the special case of MARKSYM_BLANK.                        */
    /**************************************************************************/
    if ( pFontData->Info.Type != FT_MARKER )
    {
        if ( (CodePt > pMetrics->usLastChar + pMetrics->usFirstChar) ||
             (CodePt < pMetrics->usFirstChar) )
        {
            /******************************************************************/
            /* The codepoint we want is not valid for this font so set the    */
            /* codepoint to the default.  The usDefaultChar field is relative */
            /* to usFirstChar and so add this value for the default codepoint.*/
            /******************************************************************/
            CodePt = pMetrics->usDefaultChar + pMetrics->usFirstChar;
        }
    }

    /**************************************************************************/
    /* If the font is a device font then we must check to see if it is        */
    /* simulated.  If so, we must translate the code point.                   */
    /**************************************************************************/
    if ( pFontData->Genre == DEVICE_FONT )
    {
        if (pFontData->Simulated)
        {
            /******************************************************************/
            /* If it's a simulated font then we have to translate it          */
            /******************************************************************/
            /******************************************************************/
//          pDfltFontInfo = &(DCIData->DCIPdbInstance->DfltFont);
//          pFont         = pDfltFontInfo->Info.pFont;
//          RootCodePage  = pFont->Metrics.usCodePage;

            /******************************************************************/
            /* PD00083: Pickup RootCodePage from FontData metrics instead of  */
            /* the DfltFont metrics.  The codepage in the DfltFont metrics    */
            /* contains 0 for MultiCp outline fonts.                          */
            /******************************************************************/
            RootCodePage  = pMetrics->usCodePage;

            /******************************************************************/
            /* Find the code page requested in the map table.                 */
            /******************************************************************/
            for (i = 0; i < CPT_MAP_TABLE_SIZE ; i++)
            {
                if (CPTMapTable[i].usRootCP == RootCodePage)
                {
                    /**********************************************************/
                    /* Found the correct entry, so quit.                      */
                    /**********************************************************/
                    break;
                }
            }

            /******************************************************************/
            /* PD00083: Use FontData metrics.                                 */
            /******************************************************************/
            DefaultChar = pMetrics->usDefaultChar;

            CodePt = prdt_TranslateChar( (BYTE)CodePt,
                                         pFontData->CodeTable,
                                         i);

            /******************************************************************/
            /* If return code is an error, then there is no corresponding     */
            /* character in the root code page.  Therefore we must substitute */
            /* the default character.                                         */
            /******************************************************************/
            if (CodePt == (USHORT)ERROR_NEG) /* CON3203 */  /* PD00460 */
            {
                CodePt = DefaultChar;
            }

        } /* If simulated ... */

    } /* If Device font ... */

    pCPtInfo->CodePoint = CodePt;

    /**************************************************************************/
    /* Pick up the per-character definitions.                                 */
    /**************************************************************************/
    if ( pFontData->Genre == DEVICE_FONT )
    {
        /**********************************************************************/
        /* Set the width - if the font is fixed pitch this is constant and has*/
        /* already been set in prdt_EstablishFont.                            */
        /**********************************************************************/
        usCharWidth = (pFontInfo->pFont->WidthFlag & FMF_WIDTH_MASK);

        if ( usCharWidth != 0 )
        {
            /******************************************************************/
            /* For a fixed pitch font all setup will have been done in        */
            /* EstablishFont, so there is nothing to do.                      */
            /******************************************************************/
            return;
        }

        /**********************************************************************/
        /* If we got to here, we have a proportional font...                  */
        /**********************************************************************/
        pCPtInfo->Width = pFontInfo->pFont->CharWidth[CodePt];

        /**********************************************************************/
        /* If necessary double the width.                                     */
        /**********************************************************************/
        if ( pFontInfo->Attr & FATT_DOUBLE_WIDE )
            pCPtInfo->Width *= 2;

        /**********************************************************************/
        /* Set up WidthInWorkCoords.  See comment in EstablishFont for how    */
        /* this is done.                                                      */
        /**********************************************************************/
        if ( pCPtInfo->WorkCoords == COORD_FONT )
        {
            /******************************************************************/
            /* When using a raster font at mode 1, positioning is worked out  */
            /* in FontCoords, so the values used for clipping can also be used*/
            /* for positioning.                                               */
            /******************************************************************/
            pCPtInfo->WidthInWorkCoords = pCPtInfo->Width;
        }
        else
        {
            /******************************************************************/
            /* Our font is either outline or is at mode 2.  WorkCoords are    */
            /* COORD_WORLD.  Scale the width by the CharBox.  The << 16 is to */
            /* compensate for the CharBox units being of FIXED type.          */
            /******************************************************************/
            /******************************************************************/
            /* PD00137 Def outline font pointsize selection                   */
            /******************************************************************/
            /******************************************************************/
            /* IF a font has not been realized and the default font is an     */
            /* outline font and user has selected a pointsize                 */
            /* (PDBInstance->DfltFontPointSz != 0), then set the char box to  */
            /* the pointsize.                                                 */
            /******************************************************************/
            /******************************************************************/
            /* PD00681 : Get the lcid attribute to see if default font was    */
            /* realized.                                                      */
            /******************************************************************/
            DfltFontRealized = prdm_GetLCIDEngineAttrs(pFontInfo->LCID) &
                                                         FATTR_SEL_DEFAULT;
            if ( (DCIData->DCIPdbInstance->DDT.DDTDialogFlags &
                                          DDT_DEF_OUTLN_FNT_PSZ) &&
               (pFontData->pMetrics->fsDefn & FM_DEFN_OUTLINE) &&
               (DCIData->DCICurTxtAts->cdef.defSet == 0 || DfltFontRealized) &&
               (DCIData->DCIPdbInstance->DfltFontPointSz) )
            {
               CharBoxWidth  = prdg_ScaleValue(
                     (LONG)DCIData->DCIPdbInstance->DfltFontPointSz,
                     (LONG)DCIData->DCIPdbInstance->DDT.DDTRasterMode->ResWidth,
                      72L);
               pCPtInfo->WidthInWorkCoords =
                            prdg_ScaleValue (
                                (LONG)pCPtInfo->Width,
                                (LONG)CharBoxWidth,
                                (LONG)pFontData->pMetrics->xEmInc);
            }
            else
            {
               pCPtInfo->WidthInWorkCoords =
                            prdg_ScaleValue (
                                (LONG)pCPtInfo->Width,
                                (LONG)DCIData->DCICurTxtAts->cbnd.sizfxCell.cx,
                                (LONG)pFontData->pMetrics->xEmInc << 16);
            }

            /******************************************************************/
            /* If DW the Cpt Width field was scaled above, but this metric    */
            /* fields is not doubled - so divide by two here.                 */
            /******************************************************************/
            if ( pFontInfo->Attr & FATT_DOUBLE_WIDE )
            {
                pCPtInfo->WidthInWorkCoords /= 2;
            }

            /******************************************************************/
            /* For an outline font, these scaled widths and heights are the   */
            /* ones we want to use for clipping - so convert them to FONT     */
            /* coords and store in CPtInfo.                                   */
            /******************************************************************/
            if ( pFontData->pMetrics->fsDefn & FM_DEFN_OUTLINE )
            {
                /**************************************************************/
                /* Return a width of zero if the following function fails.    */
                /**************************************************************/
                pCPtInfo->Width = 0;

                /**************************************************************/
                /* PD00073 : Use the transform stored in DCIData.             */
                /**************************************************************/
                xfm = DCIData->DCITransform;
                xfm.lM41 = 0;        /* Ignore Origin Shift */
                xfm.lM42 = 0;
                /**************************************************************/
                /* Use prdg_XformPoint to scale the width - this takes a point*/
                /* as input and returns the vector length of the scaled point.*/
                /**************************************************************/
                Coords.x = pCPtInfo->WidthInWorkCoords;
                Coords.y = 0;

                pCPtInfo->Width = (USHORT) prdg_XformPoint(
                                               (HDC) DCIData->DcH,
                                               (PPOINTL) &Coords,
                                               (PXFORM) &xfm );
                pCPtInfo->Width = prdt_XformFontValue(
                                            pCPtInfo->Width,
                                            DEVICE_TO_FONT | CONV_X_VALUE,
                                            pFontData);

            }
        }
    }
    else
    {
        /**********************************************************************/
        /* If there are no per character definitions for this font then we can*/
        /* return now.  Note that this should only be true for device fonts,  */
        /* engine fonts should have some per character definitions.           */
        /**********************************************************************/
        if ( pFontData->pHeader->usCellSize == 0 )
            return;

        /**********************************************************************/
        /* The per character definitions come after the font metrics and the  */
        /* font definition header so set usPosition to access them.  Use this */
        /* as a first offset and then add a second offset made up of the size */
        /* of the per character definition * the position of this codepoint   */
        /* relative to the first codepoint.                                   */
        /**********************************************************************/
        usPosition  = (USHORT)pMetrics->ulSize +
                                         sizeof(FONTDEFINITIONHEADER);
        usPosition += (pFontData->pHeader->usCellSize) *
                             (CodePt - (USHORT)pMetrics->usFirstChar);

        pusCPtData = (PUSHORT)(((PBYTE)pMetrics) + usPosition);


        /**********************************************************************/
        /* If the offset to the character definition is given in the per      */
        /* character definitions then obtain it and set the Defn field of the */
        /* current code point structure to the absolute address of the        */
        /* character definition.  Note it is assumed that an engine font will */
        /* have this field in the per character definition as otherwise we    */
        /* have no mechanism to access the character definition.              */
        /**********************************************************************/
        fsChardef = pFontData->pHeader->fsChardef;

        if ( fsChardef & 0x80 )
        {
            /******************************************************************/
            /* Note double de-referencing in new code (5/4/91)                */
            /******************************************************************/
            pCPtInfo->Defn = ( (PBYTE)*((PULONG)pFontInfo->pFont) ) +
                              *pusCPtData;

            /******************************************************************/
            /* Update the pointer past this "defn offset" entry.              */
            /******************************************************************/
            pusCPtData += 2;
        }
        /*.. if ( fsChardef & 0x80 ) ................................ */

        /**********************************************************************/
        /* The other fields which may appear in the character definition are  */
        /* dealt with in the order they will appear in.  For each one the flag*/
        /* is checked and if required the data is copied across and the       */
        /* pointer advanced.                                                  */
        /*                                                                    */
        /* See comments in prdt_EstablishFont on the values used to check     */
        /* against fsChardef and also on the handling of ABC spaced fonts.    */
        /**********************************************************************/
        if ( fsChardef & 0x01 )
            pCPtInfo->Width = *pusCPtData++;

        if ( fsChardef & 0x02 )
            pCPtInfo->Height = *pusCPtData++;

        if ( fsChardef & 0x04 )
            pCPtInfo->Increment = *pusCPtData++;

        if ( (fsChardef & 0x38) == 0x38 )
        {
            pCPtInfo->ASpace = *pusCPtData++;
            pCPtInfo->BSpace = *pusCPtData++;
            pCPtInfo->CSpace = *pusCPtData++;

            pCPtInfo->Width = pCPtInfo->ASpace +
                              pCPtInfo->BSpace +
                              pCPtInfo->CSpace;
        }

        if ( fsChardef & 0x40 )
            pCPtInfo->BaseOffset = *pusCPtData++;

        pCPtInfo->WidthInWorkCoords = pCPtInfo->Width;
    }
    /*.... non device font ..........................................         */

    return;
}
#undef TFUNC


/******************************************************************************/
/*                                                                            */
/*   FUNCTION: prdt_OutlineFontSize                                           */
/*                                                                            */
/*   PARAMETERS:                                                              */
/*                                                                            */
/*   lpFontDataType  FontData;  Pointer to font data structure                */
/*   lpDCI           DCIData;                                                 */
/*                                                                            */
/*   DESCRIPTION:                                                             */
/*                                                                            */
/*   This function sets up the fields NHFS and NVFS in FontData.              */
/*   They give the size parameters (as FIXED values) passed                   */
/*   to the Font Selection Command which is used on Heritage to               */
/*   select outline fonts.                                                    */
/*                                                                            */
/* These values are translated to ascii decimal strings in PrintText.         */
/******************************************************************************/
/*CON3201
USHORT prdt_OutlineFontSize ( pFontData,
                                     DCIData )

lpFontDataType   pFontData;
lpDCI            DCIData;
                           */

USHORT prdt_OutlineFontSize (lpFontDataType   pFontData,
                             lpDCI            DCIData)

{
#define TFUNC "prdt_OutlineFontSize"

    /**************************************************************************/
    /* Local variables                                                        */
    /**************************************************************************/
    FIXED               NHFSFixed;
    FIXED               NVFSFixed;
    POINTL              Coords;
    SIZEF               CharBox;
    XFORM               xfm;
    BYTE                DfltFontRealized; /* PD00681                  */



    /**************************************************************************/
    /* PD00137 IF a font has not been realized and the default font is an     */
    /* outline font and user has selected a pointsize                         */
    /* (PDBInstance->DfltFontPointSz != 0), then set NVFSFixed to the selected*/
    /* pointsize                                                              */
    /**************************************************************************/
    /**************************************************************************/
    /* PD00681 : Get the lcid attrs to see if default font is realized.       */
    /**************************************************************************/
    DfltFontRealized =  prdm_GetLCIDEngineAttrs(pFontData->Info.LCID) &
                                                            FATTR_SEL_DEFAULT ;
    if ( (DCIData->DCIPdbInstance->DDT.DDTDialogFlags & DDT_DEF_OUTLN_FNT_PSZ)
         && (pFontData->pMetrics->fsDefn & FM_DEFN_OUTLINE) &&
         (DCIData->DCICurTxtAts->cdef.defSet == 0 || DfltFontRealized) &&
         (DCIData->DCIPdbInstance->DfltFontPointSz) )
    {
        /**********************************************************************/
        /* PD00137 : The user can select a pointsize for the default outline  */
        /* font.  This is stored in PDBInstance-> DfltfFontPointSz in points  */
        /* (note NOT decipoints).  If the user chooses to leave it to the     */
        /* application to choose a pointsize by selecting "Program", the      */
        /* PDBInstance-> DfltFontPointSz will have a zero stored in it.  IF   */
        /* not zero we use the user selected pointsize.                       */
        /**********************************************************************/
         NVFSFixed = prdg_ScaleValue(
                          (LONG)DCIData->DCIPdbInstance->DfltFontPointSz,
                          0x10000,
                          1L );
         NHFSFixed = NVFSFixed;
    }
    else
    {

      /************************************************************************/
      /* Get local copy of the CharBox.                                       */
      /************************************************************************/
      CharBox.cx = DCIData->DCICurTxtAts->cbnd.sizfxCell.cx;
      CharBox.cy = DCIData->DCICurTxtAts->cbnd.sizfxCell.cy;

      /************************************************************************/
      /* NVFSFixed is the char box height converted from world coords to      */
      /* points (1 point = 1/72 inch).  We transform to device coords first,  */
      /* and then to points.                                                  */
      /************************************************************************/
      /************************************************************************/
      /* PD00073 : Get current world to device transform matrix from DCI      */
      /************************************************************************/
      xfm = DCIData->DCITransform;
      xfm.lM41 = 0;
      xfm.lM42 = 0;

      /************************************************************************/
      /* To get NVFSFixed, first get the length of the CharBox height in      */
      /* device coords.  prdg_XformPoint returns the length of the transform  */
      /* of the vector passed in.                                             */
      /************************************************************************/
      Coords.x = 0;
      Coords.y = (LONG) CharBox.cy;

      NVFSFixed = prdg_XformPoint ( (HDC) DCIData->DcH,
                                    (PPOINTL) &Coords,
                                    (PXFORM) &xfm );

      /************************************************************************/
      /* Now NVFSFixed is in device coords.  Translate to points.             */
      /************************************************************************/
      NVFSFixed = prdg_ScaleValue( NVFSFixed,
                                   72L,
                                   (LONG) pFontData->ResAdj.DeviceResY );

      /************************************************************************/
      /* Make sure this is in range 0.01 - 1008 (decimal).                    */
      /************************************************************************/
      if (NVFSFixed < 0x00000290)
      {
          NVFSFixed = 0x00000290;
      }
      else if (NVFSFixed > 0x03f00000)
      {
          NVFSFixed = 0x03f00000;
      }

      /************************************************************************/
      /* Work out NHFSFixed in Relative Point Size - i.e.  for a font at its  */
      /* correct aspect ratio, NHFSFixed = NVFSFixed.  Scaling is done w.r.t  */
      /* the char box.  Note that a square char box gives the font at its     */
      /* correct aspect ratio - the characters are NOT square!                */
      /*                                                                      */
      /* We could work out NHFSFixed as NVFSFixed x CharBox.y / CharBox.x.    */
      /* This won't be accurate if one of the CharBox sides is very big and   */
      /* the other is very small.                                             */
      /*                                                                      */
      /* Instead work out NHFSFixed just the same way as we found NVFSFixed - */
      /* but start off with CharBox.x instead of CharBox.y.                   */
      /************************************************************************/
      /************************************************************************/
      /* PD00847 : Calculate length in X direction NOT Y.  The scaling        */
      /* factor can be different for X and Y.                                 */
      /************************************************************************/
      Coords.x = (LONG) CharBox.cx;                             /* PD00847    */
      Coords.y = 0;                                             /* PD00847    */

      NHFSFixed = prdg_XformPoint ( (HDC) DCIData->DcH,
                                    (PPOINTL) &Coords,
                                    (PXFORM) &xfm );

      /************************************************************************/
      /* Now NHFSFixed is in device coords.  Translate to points.             */
      /************************************************************************/
      NHFSFixed = prdg_ScaleValue( NHFSFixed,
                                   72L,
                                   (LONG)pFontData->ResAdj.DeviceResX );

      /************************************************************************/
      /* Make sure this is in range 0.01 - 1008 (decimal).                    */
      /************************************************************************/
      if (NHFSFixed < 0x00000290)
      {
          NHFSFixed = 0x00000290;
      }
      else if (NHFSFixed > 0x03f00000)
      {
          NHFSFixed = 0x03f00000;
      }
    }

    /**************************************************************************/
    /* Store in FontData.  Note that if these values are out of the range     */
    /* accepted by the printer, then the text will be clipped out.            */
    /**************************************************************************/
    pFontData->NHFSFixed = NHFSFixed;
    pFontData->NVFSFixed = NVFSFixed;

#ifdef DEBUG_CHAR_BOX

    OutputPair("NHFS int part ", (ULONG) HIUSHORT(NHFSFixed), DECIMAL);
    OutputPair("NHFS 65536ths ", (ULONG) LOUSHORT(NHFSFixed), DECIMAL);
    OutputPair("NVFS int part ", (ULONG) HIUSHORT(NVFSFixed), DECIMAL);
    OutputPair("NVFS 65536ths ", (ULONG) LOUSHORT(NVFSFixed), DECIMAL);

#endif

    return (OK);
}
#undef TFUNC


/******************************************************************************/
/*                                                                            */
/*   FUNCTION: prdt_SetUpFMF                                                  */
/*                                                                            */
/*   PARAMETERS:                                                              */
/*                                                                            */
/*   BYTE            cpIndex;   codepage index into global table              */
/*   lpFMFFileStruc  pFMF;      IN - Pointer to FMF data structure            */
/*   lpMultiCp       pMulticp;  IN - Pointer to Multicp structure             */
/*   lpFMFFileStruc  pFont;     OUT- Pointer to normal FMF buffer             */
/*                                                                            */
/*   DESCRIPTION:                                                             */
/*                                                                            */
/*   This function updates pFont to be a valid FMF from the input             */
/*   MultiCp FMF or pFMF.                                                     */
/*                                                                            */
/*   This function is called from prdt_LocateFont.                            */
/*                                                                            */
/******************************************************************************/


/*
USHORT prdt_SetUpFMF( cpIndex,
                             pFMF,
                             pMultiCp,
                             pFont)

BYTE                cpIndex;
lpFMFFileStruc      pFMF;
lpMultiCpType       pMultiCp;
lpFMFFileStruc      pFont;
*/

USHORT prdt_SetUpFMF(BYTE                cpIndex,
                     lpFMFFileStruc      pFMF,
                     lpMultiCpType       pMultiCp,
                     lpFMFFileStruc      pFont)

{
#define TFUNC "prdt_SetUpFMF"

    /**************************************************************************/
    /* Local variables                                                        */
    /**************************************************************************/
    USHORT              Result;
    USHORT              NumberOfBytes;

    if ( pMultiCp )
    {
        /**********************************************************************/
        /* This is a multi-codepage FMF so apply change bytes for codepage and*/
        /* add width table to get a valid FMF in pFont.                       */
        /**********************************************************************/
        if ( Result = prdt_ExpandMultiCpFMF( cpIndex,
                                             pFMF,
                                             pMultiCp,
                                             pFont ) != OK )
        return( Result );
    }
    else
    {
        /**********************************************************************/
        /* This is a normal FMF so just copy it from pFMF buffer to the pFont */
        /* buffer and return.                                                 */
        /**********************************************************************/

        TRACE6(TFUNC, "Copy pFMF to pFont FMF ", FNULL, 0);
        if ( (pFMF->WidthFlag & FMF_WIDTH_FLAG_MASK) == 0 )
        {
            NumberOfBytes = FMF_SIZE_PROP_SPACED;
        }
        else
        {
            NumberOfBytes = FMF_SIZE_FIXED_PITCH;
        }

        prdu_memcpy( (PBYTE)pFont, (PBYTE)pFMF, NumberOfBytes );
    }

    return( OK );
}
#undef TFUNC

/******************************************************************************/
/*                                                                            */
/*   FUNCTION: prdt_ExpandMultiCpFMF                                          */
/*                                                                            */
/*   PARAMETERS:                                                              */
/*                                                                            */
/*   BYTE            cpIndex;   codepage index in global outline tbl          */
/*   lpFMFFileStruc  pFMFData;  IN - Pointer to FMF data structure            */
/*   lpMultiCpType   pMulticp;  IN - Pointer to Multicp structure             */
/*   lpFMFFileStruc  pFont;     OUT- Pointer to normal FMF buffer             */
/*                                                                            */
/*                                                                            */
/*   DESCRIPTION:                                                             */
/*                                                                            */
/*   This function updates pFont to be a valid FMF from the input             */
/*   MultiCp FMF and applies any change bytes necessary for the               */
/*   input (cpIndex) codepage.  A width table is generated from               */
/*   a Universal Width List (UWL) and Codepage Vector table (CPV)             */
/*   whose addresses are obtained from the input MultiCp structure.           */
/*                                                                            */
/*   This function is called from prdt_SetUpFMF.                              */
/******************************************************************************/


/*CON3201
USHORT prdt_ExpandMultiCpFMF( cpIndex,
                                     pFMF,
                                     pMultiCp,
                                     pFont)

BYTE                cpIndex;
lpFMFFileStruc      pFMF;
lpMultiCpType       pMultiCp;
lpFMFFileStruc      pFont;
*/

USHORT prdt_ExpandMultiCpFMF(BYTE                cpIndex,
                             lpFMFFileStruc      pFMF,
                             lpMultiCpType       pMultiCp,
                             lpFMFFileStruc      pFont)

{
#define TFUNC "prdt_ExpandMultiCpFMF"

    /**************************************************************************/
    /* Local variables                                                        */
    /**************************************************************************/
    PBYTE               pChangeBytes;   /* Change Byte pointer        */
    PUSHORT             CPV;            /* Codepage Vector table      */
/*  SEL                 SelCPVRes; CON3201-Selector of CPV resource   */
    PBYTE               pbCPVRes;       /* Selector of CPV resource   */
    USHORT              i;              /* Loop counter variable      */
    SHORT               Index;          /* Index of CP in pMultiCp    */
    USHORT              Result;
    PBYTE               pMetricsChangeByte;

    /**************************************************************************/
    /* Copy first 184 bytes from pFMF to pFont buffer                         */
    /**************************************************************************/

    TRACE6(TFUNC, "Copy First 184 bytes of FMF to pFont ", FNULL, 0);

    prdu_memcpy( (PBYTE)pFont, (PBYTE)pFMF, FMF_SIZE_FIXED_PITCH );

    /**************************************************************************/
    /* Get the index for this codepage in the MultiCp list and pickup the     */
    /* address of the first change byte.  Apply all changes to the metrics for*/
    /* this codepage                                                          */
    /**************************************************************************/
    Index  = prdt_GetMultiCpFMFIndex(
                                OutlineCodepages[cpIndex].cp,
                                pMultiCp);
    if ( Index >= 0)
    {
        /**********************************************************************/
        /* Apply necessary change bytes to FMF for this code page when the    */
        /* Index returned is not negative.                                    */
        /**********************************************************************/

        pChangeBytes = pMultiCp->pCpEntry[Index]->ChangeString;

        for ( i = 0 ; i < pMultiCp->pCpEntry[Index]->NoChangeBytes ; i++ )
        {
            /******************************************************************/
            /* The change data consist of a index byte and data byte.  The    */
            /* index is the offset into the metrics that requires changing for*/
            /* this codepage.  Increment pChangeBytes by 2 to get to next     */
            /* change data.                                                   */
            /******************************************************************/
            pMetricsChangeByte = (PBYTE)&pFont->Metrics + *pChangeBytes++;
            *pMetricsChangeByte = *pChangeBytes++;
        }
    }

    /**************************************************************************/
    /* Update codepage number in returned metrics from global table           */
    /**************************************************************************/
    pFont->Metrics.usCodePage = OutlineCodepages[cpIndex].cp;

    /**************************************************************************/
    /* For proportinal spaced fonts build the width table from the UWL table  */
    /* and the CPV resource.                                                  */
    /**************************************************************************/
    if ( pMultiCp->UWLLength)
    {
        if ( OutlineCodepages[cpIndex].CPVResId == OS2SUPPORTED)
        {
            /******************************************************************/
            /* This Code page is supported by OS/2 so get the CPV address from*/
            /* the system.                                                    */
            /******************************************************************/
            CPV = (PUSHORT)GreQueryCodePageVector(
                                        OutlineCodepages[cpIndex].cp);
        }
        else
        {
            /******************************************************************/
            /* This is a non OS/2 supported code page so get the CPV file from*/
            /* the resource to support this code page.                        */
            /******************************************************************/
         /* CON3201 ***********************************************************/
         /* Result = DosGetResource( (HMODULE)prdd_ModHandle,                 */
         /*                      (USHORT)1000,                                */
         /*                      (USHORT)OutlineCodepages[cpIndex].CPVResId,  */
         /*                      (PSEL)&SelCPVRes );                          */
         /*********************************************************************/
            Result = DosGetResource((HMODULE)prdd_ModHandle,
                                   (ULONG)1000,
                                   (ULONG)OutlineCodepages[cpIndex].CPVResId,
                                   (PPVOID)&pbCPVRes );

            TRACE4(TFUNC, "Selector", pbCPVRes, 1);

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

/*           SELECTOROF(CPV) = SelCPVRes;                          CON3201 */
/*          OFFSETOF(CPV)   = 3;          Ignore the first 3 bytes CON3201 */
            CPV = (PUSHORT)(pbCPVRes + 3);

        }
        /**********************************************************************/
        /* Translate UWL into a width table using CPV and update pFont FMF    */
        /* width fields.                                                      */
        /**********************************************************************/
        for ( i = 0; i < 256 ; i++ )
        {
            if ( CPV[i] >= pMultiCp->UWLLength )
            {
                pFont->CharWidth[i] = pFont->Metrics.usDefaultChar +
                                      pFont->Metrics.usFirstChar;
            }
            else
            {
                /**************************************************************/
                /* Note: UWLPtr is a PBYTE!                                   */
                /**************************************************************/
                pFont->CharWidth[i] =
                          *( (PUSHORT)(pMultiCp->UWLPtr) + CPV[i] );
            }
        }
    }
    return( OK );
}
#undef TFUNC


/******************************************************************************/
/*                                                                            */
/*   FUNCTION: prdt_SimulateFont                                              */
/*                                                                            */
/*   PARAMETERS:                                                              */
/*                                                                            */
/*   lpFontDataType   pFontData;                                              */
/*   USHORT           Codepage;                                               */
/*                                                                            */
/*   DESCRIPTION:                                                             */
/*                                                                            */
/*   This function takes the font specified in FontData and a                 */
/*   codepage and transforms that font so that it looks like a font           */
/*   in the new code page.                                                    */
/*                                                                            */
/******************************************************************************/
/*CON3201
VOID prdt_SimulateFont ( pFontData,
                                CodePage )


lpFontDataType   pFontData;
USHORT           CodePage;
*/

VOID prdt_SimulateFont (lpFontDataType   pFontData,
                        USHORT           CodePage)

{
#define TFUNC "prdt_GetInfoDfltFnt"

    /**************************************************************************/
    /* Local Variables                                                        */
    /**************************************************************************/
    lpFontInfoType  pFontInfo;
    lpFMFFileStruc  pFont;
    USHORT          RootCodePage;
    USHORT          DefaultChar;
    PUSHORT         RootTable;
    PUSHORT         SimulatedTable;

    /**************************************************************************/
    /* Some local pointers                                                    */
    /**************************************************************************/
    pFontInfo   = &(pFontData->Info);

    /**************************************************************************/
    /* get the code mapping table for the requested code page                 */
    /**************************************************************************/
    pFontData->CodeTable = (PUSHORT)
                              GreQueryCodePageVector( (ULONG)CodePage );
    pFontData->Simulated = TRUE;

    if ( !pFontData->CodeTable )
    {
        /**********************************************************************/
        /* If there is no mapping table for this code page (i.e.  the engine  */
        /* doesn't support it) then we can't simulate the requested code page.*/
        /* This should never arise but if it does then just carry on with the */
        /* page that we have.                                                 */
        /**********************************************************************/
        return;
    }

    /**************************************************************************/
    /* Set the codepage in Fontdata metrics to current DCI code page.         */
    /**************************************************************************/
//  pFontInfo->pFont->Metrics.usCodePage = CodePage;

    /**************************************************************************/
    /* Translate the width table if the font is proportionally spaced.        */
    /**************************************************************************/
    if (!(pFontInfo->pFont->Metrics.fsTypeFlags && FM_TYPE_FIXED) )
    {
        pFont          = pFontInfo->pFont;
        RootCodePage   = pFont->Metrics.usCodePage;
        RootTable      = pFont->CharWidth;
        SimulatedTable = pFont->CharWidth;
        DefaultChar    = (USHORT) pFont->Metrics.usDefaultChar;

        (VOID) prdt_TranslateWidthTable( RootTable,
                                         SimulatedTable,
                                         pFontData->CodeTable,
                                         RootCodePage,
                                         DefaultChar);

    }

    return;

}
#undef TFUNC



/******************************************************************************/
/*                                                                            */
/*   FUNCTION: prdt_TranslateChar                                             */
/*                                                                            */
/*   PARAMETERS:                                                              */
/*                                                                            */
/*   USHORT       InChar           Character to be translated                 */
/*   PUSHORT      pCodeTable       Code page vector table                     */
/*   USHORT       Index            Index into code page map table             */
/*                                                                            */
/*   DESCRIPTION:                                                             */
/*                                                                            */
/*   This function returns the ASCII value of the character based             */
/*   on the mapping of the root code page to the code page vector             */
/*   table.                                                                   */
/******************************************************************************/
/*CON3201
SHORT prdt_TranslateChar   ( InChar,
                                    pCodeTable,
                                    Index)

BYTE             InChar;
PUSHORT          pCodeTable;
USHORT           Index;
*/

SHORT prdt_TranslateChar   (BYTE             InChar,
                            PUSHORT          pCodeTable,
                            USHORT           Index)

{
#define TFUNC "prdt_TranslateChar"

    /**************************************************************************/
    /* Check to see if the character requested is valid, i.e.  it is in the   */
    /* Mapping Table.                                                         */
    /**************************************************************************/
    if ((pCodeTable[InChar] > CPTMapTable[Index].usSize ) ||
        (pCodeTable[InChar] < 0 ))
    {
        /**********************************************************************/
        /* Out of table range, so return an error.                            */
        /**********************************************************************/
         return(ERROR_NEG);

     }
     else
     {
        /**********************************************************************/
        /* We have a valid index, so translate the character.                 */
        /**********************************************************************/
         return(CPTMapTable[Index].TranslateTable[pCodeTable[InChar]]);
     }

}
#undef TFUNC



/******************************************************************************/
/*                                                                            */
/*   FUNCTION: prdt_TranslateWidthTable                                       */
/*                                                                            */
/*   PARAMETERS:                                                              */
/*                                                                            */
/*   PUSHORT         pInputWidthTable                                         */
/*   PUSHORT         pOutputWidthTable                                        */
/*   PUSHORT         pCPVectorTable                                           */
/*   USHORT          RootCodePage                                             */
/*   USHORT          DefaultChar                                              */
/*                                                                            */
/*                                                                            */
/*   DESCRIPTION:                                                             */
/*                                                                            */
/*   This functions moves the width table entries in InPutWidthTable          */
/*   to OutputWidthTable, translating each entry's position via the           */
/*   CodePageVectorTable.  If a code point in the new code page does          */
/*   not map to one in the root code page, the width table entry for          */
/*   that code point will be equal to the width of the default char.          */
/******************************************************************************/
/*CON3201
VOID prdt_TranslateWidthTable ( pInputWidthTable,
                                       pOutputWidthTable,
                                       pCPVectorTable,
                                       RootCodePage,
                                       DefaultChar)

PUSHORT         pInputWidthTable;
PUSHORT         pOutputWidthTable;
PUSHORT         pCPVectorTable;
USHORT          RootCodePage;
USHORT          DefaultChar;
                            */

VOID prdt_TranslateWidthTable (PUSHORT         pInputWidthTable,
                               PUSHORT         pOutputWidthTable,
                               PUSHORT         pCPVectorTable,
                               USHORT          RootCodePage,
                               USHORT          DefaultChar)

{
#define TFUNC "prdt_TransWidthTable"

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

    /**************************************************************************/
    /* Get the width of the default character                                 */
    /**************************************************************************/
    DefaultCharWidth = pInputWidthTable[DefaultChar];

    /**************************************************************************/
    /* Find the code page requested in the map table.                         */
    /**************************************************************************/
    for (i = 0; i < CPT_MAP_TABLE_SIZE ; i++)
    {
        if (CPTMapTable[i].usRootCP == RootCodePage)
        {
            /******************************************************************/
            /* Found the correct entry, so quit.                              */
            /******************************************************************/
            break;
        }
    }

    /**************************************************************************/
    /* For each entry in InWidthTable copy the value to the index in          */
    /* OutWidthTable which is correct for the new code page.  If the we get a */
    /* negative value from TranslateChar return the default character.        */
    /**************************************************************************/
    for (j = 0; j < 256 ; j++)
    {
        if ( ( pOutputWidthTable[j] =
                 pInputWidthTable[prdt_TranslateChar( (BYTE)j,
                                                       pCPVectorTable,
                                                       i)] )
                                                         == (USHORT)ERROR_NEG)
                                                         /* CON3203 */
            pOutputWidthTable[i] = DefaultCharWidth;

    }

}
#undef TFUNC

/*CON3201
SHORT prdt_GetMultiCpFMFIndex( Codepage, pMultiCp )

USHORT              Codepage;
lpMultiCpType       pMultiCp;*/

SHORT prdt_GetMultiCpFMFIndex(USHORT              Codepage,
                              lpMultiCpType       pMultiCp)

{
/******************************************************************************/
/* This function searches thru the MultiCp FMF code page list for the input   */
/* codepage.  The index of the input codepage in the FMF list is returned.  A */
/* negative number is returned when the input codepage is not in the FMF      */
/* codepage list which indicates there are no change bytes required for this  */
/* MultiCp FMF for this codepage.                                             */
/******************************************************************************/
#define TFUNC "prdt_GetMultiCpFMFIndex"

    /**************************************************************************/
    /* Local Variables                                                        */
    /**************************************************************************/
    USHORT             i;                /* Result of function call   */

    for ( i = 0 ; i < pMultiCp->NumCps ; i++ )
    {
        if ( pMultiCp->pCpEntry[i]->Cp == Codepage )
        {
            /******************************************************************/
            /* Codepage found so return index in FMF list                     */
            /******************************************************************/
            return( i );
        }
    }
    /**************************************************************************/
    /* Input codepage not in FMF list so return a negative value              */
    /**************************************************************************/
    return(ERROR_NEG);
}
#undef TFUNC

