/****************************************************************************
 *
 *  MODULE  : DIB.C
 *
 *  DESCRIPTION : Routines for dealing with Device Independent Bitmaps.
 *
 *  FUNCTION   :bmfNumDIBColors(HANDLE hDib)
 *
 *  FUNCTION   :bmfCreateDIBPalette(HANDLE hDib)
 *
 *  FUNCTION   :bmfDIBSize(HANDLE hDIB)
 *
 *  FUNCTION   :bmfDIBFromBitmap(HBITMAP hBmp, DWORD biStyle, WORD biBits,
 *                               HPALETTE hPal)
 *
 *  FUNCTION   :bmfBitmapFromDIB(HANDLE hDib, HPALETTE hPal)
 *
 *  FUNCTION   :bmfBitmapFromIcon (HICON hIcon, DWORD dwColor)
 *
 *  FUNCTION   :bmfDrawBitmap(HDC hdc, int xpos, int ypos, HBITMAP hBmp,
 *                            DWORD rop)
 *
 *  FUNCTION   :bmfDrawBitmapSize(HDC hdc, int x, int y, int xSize,
 *                                int ySize, HBITMAP hBmp, DWORD rop)
 *
 *  FUNCTION   :DIBInfo(HANDLE hbi,LPBITMAPINFOHEADER lpbi)
 *
 *  FUNCTION   :CreateBIPalette(LPBITMAPINFOHEADER lpbi)
 *
 *  FUNCTION   :PaletteSize(VOID FAR * pv)
 *
 *  FUNCTION   :NumDIBColors(VOID FAR * pv)
 *
 *  FUNCTION   :LoadUIBitmap(HANDLE hInstance, LPCTSTR szName, 
 *							 COLORREF rgbText,
 *                           COLORREF rgbFace, COLORREF rgbShadow,
 *                           COLORREF rgbHighlight, COLORREF rgbWindow,
 *                           COLORREF rgbFrame)
 *
 ****************************************************************************/

#include <windows.h>
#include <mmsystem.h>
#include <string.h>
#include <stdlib.h>
#include <shellapi.h>
#include "draw.h"

/* global variables */
extern      HANDLE        ghInstance;    //instance handle of DIB.DLL

/***************************************************************************
 *
 *  FUNCTION   :bmfNumDIBColors(HANDLE hDib)
 *
 *  PURPOSE    :Returns the number of colors required to display the DIB
 *              indicated by hDib.
 *
 *  RETURNS    :The number of colors in the DIB. Possibilities are
 *              2, 16, 256, and 0 (0 indicates a 24-bit DIB).  In
 *              the case of an error, -1 is returned.
 *
 ****************************************************************************/

WORD WINAPI bmfNumDIBColors (HANDLE hDib)
{
    WORD                bits;
    LPBITMAPINFOHEADER  lpbi;

    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
    if (!lpbi)
	return ((WORD)-1);

    /* The function NumDIBColors will return the number of colors in the
     * DIB by looking at the BitCount field in the info block
     */
    bits = NumDIBColors(lpbi);
    GlobalUnlock(hDib);
    return(bits);
}


/***************************************************************************
 *
 *  FUNCTION   :bmfCreateDIBPalette(HANDLE hDib)
 *
 *  PURPOSE    :Creates a palette suitable for displaying hDib.
 *
 *  RETURNS    :A handle to the palette if successful, NULL otherwise.
 *
 ****************************************************************************/

HPALETTE WINAPI bmfCreateDIBPalette (HANDLE hDib)
{
    HPALETTE            hPal;
    LPBITMAPINFOHEADER  lpbi;

    if (!hDib)
	return NULL;    //bail out if handle is invalid

    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
    if (!lpbi)
	return NULL;

    hPal = CreateBIPalette(lpbi);
    GlobalUnlock(hDib);
    return hPal;
}


/***************************************************************************
 *
 *  FUNCTION   :bmfDIBSize(HANDLE hDIB)
 *
 *  PURPOSE    :Return the size of a DIB.
 *
 *  RETURNS    :DWORD with size of DIB, include BITMAPINFOHEADER and
 *              palette.  Returns 0 if failed.
 *
 *  HISTORY:
 *  92/08/13 -  BUG 1642: (w-markd)
 *              Added this function so Quick Recorder could find out the
 *              size of a DIB.
 *  92/08/29 -  BUG 2123: (w-markd)
 *              If the biSizeImage field of the structure we get is zero,
 *              then we have to calculate the size of the image ourselves.
 *              Also, after size is calculated, we bail out if the 
 *              size we calculated is larger than the size of the global
 *              object, since this indicates that the structure data
 *              we used to calculate the size was invalid.
 *
 ****************************************************************************/

