/* -*- C++ -*-
 * wvtb.c  - WinVN toolbar implementation
 *
 * based on MSDNTB example from MSDN 
 * Kyle Marsh (Microsoft Developer Network Technology Group) 12/31/92
 *
 * $Id: wvtb.c 1.2 1994/12/19 16:57:39 rushing Exp $
 */
#include "./wvtbi.h"
#include <memory.h>

char szToolbarClass[7] = "WINVNTB";

#define DEFAULTBITMAPX   16
#define DEFAULTBITMAPY   15
#define DEFAULTBUTTONX   24
#define DEFAULTBUTTONY   22
#define DEFAULTBARHEIGHT 27

#define BUTTONSEPERATOR  8
#define FIRSTBUTTON      8

HBRUSH hbrDither;
DWORD  rgbFace;
DWORD  rgbShadow;
DWORD  rgbHilight;
DWORD  rgbFrame;
int    dxBitmap = 16, 
     dyBitmap = 15, 
     dxButton = 24, 
     dyButton = 22, 
     barHeight = 27;

int nSelectedBM = -1;
HDC hdcGlyphs = NULL;           // globals for fast drawing

//
// hdcMono is the DC that holds a mono bitmap, hbmMono
// that is used to create highlights
// of button faces.
// hbmDefault hold the default bitmap if there is one.
//
HDC     hdcMono = NULL;
HBITMAP hbmMono = NULL;
HBITMAP hbmDefault = NULL;

WORD wStateMasks[] = {
    TBSTATE_ENABLED,
    TBSTATE_CHECKED,
    TBSTATE_PRESSED,
    TBSTATE_HIDDEN,
    TBSTATE_INDETERMINATE
};

int iDitherCount = 0;
int iInitCount   = 0;

HINSTANCE  hInst = 0;              // Global instance handle for  DLL
HINSTANCE  hGlobalBMInst = 0;       // Global variable for passing instance

LRESULT CALLBACK ToolbarWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
void FAR PASCAL GetSysColors(PTBHDR pTBHdr);

BOOL FAR PASCAL CreateDitherBrush(BOOL bIgnoreCount);
BOOL FAR PASCAL FreeDitherBrush(void);
HBITMAP WINAPI CreateMappedBitmap(HINSTANCE hInstance, int idBitmap );

BOOL NEAR PASCAL InitGlobalObjects(void)
{

    if ( iInitCount == 0 )  
  {
       hdcGlyphs = CreateCompatibleDC(NULL);
       if (!hdcGlyphs)
           return FALSE;
       hdcMono = CreateCompatibleDC(NULL);
       if (!hdcMono)
           return FALSE;

       hbmMono = CreateBitmap(dxButton, dyButton, 1, 1, NULL);
       if (!hbmMono)
           return FALSE;

       hbmDefault = SelectObject(hdcMono, hbmMono);
    }

    iInitCount++;

    return TRUE;
}


void NEAR PASCAL FreeGlobalObjects(void)
{
  --iInitCount;

  if ( iInitCount )
    return;

  if (hdcMono) 
  {
    if (hbmDefault)
      SelectObject(hdcMono, hbmDefault);
    DeleteDC(hdcMono);      // toast the DCs
  }
  hdcMono = NULL;

  if (hdcGlyphs)
    DeleteDC(hdcGlyphs);
  hdcGlyphs = NULL;

  if (hbmMono)
    DeleteObject(hbmMono);
  hbmMono = NULL;
}

HWND /*__declspec(dllexport)*/  WINAPI CreateToolbar(HWND hwnd, DWORD ws, WORD wID, int nBitmaps,
                        HINSTANCE hBMInst, WORD wBMID,
                        LPCTBBUTTON lpButtons, int iNumButtons,
            int xButton, int yButton, int xBitmap, int yBitmap)
{

    HWND hwndToolbar;
//#ifdef _WIN32
  WNDCLASS wc;

  if (!GetClassInfo(hInst, szToolbarClass, &wc)) 
  {
    wc.lpszClassName = (LPSTR)szToolbarClass;
    wc.style   = CS_DBLCLKS | CS_GLOBALCLASS;
    wc.lpfnWndProc   = (WNDPROC)ToolbarWndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = sizeof(PTBHDR);
    wc.hInstance     = hInst;
    wc.hIcon   = NULL;
    wc.hCursor    = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
    wc.lpszMenuName  = NULL;
    RegisterClass(&wc);
  }
//#endif

  dxBitmap = xButton;//16,  
  dyBitmap = yButton;//15,  
  dxButton = xBitmap + 8;//24,  
  dyButton = yBitmap + 6;//22,  
  barHeight = yButton + 12; 


    hwndToolbar = CreateWindowEx(0L,szToolbarClass, NULL, WS_CHILD | ws,
              0, 0, 10, 10, hwnd, (HMENU)wID, hInst, NULL);

  if (hwndToolbar) 
  {

    PTBHDR pTBHdr;
    pTBHdr = GETWINDOWPOINTER(hwndToolbar, PTBHDR);
    if ( pTBHdr)
    {
      pTBHdr->dxBitmap = xButton;//16,  
      pTBHdr->dyBitmap = yButton;//15,  
      pTBHdr->dxButton = xBitmap + 8;//24,  
      pTBHdr->dyButton = yBitmap + 6;//22,  
      pTBHdr->barHeight = yButton + 11;
    } 
    //       SendMessage(hwndToolbar, TB_ADDBITMAP, nBitmaps, MAKELONG(hBMInst, wBMID));
    // pass the HINSTANCE via a global as it is a long in WIN32
    hGlobalBMInst = hBMInst;
    SendMessage(hwndToolbar, TB_ADDBITMAP, nBitmaps, MAKELONG(0, wBMID));
    SendMessage(hwndToolbar, TB_ADDBUTTONS, iNumButtons, (LPARAM)lpButtons);
  }

  return hwndToolbar;
}




void NEAR PASCAL PatB(HDC hdc,int x,int y,int dx,int dy, DWORD rgb)
{
  RECT    rc;

  rc.left   = x;
  rc.top    = y;
  rc.right  = x + dx;
  rc.bottom = y + dy;

  SetBkColor(hdc,rgb);
  ExtTextOut(hdc,0,0,ETO_OPAQUE,&rc,NULL,0,NULL);
}


// create a mono bitmap mask:
//   1's where color == COLOR_BTNFACE || COLOR_HILIGHT
//   0's everywhere else

