/*DDK*************************************************************************/
/*                                                                           */
/* 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.                                */
/*                                                                           */
/*****************************************************************************/
// bitmap.c

#define INCL_DOS
#define INCL_PM
#define INCL_GPI
#include <os2.h>

#define INCL_GRE_DCS
#define INCL_DDIMISC
#define INCL_GRE_DEVSUPPORT
#define INCL_DDICOMFLAGS
#define INCL_GRE_BITMAPS
#include <pmddi.h>

// c includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <builtin.h>

#define INCL_INNER_GRE
#include "def.h"
#include "driver.h"
#include "funcs.h"
#include "assert.h"



// --------------------------------------------------------------------------------------------------------------------
LONG ENGENTRY Bitblt(                   HDC            hdc,
                                        HDC            hdcSource,
                                        LONG           cPoints,
                                        PPOINTL        paPoints,
                                        LONG           lRop,
                                        ULONG          flOptions,
                                        PBITBLTATTRS   pAttrs,
                                        PDDC           pddc,
                                        ULONG          ulFunction )
{
  REGREC      regrec;
  ULONG       ulException;
  ULONG       lrc;
  HBITMAP     hbmDisplay;
  PDDC        pddcSrc;


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    // clean up here
    assert( FALSE );
    CheckForTermination( &regrec, ulException, pddc );
    // error result
    lrc = GPI_ERROR;
    goto depart;
  }
  ENTERDDC( pddc );


  assert( hdcSource );


  if (hdcSource) {
    if (flOptions & BLTMODE_SRC_BITMAP) {
      // hdcSource is really a bitmap handle
      hbmDisplay = (HBITMAP) GetDriverInfo( (HBITMAP) hdcSource, 1, hdc );
      if( hbmDisplay != (HBITMAP)GPI_ALTERROR ) {
        // it belongs to this print driver; modify the one on the stack for the innergre call below
        hdcSource = (HDC) hbmDisplay;
      }
    }
    else
    {
      // hdcSource is really a DC pointer
      pddcSrc = (PDDC) GetDriverInfo( hdcSource, 0, hdc );
      if( pddcSrc != (PDDC)GPI_ALTERROR ) {
        // it belongs to this print driver; modify the one on the stack for the innergre call below
        hdcSource = pddcSrc->hdcShadow;
      }
    }
  }

  lrc = InnerGreBitblt( pddc->hdcShadow, hdcSource, cPoints, paPoints, lRop, flOptions, pAttrs, ulFunction );
  assert( lrc != GPI_ERROR );


depart:
  EXITDDC( pddc );
  UNREGISTERHANDLER( regrec );
  return lrc;
}

// --------------------------------------------------------------------------------------------------------------------
LONG ENGENTRY DeviceCreateBitmap(       HDC               hdc,
                                        PBITMAPINFOHEADER pInfoHeader,
                                        ULONG             flUsage,
                                        PBYTE             pBitmapBits,
                                        PBITMAPINFO       pInfo,
                                        PDDC              pddc,
                                        ULONG             ulFunction )
{
  REGREC      regrec;
  ULONG       ulException;
  LONG        lrc;


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    // clean up here
    assert( FALSE );
    CheckForTermination( &regrec, ulException, pddc );
    // error result
    lrc = GPI_ERROR;
    goto depart;
  }
  ENTERDDC( pddc );

  lrc = InnerGreCreateBitmap( pddc->hdcShadow, pInfoHeader, flUsage, pBitmapBits, pInfo, ulFunction );
  assert( lrc != GPI_ERROR );

depart:
  EXITDDC( pddc );
  UNREGISTERHANDLER( regrec );
  return lrc;
}

// --------------------------------------------------------------------------------------------------------------------
// pddc and hdc supplied on this call are not valid to reference;
// application probably has closed DC without deleting bitmap. If
// the CBM_INIT flag is set, engine expects the driver to allocate engine
// shared memory and place the bits and the bitmap info header
// there.  Engine will subsequently free the SS alloc.