DWORD WINAPI bmfDIBSize(HANDLE hDIB)
{
    LPBITMAPINFOHEADER  lpbi;
    DWORD               dwSize;

    /* Lock down the handle, and cast to a LPBITMAPINFOHEADER
    ** so we can read the fields we need
    */
    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
    if (!lpbi)
	return 0;

    /* BUG 2123: (w-markd)
    ** Since the biSizeImage could be zero, we may have to calculate
    ** the size ourselves.
    */
    dwSize = lpbi->biSizeImage;
    if (dwSize == 0)
	dwSize = WIDTHBYTES((WORD)(lpbi->biWidth) * lpbi->biBitCount) *
	    lpbi->biHeight;


    /* The size of the DIB is the size of the BITMAPINFOHEADER
    ** structure (lpbi->biSize) plus the size of our palette plus
    ** the size of the actual data (calculated above).
    */
    dwSize += lpbi->biSize + (DWORD)PaletteSize(lpbi);

    /* BUG 2123: (w-markd)
    ** Check to see if the size is greater than the size
    ** of the global object.  If it is, the hDIB is corrupt.
    */
    GlobalUnlock(hDIB);
    if (dwSize > GlobalSize(hDIB))
	return 0;
    else
	return(dwSize);
}


/***************************************************************************
 *
 *  FUNCTION   :bmfDIBFromBitmap(HBITMAP hBmp, DWORD biStyle, WORD biBits,
 *                               HPALETTE hPal)
 *
 *  PURPOSE    :Converts the device-dependent BITMAP indicated by hBmp into
 *              a DIB.  biStyle indicates whether the palette contains
 *              DIB_RGB_COLORS or DIB_PAL_COLORS.  biBits indicates the
 *              desired number of bits in the destination DIB.  If biBits
 *              is zero, the destination DIB will be created with the
 *              minimum required bits.  hPal is a handle to the palette to be
 *              stored with the DIB data.  If hPal is NULL, the default
 *              system palette is used.
 *
 *  RETURNS    :A global handle to a memory block containing the DIB
 *              information in CF_DIB format.  NULL is returned if errors
 *              are encountered.
 *
 *  HISTORY:
 *
 *  92/08/12 -  BUG 1642: (angeld)
 *              Check the return value from GetObject, it will tell us
 *              if the handle hBmp was valid. bail out right away if it isn't
 *  92/08/29 -  BUG 2123: (w-markd)
 *              Use temporary variable to store old palette, then
 *              reselect the old palette when we are done.
 *
 ****************************************************************************/