void NEAR PASCAL CreateMask(PTBHDR pTBHdr, PTBBUTTON pTBButton, int xoffset, int yoffset, int dx, int dy)
{
  // initalize whole area with 1's
  PatBlt(hdcMono, 0, 0, dx, dy, WHITENESS);

  // create mask based on color bitmap
  // convert this to 1's
  SetBkColor(hdcGlyphs, rgbFace);
  BitBlt(hdcMono, xoffset, yoffset, pTBHdr->dxBitmap, pTBHdr->dyBitmap,
      hdcGlyphs, pTBButton->iBitmap * pTBHdr->dxBitmap, 0, SRCCOPY);
  // convert this to 1's
  SetBkColor(hdcGlyphs, rgbHilight);
  // OR in the new 1's
  BitBlt(hdcMono, xoffset, yoffset, pTBHdr->dxBitmap, pTBHdr->dyBitmap,
      hdcGlyphs, pTBButton->iBitmap * pTBHdr->dxBitmap, 0, SRCPAINT);
}


/* Given a button number, the corresponding bitmap is loaded and selected in,
 * and the Window origin set.
 * Returns NULL on Error, 1 if the necessary bitmap is already selected,
 * or the old bitmap otherwise.
 */
HBITMAP FAR PASCAL SelectBM(HDC hDC, PTBHDR pTBHdr, int nButton)
{
  PTBBMINFO pTemp;
  HBITMAP hRet;
  int nBitmap, nTot;
#ifdef _WIN32
  POINT MyPoint;
#endif

  for (pTemp=pTBHdr->pBitmaps, nBitmap=0, nTot=0; ; ++pTemp, ++nBitmap)
  {
    if (nBitmap >= pTBHdr->nBitmaps)
      return(NULL);

    if (nButton < nTot+pTemp->nButtons)
      break;

    nTot += pTemp->nButtons;
  }

  /* Special case when the required bitmap is already selected
  */
  if (nBitmap == nSelectedBM)
    return((HBITMAP)1);

  if (!pTemp->hbm || (hRet=SelectObject(hDC, pTemp->hbm))==NULL)
  {
    if (pTemp->hbm)
      DeleteObject(pTemp->hbm);

    if (pTemp->hInst)
      pTemp->hbm = CreateMappedBitmap(pTemp->hInst, pTemp->wID);
    else
      pTemp->hbm = (HBITMAP)pTemp->wID;

    if (!pTemp->hbm || (hRet=SelectObject(hDC, pTemp->hbm))==NULL)
      return(NULL);
  }

  nSelectedBM = nBitmap;
#ifdef _WIN32
  SetWindowOrgEx(hDC, nTot * pTBHdr->dxBitmap, 0, &MyPoint);
#else
  SetWindowOrg(hDC, nTot * pTBHdr->dxBitmap, 0);
#endif
  return(hRet);
}

void FAR PASCAL DrawBlankButton(HDC hdc, int x, int y, int dx, int dy, WORD state)
{
  // face color
  PatB(hdc, x, y, dx, dy, rgbFace);

  if (state & TBSTATE_PRESSED) 
  {
    PatB(hdc, x + 1, y, dx - 2, 1, rgbFrame);
    PatB(hdc, x + 1, y + dy - 1, dx - 2, 1, rgbFrame);
    PatB(hdc, x, y + 1, 1, dy - 2, rgbFrame);
    PatB(hdc, x + dx - 1, y +1, 1, dy - 2, rgbFrame);
    PatB(hdc, x + 1, y + 1, 1, dy-2, rgbShadow);
    PatB(hdc, x + 1, y + 1, dx-2, 1, rgbShadow);
  }
  else 
  {
    PatB(hdc, x + 1, y, dx - 2, 1, rgbFrame);
    PatB(hdc, x + 1, y + dy - 1, dx - 2, 1, rgbFrame);
    PatB(hdc, x, y + 1, 1, dy - 2, rgbFrame);
    PatB(hdc, x + dx - 1, y + 1, 1, dy - 2, rgbFrame);
    dx -= 2;
    dy -= 2;
    PatB(hdc, x + 1, y + 1, 1, dy - 1, rgbHilight);
    PatB(hdc, x + 1, y + 1, dx - 1, 1, rgbHilight);
    PatB(hdc, x + dx, y + 1, 1, dy, rgbShadow);
    PatB(hdc, x + 1, y + dy, dx, 1,   rgbShadow);
    PatB(hdc, x + dx - 1, y + 2, 1, dy - 2, rgbShadow);
    PatB(hdc, x + 2, y + dy - 1, dx - 2, 1,   rgbShadow);
  }
}