LONG ENGENTRY DeviceDeleteBitmap(       HDC            hdc,
                                        ULONG          hbm,
                                        PDELETERETURN  pdr,
                                        ULONG          flOptions,
                                        PDDC           pddc,
                                        ULONG          ulFunction )
{
  REGREC              regrec;
  ULONG               ulException;
  ULONG               ul;
  LONG                lrc;
  BITMAPINFOHEADER    bmi;
  PBITMAPINFOHEADER2  pInfo = NULL;
  ULONG               ulSize;
  PCHAR               pBits = NULL;
  HDC                 hdcMemory;


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    // clean up here
    if( pInfo ) {
      SSFreeMem( pInfo );
      pInfo = NULL;
    }
    if( pBits ) {
      SSFreeMem( pBits );
      pBits = NULL;
    }

    // check for the killed-thread case
    switch( ulException ) {
    case XCPT_PROCESS_TERMINATE:
    case XCPT_ASYNC_PROCESS_TERMINATE:
      DosUnsetExceptionHandler( (PEXCEPTIONREGISTRATIONRECORD)&regrec );
      DosExit( EXIT_THREAD, 0 );
    }
    // error result
    lrc = FALSE;
    goto depart;
  }


  assert( pddc == NULL );



  if( flOptions & CBM_INIT ) {
    // determine the bitmap format
    bmi.cbFix = sizeof( BITMAPINFOHEADER );
    if( !GreGetBitmapParameters( hbm, &bmi )) {
      // clean up and return an error result
      RAISEEXCEPTION( XCPT_USER );
    }

    // compute how many extra bytes needed to hold the RGB structs
    if( bmi.cBitCount == 24 ) {
        ulSize = 0;
    } else {
        ulSize = sizeof(RGB2) * (1 << bmi.cBitCount);
    }

    // allocate memory for bitmap info table; don't need a full BITMAPINFO2 structure, just first 5 fields
    // need 16 bytes for cbFix, cx, cy, cPlanes, cBitCount
    ul = SSAllocMem( &pInfo, 16 + ulSize, 0  );
    if( ul ) {
      // clean up and return an error result
      RAISEEXCEPTION( XCPT_USER );
    }

    // fill in the parameters in BITMAPINFO structure
    pInfo->cbFix     = 16;
    pInfo->cx        = bmi.cx;
    pInfo->cy        = bmi.cy;
    pInfo->cPlanes   = bmi.cPlanes;
    pInfo->cBitCount = bmi.cBitCount;

    // compute size of memory required for the bits and allocate it
    ulSize = (((bmi.cx * bmi.cBitCount + 31) >> 5) << 2) * bmi.cy;
    ul = SSAllocMem( &pBits, ulSize, 0 );
    if( ul ) {
      // clean up and return an error result
      RAISEEXCEPTION( XCPT_USER );
    }

    // to complete this operation, I must have a DC from which to select the bitmap and get bits
    hdcMemory = GreOpenDC( (HDC)0, OD_MEMORY, "*", 0, (PDEVOPENDATA) NULL );
    assert( hdcMemory );

    // select the bitmap into display memory dc
    ul = GreSelectBitmap( hdcMemory, hbm );
    assert( ul != (ULONG)HBM_ERROR );


    // get the bits from the bitmap; getbitmapbits returns the number of scanlines gotten
    ul = GreGetBitmapBits( hdcMemory, hbm, 0, bmi.cy, pBits, pInfo );
    assert( ul == bmi.cy );

    // deselect the bitmap
    GreSelectBitmap( hdcMemory, (HBITMAP)0  );

    // close the display OD_MEMORY  DC
    GreCloseDC( hdcMemory );

    // delete the engine bitmap
    ul = InnerGreDeleteBitmap( hbm, ulFunction );
    if( !ul ) {
      // clean up and return error result
      RAISEEXCEPTION( XCPT_USER );
    }

    // return bitmapinfo and bits to the graphics engine; GRE frees pInfo and pBits
    pdr->pInfo = (ULONG)pInfo ;
    pdr->pBits = (ULONG)pBits ;

    lrc = TRUE;

  } else {
    lrc = InnerGreDeleteBitmap( hbm, ulFunction );
    assert( lrc );
  }

depart:
  UNREGISTERHANDLER( regrec );
  return lrc;
}