HANDLE WINAPI bmfDIBFromBitmap (HBITMAP hBmp, DWORD biStyle, WORD biBits,
				    HPALETTE hPal)
{
    BITMAP                  bm;
    BITMAPINFOHEADER        bi;
    BITMAPINFOHEADER FAR    *lpbi;
    DWORD                   dwLen;
    HANDLE                  hDib;
    HANDLE                  hMem;
    HDC                     hdc;
    HPALETTE                hOldPal;

    if (!hBmp || !(GetObject(hBmp,sizeof(bm),(LPSTR)&bm)))
	 {
#if DEBUG
	  OutputDebugString(TEXT("bmfDIBFromBitmap:   INVALID HBITMAP!!!\n\r"));
#endif          
	return NULL;    //bail out if handle is invalid
	 }

    /* get default system palette if hPal is invalid */
    if (hPal == NULL)
	hPal = GetStockObject(DEFAULT_PALETTE);

    if (biBits == 0)
	biBits =  bm.bmPlanes * bm.bmBitsPixel;

    /* set up BITMAPINFOHEADER structure */
    bi.biSize               = sizeof(BITMAPINFOHEADER);
    bi.biWidth              = bm.bmWidth;
    bi.biHeight             = bm.bmHeight;
    bi.biPlanes             = 1;
    bi.biBitCount           = biBits;
    bi.biCompression        = biStyle;
    bi.biSizeImage          = 0;
    bi.biXPelsPerMeter      = 0;
    bi.biYPelsPerMeter      = 0;
    bi.biClrUsed            = 0;
    bi.biClrImportant       = 0;

    dwLen  = bi.biSize + PaletteSize(&bi);

    hdc = GetDC(NULL);
    /* BUG 2123: (w-markd)
    ** Store the previous palette in hOldPal, restore it on exit.
    */
    hOldPal = SelectPalette(hdc,hPal,FALSE);
    RealizePalette(hdc);

    /* get global memory for DIB */
    hDib = GlobalAlloc(GHND,dwLen);

    if (!hDib)
    {
	/* could not allocate memory; clean up and exit */
	SelectPalette(hdc,hOldPal,FALSE);
	ReleaseDC(NULL,hdc);
	return NULL;
    }

    lpbi = (VOID FAR *)GlobalLock(hDib);
    if (!lpbi)
    {
	/* could not lock memory; clean up and exit */
	SelectPalette(hdc,hOldPal,FALSE);
	ReleaseDC(NULL,hdc);
	GlobalFree(hDib);
	return NULL;
    }

    *lpbi = bi;

    /*  call GetDIBits with a NULL lpBits param, so it will calculate the
     *  biSizeImage field for us
     */
    GetDIBits(hdc, hBmp, 0, (WORD)bi.biHeight,
	NULL, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);

    bi = *lpbi;
    GlobalUnlock(hDib);

    /* If the driver did not fill in the biSizeImage field, make one up */
    if (bi.biSizeImage == 0)
    {
	bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;

	if (biStyle != BI_RGB)
	    bi.biSizeImage = (bi.biSizeImage * 3) / 2;
    }

    /*  realloc the buffer big enough to hold all the bits */
    dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
    hMem = GlobalReAlloc(hDib,dwLen,GMEM_MOVEABLE);
    if (!hMem)
    {
	/* could not allocate memory; clean up and exit */
	GlobalFree(hDib);
	SelectPalette(hdc,hOldPal,FALSE);
	ReleaseDC(NULL,hdc);
	return NULL;
    }
    else
	hDib = hMem;

    /*  call GetDIBits with a NON-NULL lpBits param, and actualy get the
     *  bits this time
     */
    lpbi = (VOID FAR *)GlobalLock(hDib);
    if (!lpbi)
    {
	/* could not lock memory; clean up and exit */
	GlobalFree(hDib);
	SelectPalette(hdc,hOldPal,FALSE);
	ReleaseDC(NULL,hdc);
	return NULL;
    }

    if (GetDIBits( hdc, hBmp, 0, (WORD)bi.biHeight,
	   (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi),
	   (LPBITMAPINFO)lpbi, DIB_RGB_COLORS) == 0)
    {
	/* clean up and exit */
	GlobalUnlock(hDib);
	GlobalFree(hDib);
	SelectPalette(hdc,hOldPal,FALSE);
	ReleaseDC(NULL,hdc);
	return NULL;
    }

    bi = *lpbi;

    /* clean up and exit */
    GlobalUnlock(hDib);
    SelectPalette(hdc,hOldPal,FALSE);
    ReleaseDC(NULL,hdc);
    return hDib;
}


/***************************************************************************
 *
 *  FUNCTION   :bmfBitmapFromDIB(HANDLE hDib, HPALETTE hPal)
 *
 *  PURPOSE    :Converts DIB information into a device-dependent BITMAP
 *              suitable for display on the current display device.  hDib is
 *              a global handle to a memory block containing the DIB
 *              information in CF_DIB format.  hPal is a handle to a palette
 *              to be used for displaying the bitmap.  If hPal is NULL, the
 *              default system palette is used during the conversion.
 *
 *  RETURNS    :Returns a handle to a bitmap is successful, NULL otherwise.
 *
 *  HISTORY:
 *  92/08/29 -  BUG 2123: (w-markd)
 *              Check if DIB is has a valid size, and bail out if not.
 *              If no palette is passed in, try to create one.  If we
 *              create one, we must destroy it before we exit.
 *
 ****************************************************************************/

