/*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 = PRDBSELE
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prdb_DeviceSelectBitmap
 *
 * 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_GPIERRORS
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#include <os2.h>
#undef INCL_DOSPROCESS                  /* Convert to C/SET2    CON3201       */
#undef INCL_DOSSEMAPHORES
#undef INCL_GPIERRORS
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS

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

#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>

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

#include <prdaextf.h>
#include <prdiextf.h>
#include <prdbtyp1.h>
#include <prdbextf.h>
#include <prdgextf.h>
#include <prdyextf.h>
#include <prdbsize.h>

/* extern PFSRSEM pBMLockSem;     CON3201 */
extern HMTX     hmtxBMLockSem; /* CON3201 */

#define TFUNC "prdb_DevSelectBM"
/******************************************************************************/
/*  FUNCTION: prdb_DeviceSelectBitmap                                         */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  See "OS/2 Technical Reference: I/O Subsytems and Device Drivers"          */
/*                                                                            */
/*  hanDC  DcH;                                                               */
/*  PBYTE  ArgHandle;                                                         */
/*  lpDCI  DCIData;                                                           */
/*  ULONG  FunN;                                                              */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function selects a new bitmap into the DC (or if ArgHandle is NULL   */
/*  just deselects the currently selected bitmap).                            */
/******************************************************************************/
ULONG EXPENTRY prdb_DeviceSelectBitmap( hanDC            DcH,
                                        BitmapListEntry *ArgHandle,
                                        lpDCI            DCIData,
                                        ULONG            FunN )

{
    /**************************************************************************/
    /*  Local variables                                                       */
    /**************************************************************************/
/*  BitmapListEntry far *ListEntry;       Pointers for accessing              */
/*  BitmapListEntry far *OldEntry;        bitmap list                         */
    BitmapListEntry     *ListEntry;    /* Pointers for accessing     CON3201  */
    BitmapListEntry     *OldEntry;     /* bitmap list                CON3201  */


    /**************************************************************************/
    /*  Trace the function parameters                                         */
    /**************************************************************************/
    TRACE8("prdbSelect", "FuncNo", &FunN, 1);
    TRACE8("prdbSelect", "DcH", &DcH, 1);
    TRACE8("prdbSelect", "Handle", &ArgHandle, 1);
    TRACE8("prdbSelect", "DCIData", &DCIData, 1);


    /**************************************************************************/
    /*  If this is not a memory DC then it is an error to select a bitmap into*/
    /*  it.                                                                   */
    /**************************************************************************/
    if (DCIData->DCIDCType != OD_MEMORY)
    {
      LOGERR("prdbSelect", "Not Memory DC", FNULL, 0,PMERR_INV_FOR_THIS_DC_TYPE);
      return(ERROR_ZERO);
    }

    /******************************************************************/
    /* Do entry processsing                                           */
    /******************************************************************/
#ifdef PRD_TIMING
    DEKHOOK0(A,7,63)
#endif
    prdm_EnterDriver(DCIData);

    if (ArgHandle == FNULL)
    {

        /**********************************************************************/
        /*  The bitmap handle we are given is NULL indicating that we should  */
        /*  simply deselect the currently selected bitmap.                    */
        /**********************************************************************/
        TRACE4("prdbSelect", "Null handle/Deselect", FNULL, 0);
        if (ListEntry = (pBMListEntry)DCIData->DCISelBitmap)
        {

            /******************************************************************/
            /*  The DC has a currently selected bitmap to deselect.           */
            /******************************************************************/
            TRACE4("prdbSelect", "Selected Bitmap", FNULL, 0);

            /******************************************************************/
            /*  Remove the association with the DC in the bitmap list entry   */
            /*  data and reset the DC origin to default                       */
            /******************************************************************/
            ListEntry->DCHandle = NULL;
            ListEntry->XOrigin  = 0;
            ListEntry->YOrigin  = 0;

            /******************************************************************/
            /*  deselect the bitmap                                           */
            /******************************************************************/
            DCIData->DCISelBitmap = NULL;
            prdm_LeaveDriver(DCIData);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,E3)
#endif
            return (OK);
        }
        else
        {
            /******************************************************************/
            /*  There is no bitmap selected in the DC Instance data.  Treat as*/
            /*  a noop and just return OK.                                    */
            /******************************************************************/
            prdm_LeaveDriver(DCIData);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,E3)
#endif
            return (OK);
        }
    }
    else
    {
        /**********************************************************************/
        /*  The bitmap handle is not null so we must select a new bitmap as   */
        /*  well as deselecting the current one.                              */
        /**********************************************************************/
/*      FSRSemEnter(hmtxBMLockSem);    CON3201 */
        DosRequestMutexSem(hmtxBMLockSem, SEM_INDEFINITE_WAIT);
        if (!(ListEntry = ArgHandle))
        {

            /******************************************************************/
            /*  We can't find a bitmap with that handle so log and return an  */
            /*  error.                                                        */
            /******************************************************************/
/*          FSRSemLeave(hmtxBMLockSem);  CON3201 */
            DosReleaseMutexSem(hmtxBMLockSem);
            prdm_LeaveDriver(DCIData);
            LOGERR("prdbSelect", "Bitmap not found", FNULL, 0,PMERR_INV_HBITMAP);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,E3)
#endif
            return(ERROR_ZERO);
        }
        if (ListEntry->DCHandle != NULL)
        {

            /******************************************************************/
            /*  This bitmap is already selected into a DC                     */
            /******************************************************************/
            TRACE4("prdbSelect", "Already Selected", FNULL, 0);
            if (ListEntry->DCHandle == DCIData)
            {

                /**************************************************************/
                /*  It is selected into the one we want to select it into so  */
                /*  everyone's happy - return OK                              */
                /**************************************************************/
                TRACE4("prdbSelect", "in right DC", FNULL, 0);
/*              FSRSemLeave(hmtxBMLockSem);     CON3201 */
                DosReleaseMutexSem(hmtxBMLockSem);
                prdm_LeaveDriver(DCIData);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,E3)
#endif
                return(OK);
            }
            else
            {
                /**************************************************************/
                /*  It is selected into another DC so log and return an error.*/
                /**************************************************************/
                LOGERR("prdbSelect", "in wrong DC", FNULL, 0,
                       PMERR_BITMAP_IN_USE);
/*              FSRSemLeave(hmtxBMLockSem);   CON3201 */
                DosReleaseMutexSem(hmtxBMLockSem);
                prdm_LeaveDriver(DCIData);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,E3)
