#include <WinTen.h>
#include <Windows.h>
#include <ClipApi.h>

#define PALVERSION 0x0300   // Windows 3.0 and later

void RegisterResource( HANDLE hResource, LPSTR szType );

typedef FAR * FARP;

HANDLE _fwAddGlobal( HGLOBAL hMem );         // HandList.c
void   _fwDelGlobal( HGLOBAL hMem );

//----------------------------------------------------------------------------//

HGLOBAL DibRead( LPSTR szDibName )
{
   HFILE   hFile;
   LONG    lSize;
   HGLOBAL hDib = 0;
   BITMAPFILEHEADER Header;

   if( hFile = _lopen( szDibName, READ ) )
   {
      if( hDib = GlobalAlloc( GMEM_MOVEABLE | GMEM_DISCARDABLE,
                              lSize = _llseek( hFile, 0, 2 ) ) )
      {
         _llseek( hFile, 0, 0 );
         _lread( hFile, &Header, sizeof( BITMAPFILEHEADER ) );
         _hread( hFile, GlobalLock( hDib ),
                 lSize - sizeof( BITMAPFILEHEADER ) );

         GlobalUnlock( hDib );
      }
      _lclose( hFile );
   }
   return hDib;
}

//---------------------------------------------------------------------------//

WORD far pascal wDIBColors( LPBITMAPINFOHEADER lpBmp )
{
   WORD wBitCount;
   DWORD dwClrUsed;

   if( lpBmp )
   {
      if( lpBmp->biClrUsed )
          return (WORD) lpBmp->biClrUsed;

      wBitCount = lpBmp->biBitCount;

      switch( wBitCount )
      {
         case 1:
            return 2;

         case 4:
            return 16;

         case 8:
            return 256;

         default:
            return 0;
      }
   }
   else
      return 0;
}

//---------------------------------------------------------------------------//

LPSTR DibBits( LPBITMAPINFOHEADER lpBmp )
{
    LPSTR lpBits;
    WORD  wColors = wDIBColors( lpBmp );

    lpBits  = ( (LPSTR) lpBmp ) + (WORD) lpBmp->biSize;
    lpBits += wColors * sizeof( RGBQUAD );

    return lpBits;
}

//---------------------------------------------------------------------------//

HPALETTE CreateDIBPalette ( HGLOBAL hDIB )
{
   LPLOGPALETTE     lpPal;
   HANDLE           hLogPal;
   HPALETTE         hPal = NULL;
   int              i, wNumColors;
   LPSTR            lpbi;
   LPBITMAPINFO     lpbmi;

   if (!hDIB)
      return NULL;

   lpbi         = GlobalLock (hDIB);
   lpbmi        = (LPBITMAPINFO) lpbi;
   wNumColors   = wDIBColors ( (LPBITMAPINFOHEADER) lpbi );

   if( wNumColors )
   {
      hLogPal = GlobalAlloc ( GHND, sizeof (LOGPALETTE) +
                             sizeof (PALETTEENTRY) * wNumColors );

      if( !hLogPal )
      {
         GlobalUnlock (hDIB);
         return NULL;
      }

      lpPal = (LPLOGPALETTE) GlobalLock ( hLogPal );

      lpPal->palVersion    = PALVERSION;
      lpPal->palNumEntries = wNumColors;

      for (i = 0;  i < wNumColors;  i++)
      {
          lpPal->palPalEntry[i].peRed   = lpbmi->bmiColors[i].rgbRed;
          lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
          lpPal->palPalEntry[i].peBlue  = lpbmi->bmiColors[i].rgbBlue;
          lpPal->palPalEntry[i].peFlags = 0;
      }

      hPal = CreatePalette ( lpPal );
      RegisterResource( hPal, "PAL" );

      GlobalUnlock ( hLogPal );
      GlobalFree   ( hLogPal );
   }

   GlobalUnlock ( hDIB );

   return hPal;

}

//---------------------------------------------------------------------------//