HBITMAP WINAPI bmfBitmapFromDIB(HANDLE hDib, HPALETTE hPal)
{
    LPBITMAPINFOHEADER  lpbi;
    HPALETTE            hPalT;
    HDC                 hdc;
    HBITMAP             hBmp;
    DWORD               dwSize;
    BOOL                bMadePalette = FALSE;

    if (!hDib)
	return NULL;    //bail out if handle is invalid
    
    /* BUG 2123: (w-markd)
    ** Check to see if we can get the size of the DIB.  If this call
    ** fails, bail out.
    */
    dwSize = bmfDIBSize(hDib);
    if (!dwSize)
	return NULL;

    lpbi = (VOID FAR *)GlobalLock(hDib);
    if (!lpbi)
	return NULL;

    /* prepare palette */
    /* BUG 2123: (w-markd)
    ** If the palette is NULL, we create one suitable for displaying
    ** the dib.
    */
    if (!hPal)
    {
	hPal = bmfCreateDIBPalette(hDib);
	if (!hPal)
	{
	    GlobalUnlock(hDib);
	    #ifdef V101
	    #else
	    bMadePalette = TRUE;
	    #endif
	    return NULL;
	}
	#ifdef V101
	/* BUGFIX: mikeroz 2123 - this flag was in the wrong place */
	bMadePalette = TRUE;
	#endif
    }
    hdc = GetDC(NULL);
    hPalT = SelectPalette(hdc,hPal,FALSE);
    RealizePalette(hdc);     // GDI Bug...????

    /* Create the bitmap.  Note that a return value of NULL is ok here */
    hBmp = CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)lpbi, (LONG)CBM_INIT,
			  (LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
			  (LPBITMAPINFO)lpbi, DIB_RGB_COLORS );

    /* clean up and exit */
    /* BUG 2123: (w-markd)
    ** If we made the palette, we need to delete it.
    */
    if (bMadePalette)
	DeleteObject(SelectPalette(hdc,hPalT,FALSE));
    else
	SelectPalette(hdc,hPalT,FALSE);
    ReleaseDC(NULL,hdc);
    GlobalUnlock(hDib);
    return hBmp;
}


/***************************************************************************
 *
 *  FUNCTION   :bmfBitmapFromIcon (HICON hIcon, DWORD dwColor)
 *
 *  PURPOSE    :Converts an icon into a bitmap.  hIcon is a handle to a
 *              windows ICON object.  dwColor sets the background color for
 *              the bitmap.
 *
 *  RETURNS    :A handle to the bitmap is successful, NULL otherwise.
 *
 ****************************************************************************/


HBITMAP WINAPI bmfBitmapFromIcon (HICON hIcon, DWORD dwColor)
{
    HDC     hDC;
    HDC     hMemDC = 0;
    HBITMAP hBitmap = 0;
    HBITMAP hOldBitmap;
    HBRUSH  hBrush = 0;
    HBRUSH  hOldBrush;
    int     xIcon, yIcon;

    hDC = GetDC(NULL);
    hMemDC = CreateCompatibleDC( hDC );
    if (hMemDC)
    {
	/* get the size for the destination bitmap */
	xIcon = GetSystemMetrics(SM_CXICON);
	yIcon = GetSystemMetrics(SM_CYICON);
	hBitmap = CreateCompatibleBitmap(hDC, xIcon, yIcon);
	if (hBitmap)
	{
	    hBrush = CreateSolidBrush(dwColor);
	    if (hBrush)
	    {
		hOldBitmap = SelectObject (hMemDC, hBitmap);
		hOldBrush  = SelectObject (hMemDC, hBrush);

		/* draw the icon on the memory device context */
		PatBlt   (hMemDC, 0, 0, xIcon, yIcon, PATCOPY);
		DrawIcon (hMemDC, 0, 0, hIcon);

		/* clean up and exit */
		DeleteObject(SelectObject(hMemDC, hOldBrush));
		SelectObject(hMemDC, hOldBitmap);
		DeleteDC(hMemDC);
		ReleaseDC(NULL, hDC);
		return hBitmap;
	    }
	}
    }

    /* clean up resources and exit */
    if (hBitmap)
	DeleteObject(hBitmap);
    if (hMemDC)
	DeleteDC(hMemDC);
    ReleaseDC (NULL, hDC);
    return NULL;
}


/***************************************************************************
 *
 *  FUNCTION   :bmfDrawBitmap(HDC hdc, int xpos, int ypos, HBITMAP hBmp,
 *                            DWORD rop)
 *
 *  PURPOSE    :Draws bitmap hBmp at the specifed position in DC hdc
 *
 *  RETURNS    :Return value of BitBlt() or FALSE if in an error is
 *              encountered.  Note that BitBlt returns true if successful.
 *
 ****************************************************************************/

