/*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 = PRDTCSTR
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prdt_CharString
 *             prdt_CharStringPos
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

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

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

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

#include <prdconse.h>
#include <prdbcone.h>
#include <prddcone.h>
#include <prdtcone.h>

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

#include <prdbtyp1.h>
#include <prdbextf.h>
#include <prdcextf.h>
#include <prdgextf.h>
#include <prdtextf.h>
#include <prdnextf.h>
#include <prdfextf.h>
#include <prdncone.h>

/******************************************************************************/
/*  Set up external access to the engine handlers for CharStringPos.          */
/******************************************************************************/
extern PFNL da_CharStringPos;

/******************************************************************************/
/*  PD00669 : Have to add the following two defines until we move to the new  */
/*  2.0 Toolkit.  Once we make the move, these should be in the new PMGPI.H   */
/*  and these should be removed... watch for the 'duplicate define' message...*/
/******************************************************************************/
/* #define CHS_UNDERSCORE  0x0200L CON3201 - Already in PMGPI.H               */
/* #define CHS_STRIKEOUT   0x0400L CON3201 - Already in PMGPI.H               */

/******************************************************************************/
/*  FUNCTION: prdt_CharString                                                 */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  See "OS/2 Technical Reference: I/O Subsytems and Device Drivers"          */
/*                                                                            */
/*  HDC    DcH;                                                               */
/*  LONG   ArgCharNum;                                                        */
/*  PCH    ArgCodePoints;                                                     */
/*  lpDCI  DCIData;                                                           */
/*  ULONG  FunN;                                                              */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  Let prdt_CharStringPos do all the work; call it with no start position,   */
/*  opaque rectangle, options, position vectors or colors.                    */
/******************************************************************************/
ULONG EXPENTRY prdt_CharString( HDC    DcH,
                                LONG   ArgCharNum,
                                PCH    ArgCodePoints,
                                lpDCI  DCIData,
                                ULONG  FunN)

