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

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

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

#define INCL_WINP_SELECTIVE
#define INCL_WINP_SEI
#include <pmwinx.h>
#undef INCL_WINP_SELECTIVE
#undef INCL_WINP_SEI
#undef INCL_32                          /* Convert to C/SET2    CON3201       */

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

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

#include <prdmtypt.h>
#include <prdupatt.h>

#include <prdeextf.h>
#include <prdaextf.h>
#include <prdgextf.h>
#include <prduextf.h>
#include <prdtextf.h>
#include <prdicone.h>

/******************************************************************************/
/*  FUNCTION: prde_RestoreDC                                                  */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  lpDCI     DCIData;  Pointer to DC Instance data                           */
/*  long int  Count;    The count for accessing an DC in the stack            */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function allows a DC to be restored from the 'stack' of DCs.  Count  */
/*  can be negative or positive indicating either a count from the top or from*/
/*  the bottom of the stack respectively.  All DCs between the restored one   */
/*  and the current one are discarded and their memory allocation freed.      */
/*                                                                            */
/*  CHANGES:                                                                  */
/*                                                                            */
/*  This function should not need any changes to accomodate new fields in the */
/*  DC Instance data as long as the functions called from it allow for these  */
/*  changes.                                                                  */
/******************************************************************************/
#if 0
USHORT pascal prde_RestoreDC(DCIData, Count)

long int  Count;
lpDCI     DCIData;
#endif

SHORT prde_RestoreDC( lpDCI  DCIData,                              /* CON3201 */
                      long   Count )                               /* CON3201 */

{
#define TFUNC "prde_RestoreDC"

    /**************************************************************************/
    /*  Local variables                                                       */
    /**************************************************************************/
    lpDCI     NextDCIData;             /* Next DC instance in stack           */
    lpDCI     OldDCIData;              /* Pointer used to free DC Instance    */
                                       /* data and related data               */
    long int  Pops;                    /* The number of pops required to take */
                                       /* us to the desired DC Instance data  */
    long int  i;                       /* Loop control variable               */
    XFORM     xfmTemp;                 /* PD00073                             */

#ifdef PRD_TIMING
    DEKHOOK0(A,7,4D)
#endif

    prdm_EnterDriver(DCIData);

#ifdef DEBUG_FSM
    OutputString("Enter RestoreDC");
#endif

    TRACE8(TFUNC, "DCIData add",&DCIData,1);
    TRACE8(TFUNC, "Count", &Count, 1);
    TRACE4(TFUNC, "SaveCount", &DCIData->DCISaveCount, 1);

    /**************************************************************************/
    /*  Work out how many pops are required.  A negative number indicates     */
    /*  counting down from the top of the stack so just do abs(Counts) pops.  */
    /*  A positive number indicates counting from bottom of the stack so      */
    /*  subtract this from the number of DCs in the stack (allowing an add in */
    /*  of 1 because the current DC is effectively the top of the stack but it*/
    /*  is not counted in DCISaveCount).                                      */
    /**************************************************************************/
    Pops = 0;
    if (Count <= 0)
    {
        Pops = -Count;
    }
    else
    {
        Pops = DCIData->DCISaveCount + 1 - Count;
    }
    TRACE4(TFUNC, "No pops", &Pops, 1);

    /**************************************************************************/
    /*  See if we can actually do this number of pops.  Note we can only      */
    /*  restore DCs from the stack we can't restore the current DC (ie Pops ==*/
    /*  0).                                                                   */
    /**************************************************************************/
    if ((Pops <= 0) || (Pops > DCIData->DCISaveCount))
    {
        LOGERR(TFUNC, "Invalid Pop", &Pops, 1,PMERR_INV_LENGTH_OR_COUNT);
        prdm_LeaveDriver(DCIData);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,CD)
#endif
     /* return ((USHORT)ERROR_NEG); */
        return ((SHORT)ERROR_NEG);                                 /* CON3201 */
    }

    /**************************************************************************/
    /*  NextDCIData is a pointer to the next DC Instance to be thrown away.   */
    /*  Note we don't throw away the current DC instead we have to throw away */
    /*  as many DCs as is necessary till NextDCIData points to the one we want*/
    /*  and then copy this to the current DC Instance data.  We have to do    */
    /*  this because we can't alter the pointer to the current DC Instance    */
    /*  data from this function so instead we have to alter the current DC    */
    /*  Instance data itself.                                                 */
    /**************************************************************************/
    NextDCIData = DCIData->DCINextEntry;

    /**************************************************************************/
    /*  Now free the memory pointed to by entries in the first DC Instance    */
    /*  (but keep the DCI memory for the new DCI)                             */
    /**************************************************************************/
    (VOID)prde_FreeDCItems(DCIData);

    /******************************************************************/
    /* PD00474 : Mark the pattern as invalid                          */
    /******************************************************************/
    DCIData->usPatValid = FALSE;

    /**************************************************************************/
    /*  "Pop" a DC off the list for the required number of pops, returning the*/
    /*  freed memory to the heap for each pop.  Note that to get the DC on top*/
    /*  of the stack (ie the last one saved) we don't actually need to execute*/
    /*  this loop at all.                                                     */
    /**************************************************************************/
    for (i = 1; i < Pops; i++)
    {
        OldDCIData = NextDCIData;
        NextDCIData = OldDCIData->DCINextEntry;

        /**********************************************************************/
        /*  Call routine to free heap items pointed to from within the DC     */
        /*  Instance data structure.                                          */
        /**********************************************************************/
        TRACE4(TFUNC, "Free DCItems", FNULL, 0);
        (void) prde_FreeDCItems (OldDCIData);

        /**********************************************************************/
        /*  Free the DC Instance data structure.                              */
        /**********************************************************************/
        TRACE4(TFUNC, "Freeheapitem", FNULL, 0);
        (VOID)prdg_FreeHeapItem(OldDCIData, sizeof(DCIType),
                                (PUSHORT)OldDCIData);
    }

    /******************************************************************/
    /* Save the currently active world-device transform (in DCIData). */
    /* PD00073                                                        */
    /******************************************************************/