BOOL WINAPI bmfDrawBitmap (HDC hdc, int xpos, int ypos, HBITMAP hBmp,
			       DWORD rop)
{
    HDC       hdcBits;
    BITMAP    bm;
    BOOL      bResult;

    if (!hdc || !hBmp)
	return FALSE;

    hdcBits = CreateCompatibleDC(hdc);
    if (!hdcBits)
	return FALSE;
    GetObject(hBmp,sizeof(BITMAP),(LPSTR)&bm);
    SelectObject(hdcBits,hBmp);
    bResult = BitBlt(hdc,xpos,ypos,bm.bmWidth,bm.bmHeight,hdcBits,0,0,rop);
    DeleteDC(hdcBits);

    return bResult;
}


/***************************************************************************
 *
 *  FUNCTION   :DIBInfo(HANDLE hbi,LPBITMAPINFOHEADER lpbi)
 *
 *  PURPOSE    :Retrieves the DIB info associated with a CF_DIB
 *              format memory block.
 *
 *  RETURNS    :TRUE (non-zero) if successful;  FALSE (zero) otherwise.
 *
 ****************************************************************************/

BOOL DIBInfo (HANDLE hbi, LPBITMAPINFOHEADER lpbi)
{
    if (!hbi)
	return FALSE;

    *lpbi = *(LPBITMAPINFOHEADER)GlobalLock (hbi);
    if (!lpbi)
	return FALSE;
    /* fill in the default fields */
    if (lpbi->biSize != sizeof (BITMAPCOREHEADER))
    {
	if (lpbi->biSizeImage == 0L)
	    lpbi->biSizeImage =
	    WIDTHBYTES(lpbi->biWidth*lpbi->biBitCount) * lpbi->biHeight;
	if (lpbi->biClrUsed == 0L)
	    lpbi->biClrUsed = NumDIBColors (lpbi);
    }
    GlobalUnlock (hbi);
    return TRUE;
}

/***************************************************************************
 *
 *  FUNCTION   :CreateBIPalette(LPBITMAPINFOHEADER lpbi)
 *
 *  PURPOSE    :Given a Pointer to a BITMAPINFO struct will create a
 *              a GDI palette object from the color table.
 *
 *  RETURNS    :A handle to the palette if successful, NULL otherwise.
 *
 ****************************************************************************/

