/*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 = PRDQESUB
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prdq_NewFrame
 *             prdq_FlushOutput
 *             prdq_RawData
 *             prdq_JournalData
 *             prdq_SetMode
 *
 * 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_SPL
#define INCL_GPIERRORS
#define INCL_DEV
#include <os2.h>
#undef INCL_DOSPROCESS       /* CON3201 */
#undef INCL_DOSSEMAPHORES
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS
#undef INCL_SPL
#undef INCL_GPIERRORS
#undef INCL_DEV

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

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

#include <prdtcone.h>

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

#include <prdaextf.h>
#include <prdeextf.h>
#include <prdgextf.h>
#include <prdtextf.h>
#include <prdjextf.h>
#include <prdpextf.h>
#include <prdqextf.h>
#include <prdyextf.h>
#include <prdnextf.h>
#include <prdncone.h>

extern lpDDTType  DDT [];
extern USHORT               OutlineCodepageEntries;

/******************************************************************************/
/*  FUNCTION: prdq_NewFrame                                                   */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  hanDC   DcH;          Handle to DC Instance data                          */
/*  ULONG   ArgInCount;   Unused parameter                                    */
/*  PULONG  ArgInData;    Unused parameter                                    */
/*  PULONG  ArgOutCount;  Unused parameter                                    */
/*  PULONG  ArgOutData;   Unused parameter                                    */
/*  lpDCI   DCIData;      Pointer to DC Instance data                         */
/*                                                                            */
/*  NOTE : see prdqedoc.c for comments about the State variables              */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  NewFrame calls ProcessPage to output the page to printer/spooler, and     */
/*  increments PageNumber.  From IMPLICIT state the same calls are made, but  */
/*  note that ProcessPage may issue a SplQmStartDoc for the first page.       */
/*  RAW_xx state => xx , other states are unchanged.  Return error if purging,*/
/*  or in WAIT_START state.  Note NewFrame not called for a Q_STD DC.         */
/******************************************************************************/
SHORT prdq_NewFrame(hanDC   DcH,          /* CON3203 */
                     ULONG   ArgInCount,
                     PULONG  ArgInData,
                     PULONG  ArgOutCount,
                     PUSHORT ArgOutData,
                     lpDCI   DCIData)