// --------------------------------------------------------------------------------------------------------------------
LONG ENGENTRY DeviceSelectBitmap(       HDC            hdc,
                                        ULONG          hbm,
                                        PDDC           pddc,
                                        ULONG          ulFunction )
{
  REGREC      regrec;
  ULONG       ulException;
  LONG        lrc;


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    // clean up here
    assert( FALSE );
    CheckForTermination( &regrec, ulException, pddc );
    // error result
    lrc = FALSE;
    goto depart;
  }
  ENTERDDC( pddc );


  lrc = InnerGreSelectBitmap( pddc->hdcShadow, hbm, ulFunction );
  if( lrc == (LONG)HBM_ERROR ) {
    lrc = FALSE;
  } else {
    lrc = TRUE;
  }

depart:
  EXITDDC( pddc );
  UNREGISTERHANDLER( regrec );
  return lrc;
}

// --------------------------------------------------------------------------------------------------------------------
LONG ENGENTRY DrawBits(                 HDC            hdc,
                                        PBYTE          pBitmapBits,
                                        PBITMAPINFO    pInfo,
                                        LONG           cPoints,
                                        PPOINTL        paPoints,
                                        LONG           lRop,
                                        ULONG          flOptions,
                                        PDDC           pddc,
                                        ULONG          ulFunction )
{
  REGREC      regrec;
  ULONG       ulException;
  LONG        lrc;


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    // clean up here
    assert( FALSE );
    CheckForTermination( &regrec, ulException, pddc );
    // error result
    lrc = GPI_ERROR;
    goto depart;
  }
  ENTERDDC( pddc );

  lrc = InnerGreDrawBits( pddc->hdcShadow, pBitmapBits, pInfo, cPoints, paPoints, lRop, flOptions, ulFunction );
  assert( lrc != GPI_ERROR );

depart:
  EXITDDC( pddc );
  UNREGISTERHANDLER( regrec );
  return lrc;
}

// --------------------------------------------------------------------------------------------------------------------
LONG ENGENTRY DrawBorder(               HDC            hdc,
                                        PRECTL         prectl,
                                        ULONG          cxBorder,
                                        ULONG          cyBorder,
                                        LONG           clrBorder,
                                        LONG           clrInterior,
                                        ULONG          flCmd,
                                        PDDC           pddc,
                                        ULONG          ulFunction )
{
  REGREC      regrec;
  ULONG       ulException;
  LONG        lrc;


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    // clean up here
    assert( FALSE );
    CheckForTermination( &regrec, ulException, pddc );
    // error result
    lrc = FALSE;
    goto depart;
  }
  ENTERDDC( pddc );


  lrc = InnerGreDrawBorder( pddc->hdcShadow,prectl, cxBorder, cyBorder, clrBorder, clrInterior, flCmd, ulFunction );
  assert( lrc );

depart:
  EXITDDC( pddc );
  UNREGISTERHANDLER( regrec );
  return lrc;
}

// --------------------------------------------------------------------------------------------------------------------
LONG ENGENTRY GetBitmapBits(            HDC            hdc,
                                        ULONG          hbm,
                                        LONG           lScanStart,
                                        LONG           lScanCount,
                                        PBYTE          pBitmapBits,
                                        PBITMAPINFO    pInfo,
                                        PDDC           pddc,
                                        ULONG          ulFunction )
{
  REGREC      regrec;
  ULONG       ulException;
  LONG        lrc;
  HBITMAP     hbmDisplay;


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    // clean up here
    assert( FALSE );
    CheckForTermination( &regrec, ulException, pddc );
    // error result
    lrc = GPI_ALTERROR;
    goto depart;
  }
  ENTERDDC( pddc );


  if( hbm ) {
    // get the bitmap handle of our shadow DC
    hbmDisplay = GetDriverInfo( hbm, 1, hdc );
    assert( hbmDisplay != (HBITMAP)GPI_ALTERROR );
    if( hbmDisplay != (HBITMAP)GPI_ALTERROR ) {
      lrc = InnerGreGetBitmapBits( pddc->hdcShadow, hbmDisplay, lScanStart, lScanCount, pBitmapBits, pInfo, ulFunction );
    } else {
      lrc = GPI_ALTERROR;
    }
  } else {
    // uses bitmap already selected into the DC
    lrc = InnerGreSetBitmapBits( pddc->hdcShadow, hbm, lScanStart, lScanCount, pBitmapBits, pInfo,  ulFunction );
    assert( lrc != (LONG)GPI_ALTERROR );
  }