void FAR PASCAL DrawButton(HDC hdc, int x, int y, int dx, int dy, PTBHDR pTBHdr, PTBBUTTON ptButton)
{
  int yOffset;
  HBRUSH hbrOld, hbr;
  BOOL bMaskCreated = FALSE;
  BYTE state;
  int xButton = 0;    // assume button is down
  int dxFace, dyFace;
  int xCenterOffset;

  dxFace = dx;
  dyFace = dy;

  // make local copy of state and do proper overriding
  state = ptButton->fsState;
  if (state & TBSTATE_INDETERMINATE) 
  {
    if (state & TBSTATE_PRESSED)
      state &= ~TBSTATE_INDETERMINATE;
    else if (state & TBSTATE_ENABLED)
      state = TBSTATE_INDETERMINATE;
    else
      state &= ~TBSTATE_INDETERMINATE;
  }

  // get the proper button look - up or down.
  if (!(state & (TBSTATE_PRESSED | TBSTATE_CHECKED))) 
  {
    xButton = dx;  // use 'up' version of button
    dxFace -= 2;   
    dyFace -= 2;   // extents to ignore button highlight
  }

  DrawBlankButton(hdc, x, y, dx, dy, state);


  // move coordinates inside border and away from upper left highlight.
  // the extents change accordingly.
  x += 2;
  y += 2;
  dxFace -= 3;     
  dyFace -= 3;

  if (!SelectBM(hdcGlyphs, pTBHdr, ptButton->iBitmap))
    return;

  // calculate offset of face from (x,y).  y is always from the top,
  // so the offset is easy.  x needs to be centered in face.
  yOffset = 1;
  xCenterOffset = (dxFace - pTBHdr->dxBitmap)/2;
  if (state & (TBSTATE_PRESSED | TBSTATE_CHECKED))
  {
    // pressed state moves down and to the right
    // (x moves automatically as face size grows)
    yOffset++;
  }

  // now put on the face
  if (state & TBSTATE_ENABLED) 
  {
    // regular version
    BitBlt(hdc, x+xCenterOffset, y + yOffset, pTBHdr->dxBitmap, pTBHdr->dyBitmap,
    hdcGlyphs, ptButton->iBitmap * pTBHdr->dxBitmap, 0, SRCCOPY);
  } 
  else 
  {
    // disabled version (or indeterminate)
    bMaskCreated = TRUE;
    CreateMask(pTBHdr, ptButton, xCenterOffset, yOffset, dxFace, dyFace);

    SetTextColor(hdc, 0L);   // 0's in mono -> 0 (for ROP)
    SetBkColor(hdc, 0x00FFFFFF); // 1's in mono -> 1

    // draw glyph's white understrike
    if (!(state & TBSTATE_INDETERMINATE)) 
    {
      hbr = CreateSolidBrush(rgbHilight);
      if (hbr) 
      {
        hbrOld = SelectObject(hdc, hbr);
        if (hbrOld) 
        {
          // draw hilight color where we have 0's in the mask
          BitBlt(hdc, x + 1, y + 1, dxFace, dyFace, hdcMono, 0, 0, 0x00B8074A);
          SelectObject(hdc, hbrOld);
        }
        DeleteObject(hbr);
      }
    }

    // gray out glyph
    hbr = CreateSolidBrush(rgbShadow);
    if (hbr) 
    {
      hbrOld = SelectObject(hdc, hbr);
      if (hbrOld) 
      {
        // draw the shadow color where we have 0's in the mask
        BitBlt(hdc, x, y, dxFace, dyFace, hdcMono, 0, 0, 0x00B8074A);
        SelectObject(hdc, hbrOld);
      }
      DeleteObject(hbr);
    }

    if (state & TBSTATE_CHECKED) 
    {
      BitBlt(hdcMono, 1, 1, dxFace - 1, dyFace - 1, hdcMono, 0, 0, SRCAND);
    }
  }

  if (state & (TBSTATE_CHECKED | TBSTATE_INDETERMINATE)) 
  {

    hbrOld = SelectObject(hdc, hbrDither);
    if (hbrOld) 
    {

      if (!bMaskCreated)
        CreateMask(pTBHdr, ptButton, xCenterOffset, yOffset, dxFace, dyFace);

      SetTextColor(hdc, 0L);    // 0 -> 0
      SetBkColor(hdc, 0x00FFFFFF); // 1 -> 1

      // only draw the dither brush where the mask is 1's
      BitBlt(hdc, x, y, dxFace, dyFace, hdcMono, 0, 0, 0x00E20746);

      SelectObject(hdc, hbrOld);
    }
  }
}

void NEAR PASCAL ToolbarPaint(HWND hWnd, PTBHDR pTBHdr)
{
  RECT rc;
  HDC hdc;
  PAINTSTRUCT ps;
  int iButton, xButton, yButton;
  int cButtons = pTBHdr->iNumButtons;
  PTBBUTTON pAllButtons = pTBHdr->Buttons;
  HBITMAP hbmOldGlyphs;
  int iCacheWidth = 0;
  int dx,dy;

  GetSysColors(pTBHdr);

  hdc = BeginPaint(hWnd, &ps);

  GetClientRect(hWnd, &rc);
  if (!rc.right)
    goto Error1;

  dx = pTBHdr->dxButton;
  dy = pTBHdr->dyButton;

  // setup global stuff for fast painting

  nSelectedBM = -1;
  hbmOldGlyphs = SelectBM(hdcGlyphs, pTBHdr, 0);
  if (!hbmOldGlyphs)
    goto Error1;

  yButton = ((rc.bottom - rc.top) - dy) / 2;
  rc.top = yButton;
  rc.bottom = yButton + dy;

  for (iButton = 0, xButton = FIRSTBUTTON;
     iButton < cButtons;
     iButton++) 
  {

    PTBBUTTON ptbButton = &pAllButtons[iButton];

    if (ptbButton->fsState & TBSTATE_HIDDEN) 
    {
    /* Do nothing */ ;
    } 
    else if (ptbButton->fsStyle & TBSTYLE_SEP) 
    {
      xButton += ptbButton->iBitmap;
    } 
    else 
    {
      rc.left = xButton;
      rc.right = xButton + dx;
      if (RectVisible(hdc, &rc)) 
      {
        DrawButton(hdc, xButton, yButton, dx, dy, pTBHdr, ptbButton);
      }

      xButton += dx - 1;
    }
  }

  SelectObject(hdcGlyphs, hbmOldGlyphs);

Error1:
  EndPaint(hWnd, &ps);
}


static BOOL NEAR PASCAL GetItemRect(PTBHDR pTBHdr, UINT uButton, LPRECT lpRect)
{
  UINT iButton, xPos;
  PTBBUTTON pButton;

  if (uButton>=(UINT)pTBHdr->iNumButtons
  || (pTBHdr->Buttons[uButton].fsState&TBSTATE_HIDDEN))
  {
    return(FALSE);
  }

  xPos = FIRSTBUTTON;

  for (iButton=0, pButton=pTBHdr->Buttons; iButton<uButton;
     ++iButton, ++pButton)
  {
    if (pButton->fsState & TBSTATE_HIDDEN)
    {
      /* Do nothing */ ;
    }
    else if (pButton->fsStyle & TBSTYLE_SEP)
    {
      xPos += pButton->iBitmap;
    }
    else
    {
      xPos += pTBHdr->dxButton - 1;
    }
  }

  /* pButton should now point at the required button, and xPos should be
  * its left edge.  Note that we already checked if the button was
  * hidden above.
  */
  lpRect->left   = xPos;
  lpRect->right  = xPos + (pButton->fsStyle&TBSTYLE_SEP
          ? pButton->iBitmap : pTBHdr->dxButton);
  lpRect->top    = (pTBHdr->barHeight - pTBHdr->dyButton) / 2;
  lpRect->bottom = lpRect->top + pTBHdr->dyButton;

  return(TRUE);
}


static void NEAR PASCAL InvalidateButton(HWND hwnd, PTBHDR pTBHdr, PTBBUTTON pButtonToPaint)
{
  RECT rc;

  if (GetItemRect(pTBHdr, pButtonToPaint-pTBHdr->Buttons, &rc))
  {
    InvalidateRect(hwnd, &rc, FALSE);
  }
}