BOOL DibDraw( HDC hDC, HGLOBAL hDib, WORD wCol, WORD wRow,
              HPALETTE hPalette, WORD wWidth, WORD wHeight )
{
    LPBITMAPINFOHEADER lpBmp;
    LPSTR              lpBits;
    HPALETTE           oldPal = (HPALETTE) 0;
    HBITMAP            hBmpOld;

    lpBmp = ( LPBITMAPINFOHEADER ) GlobalLock( hDib );

    if( lpBmp )
    {
       lpBits = DibBits(lpBmp);

       if( hPalette )
       {
          oldPal = SelectPalette( hDC, hPalette, FALSE);
          RealizePalette( hDC );
       }

        if( ( wWidth == 0 ) || ( wHeight == 0 ) )
           SetDIBitsToDevice( hDC, wCol, wRow, lpBmp->biWidth,
                              lpBmp->biHeight, 0, 0, 0,
                              lpBmp->biHeight, lpBits, lpBmp, DIB_RGB_COLORS );
        else
           StretchDIBits( hDC, wCol, wRow, wWidth, wHeight,
                          0, 0, lpBmp->biWidth, lpBmp->biHeight,
                          lpBits, lpBmp, DIB_RGB_COLORS, SRCCOPY );

        if( oldPal )
        {
           SelectPalette( hDC, oldPal, TRUE );
           RealizePalette( hDC );
        }

        GlobalUnlock( hDib );

		return TRUE;
	}
	return FALSE;
}

//---------------------------------------------------------------------------//

CLIPPER DIBREAD() //  ( cBitmap ) -> hGlobalMemBitmap
{
    _retni( _fwAddGlobal( DibRead( _parc( 1 ) ) ) );
}

//---------------------------------------------------------------------------//

CLIPPER GLOBALFREE() // ( hGlobal )
{
   HGLOBAL hMem = _parni( 1 );

   if( hMem )
   {
      GlobalFree( hMem );
      _fwDelGlobal( hMem );
   }
}

//---------------------------------------------------------------------------//

CLIPPER DIBPALETTE() // ( hMemBitmap ) --> hPalette
{
   _retni( CreateDIBPalette( _parni( 1 ) ) );
}

//---------------------------------------------------------------------------//

CLIPPER DIBDRAW() // ( hDC, hMemBitmap, hPalette, nRow, nCol, nWidth, nHeight )
{
    HDC       hDC  = _parni( 1 );
    HGLOBAL   hDib = _parni( 2 );
    HPALETTE  hPal = _parni( 3 );

    if( hDC && hDib )
       _retl( DibDraw( hDC, hDib, _parni( 5 ), _parni( 4 ), hPal,
                       _parni( 6 ), _parni( 7 ) ) );
}

//---------------------------------------------------------------------------//

CLIPPER DIBWIDTH() // ( HGLOBAL hDIBGlobal )
{
    HGLOBAL hDIBGlobal = _parni( 1 );
    LPBITMAPINFOHEADER lpBmp;

    lpBmp = ( LPBITMAPINFOHEADER ) GlobalLock( hDIBGlobal );

    _retni( lpBmp ? (WORD) lpBmp->biWidth : 0 );

    GlobalUnlock( hDIBGlobal );
}

//---------------------------------------------------------------------------//

CLIPPER DIBHEIGHT() //    HGLOBAL hDIBGlobal
{
    HGLOBAL hDIBGlobal = _parni( 1 );
    LPBITMAPINFOHEADER lpBmp;

    lpBmp = ( LPBITMAPINFOHEADER ) GlobalLock( hDIBGlobal );

    _retni( lpBmp ? (WORD) lpBmp->biHeight : 0 );

    GlobalUnlock( hDIBGlobal );
}

//---------------------------------------------------------------------------//

BOOL DibWrite( LPSTR szFileName, HGLOBAL hDIB )
{
   LPBITMAPINFO Info = ( LPBITMAPINFO ) GlobalLock( hDIB );
   void huge * Bits  = ( FARP ) Info + Info->bmiHeader.biSize +
                       wDIBColors( Info ) * sizeof( RGBQUAD );
   long lSize = GlobalSize( hDIB );
   BITMAPFILEHEADER bmf;
   int hBmp;

   bmf.bfType      = 'BM';
   bmf.bfSize      = sizeof( bmf ) + lSize;
   bmf.bfReserved1 = 0;
   bmf.bfReserved2 = 0;
   bmf.bfOffBits   = sizeof( bmf ) + ( FARP ) Bits - ( FARP) Info;

   if( ( hBmp = _lcreat( szFileName, 0 ) ) != HFILE_ERROR )
   {
      _hwrite( hBmp, &bmf, sizeof( bmf ) );
      _hwrite( hBmp, Info, lSize );
      _lclose( hBmp );
      GlobalUnlock( hDIB );
      return TRUE;
   }
   else
   {
      GlobalUnlock( hDIB );
      return FALSE;
   }
}

//---------------------------------------------------------------------------//

CLIPPER DIBWRITE()  // ( cFileName, hDib ) --> lSuccess
{
   _retl( DibWrite( _parc( 1 ), ( HGLOBAL ) _parni( 2 ) ) );
}

//---------------------------------------------------------------------------//