HPALETTE CreateBIPalette (LPBITMAPINFOHEADER lpbi)
{
    LPLOGPALETTE        pPal;
    HPALETTE            hPal = NULL;
    WORD                nNumColors;
    BYTE                red;
    BYTE                green;
    BYTE                blue;
    int                 i;
    RGBQUAD             FAR *pRgb;
    HANDLE hMem;

    if (!lpbi)
	return NULL;

    if (lpbi->biSize != sizeof(BITMAPINFOHEADER))
	return NULL;

    /* Get a pointer to the color table and the number of colors in it */
    pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
    nNumColors = NumDIBColors(lpbi);

    if (nNumColors)
    {
	/* Allocate for the logical palette structure */
	hMem = GlobalAlloc(GMEM_MOVEABLE,
	sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
	if (!hMem)
	    return NULL;
	pPal = (LPLOGPALETTE)GlobalLock(hMem);
	if (!pPal)
	{
	    GlobalFree(hMem);
	    return NULL;
	}

	pPal->palNumEntries = nNumColors;
	pPal->palVersion    = PALVERSION;

	/* Fill in the palette entries from the DIB color table and
	 * create a logical color palette.
	 */
	for (i = 0; (unsigned)i < nNumColors; i++)
	{
	    pPal->palPalEntry[i].peRed   = pRgb[i].rgbRed;
	    pPal->palPalEntry[i].peGreen = pRgb[i].rgbGreen;
	    pPal->palPalEntry[i].peBlue  = pRgb[i].rgbBlue;
	    pPal->palPalEntry[i].peFlags = (BYTE)0;
	}
	hPal = CreatePalette(pPal);
	/* note that a NULL return value for the above CreatePalette call
	 * is acceptable, since this value will be returned, and is not
	 * used again here
	 */
	GlobalUnlock(hMem);
	GlobalFree(hMem);
    }
    else if (lpbi->biBitCount == 24)
    {
	/* A 24 bitcount DIB has no color table entries so, set the number of
	 * to the maximum value (256).
	 */
	nNumColors = MAXPALETTE;
	hMem =GlobalAlloc(GMEM_MOVEABLE,
	sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
	if (!hMem)
	    return NULL;
	pPal = (LPLOGPALETTE)GlobalLock(hMem);
	if (!pPal)
	{
	    GlobalFree(hMem);
	    return NULL;
	}

	pPal->palNumEntries = nNumColors;
	pPal->palVersion    = PALVERSION;

	red = green = blue = 0;

	/* Generate 256 (= 8*8*4) RGB combinations to fill the palette
	 * entries.
	 */
	for (i = 0; (unsigned)i < pPal->palNumEntries; i++)
	{
	    pPal->palPalEntry[i].peRed   = red;
	    pPal->palPalEntry[i].peGreen = green;
	    pPal->palPalEntry[i].peBlue  = blue;
	    pPal->palPalEntry[i].peFlags = (BYTE)0;

	    if (!(red += 32))
	    if (!(green += 32))
		blue += 64;
	}
	hPal = CreatePalette(pPal);
	/* note that a NULL return value for the above CreatePalette call
	 * is acceptable, since this value will be returned, and is not
	 * used again here
	 */
	GlobalUnlock(hMem);
	GlobalFree(hMem);
    }
    return hPal;
}
/***************************************************************************
 *
 *  FUNCTION   :PaletteSize(VOID FAR * pv)
 *
 *  PURPOSE    :Calculates the palette size in bytes. If the info. block
 *              is of the BITMAPCOREHEADER type, the number of colors is
 *              multiplied by 3 to give the palette size, otherwise the
 *              number of colors is multiplied by 4.
 *
 *  RETURNS    :Palette size in number of bytes.
 *
 ****************************************************************************/

WORD PaletteSize (VOID FAR *pv)
{
    LPBITMAPINFOHEADER  lpbi;
    WORD                NumColors;

    lpbi      = (LPBITMAPINFOHEADER)pv;
    NumColors = NumDIBColors(lpbi);

    if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
	return (NumColors * sizeof(RGBTRIPLE));
    else
	return (NumColors * sizeof(RGBQUAD));
}


/***************************************************************************
 *
 *  FUNCTION   :NumDIBColors(VOID FAR * pv)
 *
 *  PURPOSE    :Determines the number of colors in the DIB by looking at
 *              the BitCount field in the info block.
 *              For use only internal to DLL.
 *
 *  RETURNS    :The number of colors in the DIB.
 *
 ****************************************************************************/

WORD NumDIBColors (VOID FAR * pv)
{
    int                 bits;
    LPBITMAPINFOHEADER  lpbi;
    LPBITMAPCOREHEADER  lpbc;

    lpbi = ((LPBITMAPINFOHEADER)pv);
    lpbc = ((LPBITMAPCOREHEADER)pv);

    /*  With the BITMAPINFO format headers, the size of the palette
     *  is in biClrUsed, whereas in the BITMAPCORE - style headers, it
     *  is dependent on the bits per pixel ( = 2 raised to the power of
     *  bits/pixel).
     */
    if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
    {
	if (lpbi->biClrUsed != 0)
	    return (WORD)lpbi->biClrUsed;
	bits = lpbi->biBitCount;
    }
    else
	bits = lpbc->bcBitCount;

    switch (bits)
    {
    case 1:
	return 2;
    case 4:
	return 16;
    case 8:
	return 256;
    default:
	/* A 24 bitcount DIB has no color table */
	return 0;
    }
}


/***************************************************************************
 *
 *  FUNCTION   :bmfDrawBitmapSize(HDC hdc, int x, int y, int xSize,
 *              int ySize, HBITMAP hBmp, DWORD rop)
 *
 *  PURPOSE    :Draws bitmap <hBmp> at the specifed position in DC <hdc> with
 *              a specified size.
 *
 *  RETURNS    :Return value of BitBlt() or false in an error is
 *              encountered.  Note that BitBlt returns true if successful.
 *
 *  HISTORY:
 *  92/08/13 -  BUG 1642: (w-markd)
 *              Exported this function.
 *              Also stored object that was returned from SelectObject,
 *              and selected this back into the hdc before deleting.
 *
 ****************************************************************************/

BOOL WINAPI bmfDrawBitmapSize (HDC hdc, int xpos, int ypos, int xSize, int ySize, HBITMAP hBmp, DWORD rop)
{
    HDC         hdcBits;
    BOOL        bResult;
    HBITMAP     hOldBmp;

    if (!hdc || !hBmp)
	return FALSE;

    hdcBits = CreateCompatibleDC(hdc);
    if (!hdcBits)
	return FALSE;
    /* BUG 1642: (w-markd)
    ** Remeber old bmp and reselect into hdc before DeleteDC
    */
    hOldBmp = SelectObject(hdcBits,hBmp);
    bResult = BitBlt(hdc,xpos,ypos,xSize, ySize,hdcBits, 0,0,rop);
    SelectObject(hdcBits, hOldBmp);
    DeleteDC(hdcBits);

    return bResult;
}

//----------------------------------------------------------------------------
//  LoadUIBitmap() - load a bitmap resource
//
//      load a bitmap resource from a resource file, converting all
//      the standard UI colors to the current user specifed ones.
//
//      this code is designed to load bitmaps used in "gray ui" or
//      "toolbar" code.
//
//      the bitmap must be a 4bpp windows 3.0 DIB, with the standard
//      VGA 16 colors.
//
//      the bitmap must be authored with the following colors
//
//          Button Text        Black        (index 0)
//          Button Face        lt gray      (index 7)
//          Button Shadow      gray         (index 8)
//          Button Highlight   white        (index 15)
//          Window Color       yellow       (index 11)
//          Window Frame       green        (index 10)
//
//      Example:
//
//          hbm = LoadUIBitmap(hInstance, "TestBmp",
//              GetSysColor(COLOR_BTNTEXT),
//              GetSysColor(COLOR_BTNFACE),
//              GetSysColor(COLOR_BTNSHADOW),
//              GetSysColor(COLOR_BTNHIGHLIGHT),
//              GetSysColor(COLOR_WINDOW),
//              GetSysColor(COLOR_WINDOWFRAME));
//
//      Author:     JimBov, ToddLa
//      History:    5/13/92 - added to dib.c in sndcntrl.dll, t-chrism
//
//----------------------------------------------------------------------------
HBITMAP WINAPI LoadUIBitmap(
    HANDLE      hInstance,          // EXE file to load resource from
    LPCTSTR      szName,             // name of bitmap resource
    COLORREF    rgbText,            // color to use for "Button Text"
    COLORREF    rgbFace,            // color to use for "Button Face"
    COLORREF    rgbShadow,          // color to use for "Button Shadow"
    COLORREF    rgbHighlight,       // color to use for "Button Hilight"
    COLORREF    rgbWindow,          // color to use for "Window Color"
    COLORREF    rgbFrame)           // color to use for "Window Frame"
{
    LPBYTE              lpb;
    HBITMAP             hbm;
    LPBITMAPINFOHEADER  lpbi = NULL;
    HANDLE              h;
    HDC                 hdc;
    LPDWORD             lprgb;
    HRSRC               hrsrc;

    // convert a RGB into a RGBQ
    #define RGBQ(dw) RGB(GetBValue(dw),GetGValue(dw),GetRValue(dw))

    hrsrc = FindResource(hInstance, szName, RT_BITMAP);
    if (hrsrc)
    {
        h = LoadResource(hInstance,hrsrc);
        if (h)
            lpbi = (LPBITMAPINFOHEADER)LockResource(h);
    }

    if (!lpbi)
	return(NULL);

    if (lpbi->biSize != sizeof(BITMAPINFOHEADER))
	return NULL;

    if (lpbi->biBitCount != 4)
	return NULL;

    lprgb = (LPDWORD)((LPBYTE)lpbi + (int)lpbi->biSize);
    lpb   = (LPBYTE)(lprgb + 16);

    lprgb[0]  = RGBQ(rgbText);          // Black
    lprgb[7]  = RGBQ(rgbFace);          // lt gray
    lprgb[8]  = RGBQ(rgbShadow);        // gray
    lprgb[15] = RGBQ(rgbHighlight);     // white
    lprgb[11] = RGBQ(rgbWindow);        // yellow
    lprgb[10] = RGBQ(rgbFrame);         // green

    hdc = GetDC(NULL);

    hbm = CreateDIBitmap(hdc, lpbi, CBM_INIT, (LPVOID)lpb,
	(LPBITMAPINFO)lpbi, DIB_RGB_COLORS);

    ReleaseDC(NULL, hdc);
    UnlockResource(h);
    FreeResource(h);
    return(hbm);
}// LoadUIBitmap