{
    return(prdt_CharStringPos(DcH, (PPOINTL)0, (PRECTL)0, 0L, ArgCharNum,
                              ArgCodePoints, (PLONG)NULL, (PCSP_INFO)NULL,
                              DCIData, MAKELONG(NGreCharStringPos,
                              HIUSHORT(FunN))));
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdt_CharStringPos                                              */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  See "OS/2 Technical Reference: I/O Subsytems and Device Drivers"          */
/*                                                                            */
/*  HDC        DcH                                                            */
/*  PPOINTL    ArgStart                                                       */
/*  PRECTL     ArgOpaqueRect                                                  */
/*  ULONG      ArgOptions                                                     */
/*  LONG       ArgCharNum                                                     */
/*  PCH        ArgCodePoints                                                  */
/*  PLONG      ArgPosVector                                                   */
/*  PCSP_INFO  ArgAttrs                                                       */
/*  lpDCI      DCIData                                                        */
/*  ULONG      FunN                                                           */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function does error checking, some set up and then calls             */
/*  prdt_TextOut???Ffont to do the work.                                      */
/******************************************************************************/
ULONG EXPENTRY prdt_CharStringPos( HDC        DcH,
                                   PPOINTL    ArgStart,
                                   PRECTL     ArgOpaqueRect,
                                   ULONG      ArgOptions,
                                   LONG       ArgCharNum,
                                   PCH        ArgCodePoints,
                                   PLONG      ArgPosVector,
                                   PCSP_INFO  ArgAttrs,
                                   lpDCI      DCIData,
                                   ULONG      FunN)

{

#define TFUNC "prdt_CharStrPos"

    /**************************************************************************/
    /*  Local Variables                                                       */
    /**************************************************************************/
    ULONG           Command;           /* Command part of FunN                */
    lpFontInfoType  pFontInfo;
    lpFontDataType  pFontData;
    LONG            RetVal;
    pBMListEntry    ListEntry;         /* Pointer to bitmap list entry        */
    PDCHARBUNDLE    CurTxtAts;         /* Pointer to current text attrs       */
    ULONG           ForeColor;
    ULONG           BackColor;
    TextAttrsType   TextAttrs;         /* Foreground and background colors and*/
                                       /* mixes                               */
    PEDFH           pedfh;             /* pointer to download engine font     */
                                       /* header                              */
    USHORT          usPatType;         /* type of pattern                     */
    lpDDTType       pDDT;              /* DDT Pointer                         */
    PBYTE              GSTabPtr;     /* Pointer to a g/s pattern      */
    PBYTE              GSTabPtr2;
    USHORT          i;
    BOOL            bCHS_OverrideUS;   /* Flag to verify underscore override  */
    BOOL            bCHS_OverrideSO;   /* Flag to verify strikeout override   */
    PBYTE          *pbTemp;

#ifdef PRD_TIMING

    DEKHOOK0(A,9,5A)

#endif

    /**************************************************************************/
    /*  Get the semaphore.                                                    */
    /**************************************************************************/
    prdm_EnterDriver(DCIData);

    /**************************************************************************/
    /*  Get the command flags (combined with current mask so that Q-STD does  */
    /*  no drawing.                                                           */
    /**************************************************************************/
    Command = FunN & DCIData->CommandMask;

    /**************************************************************************/
    /*  Do the new framework drawing function - sets DRAWN_INTO flag if       */
    /*  COM_DRAW is set.  Returns error if not in a suitable state.           */
    /**************************************************************************/
    if ((RetVal = prdn_CheckDrawingState(&Command, DCIData)) != OK)
    {
        RetVal = (RetVal == ERR_PURGE) ? OK : ERROR_ZERO;
        goto EXIT_FUNCTION;
    }

    /**************************************************************************/
    /*  If there is nothing to draw then we can simply exit.                  */
    /*                                                                        */
    /*  Note the check for an opaque rectangle being present even if the      */
    /*  number of characters to output is zero.  This is how the engine       */
    /*  simulates underlining and strikeout attributes for image fonts.       */
    /**************************************************************************/
    if ((ArgCharNum == 0) && !(ArgOptions & CHS_OPAQUE))
    {
        RetVal = OK;
        goto EXIT_FUNCTION;
    }

    /**************************************************************************/
    /*  Check that if target is a memory DC then there is a currently selected*/
    /*  bitmap.                                                               */
    /**************************************************************************/
    if ((DCIData->DCIDCType == OD_MEMORY) &&
         (DCIData->DCISelBitmap == FNULL))
    {
        LOGERR(TFUNC, "Bitmap not selected", FNULL, 0,
               PMERR_BITMAP_NOT_SELECTED);
        RetVal = ERROR_ZERO;
        goto EXIT_FUNCTION;
    }

    /**************************************************************************/
    /*  Call not allowed within area.                                         */
    /**************************************************************************/
    if (Command & COM_AREA)
    {
        LOGERR(TFUNC, "Invalid in area", FNULL, 0, PMERR_INV_IN_AREA);
        RetVal = ERROR_ZERO;
        goto EXIT_FUNCTION;
    }

    /**************************************************************************/
    /*  Set up local font pointers.                                           */
    /**************************************************************************/
    pFontData = &DCIData->DCIFontData;
    pFontInfo = &pFontData->Info;
    CurTxtAts = DCIData->DCICurTxtAts;

    /**************************************************************************/
    /*  PD00669 : Need to check for two new flags for Cruiser... allows us to */
    /*  selectively turn on and off the underscore and/or strikeout flags for */
    /*  one string.  Note that if we turn either of these flags on in the     */
    /*  CurTxtAts here we need to turn them back off at the end of this       */
    /*  function.                                                             */
    /**************************************************************************/
    bCHS_OverrideUS = FALSE;
    bCHS_OverrideSO = FALSE;
    if (ArgOptions & (CHS_UNDERSCORE | CHS_STRIKEOUT))
    {

        /**********************************************************************/
        /*  OK... we know we've hit the new Cruiser flags, so we now need to  */
        /*  determine whether or not they're redundant.  If they are, we won't*/
        /*  do anything 'cause otherwise we'd end up turning the flags off at */
        /*  the end of the function (mondo badness, dude).                    */
        /**********************************************************************/
        if ((ArgOptions & CHS_UNDERSCORE) &&
            !(CurTxtAts->cdef.fFlags & CDEF_UNDERSCORE))
        {
            DCIData->DCICurTxtAts->cdef.fFlags |= CDEF_UNDERSCORE;
            bCHS_OverrideUS = TRUE;
        }
        if ((ArgOptions & CHS_STRIKEOUT) &&
            !(CurTxtAts->cdef.fFlags & CDEF_STRIKEOUT))
        {
            DCIData->DCICurTxtAts->cdef.fFlags |= CDEF_STRIKEOUT;
            bCHS_OverrideSO = TRUE;
        }
    }

    /**************************************************************************/
    /*  Following error checking only needed if there are chars to be drawn   */
    /*  (rather than just an opaque rectangle).                               */
    /**************************************************************************/
    if (ArgCharNum != 0)
    {

        /**********************************************************************/
        /*  Raster fonts are not allowed within path.                         */
        /**********************************************************************/
        if ((Command & COM_PATH) &&
            !(pFontData->pMetrics->fsDefn & FM_DEFN_OUTLINE))
        {
            LOGERR(TFUNC, "Invalid in path", FNULL, 0, PMERR_INV_IN_PATH);
            RetVal = ERROR_ZERO;
            goto EXIT_FUNCTION;
        }

        /**********************************************************************/
        /*  Check DC simulation required flags.  For CharStringPos, simulate  */
        /*  if engine attributes are required, or if mode/attributes/etc      */
        /*  forces it.  See prdasetb.c for comment.  If siml flags set, but   */
        /*  the COM_DEVICE flag is not set, then call to simulation.  If both */
        /*  flags set, then this is already a simulation, so we carry on to   */
        /*  print it.                                                         */
        /**********************************************************************/

        /**********************************************************************/
        /*  PD00073 : Do not call back to engine for simulation for outline   */
        /*  fonts.                                                            */
        /**********************************************************************/
        /**********************************************************************/
        /*  C/Set2 Conversion - Currently the engine by default will take     */
        /*  care of fxExtra and fxBreakExtra for 16-bit drivers.  We will     */
        /*  add the two conditions in the if statement below so that the      */
        /*  engine will go ahead and do the simulation for us (ie figure      */
        /*  the character spacing for us.  Also had to add similar conditions */
        /*  in prda_SetTextSimlFlag. Jim Russell                              */
        /*  This is also true for usTextAlign                                 */
        /**********************************************************************/
        if ((pFontData->Genre == DEVICE_FONT) &&
            (pFontData->pMetrics->fsDefn & FM_DEFN_OUTLINE) &&
            (CurTxtAts->cbnd.fxExtra == 0) &&
            (CurTxtAts->cbnd.fxBreakExtra == 0) &&
            (CurTxtAts->cbnd.usTextAlign == (TA_NORMAL_HORIZ |
                                             TA_NORMAL_VERT)))
        {
            goto SKIP_SIMULATION;
        }
        if ((DCIData->DCIStateFlags & TEXT_SIML_REQD)
              && !(Command & COM_DEVICE))
        {
            RetVal = ENG_CALL;
            goto EXIT_FUNCTION;
        }

        /**********************************************************************/
        /*  The driver does not support kerning directly.                     */
        /*                                                                    */
        /*  If the font requires kerning then call a simulation unless        */
        /*  COM_DEVICE is set in which case we proceed but ignoring an        */
        /*  kerning.                                                          */
        /**********************************************************************/
        if ((pFontData->pMetrics->usKerningPairs != 0) &&
            !(Command & COM_DEVICE))
        {
            RetVal = ENG_CALL;
            goto EXIT_FUNCTION;
        }
        if (pFontData->Genre != DEVICE_FONT)
        {

            /******************************************************************/
            /*  PD00060 : Simulate attributed system fonts.  The ENG_ATTS_REQD*/
            /*  flag is set in SetTextSimlFlags                               */
            /******************************************************************/
            if ((DCIData->DCIStateFlags & ENG_ATTS_REQD)
                && !(Command & COM_DEVICE))
            {
                RetVal = ENG_CALL;
                goto EXIT_FUNCTION;
            }

        }
    }

SKIP_SIMULATION:

    /**************************************************************************/
    /*  Establish Foreground and Background Color and Mix.                    */
    /**************************************************************************/
    ListEntry         = (pBMListEntry)DCIData->DCISelBitmap;
    TextAttrs.ForeMix = CurTxtAts->cbnd.usMixMode;
    TextAttrs.BackMix = CurTxtAts->cbnd.usBackMixMode;
    if (ArgOptions & CHS_ATTR_INFO)
    {
        ForeColor = ArgAttrs->lColor;
        BackColor = ArgAttrs->lBackColor;
    }
    else
    {
        ForeColor = CurTxtAts->cbnd.lColor;
        BackColor = CurTxtAts->cbnd.lBackColor;
    }
    TextAttrs.ForeColor = prdc_ColorToPelBits(ForeColor, DCIData,
                                              ListEntry->DCTPtr);

    /**************************************************************************/
    /*  We only need to set up the background color if the background mix is  */
    /*  not LEAVEALONE.                                                       */
    /**************************************************************************/
    if ((TextAttrs.BackMix != FM_LEAVEALONE) || (ArgOptions & CHS_OPAQUE))
    {
        TextAttrs.BackColor = prdc_ColorToPelBits(BackColor, DCIData,
                                                  ListEntry->DCTPtr);
    }

    /**************************************************************************/
    /*  Handle an Opaque rectangle if present.                                */
    /**************************************************************************/
    if (ArgOptions & CHS_OPAQUE)
    {

        /**********************************************************************/
        /*  PD0076 : GreyScale opaque rect                                    */
        /**********************************************************************/
        if (Command & COM_DRAW)
        {

            /******************************************************************/
            /*  Local variable                                                */
            /******************************************************************/
            pDDT     = &DCIData->DCIPdbInstance->DDT;
            GSTabPtr = FNULL;

            /******************************************************************/
            /*  See if we need to greyscale                                   */
            /******************************************************************/
           if ( prdb_GetGreyScaleInfo(BackColor, &usPatType,
                                      &GSTabPtr2, DCIData) )
            {
                if (usPatType != PAT_ALL_ONES)
                {
                   GSTabPtr = GSTabPtr2;
                }
            }
        }
        if (prdt_SetOpaqueRect(DcH, ArgOpaqueRect, TextAttrs.BackColor,
                               Command, DCIData, GSTabPtr) != OK)
        {
            RetVal = ERROR_ZERO;
            goto EXIT_FUNCTION;
        }
    }

    /**************************************************************************/
    /*  If number of codepoints is zero then return now having drawn any      */
    /*  opaque rectangle.                                                     */
    /**************************************************************************/
    if (ArgCharNum == 0)
    {
        RetVal = OK;
        goto EXIT_FUNCTION;
    }

    if ((pFontData->Genre == DEVICE_FONT) ||
        (pFontData->Genre == ENG_DOWNLD_FONT))
    {
        RetVal = prdt_TextOutDevFont(DcH, Command, ArgStart, ArgOpaqueRect,
                                     ArgOptions, ArgCharNum, ArgCodePoints,
                                     ArgPosVector, &TextAttrs, DCIData,
                                     pFontData);
    }
    else
    {
        RetVal = prdt_TextOutEngFont(DcH, Command, ArgStart, ArgOpaqueRect,
                                     ArgOptions, ArgCharNum, ArgCodePoints,
                                     ArgPosVector, &TextAttrs, DCIData,
                                     pFontData, ForeColor);
    }

EXIT_FUNCTION:

    /**************************************************************************/
    /*  Tidy up...                                                            */
    /**************************************************************************/
    prdm_LeaveDriver(DCIData);

#ifdef PRD_TIMING

    DEKHOOK0(A,9,DA)

#endif

    /**************************************************************************/
    /*  PD00669 : Modified the return sequence from here on down so we could  */
    /*  return only once (required if we're going to check for override       */
    /*  flags).                                                               */
    /**************************************************************************/
    if (RetVal == ENG_CALL)
    {

        /**********************************************************************/
        /*  Return to engine if the COM_DEVICE bit allows, otherwise just     */
        /*  return OK.                                                        */
        /**********************************************************************/
        if (!(Command & COM_DEVICE))
        {
            RetVal = (USHORT)da_CharStringPos(DcH, ArgStart, ArgOpaqueRect,
                                              ArgOptions, ArgCharNum,
                                              ArgCodePoints, ArgPosVector,
                                              ArgAttrs, DCIData, FunN);
        }
        else
        {
            RetVal = OK;
        }
    }

    /**************************************************************************/
    /*  PD00669 : We need to see if there were any overrides active for the   */
    /*  CDEF_UNDERSCORE or CDEF_STRIKEOUT... if so, we need to deactivate the */
    /*  attributes in the current text attribute bundle before we bail out.   */
    /**************************************************************************/
    if (bCHS_OverrideUS)
    {
        DCIData->DCICurTxtAts->cdef.fFlags &= ~CDEF_UNDERSCORE;
    }
    if (bCHS_OverrideSO)
    {
        DCIData->DCICurTxtAts->cdef.fFlags &= ~CDEF_STRIKEOUT;
    }

    /**************************************************************************/
    /*  T-t-t-thats all, folks...                                             */
    /**************************************************************************/
    return(RetVal);
}
#undef TFUNC