int FAR PASCAL TBHitTest(PTBHDR pTBHdr, int xPos, int yPos)
{
  int iButton;
  int cButtons = pTBHdr->iNumButtons;
  PTBBUTTON pButton;

  //
  //
  // What we do is adjust the x and y to account for
  //    the x-offset to the first button. If x is less
  //    then this value then no button is pushed.
  //
  xPos -= FIRSTBUTTON;
  if (xPos < 0)
    return(-1);

  //
  // Account for the space above and below the buttons.
  //
  //
  yPos -= ((pTBHdr->barHeight - pTBHdr->dyButton) / 2);
  if (yPos < 0 || yPos >= pTBHdr->dyButton)
    return(-1);


  //
  // xPos and yPos are now adjusted so that the first button
  // would be at 0,0 on the toolbar. Next we are going to walk the
  // butons and for each one will adjust xPos and yPos so that
  // the next button is at 0,0. If xPos or yPos are less then 0
  // no button is hit. If for any button xPos and yPos are within
  // pTBHdr->nButWidth and pTBHdr->nButHeight then the given button
  // is hit.
  //
  for (iButton=0, pButton=pTBHdr->Buttons; iButton<cButtons;
    ++iButton, ++pButton)
  {
    //
    // Ignore hidden buttons
    //
    if (pButton->fsState & TBSTATE_HIDDEN)
    ; // Do nothing
    //
    // If this is a seperator adjust by seperater width
    //
    else if (pButton->fsStyle & TBSTYLE_SEP)
      xPos -= pButton->iBitmap;
    else
    //
    // Ok this is a regular button adjust as such
    //
      xPos -= pTBHdr->dxButton - 1;

    if (xPos < 0)
    {
      if (pButton->fsStyle&TBSTYLE_SEP)
        break;

      return(iButton);
    }
  }

  return(-1 - iButton);
}


int FAR PASCAL PositionFromID(PTBHDR pTBHdr, int id)
{
  int i;
  int cButtons = pTBHdr->iNumButtons;
  PTBBUTTON pAllButtons = pTBHdr->Buttons;

  for (i = 0; i < cButtons; i++)
    if (pAllButtons[i].idCommand == id)
      return i;     // position found

  return -1;    // ID not found!
}

// check a radio button by button index.
// the button matching idCommand was just pressed down.  this forces
// up all other buttons in the group.
// this does not work with buttons that are forced up with

void NEAR PASCAL MakeGroupConsistant(HWND hWnd, PTBHDR pTBHdr, int idCommand)
{
  int i, iFirst, iLast, iButton;
  int cButtons = pTBHdr->iNumButtons;
  PTBBUTTON pAllButtons = pTBHdr->Buttons;

  iButton = PositionFromID(pTBHdr, idCommand);

  if (iButton < 0)
  return;

  // assertion
  //    if (!(pAllButtons[iButton].fsStyle & TBSTYLE_CHECK))
  // return;

  // did the pressed button just go down?
  if (!(pAllButtons[iButton].fsState & TBSTATE_CHECKED))
    return;         // no, can't do anything

  // find the limits of this radio group

  for (iFirst = iButton; (iFirst > 0) && (pAllButtons[iFirst].fsStyle & TBSTYLE_GROUP); iFirst--)
    if (!(pAllButtons[iFirst].fsStyle & TBSTYLE_GROUP))
      iFirst++;

  cButtons--;
  for (iLast = iButton; (iLast < cButtons) && (pAllButtons[iLast].fsStyle & TBSTYLE_GROUP); iLast++)
    if (!(pAllButtons[iLast].fsStyle & TBSTYLE_GROUP))
      iLast--;

  // search for the currently down button and pop it up
  for (i = iFirst; i <= iLast; i++) 
  {
    if (i != iButton) 
    {
      // is this button down?
      if (pAllButtons[i].fsState & TBSTATE_CHECKED) 
      {
        pAllButtons[i].fsState &= ~TBSTATE_CHECKED;     // pop it up
        InvalidateButton(hWnd, pTBHdr, &pAllButtons[i]);
        break;          // only one button is down right?
      }
    }
  }
}

/* Adds a new bitmap to the list of BMs available for this toolbar.
 * Returns the index of the first button in the bitmap or -1 if there
 * was an error.
 */
static int NEAR PASCAL AddBitmap(PTBHDR pTBHdr, int nButtons,
      HINSTANCE hBMInst, WORD wBMID)
{
  PTBBMINFO pTemp;
  int nBM, nIndex;

  if (pTBHdr->pBitmaps)
  {
    /* Check if the bitmap has already been added
    */
    for (nBM=pTBHdr->nBitmaps, pTemp=pTBHdr->pBitmaps, nIndex=0;
        nBM>0; nBM--, ++pTemp)
    {
      if (pTemp->hInst==hGlobalBMInst && pTemp->wID==wBMID)
      {
        /* We already have this bitmap, but have we "registered" all
        * the buttons in it?
        */
        if (pTemp->nButtons >= nButtons)
          return(nIndex);
        if (nBM == 1)
        {
          /* If this is the last bitmap, we can easily increase the
          * number of buttons without messing anything up.
          */
          pTemp->nButtons = nButtons;
          return(nIndex);
        }
      }

      nIndex += pTemp->nButtons;
    }

    pTemp = (PTBBMINFO)LocalReAlloc((HANDLE)pTBHdr->pBitmaps,
        (pTBHdr->nBitmaps+1)*sizeof(TBBMINFO), LMEM_MOVEABLE);
    if (!pTemp)
      return(-1);
    pTBHdr->pBitmaps = pTemp;
  }
  else
  {
    pTBHdr->pBitmaps = (PTBBMINFO)LocalAlloc(LPTR, sizeof(TBBMINFO));
    if (!pTBHdr->pBitmaps)
      return(-1);
  }

  pTemp = pTBHdr->pBitmaps + pTBHdr->nBitmaps;

  pTemp->hInst = hGlobalBMInst;
  pTemp->wID = wBMID;
  pTemp->nButtons = nButtons;
  pTemp->hbm = NULL;

  ++pTBHdr->nBitmaps;

  for (nButtons=0, pTemp--; pTemp>=pTBHdr->pBitmaps; pTemp--)
     nButtons += pTemp->nButtons;

  return(nButtons);
}