#endif
                return (ERROR_ZERO);
            }
        }

        /**********************************************************************/
        /*  now lock this new bitmap                                          */
        /**********************************************************************/
        if (ListEntry->BMLocked)
        {
/*          FSRSemLeave(hmtxBMLockSem); CON3201 */
            DosReleaseMutexSem(hmtxBMLockSem);
            LOGERR("prdbDelete", "bitmap locked", FNULL, 0,PMERR_BITMAP_IN_USE);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,E3)
#endif
            return (ERROR_ZERO);
        }
        ListEntry->BMLocked = TRUE;
/*      FSRSemLeave(hmtxBMLockSem);     CON3201 */
        DosReleaseMutexSem(hmtxBMLockSem);
        if (DCIData->DCISelBitmap != NULL)
        {

            /******************************************************************/
            /*  A bitmap is already selected for this DC so deselect it       */
            /******************************************************************/
            TRACE4("prdbSelect", "Other Bitmap selected",
               &DCIData->DCISelBitmap, 1);

            /******************************************************************/
            /*  Get the bitmap list entry for the currently selected bitmap   */
            /*  and remove the association with this DC.                      */
            /******************************************************************/
            OldEntry = (pBMListEntry)DCIData->DCISelBitmap;
            OldEntry->DCHandle = NULL;
            OldEntry->XOrigin  = 0;
            OldEntry->YOrigin  = 0;
        }
        TRACE4("prdbSelect", "Select this Bitmap", FNULL, 0);

        /**********************************************************************/
        /*  Select the given bitmap into this DC.                             */
        /**********************************************************************/
        DCIData->DCISelBitmap = (PBYTE)ArgHandle;

        /**********************************************************************/
        /*  Associate the bitmap with this DC.                                */
        /**********************************************************************/
        ListEntry->DCHandle = DCIData;

        /**********************************************************************/
        /*  the new bitmap has been selected so it can now be unlocked        */
        /**********************************************************************/
        ListEntry->BMLocked = FALSE;

        /**********************************************************************/
        /*  set the DC origin                                                 */
        /**********************************************************************/
        ListEntry->XOrigin = DCIData->DCIOrigin.X;
        ListEntry->YOrigin = DCIData->DCIOrigin.Y;

        /**********************************************************************/
        /*  Update the current band parameters for this DC to be the size of  */
        /*  this bitmap.                                                      */
        /**********************************************************************/
        DCIData->DCICurrBand.BDCoords[0].X  = 0;
        DCIData->DCICurrBand.BDCoords[0].Y  = 0;
        DCIData->DCICurrBand.BDCoords[1].X  = (USHORT) ListEntry->Parms.Width;
        DCIData->DCICurrBand.BDCoords[1].Y  = (USHORT) ListEntry->Parms.Height;

        /**********************************************************************/
        /*  Set up the GraphicsBand and TextBand pointers in the DC Instance  */
        /*  data.                                                             */
        /**********************************************************************/
        DCIData->DCICurrBand.BDGraphicsBand = (PBYTE)ListEntry;
        DCIData->DCICurrBand.BDTextBand     = FNULL;
        TRACE4("prdbSelect", "Band Coords", DCIData->DCICurrBand.BDCoords,2);

        /**********************************************************************/
        /*  Select the default clip region                                    */
        /**********************************************************************/
        (VOID)prdi_DefaultClip(DCIData);
        prdm_LeaveDriver(DCIData);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,E3)
#endif
        return (OK);
    }
}
#undef TFUNC