//  xfmTemp = DCIData->DCITransform;

    /**************************************************************************/
    /*  Make sure we don't lose text or graphics band information in the DC   */
    /*  being overwritten                                                     */
    /**************************************************************************/
    NextDCIData->DCICurrBand.BDTextBand = DCIData->DCICurrBand.BDTextBand;
    NextDCIData->DCICurrBand.BDGraphicsBand =
                                            DCIData->DCICurrBand.BDGraphicsBand;
    NextDCIData->DCICurrBand.BDCoords[0].X = DCIData->DCICurrBand.BDCoords[0].X;
    NextDCIData->DCICurrBand.BDCoords[0].Y = DCIData->DCICurrBand.BDCoords[0].Y;
    NextDCIData->DCICurrBand.BDCoords[1].X = DCIData->DCICurrBand.BDCoords[1].X;
    NextDCIData->DCICurrBand.BDCoords[1].Y = DCIData->DCICurrBand.BDCoords[1].Y;

    /**************************************************************************/
    /*  Make sure that we don't lose the flag that tells us whether this is a */
    /*  text only DC.                                                         */
    /**************************************************************************/
    NextDCIData->TextOnlyDC = DCIData->TextOnlyDC;

    /**************************************************************************/
    /* PD00654 : Make sure we don't loose the page number that lets us know   */
    /* whether we have sent the SIC on the first page.                        */
    /**************************************************************************/
    NextDCIData->DCIPageNumber = DCIData->DCIPageNumber;

    /**************************************************************************/
    /*  FIX : AK 16/5/91 Keep the current DCIData Flasg: DRAWIN_INTO, ABORTED,*/
    /*  etc remain constant over a RestoreDC                                  */
    /**************************************************************************/
    NextDCIData->Flags = DCIData->Flags;

    /**************************************************************************/
    /*  Make sure that we don't lose the heap list                            */
    /**************************************************************************/
    NextDCIData->DCIHeapList = DCIData->DCIHeapList;

    /**************************************************************************/
    /*  And also save the current heap info (as more heaps may have been added*/
    /*  since the save_dc).                                                   */
    /**************************************************************************/
 /* NextDCIData->DCICurrHHeap   = DCIData->DCICurrHHeap;   */
 /* NextDCIData->DCICurrHeapSel = DCIData->DCICurrHeapSel; */
    NextDCIData->DCICurrHeap   = DCIData->DCICurrHeap;             /* CON3201 */

    /**************************************************************************/
    /*  And also save the current pointer to download engine font header      */
    /*  linked list (since more headers may have been added since save DC).   */
    /**************************************************************************/
    NextDCIData->DCIEDFList = DCIData->DCIEDFList;

    /**************************************************************************/
    /*  Also don't lose the SelBitmap                                         */
    /**************************************************************************/
    NextDCIData->DCISelBitmap = DCIData->DCISelBitmap;

    /**************************************************************************/
    /*  AK FIX 4/24/91.  Trap in PTT testcase.                                */
    /*                                                                        */
    /*  Fix: need to retain the Framework State variable - (IMPLICIT,         */
    /*  WAIT_START, etc).  Problem was caused by StartDoc, SaveDC, EndDoc,    */
    /*  RestoreDC, BeginCloseDC.  BeginClose is in the       state.           */
    /**************************************************************************/
    NextDCIData->State = DCIData->State;

    /**************************************************************************/
    /*  Finally, copy the new DC instance to the memory previously occupied by*/
    /*  the current DC prior to this Restore call.  Note that all the data    */
    /*  hung from this DC has not been freed so the hung data is still valid. */
    /**************************************************************************/
    prdu_memcpy((PBYTE) DCIData, (PBYTE) NextDCIData, (USHORT) sizeof(DCIType));

    /******************************************************************/
    /* Only rescale the character box if the world-device scaling is  */
    /* different. Ignore origin changes. Possibly ignore rotation/    */
    /* shearing.                                                      */
    /* PD00073 .                                                      */
    /******************************************************************/