{
#define TFUNC "prdq_NewFrame"

    SHORT  return_value;

#ifdef DEBUG_FSM

    OutputString("DevEsc NewFrame");

#endif

    switch (DCIData->State)
    {
        case WAIT_START:

            /******************************************************************/
            /*  Expecting a StartDoc or Begin_Close                           */
            /******************************************************************/
            return(ERROR_NEG);
        case PURGE:

            /******************************************************************/
            /*  Just return when purging, without any output.                 */
            /******************************************************************/
            return(OK);
        case IMPLICIT:
            if (DCIData->Flags & QUEUED_STD)
            {

                /**************************************************************/
                /*  Enforce StartDoc for Q_STD document.                      */
                /**************************************************************/
                return(ERROR_NEG);
            }
        case RAW_IMPLICIT:
        case EXPLICIT:
        case RAW_EXPLICIT:

            /******************************************************************/
            /*  Output the page to the device/spooler.                        */
            /******************************************************************/
            /* PD00297 : Here we set the flag to indicate that this   */
            /*  frame is "DRAWN_INTO". This will allow the DEVESC(NEW */
            /*  FRAME) to force a form feed even though the page may  */
            /*  be blank. Also, consecutive DEVESC(NEWFRAME)s  will   */
            /*  eject consecutive blank pages.                        */
            /**********************************************************/
            DCIData->Flags |= DRAWN_INTO;

            if ((return_value = prdn_ProcessPage(DCIData)) != OK)
            {

                /**************************************************************/
                /*  May have ERROR, ERR_ABORT, ERR_PURGE                      */
                /**************************************************************/
                if (return_value == ERROR)  /* CON3203 */
                {
                    return(ERROR_NEG);
                }
                else
                {

                    /**********************************************************/
                    /*  Purging or aborting: return OK back up to ap.  If we  */
                    /*  are purging, then further calls will also return OK   */
                    /*  without any output, until an EndDoc, StartDoc,        */
                    /*  BeginClose gets us out of PURGE state If aborting,    */
                    /*  then the state is now WAIT_START, so we are ready for */
                    /*  a StartDoc or BeginClose.                             */
                    /**********************************************************/
                    return(OK);
                }
            }

            /******************************************************************/
            /*  Increment page count.  Do this here, because we need to know  */
            /*  (in PrepareNextPage) what page we are on - to set up the 2nd  */
            /*  form of a dual form job.                                      */
            /******************************************************************/
            DCIData->DCIPageNumber++;

            /******************************************************************/
            /*  And get a new page                                            */
            /******************************************************************/
            if (prdn_PrepareNextPage(DCIData) != OK)
            {

                /**************************************************************/
                /*  Memory error, or similar.                                 */
                /**************************************************************/
                return(ERROR_NEG);
            }
            break;
    }

    /**************************************************************************/
    /*  Get out of RawData states.                                            */
    /**************************************************************************/
    if (DCIData->State == RAW_EXPLICIT)
        DCIData->State = EXPLICIT;
    else
        if (DCIData->State == RAW_IMPLICIT)
            DCIData->State = IMPLICIT;

    /**************************************************************************/
    /*  Set flag indicating to RawData that need to re-establish the default  */
    /*  font.  This is not necessary for NewFrame, as the state is            */
    /*  IMPLICIT/EXPLICIT for the 1st RawData in a page, and is RAW_xx for    */
    /*  further calls on that page.  However, a call to SetMode between 2     */
    /*  RawData calls requires us to re-establish the font, indicated by this */
    /*  flag.  This replaces the EstDfltFont flag in the old code.            */
    /**************************************************************************/
    DCIData->Flags |= RESET_DFLT_FONT;
    return(OK);
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdq_FlushOutput                                                */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  hanDC   DcH;          Handle to DC                                        */
/*  ULONG   ArgInCount;   Unused parameter                                    */
/*  PULONG  ArgInData;    Unused parameter                                    */
/*  PULONG  ArgOutCount;  Unused parameter                                    */
/*  PULONG  ArgOutData;   Unused parameter                                    */
/*  lpDCI   DCIData;      Pointer to DC Instance data                         */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  Flushes current band without printing it, and restarts band.  Banding:    */
/*  this will clear out just one band, not an entire page.  Note: not called  */
/*  for QUEUED_STD DC.                                                        */
/******************************************************************************/
 SHORT  prdq_FlushOutput(hanDC   DcH,             /* CON3203 */
                         ULONG   ArgInCount,
                         PULONG  ArgInData,
                         PULONG  ArgOutCount,
                         PUSHORT ArgOutData,
                         lpDCI   DCIData)

{
#define TFUNC "prdq_FlushOutput"

#ifdef DEBUG_FSM

    OutputString("DevEsc FlushOutput");

#endif

    switch (DCIData->State)
    {
        case WAIT_START:

            /******************************************************************/
            /*  Error - no open document                                      */
            /******************************************************************/
            LOGERR(TFUNC, "No Open Document", FNULL, 0, PMERR_STARTDOC_NOT_ISSUED);
            return(ERROR_NEG);
        case PURGE:

            /******************************************************************/
            /*  Flushing a purged document.  Just return OK to ap.            */
            /******************************************************************/
            return(OK);
        case IMPLICIT:
        case EXPLICIT:
        case RAW_IMPLICIT:
        case RAW_EXPLICIT:

            /******************************************************************/
            /*  Must flush the band, and start a new one                      */
            /******************************************************************/
            prdj_FreeBand(DCIData, &DCIData->DCICurrBand);
            if (prdj_MakeBand(DCIData, &DCIData->DCICurrBand) != OK)
            {
                return(ERROR_NEG);
            }

            /******************************************************************/
            /*  This band is now empty.                                       */
            /******************************************************************/
            DCIData->Flags &= ~DRAWN_INTO;
            return(OK);
    }
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdq_RawData                                                    */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  ULONG  ArgInCount;  Amount of raw data                                    */
/*  PCHAR  ArgInData;   Pointer to start of raw data                          */
/*  lpDCI  DCIData;     Pointer to DC Instance data                           */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function allows raw data to be sent to the printer.  It must be      */
/*  written in sections of less than 64K.  If it is a Direct Raw DC then the  */
/*  data must first be passed through the parser in order to respond correctly*/
/*  to formfeeds before it can be written to the printer.                     */
/*                                                                            */
/*  The printer may need to be opened ( if this is the 1st page ), or         */
/*  SplQmStartDoc issued (when IMPLICIT, 1st page).  The data can then be     */
/*  sent.                                                                     */
/******************************************************************************/
/* CON3203 */
SHORT  prdq_RawData(ULONG ArgInCount, PCHAR ArgInData, lpDCI DCIData)

{
#define TFUNC "prdq_RawData"

    /**************************************************************************/
    /*  Local Variables                                                       */
    /**************************************************************************/
    SHORT              return_value;
    USHORT              Result;
    lpPDBI              PDBInst;       /* Pointer to the PDB Instance data    */
    lpDDTType           pDDT;          /* Pointer to the DDT                  */
    USHORT              Count;         /* The amount of data in the block     */
                                       /* being written                       */
    USHORT              i;             /* Loop control variable               */
    PCHAR               ptr;           /* Pointer used to access the raw data */
    USHORT              BytesToWrite;  /* Parameters for passing to           */
    PCHAR               Data;          /* prdm_PrtWrite                       */
    USHORT              BytesWritten;  /* number of bytes prtwritten          */
    BOOL                FirstRawData;
    lpDfltFontInfoType  pDfltDeviceFontInfo;

#ifdef DEBUG_FSM

    OutputString("DevEsc RawData");

#endif

    /**************************************************************************/
    /*  Set up useful pointers                                                */
    /**************************************************************************/
    PDBInst             = DCIData->DCIPdbInstance;
    pDDT                = &PDBInst->DDT;
    pDfltDeviceFontInfo = &PDBInst->DfltDeviceFont;

    /**************************************************************************/
    /*  If no bytes to send or this is an Info DC then just return OK.  From  */
    /*  now on we assume that the DC is either Direct or Queued Raw.          */
    /**************************************************************************/
    if ((ArgInCount == 0L)|| (DCIData->Flags & INFO))
        return (OK);
    else
        if (DCIData->Flags & MEMORY)
            return (ERROR_NEG);

    /**************************************************************************/
    /*  Clear all DCIDownCpFlags.Used to prevent downloading codepage BIN     */
    /*  files on spurious Gpi calls.                                          */
    /**************************************************************************/
    for (i = 0; i < OutlineCodepageEntries; i++)
    {
        DCIData->DCIDownCpFlags[i].Used = FALSE;
    }

    /**************************************************************************/
    /*  We change the state variable at the end of the following switch       */
    /*  statement.  However we need to record whether this is the first Raw   */
    /*  Data call or not - do that with this flag.                            */
    /**************************************************************************/
    FirstRawData = FALSE;
    switch (DCIData->State)
    {
        case WAIT_START:

            /******************************************************************/
            /*  Error - no open document                                      */
            /******************************************************************/
            return(ERROR_NEG);
        case PURGE:

            /******************************************************************/
            /*  Just ignore and return OK.                                    */
            /******************************************************************/
            return(OK);
        case IMPLICIT:
            if (DCIData->Flags & QUEUED_STD)
            {

                /**************************************************************/
                /*  Enforce StartDoc for Q_STD document.                      */
                /**************************************************************/
                return(ERROR_NEG);
            }
        case EXPLICIT:
            if (DCIData->DCIPageNumber == 1)
            {
                if ((DCIData->Flags & QUEUED) && (DCIData->State == IMPLICIT))
                {

                    /**********************************************************/
                    /* Make SplQmOpen call.                    PD00227        */
                    /**********************************************************/
                    if ( !(DCIData->Flags & QM_OPEN_ISSUED) )
                    {
                       if (prde_OpenSpooler( PDBInst) != OK)
                       {
                          return ( ERROR_NEG );
                       }
                       DCIData->Flags |= QM_OPEN_ISSUED;
                       DCIData->DCISplHandle = PDBInst->PDBSplHandle;
                    }
                    /**********************************************************/
                    /*  Start spooler doc, as this is the 1st RawData on the  */
                    /*  1st page ( later calls will be in RAW_IMPLICIT state. */
                    /**********************************************************/
                    if (SplQmStartDoc((HSPL)DCIData->DCISplHandle,
                                      (PSZ) DCIData->DCIDocName) != OK)
                    {
                         return(ERROR_NEG);
                    }
                    DCIData->Flags |= QM_START_ISSUED;
                }
                else
                    if (DCIData->Flags & DIRECT)
                    {
                        return_value = prdn_OpenPrinter(DCIData);
                        if (return_value != OK)
                        {

                            /**************************************************/
                            /*  May have ERROR, ERR_ABORT, ERR_PURGE          */
                            /**************************************************/
                            if (return_value == ERROR) /* CON3203 */
                            {
                                return(ERROR_NEG);
                            }
                            else
                            {

                                /**********************************************/
                                /*  If purging or aborting, just return       */
                                /*  without outputing anything.               */
                                /**********************************************/
                                return(OK);
                            }
                        }
                    }
            }

            /******************************************************************/
            /*  First Raw Data this page...                                   */
            /******************************************************************/
            FirstRawData = TRUE;
            break;
        case RAW_IMPLICIT:
        case RAW_EXPLICIT:
            break;

    }

    /**************************************************************************/
    /*  State changed now - may return an error lower down.                   */
    /**************************************************************************/
    if (DCIData->State == IMPLICIT)
    {
        DCIData->State = RAW_IMPLICIT;
    }
    else
        if (DCIData->State == EXPLICIT)
        {
            DCIData->State = RAW_EXPLICIT;
        }

    /**************************************************************************/
    /*  If this is the first RawData call in a page, then do some setup &     */
    /*  initialisation things - these are not done between two RawData calls  */
    /*  on one page.                                                          */
    /*                                                                        */
    /*  After a NewFrame we will do everything - including establish the      */
    /*  default font.                                                         */
    /**************************************************************************/
    if (FirstRawData)
    {

        /**********************************************************************/
        /*  Don't need a card.  Ensure that no prompting is done.             */
        /**********************************************************************/
        DCIData->DCICardCount = 0;

        /**********************************************************************/
        /*  If this is the first RawData call for a page then do some printer */
        /*  initialisation.  This may include first-page init sequences, card */
        /*  prompting, and inter-page sequences.                              */
        /**********************************************************************/
        if ((return_value = prdn_InitialisePrinter(DCIData)) != OK)
        {

            /******************************************************************/
            /*  May have ERROR, ERR_ABORT, ERR_PURGE - note that the state has*/
            /*  already been changed.                                         */
            /******************************************************************/
            if (return_value == ERROR)                     /* CON3203 */
                return(ERROR_NEG);
            else
                return(OK);
        }
    }

    /**************************************************************************/
    /*  Establish default device font if this is the first rawdata call on a  */
    /*  page or if the default device font is different now.  Note: the flag  */
    /*  is redundant for NewFrame calls, as the state indicates the need to   */
    /*  re-establish.  But after a SetMode or SetCodePage we do need this     */
    /*  flag.                                                                 */
    /**************************************************************************/
    if ((FirstRawData) || (DCIData->Flags & RESET_DFLT_FONT))
    {

        /**********************************************************************/
        /*  Establish the default font if necessary.  This happens at start of*/
        /*  day and after the default font has been changed by a DevEsc       */
        /*  (SetMode) or SetcodePage that changed the current code page.      */
        /**********************************************************************/
        return_value = prde_OutputDefaultFontCodes(DCIData);
        if (return_value != OK)
        {

            /******************************************************************/
            /*  May have ERROR, ERR_ABORT, ERR_PURGE - note that the state has*/
            /*  already been changed.                                         */
            /******************************************************************/
            if (return_value == ERROR)                     /* CON3203 */
            {
                return(ERROR_NEG);
            }
            else
            {

                /**************************************************************/
                /*  Just return OK with no output.                            */
                /**************************************************************/
                return(OK);
            }
        }

        /**********************************************************************/
        /*  No longer need to set up the default font.                        */
        /**********************************************************************/
        DCIData->Flags &= ~RESET_DFLT_FONT;
    }

    /**************************************************************************/
    /*  Now output Raw data to Prt or Spl file.  The DOS function PrtWrite    */
    /*  limits data writes to blocks of 64K-1 bytes so keep writing blocks    */
    /*  until all the raw data has been written.                              */
    /**************************************************************************/
    do
    {

        /**********************************************************************/
        /*  Limit data count to 64K - 1                                       */
        /**********************************************************************/
        Count = (USHORT)min(65535L, ArgInCount);

        if (DCIData->Flags & QUEUED_RAW)
        {

            /******************************************************************/
            /*  DC is Queued Raw so send the data to the spooler.             */
            /******************************************************************/
            if (SplQmWrite((HSPL)DCIData->DCISplHandle, (ULONG)Count,
                           ArgInData) != OK)
                return(ERROR_NEG);
        }
        else
        {

            /******************************************************************/
            /*  The raw data is to be sent to the printer.  If the formfeed   */
            /*  control flag is set to prdg_FFnever then we can send the data */
            /*  straight to the printer.  Otherwise we must put it through the*/
            /*  raw data parser via the macro prdm_Parser.                    */
            /******************************************************************/
            if (PDBInst->FFcontrol != prdg_FFnever)
            {
                for (i = 0, ptr = ArgInData; i < Count; i++, ptr++)
                {
                    TRACE4(TFUNC, "Character", ptr, 1);
                    prdm_Parser(*ptr);
                }
            }

            /******************************************************************/
            /*  Write the string to the DOS Device.                           */
            /******************************************************************/
            Data         = ArgInData;
            BytesToWrite = Count;
            return_value = prdn_PrtWrite(DCIData, Data, BytesToWrite, PDBInst,
                                         BytesWritten);
            if (return_value != OK)
            {

                /**************************************************************/
                /*  May be ERR_ABORT or ERR_CANCEL; if user cancel then the   */
                /*  state will have been set to PURGE in the prdn_PrtWrite    */
                /*  function.  We return OK up to application - NOT an error. */
                /**************************************************************/
                return(OK);
            }
        }
    } while(ArgInData += Count, ArgInCount -= Count);

    /**************************************************************************/
    /*  ...continue until all data has been written.                          */
    /**************************************************************************/
    return(OK);
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdq_JournalData                                                */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  ULONG   ArgInCount;   Amount of data to transfer to                       */
/*                        journal                                             */
/*  PULONG  ArgInData;    Pointer to data to transfer to                      */
/*                        journal                                             */
/*  PULONG  ArgOutCount;  Unused parameter                                    */
/*  PULONG  ArgOutData;   Unused parameter                                    */
/*  lpDCI   DCIData;      Pointer to DC Instance data                         */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  Writes the data indicated by ArgInData and ArgInCount to the journal.     */
/******************************************************************************/
 SHORT  prdq_JournalData( ULONG   ArgInCount,    /* CON3203 */
                          PULONG  ArgInData,
                          PULONG  ArgOutCount,
                          PUSHORT ArgOutData,
                          lpDCI   DCIData)

{
#define TFUNC "prdq_JournalData"

    /**************************************************************************/
    /*  Local Variables                                                       */
    /**************************************************************************/
    ULONG  BytesWritten;              /* The number of bytes written by the  */
                                       /* DosWrite call                       */

    /**************************************************************************/
    /*  Note that although ArgInCount is a ULONG and the buffer length passed */
    /*  to DosWrite is a Word, there's no need to split up the data since it  */
    /*  was put on the spool file by DD-1 (PRDJEND) and the maximum possible  */
    /*  length is given by the constant BUFFER_LENGTH.                        */
    /**************************************************************************/
    TRACE4(TFUNC, "Entry", FNULL, 0);

#ifdef DEBUG_FSM

    OutputString("DevEsc JournalData");

#endif

    /**************************************************************************/
    /*  Take the data pointed to by ArgInData and write to the journal file.  */
    /**************************************************************************/
/*    (VOID)DosWrite(DCIData->DCIDosJrnHnd, (PCHAR)ArgInData,      *
 *                  (unsigned)ArgInCount, (PUSHORT)&BytesWritten); *
 *    ****OLD CODE, Changed parameters of DosWrite****             *
 */
    (VOID)DosWrite(DCIData->DCIDosJrnHnd, (PVOID)ArgInData,
                   ArgInCount, &BytesWritten);
    if (BytesWritten != ArgInCount)
    {
        TRACE4(TFUNC, "Error writing", FNULL, 0);
        return(ERROR_NEG);
    }
    return((SHORT)OK);   /* CON3203 */
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdq_SetMode                                                    */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  ULONG   ArgInCount;   Unused parameter                                    */
/*  PULONG  ArgInData;    Pointer to input data                               */
/*  PULONG  ArgOutCount;  Unused parameter                                    */
/*  PULONG  ArgOutData;   Unused parameter                                    */
/*  lpDCI   DCIData;      Pointer to DC Instance data                         */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  Sets the printer into a particular mode.  Currently the only mode         */
/*  specified is mode 0 which allows the default font codepage to be altered. */
/******************************************************************************/
 SHORT  prdq_SetMode( ULONG   ArgInCount,    /* CON3203 */
                      PULONG  ArgInData,
                      PULONG  ArgOutCount,
                      PUSHORT ArgOutData,
                      lpDCI   DCIData)


{
#define TFUNC "prdq_SetMode"

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

#ifdef DEBUG_FSM

    OutputString("DevEsc SetMode");

#endif

    /**************************************************************************/
    /*  Check the mode.                                                       */
    /**************************************************************************/
    if (!(*((PULONG)ArgInData)))
    {

        /**********************************************************************/
        /*  Mode 0 allows the default font codepage to be altered.            */
        /**********************************************************************/
        TRACE6(TFUNC, "Mode 0", FNULL, 0);
        ArgInData++;
        CodePage = *((PUSHORT)ArgInData);
        TRACE6(TFUNC, "CodePage", &CodePage, 1);

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

        /**********************************************************************/
        /*  If we get a     return code, log an error and exit                */
        /**********************************************************************/
        if (Result == ERROR_ZERO)
            goto SETCP_LOGERR_EXIT;

        /**********************************************************************/
        /*  Otherwise we fall through to SETCP_OK_FAST_EXIT                   */
        /**********************************************************************/
    }
    else
    {

        /**********************************************************************/
        /*  Mode != 0: Log an error.                                          */
        /**********************************************************************/
        TRACE6(TFUNC, "Invalid Mode", ArgInData, 1);
        goto SETCP_LOGERR_EXIT;
    }

SETCP_OK_FAST_EXIT:
    return(OK);

SETCP_LOGWARN_EXIT:

    /**************************************************************************/
    /*  After logging a warning return OK not an error - see prda_SetCodePage */
    /*  for reasons.                                                          */
    /**************************************************************************/
    LOGWARNING(TFUNC, "Invalid code page", FNULL, 0, PMERR_INV_CODEPAGE);
    return(OK);

SETCP_LOGERR_EXIT:
    LOGERR(TFUNC, "Invalid code page", FNULL, 0, PMERR_INV_CODEPAGE);
    return(ERROR_NEG);
}
#undef TFUNC