depart:
  EXITDDC( pddc );
  UNREGISTERHANDLER( regrec );
  return lrc;
}

// --------------------------------------------------------------------------------------------------------------------
LONG ENGENTRY GetPel(                   HDC            hdc,
                                        PPOINTL        pPel,
                                        PDDC           pddc,
                                        ULONG          ulFunction )
{
  REGREC      regrec;
  ULONG       ulException;
  LONG        lrc;


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    // clean up here
    assert( FALSE );
    CheckForTermination( &regrec, ulException, pddc );
    // error result
    lrc = FALSE;
    goto depart;
  }
  ENTERDDC( pddc );


  lrc = InnerGreGetPel( pddc->hdcShadow, pPel, ulFunction );

depart:
  EXITDDC( pddc );
  UNREGISTERHANDLER( regrec );
  return lrc;
}

// --------------------------------------------------------------------------------------------------------------------
LONG ENGENTRY ImageData(                HDC            hdc,
                                        PBYTE          pData,
                                        LONG           cBits,
                                        ULONG          ulRowOffset,
                                        PDDC           pddc,
                                        ULONG          ulFunction )
{
  REGREC      regrec;
  ULONG       ulException;
  LONG        lrc;


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    // clean up here
    assert( FALSE );
    CheckForTermination( &regrec, ulException, pddc );
    // error result
    lrc = GPI_ERROR;
    goto depart;
  }
  ENTERDDC( pddc );

  lrc = InnerGreImageData( pddc->hdcShadow, pData, cBits, ulRowOffset, ulFunction );
  assert( lrc != GPI_ERROR );

depart:
  EXITDDC( pddc );
  UNREGISTERHANDLER( regrec );
  return lrc;
}

// --------------------------------------------------------------------------------------------------------------------
LONG ENGENTRY SetBitmapBits(            HDC            hdc,
                                        ULONG          hbm,
                                        LONG           lScanStart,
                                        LONG           lScanCount,
                                        PBYTE          pBitmapBits,
                                        PBITMAPINFO    pInfo,
                                        PDDC           pddc,
                                        ULONG          ulFunction )
{
  REGREC      regrec;
  ULONG       ulException;
  LONG        lrc;
  HBITMAP     hbmDisplay;


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    // clean up here
    assert( FALSE );
    CheckForTermination( &regrec, ulException, pddc );
    // error result
    lrc = GPI_ALTERROR;
    goto depart;
  }
  ENTERDDC( pddc );




  if( hbm ) {
    // get the bitmap handle of our shadow DC
    hbmDisplay = GetDriverInfo( hbm, 1, hdc );
    assert( hbmDisplay != (HBITMAP)GPI_ALTERROR );
    if (hbmDisplay != (HBITMAP)GPI_ALTERROR ) {
      lrc = InnerGreSetBitmapBits( pddc->hdcShadow, hbmDisplay, lScanStart, lScanCount, pBitmapBits, pInfo, ulFunction );
    } else {
      lrc = GPI_ALTERROR;
    }
  } else {
    // uses bitmap already selected into the DC
    lrc = InnerGreSetBitmapBits( pddc->hdcShadow, hbm, lScanStart, lScanCount, pBitmapBits, pInfo,  ulFunction );
    assert( lrc != (LONG)GPI_ALTERROR );
  }

depart:
  EXITDDC( pddc );
  UNREGISTERHANDLER( regrec );
  return lrc;
}

// --------------------------------------------------------------------------------------------------------------------
LONG ENGENTRY SetPel(                   HDC            hdc,
                                        PPOINTL        pPel,
                                        PDDC           pddc,
                                        ULONG          ulFunction )
{
  REGREC      regrec;
  ULONG       ulException;
  LONG        lrc;


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    // clean up here
    assert( FALSE );
    CheckForTermination( &regrec, ulException, pddc );
    // error result
    lrc = GPI_ERROR;
    goto depart;
  }
  ENTERDDC( pddc );

  lrc = InnerGreSetPel( pddc->hdcShadow, pPel, ulFunction );
  assert( lrc != GPI_ERROR );

depart:
  EXITDDC( pddc );
  UNREGISTERHANDLER( regrec );
  return lrc;
}