#if 0
//  if ( prdg_MatrixScaleDifferent( DCIData->DCITransform, xfmTemp ) )
//  {
//      /**************************************************************/
//      /* Need to rescale the Character Box.                         */
//      /* Use old and new transforms to calculate new transform.     */
//      /* This routine also used in NotifyTransformChange,           */
//      /**************************************************************/
//      prdt_RescaleCharBox( DCIData, DCIData->DCITransform, xfmTemp );
//  }
//
//  DCIData->DCITransform = xfmTemp;
#endif

    /**************************************************************************/
    /*  Code page may have changed.  If so we need to make sure the code page */
    /*  of the default font (in PrinterData which does not get restored)      */
    /*  matches DCIData->DCICodePage of the DC being restored.  Note - not for*/
    /*  memory DC; there are no device fonts in this case                     */
    /**************************************************************************/
    if (DCIData->DCIDCType != OD_MEMORY)
    {
        if (!(DCIData->DCIDefTxtAts->cdef.fFlags & CDEF_GENERIC))
        {

            /******************************************************************/
            /*  Device font is not system font.                               */
            /******************************************************************/
            (VOID)prda_FindDeviceCodePage(DCIData->DCICodePage, DCIData,
                                          &DCIData->DCIPdbInstance->DfltFont);
        }

        /**********************************************************************/
        /*  Default device font                                               */
        /**********************************************************************/
        (VOID)prda_FindDeviceCodePage(DCIData->DCICodePage, DCIData,
                                      &DCIData->DCIPdbInstance->DfltDeviceFont);
    }

    /**************************************************************************/
    /*  PD00065 : Now let's ensure that the font we think we have is indeed   */
    /*  the font we have...                                                   */
    /**************************************************************************/
    (VOID)prdt_LocateFont(&DCIData->DCIFontData, DCIData);

    /**************************************************************************/
    /*  And throw away the memory the new DC was occupying (but not the memory*/
    /*  the hung items were occupying as these form part of the new current   */
    /*  DC.                                                                   */
    /**************************************************************************/
    (VOID)prdg_FreeHeapItem(NextDCIData, sizeof(DCIType),
                            (PUSHORT)NextDCIData);
    TRACE4(TFUNC, "Pattern", DCIData->DCICurPtnAts, 12);
    TRACE4(TFUNC, "Return OK", FNULL, 0);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,CD)