static BOOL NEAR PASCAL InsertButtons(HWND hWnd, PTBHDR pTBHdr,
      UINT uWhere, UINT uButtons, LPTBBUTTON lpButtons)
{
  PTBBUTTON pIn, pOut;

  if (!pTBHdr)
    return(FALSE);

  pTBHdr = (PTBHDR)LocalReAlloc((HANDLE)pTBHdr, sizeof(TBHDR)-sizeof(TBBUTTON)
      + (pTBHdr->iNumButtons+uButtons)*sizeof(TBBUTTON), LMEM_MOVEABLE);
  if (!pTBHdr)
    return(FALSE);

  SETWINDOWPOINTER(hWnd, PTBHDR, pTBHdr);

  if (uWhere > (UINT)pTBHdr->iNumButtons)
    uWhere = pTBHdr->iNumButtons;

  for (pIn=pTBHdr->Buttons+pTBHdr->iNumButtons-1, pOut=pIn+uButtons,
      uWhere=(UINT)pTBHdr->iNumButtons-uWhere; uWhere>0;
      pIn--, pOut--, uWhere--)
    *pOut = *pIn;

  for (lpButtons=lpButtons+uButtons-1, pTBHdr->iNumButtons+=(int)uButtons;
      uButtons>0;
      pOut--, lpButtons--, uButtons--)
  {
    *pOut = *lpButtons;

    if ((pOut->fsStyle&TBSTYLE_SEP) && pOut->iBitmap<=0)
      pOut->iBitmap = BUTTONSEPERATOR;
  }

  /* We need to completely redraw the toolbar at this point.
  */
  InvalidateRect(hWnd, NULL, TRUE);

  return(TRUE);
}


static BOOL NEAR PASCAL DeleteButton(HWND hWnd, PTBHDR pTBHdr, UINT uIndex)
{
  PTBBUTTON pIn, pOut;

  if (uIndex >= (UINT)pTBHdr->iNumButtons)
    return(FALSE);

  pTBHdr->iNumButtons--;
  for (pOut=pTBHdr->Buttons+uIndex, pIn=pOut+1;
    uIndex<(UINT)pTBHdr->iNumButtons; ++uIndex, ++pIn, ++pOut)
    *pOut = *pIn;

  /* We need to completely redraw the toolbar at this point.
  */
  InvalidateRect(hWnd, NULL, TRUE);

  return(TRUE);
}