#endif
    prdm_LeaveDriver(DCIData);
    return(OK);
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prde_FreeDCItems                                                */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  lpDCI  DCIData;  Pointer to DC Instance data                              */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function frees items in the DC Instance data which are attached to   */
/*  the DC Instance data by pointers.  It does not free the DC Instance data  */
/*  structure itself.                                                         */
/*                                                                            */
/*  CHANGES:                                                                  */
/*                                                                            */
/*  This function will have to be able to free any extra bits of data hung    */
/*  from the DC Instance data.                                                */
/******************************************************************************/
#if 0
VOID pascal prde_FreeDCItems(DCIData)

lpDCI   DCIData;
#endif

VOID prde_FreeDCItems(lpDCI DCIData)                               /* CON3201 */

{
#define TFUNC "prde_FreeDCItems"

    /**************************************************************************/
    /*  Free the text attribute bundle                                        */
    /**************************************************************************/
    TRACE4(TFUNC, "return addr", &(DCIData->DCICurTxtAts), 1);
    (VOID)prdg_FreeHeapItem(DCIData, sizeof(DCHARBUNDLE),
                            (PUSHORT)(DCIData->DCICurTxtAts));

    /**************************************************************************/
    /*  Free the line attribute bundle                                        */
    /**************************************************************************/
    TRACE4(TFUNC, "return addr", &(DCIData->DCICurLinAts), 1);
    (VOID)prdg_FreeHeapItem(DCIData, sizeof(DLINEBUNDLE),
                            (PUSHORT)(DCIData->DCICurLinAts));

    /******************************************************************/
    /* Free the marker attribute bundle                               */
    /******************************************************************/
    TRACE4(TFUNC, "return addr", &(DCIData->DCICurMrkAts), 1);
    (VOID)prdg_FreeHeapItem(DCIData, sizeof(DMARKERBUNDLE),
                            (PUSHORT)(DCIData->DCICurMrkAts));

    /******************************************************************/
    /* Free the pattern attribute bundle                              */
    /******************************************************************/
    TRACE4(TFUNC, "return addr", &(DCIData->DCICurPtnAts), 1);
    (VOID)prdg_FreeHeapItem(DCIData, sizeof(DAREABUNDLE),
                            (PUSHORT)(DCIData->DCICurPtnAts));

    /******************************************************************/
    /* Free the image attribute bundle                                */
    /******************************************************************/
    TRACE4(TFUNC, "return addr", &(DCIData->DCICurImgAts), 1);
    (VOID)prdg_FreeHeapItem(DCIData, sizeof(DIMAGEBUNDLE),
                            (PUSHORT)(DCIData->DCICurImgAts));

    /**************************************************************************/
    /*  Free the color table (if there was one).  This is not done in the new */
    /*  framework, as we allocate this just once, at EnableDC time.           */
    /**************************************************************************/
#if 0
//    if (DCIData->DCIColFormat != LCOLF_RGB)
//    {
//        TRACE4(TFUNC,"return addr",&(DCIData->DCIColorTable),1);
//        (VOID)prdg_FreeHeapItem(DCIData,
//                             DCIData->DCIColTabSize * sizeof(ColorTableType),
//                             (unsigned far *)&(DCIData->DCIColorTable));
//    }
#endif
    /**************************************************************************/
    /*  Free the memory for the clip rectangles.                              */
    /**************************************************************************/
    (VOID)prdg_FreeHeapItem(DCIData, MAX_CLIP_RECTS * sizeof(ClipRectangle),
                            (PUSHORT)(DCIData->DCIClipRects));
    return;
}
#undef TFUNC