LRESULT CALLBACK ToolbarWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
  BOOL fSameButton;
  PTBBUTTON ptbButton;
  PTBHDR pTBHdr;
  int iPos;
  BYTE fsState;

  pTBHdr = GETWINDOWPOINTER(hWnd, PTBHDR);

  switch (wMsg) 
  {
  case WM_CREATE:

    #define lpcs ((LPCREATESTRUCT)lParam)

    if (!CreateDitherBrush(FALSE))
      return -1;

    if (!InitGlobalObjects()) 
    {
      FreeGlobalObjects();
      return -1;
    }

    /* create the state data for this toolbar */

    pTBHdr = ALLOCWINDOWPOINTER(PTBHDR, sizeof(TBHDR)-sizeof(TBBUTTON));
    if (!pTBHdr)
      return -1;

    /* The struct is initialized to all NULL when created.
    */
    pTBHdr->hwndCommand = lpcs->hwndParent;

    SETWINDOWPOINTER(hWnd, PTBHDR, pTBHdr);

    break;

  case WM_DESTROY:
    if (pTBHdr)
    {
      PTBBMINFO pTemp;
      int i;

      /* Free all the bitmaps before exiting
      */
      for (pTemp=pTBHdr->pBitmaps, i=pTBHdr->nBitmaps-1; i>=0;
        ++pTemp, i--)
      {
        if (pTemp->hInst && pTemp->hbm)
          DeleteObject(pTemp->hbm);
      }

      FREEWINDOWPOINTER(pTBHdr);
      SETWINDOWPOINTER(hWnd, PTBHDR, 0);
    }
    FreeGlobalObjects();
    FreeDitherBrush();
    break;

  case WM_PAINT:
    ToolbarPaint(hWnd, pTBHdr);
    break;

  case WM_SIZE:
  {
    RECT rcParent;
    HWND hwndParent;

    //
    // If there is no parent, then this is a top level window
    // so don't size the toolbar
    //
    hwndParent = GetParent(hWnd);
    if (hwndParent) 
    {
      GetClientRect(hwndParent, &rcParent);

      SetWindowPos(hWnd, NULL, 0, 0,
            rcParent.right+(GetSystemMetrics(SM_CXBORDER)*2),
            pTBHdr->barHeight,
            SWP_NOZORDER);
    }

  break;
  }

  case WM_COMMAND:
  case WM_DRAWITEM:
  case WM_MEASUREITEM:
  case WM_VKEYTOITEM:
  case WM_CHARTOITEM:
    SendMessage(pTBHdr->hwndCommand, wMsg, wParam, lParam);
    break;

  case WM_LBUTTONDOWN:
#if 1 //S.Yoshida
  case WM_LBUTTONDBLCLK:
#endif

    iPos = TBHitTest(pTBHdr, LOWORD(lParam), HIWORD(lParam));
    if (iPos >= 0)
    {
      ptbButton = pTBHdr->Buttons + iPos;

      pTBHdr->pCaptureButton = ptbButton;
      SetCapture(hWnd);

      if (ptbButton->fsState & TBSTATE_ENABLED)
      {
        ptbButton->fsState |= TBSTATE_PRESSED;
        InvalidateButton(hWnd, pTBHdr, ptbButton);
        UpdateWindow(hWnd);         // imedeate feedback
      }

      SendMessage(pTBHdr->hwndCommand, WM_COMMAND, GETWINDOWID(hWnd), MAKELONG(pTBHdr->pCaptureButton->idCommand, TBN_BEGINDRAG));
    }
    break;

  case WM_MOUSEMOVE:
    if (pTBHdr->pCaptureButton!=NULL
      && (pTBHdr->pCaptureButton->fsState & TBSTATE_ENABLED)) 
    {

      iPos = TBHitTest(pTBHdr, LOWORD(lParam), HIWORD(lParam));
      fSameButton = (iPos>=0
        && pTBHdr->pCaptureButton==pTBHdr->Buttons+iPos);
      if (fSameButton == !(pTBHdr->pCaptureButton->fsState & TBSTATE_PRESSED)) 
      {
        pTBHdr->pCaptureButton->fsState ^= TBSTATE_PRESSED;
        InvalidateButton(hWnd, pTBHdr, pTBHdr->pCaptureButton);
      }
    }
    break;

  case WM_LBUTTONUP:
    if (pTBHdr->pCaptureButton != NULL) 
    {

      int idCommand;

      idCommand = pTBHdr->pCaptureButton->idCommand;

      ReleaseCapture();

      SendMessage(pTBHdr->hwndCommand, WM_COMMAND, GETWINDOWID(hWnd), MAKELONG(idCommand, TBN_ENDDRAG));

      iPos = TBHitTest(pTBHdr, LOWORD(lParam), HIWORD(lParam));
      if ((pTBHdr->pCaptureButton->fsState&TBSTATE_ENABLED) && iPos>=0
        && (pTBHdr->pCaptureButton==pTBHdr->Buttons+iPos)) 
      {
        pTBHdr->pCaptureButton->fsState &= ~TBSTATE_PRESSED;

        if (pTBHdr->pCaptureButton->fsStyle & TBSTYLE_CHECK) 
        {
          if (pTBHdr->pCaptureButton->fsStyle & TBSTYLE_GROUP) 
          {

            // group buttons already checked can't be force
            // up by the user.

            if (pTBHdr->pCaptureButton->fsState & TBSTATE_CHECKED) 
            {
              pTBHdr->pCaptureButton = NULL;
              break;  // bail!
            }

            pTBHdr->pCaptureButton->fsState |= TBSTATE_CHECKED;
            MakeGroupConsistant(hWnd, pTBHdr, idCommand);
          } 
          else 
          {
            pTBHdr->pCaptureButton->fsState ^= TBSTATE_CHECKED; // toggle
          }
        }

        InvalidateButton(hWnd, pTBHdr, pTBHdr->pCaptureButton);
        pTBHdr->pCaptureButton = NULL;
        SendMessage(pTBHdr->hwndCommand, WM_COMMAND, idCommand, 0L);
      }
      else 
      {
        pTBHdr->pCaptureButton = NULL;
      }
    }
    break;

  case TB_SETSTATE:
    iPos = PositionFromID(pTBHdr, (int)wParam);
    if (iPos < 0)
      return(FALSE);
    ptbButton = pTBHdr->Buttons + iPos;

    fsState = (BYTE)(LOWORD(lParam) ^ ptbButton->fsState);
    ptbButton->fsState = (BYTE)LOWORD(lParam);

    if (fsState & TBSTATE_HIDDEN)
      InvalidateRect(hWnd, NULL, TRUE);
    else if (fsState)
      InvalidateButton(hWnd, pTBHdr, ptbButton);
    return(TRUE);

  case TB_GETSTATE:
    iPos = PositionFromID(pTBHdr, (int)wParam);
    if (iPos < 0)
      return(-1L);
    return(pTBHdr->Buttons[iPos].fsState);

  case TB_ENABLEBUTTON:
  case TB_CHECKBUTTON:
  case TB_PRESSBUTTON:
  case TB_HIDEBUTTON:
  case TB_INDETERMINATE:

    iPos = PositionFromID(pTBHdr, (int)wParam);
    if (iPos < 0)
      return(FALSE);
    ptbButton = &pTBHdr->Buttons[iPos];
    fsState = ptbButton->fsState;

    if (LOWORD(lParam))
      ptbButton->fsState |= wStateMasks[wMsg - TB_ENABLEBUTTON];
    else
      ptbButton->fsState &= ~wStateMasks[wMsg - TB_ENABLEBUTTON];

    // did this actually change the state?
    if (fsState != ptbButton->fsState) 
    {
      // is this button a member of a group?
      if ((wMsg == TB_CHECKBUTTON) && (ptbButton->fsStyle & TBSTYLE_GROUP))
        MakeGroupConsistant(hWnd, pTBHdr, (int)wParam);

      if (wMsg == TB_HIDEBUTTON)
        InvalidateRect(hWnd, NULL, TRUE);
      else
        InvalidateButton(hWnd, pTBHdr, ptbButton);
    }
    return(TRUE);

  case TB_ISBUTTONENABLED:
  case TB_ISBUTTONCHECKED:
  case TB_ISBUTTONPRESSED:
  case TB_ISBUTTONHIDDEN:
  case TB_ISBUTTONINDETERMINATE:
    iPos = PositionFromID(pTBHdr, (int)wParam);
    if (iPos < 0)
      return(-1L);
    return (LRESULT)pTBHdr->Buttons[iPos].fsState
        & wStateMasks[wMsg - TB_ISBUTTONENABLED];

  case TB_ADDBITMAP:
    return(AddBitmap(pTBHdr, wParam,
        (HINSTANCE)LOWORD(lParam), HIWORD(lParam)));

  case TB_ADDBUTTONS:
    return(InsertButtons(hWnd, pTBHdr, (UINT)-1, wParam,
        (LPTBBUTTON)lParam));

  case TB_INSERTBUTTON:
    return(InsertButtons(hWnd, pTBHdr, wParam, 1, (LPTBBUTTON)lParam));

  case TB_DELETEBUTTON:
    return(DeleteButton(hWnd, pTBHdr, wParam));

  case TB_GETBUTTON:
    if (wParam >= (UINT)pTBHdr->iNumButtons)
      return(FALSE);

    *((LPTBBUTTON)lParam) = *(pTBHdr->Buttons+wParam);

    return(TRUE);

  case TB_BUTTONCOUNT:
    return(pTBHdr->iNumButtons);

  case TB_COMMANDTOINDEX:
    return(PositionFromID(pTBHdr, (int)wParam));

  default:
    return DefWindowProc(hWnd, wMsg, wParam, lParam);
  }

  return 0L;
}

void FAR PASCAL GetSysColors(PTBHDR pTBHdr)
{
   static COLORREF rgbSaveFace    = 0xffffffffL,
                   rgbSaveShadow  = 0xffffffffL,
                   rgbSaveHilight = 0xffffffffL,
                   rgbSaveFrame   = 0xffffffffL;
#if 1 //S.Yoshida
  static nSysColorChanges        = 0;
#endif
  int i;
  PTBBMINFO pBitmap;

  rgbFace    = GetSysColor(COLOR_BTNFACE);
  rgbShadow  = GetSysColor(COLOR_BTNSHADOW);
  rgbHilight = GetSysColor(COLOR_BTNHIGHLIGHT);
  rgbFrame   = GetSysColor(COLOR_WINDOWFRAME);

  if (rgbSaveFace!=rgbFace || rgbSaveShadow!=rgbShadow
    || rgbSaveHilight!=rgbHilight || rgbSaveFrame!=rgbFrame)
  {
#if 1 //S.Yoshida
    nSysColorChanges ++;
#endif
    rgbSaveFace    = rgbFace;
    rgbSaveShadow  = rgbShadow;
    rgbSaveHilight = rgbHilight;
    rgbSaveFrame   = rgbFrame;
#if 1 //S.Yoshida
  }
   
  if( nSysColorChanges != pTBHdr->nSysColorChanges ) 
  {
#endif
    // Update the brush for pushed-in buttons
    CreateDitherBrush(TRUE);

    /* Reset all of the bitmaps if the sys colors have changed
    * since the last time the bitmaps were created.
    */
    for (i=pTBHdr->nBitmaps-1, pBitmap=pTBHdr->pBitmaps; i>=0;
      i--, ++pBitmap)
    {
      if (pBitmap->hInst && pBitmap->hbm)
      {
        DeleteObject(pBitmap->hbm);
        pBitmap->hbm = NULL;
      }
    }
  }
}


//int   FAR PASCAL LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine);
int   FAR PASCAL WEP (int bSystemExit);

int FAR PASCAL LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine)
{

 


/*
 WNDCLASS wc;
   hInst = (HINSTANCE) hModule;
  if (!GetClassInfo(hInst, szToolbarClass, &wc)) 
  {

    wc.lpszClassName = (LPSTR)szToolbarClass;
    wc.style  = CS_DBLCLKS | CS_GLOBALCLASS;
    wc.lpfnWndProc  = (WNDPROC)ToolbarWndProc;
    wc.cbClsExtra   = 0;
    wc.cbWndExtra    = sizeof(PTBHDR);
    wc.hInstance     = hInst;
    wc.hIcon  = NULL;
    wc.hCursor   = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
    wc.lpszMenuName    = NULL;

    RegisterClass(&wc);
  } 
  
    return 1;
*/  
    HGLOBAL    hgblClassStruct;
    LPWNDCLASS lpClassStruct;
    static HINSTANCE hinstLib = 0;

    /* Has the library been initialized yet? */
  hInst = (HINSTANCE) hModule;
    if (hinstLib == NULL) 
    {
        hgblClassStruct = GlobalAlloc(GHND, sizeof(WNDCLASS));
        if (hgblClassStruct != NULL) 
        {
            lpClassStruct = (LPWNDCLASS) GlobalLock(hgblClassStruct);

            if (lpClassStruct != NULL) 
            {

                /* Define the class attributes. */

                lpClassStruct->style = CS_DBLCLKS | CS_GLOBALCLASS;
                lpClassStruct->lpfnWndProc = (WNDPROC)ToolbarWndProc;
                lpClassStruct->cbWndExtra = sizeof(PTBHDR);
                lpClassStruct->hInstance = hInst;
                lpClassStruct->hIcon = NULL;
                lpClassStruct->hCursor = LoadCursor(NULL, IDC_ARROW);

                lpClassStruct->hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
                lpClassStruct->lpszMenuName = NULL;
                lpClassStruct->lpszClassName = (LPSTR)szToolbarClass;

                hinstLib = (RegisterClass(lpClassStruct)) ?
                    hInst : NULL;

                GlobalUnlock(hgblClassStruct);
            }

            GlobalFree(hgblClassStruct);
        }
    }
    return (hinstLib ? 1 : 0);  /* return 1 = success; 0 = fail */  


}


HBITMAP NEAR PASCAL CreateDitherBitmap()
{
    PBITMAPINFO pbmi;
    HBITMAP hbm;
    HDC hdc;
    int i;
    long patGray[8];
    DWORD rgb;

    pbmi = (PBITMAPINFO)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 16));
    if (!pbmi)
        return NULL;

    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    pbmi->bmiHeader.biWidth = 8;
    pbmi->bmiHeader.biHeight = 8;
    pbmi->bmiHeader.biPlanes = 1;
    pbmi->bmiHeader.biBitCount = 1;
    pbmi->bmiHeader.biCompression = BI_RGB;

    rgb = GetSysColor(COLOR_BTNFACE);
    pbmi->bmiColors[0].rgbBlue  = GetBValue(rgb);
    pbmi->bmiColors[0].rgbGreen = GetGValue(rgb);
    pbmi->bmiColors[0].rgbRed   = GetRValue(rgb);
    pbmi->bmiColors[0].rgbReserved = 0;

    rgb = GetSysColor(COLOR_BTNHIGHLIGHT);
    pbmi->bmiColors[1].rgbBlue  = GetBValue(rgb);
    pbmi->bmiColors[1].rgbGreen = GetGValue(rgb);
    pbmi->bmiColors[1].rgbRed   = GetRValue(rgb);
    pbmi->bmiColors[1].rgbReserved = 0;


    /* initialize the brushes */

    for (i = 0; i < 8; i++)
       if (i & 1)
           patGray[i] = 0xAAAA5555L;   //  0x11114444L; // lighter gray
       else
           patGray[i] = 0x5555AAAAL;   //  0x11114444L; // lighter gray

    hdc = GetDC(NULL);

    hbm = CreateDIBitmap(hdc, &pbmi->bmiHeader, CBM_INIT, patGray, pbmi, DIB_RGB_COLORS);

    ReleaseDC(NULL, hdc);

#ifdef _WIN32
    LocalFree((HANDLE)pbmi);
#else
   LocalFree((HLOCAL)pbmi);    
#endif

    return hbm;
}

BOOL FAR PASCAL CreateDitherBrush(BOOL bIgnoreCount)
{
  HBITMAP hbmGray;
  HBRUSH hbrSave;

  if (bIgnoreCount && !iDitherCount)
  {
    return TRUE;
  }

  if (iDitherCount>0 && !bIgnoreCount)
  {
    iDitherCount++;
    return TRUE;
  }

  hbmGray = CreateDitherBitmap();
  if (hbmGray)
  {
    hbrSave = hbrDither;
    hbrDither = CreatePatternBrush(hbmGray);
    DeleteObject(hbmGray);
    if (hbrDither)
    {
      if (hbrSave)
      {
        DeleteObject(hbrSave);
      }
      if (!bIgnoreCount)
      {
        iDitherCount = 1;
      }
      return TRUE;
    }
    else
    {
      hbrDither = hbrSave;
    }
  }

  return FALSE;
}

BOOL FAR PASCAL FreeDitherBrush(void)
{
    iDitherCount--;

    if (iDitherCount > 0)
        return FALSE;

    DeleteObject(hbrDither);
    hbrDither = NULL;

    return TRUE;
}

typedef struct tagCOLORMAP
{
    COLORREF bgrfrom;
    COLORREF bgrto;
    COLORREF sysColor;
} COLORMAP;

// these are the default colors used to map the dib colors
// to the current system colors

#define BGR_BUTTONTEXT      (RGB(000,000,000))  // black
#define BGR_BUTTONSHADOW    (RGB(128,128,128))  // dark grey
#define BGR_BUTTONFACE      (RGB(192,192,192))  // bright grey
#define BGR_BUTTONHILIGHT   (RGB(255,255,255))  // white
#define BGR_BACKGROUNDSEL   (RGB(255,000,000))  // blue
#define BGR_BACKGROUND      (RGB(255,000,255))  // magenta
#define FlipColor(rgb)      (RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb)))

HBITMAP WINAPI CreateMappedBitmap(HINSTANCE hInstance, int idBitmap )
{
  HDC           hdc, hdcMem = NULL;
  HANDLE        h;
  DWORD FAR     *p;
  LPSTR         lpBits;
  HANDLE        hRes;
  LPBITMAPINFOHEADER    lpBitmapInfo;
  HBITMAP       hbm = NULL, hbmOld;
  int numcolors, i;
  int wid, hgt;

#ifdef WIN32 //S.Yoshida
  LPVOID        hResCopy;
  int           sizeCopy;
#endif

  static COLORMAP ColorMap[] = {
  {BGR_BUTTONTEXT,    BGR_BUTTONTEXT,    COLOR_BTNTEXT},     // black
  {BGR_BUTTONSHADOW,  BGR_BUTTONSHADOW,  COLOR_BTNSHADOW},   // dark grey
  {BGR_BUTTONFACE,    BGR_BUTTONFACE,    COLOR_BTNFACE},     // bright grey
  {BGR_BUTTONHILIGHT, BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white
#if 0 //Iinuma
    {BGR_BACKGROUNDSEL, BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT},   // blue
#endif
    {BGR_BACKGROUND,    BGR_BACKGROUND,    COLOR_WINDOW}       // magenta
  };

  #define NUM_MAPS (sizeof(ColorMap)/sizeof(COLORMAP))

  h = FindResource(hInstance, MAKEINTRESOURCE(idBitmap), RT_BITMAP);
  if (!h)
    return NULL;

#ifdef WIN32 //S.Yoshida
  sizeCopy = SizeofResource( hInstance, h );
  hResCopy = GlobalAlloc( GPTR, sizeCopy );
  if (!hResCopy)
    return NULL;
#endif

  hRes = LoadResource(hInstance, h);

  /* Lock the bitmap and get a pointer to the color table. */
  lpBitmapInfo = (LPBITMAPINFOHEADER)LockResource(hRes);
  if (!lpBitmapInfo) 
  {
#ifdef WIN32 //S.Yoshida
    GlobalFree( hResCopy );
#endif
    return NULL;
  }

#ifdef WIN32 //S.Yoshida
  memcpy( hResCopy, lpBitmapInfo, sizeCopy );
  lpBitmapInfo = hResCopy;
#endif

  //
  // So what are the new colors anyway ?
  //
  for (i=0; i < NUM_MAPS; i++) 
  {
    ColorMap[i].bgrto = FlipColor(GetSysColor((int)ColorMap[i].sysColor));
  }

  p = (DWORD FAR *)(((LPSTR)lpBitmapInfo) + lpBitmapInfo->biSize);

  /* Replace button-face and button-shadow colors with the current values
  */
  numcolors = 16;

#if 0 //S.Yoshida
  /* trying to write to the colormap causes an access  */
  /* violation under WIN32 (??)                        */
  /*   so, for consistency, don't do it at all         */
#endif

#if 1 //S.Yoshida
  while (numcolors-- > 0) 
  {
    for (i = 0; i < NUM_MAPS; i++) 
    {
      if (*p == ColorMap[i].bgrfrom) 
      {
        *p = ColorMap[i].bgrto;
        break;
      }
    }
    p++;
  }
#endif

  /* First skip over the header structure */
  lpBits = (LPSTR)(lpBitmapInfo + 1);

  /* Skip the color table entries, if any */
  lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);

  /* Create a color bitmap compatible with the display device */
  i = wid = (int)lpBitmapInfo->biWidth;
  hgt = (int)lpBitmapInfo->biHeight;
  hdc = GetDC(NULL);

  hdcMem = CreateCompatibleDC(hdc);
  if (hdcMem) 
  {
    hbm = CreateCompatibleBitmap(hdc, i, hgt);
    if (hbm) 
    {
      hbmOld = SelectObject(hdcMem, hbm);

      // set the main image
      StretchDIBits(hdcMem, 0, 0, wid, hgt, 0, 0, wid, hgt, lpBits,
              (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS, SRCCOPY);

      SelectObject(hdcMem, hbmOld);
    }

    DeleteObject(hdcMem);
  }

  ReleaseDC(NULL, hdc);

  UnlockResource(hRes);
  FreeResource(hRes);
#ifdef WIN32 //S.Yoshida
  GlobalFree(hResCopy);
#endif

  return hbm;
}


#pragma alloc_text(FIXEDSEG, WEP)

//---------------------------------------------------------------------------
// WEP
//---------------------------------------------------------------------------
int FAR PASCAL WEP (int bSystemExit)
{
    return(1);
}

#ifdef _WIN32
BOOL WINAPI DllMain( HINSTANCE hinstDLL,  // handle to DLL module
          DWORD fdwReason,     // reason for calling function
          LPVOID lpReserved )  // reserved
{
    // Perform actions based on the reason for calling.
    switch( fdwReason ) 
    { 
        case DLL_PROCESS_ATTACH:
         // Initialize once for each new process.
         // Return FALSE to fail DLL load.
       hInst = hinstDLL;
            break;

        case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;

        case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;

        case DLL_PROCESS_DETACH:
         // Perform any necessary cleanup.
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}

#endif
