/*===========================================================================*/
/*                                                                           */
/* File    : TOOLBOX.C                                                       */
/*                                                                           */
/* Purpose : Implements a Windows "toolbox" control class.                   */
/*                                                                           */
/* History :                                                                 */
/*                                                                           */
/* (C) Copyright 1991      Marc Adler/Magma Systems     All Rights Reserved  */
/*===========================================================================*/

#include <memory.h>
#include <windows.h>
#include "ico.h"


HWND hWndTool;       /* drawing-tool toolbox  */
TOOLBOX ToolBox =
{
  2, 40, 40
};

HWND hWndColor;      /* color palette toolbox */
TOOLBOX ColorBox =
{
  2, 40, 40
};


/****************************************************************************/
/*                                                                          */
/* Function : ToolboxInit()                                                 */
/*                                                                          */
/* Purpose  : Initializes the two toolboxes which IKE uses.                 */
/*                                                                          */
/* Returns  : TRUE if successful, FALSE if not.                             */
/*                                                                          */
/****************************************************************************/
BOOL PASCAL ToolboxInit(HWND hWnd)
{
  HWND hButtonTool, hButtonColor;
  int  i;

  /*
    Create the drawing-tools toolbox
  */
  hWndTool = CreateWindow("ToolBox",
                          (LPSTR) "Drawing Tools",
                          WS_CHILD | WS_BORDER | WS_CAPTION | 
                          WS_OVERLAPPED | WS_VISIBLE | WS_CLIPSIBLINGS,
                          5, 272,
                          ToolBox.cxButton*4 + 2*GetSystemMetrics(SM_CXBORDER),
                          ToolBox.cyButton*2 + GetSystemMetrics(SM_CYCAPTION)
                                             + 2*GetSystemMetrics(SM_CYBORDER),
                          hWnd,
                          100,
                          hInst,
                          (LPSTR) &ToolBox);
  if (!hWndTool)
  {
    MessageBox(hWnd, "Can't create hWndTool", NULL, MB_OK);
    return FALSE;
  }

  /*
    Add each button to the drawing-tools toolbox
  */
  hButtonTool = (HWND) 
    SendMessage(hWndTool, TBM_CREATEBUTTON, ID_PENCIL, (LONG)(LPSTR)"Pencil");
  SendMessage(hWndTool, TBM_CREATEBUTTON, ID_LINE, (LONG)(LPSTR)"Line");
  SendMessage(hWndTool, TBM_CREATEBUTTON, ID_OPENRECT,(LONG)(LPSTR)"OpenRect");
  SendMessage(hWndTool, TBM_CREATEBUTTON, ID_FILLRECT,(LONG)(LPSTR)"FillRect");
  SendMessage(hWndTool, TBM_CREATEBUTTON, ID_CIRCLE, (LONG)(LPSTR)"Circle");
  SendMessage(hWndTool, TBM_CREATEBUTTON, ID_FILLCIRC,(LONG)(LPSTR)"FillCirc");
  SendMessage(hWndTool, TBM_CREATEBUTTON, ID_SELECT,  (LONG)(LPSTR)"Net");
  SendMessage(hWndTool, TBM_CREATEBUTTON, ID_FLOOD,   (LONG)(LPSTR)"Floodfill");

  /*
    Create the color palette toolbox
  */
  hWndColor = CreateWindow("ToolBox",
                          (LPSTR) "Colors",
                          WS_CHILD | WS_BORDER | WS_CAPTION | 
                          WS_OVERLAPPED | WS_VISIBLE | WS_CLIPSIBLINGS,
                          176, 272,
                          ToolBox.cxButton*8 + 2*GetSystemMetrics(SM_CXBORDER),
                          ToolBox.cyButton*2 + GetSystemMetrics(SM_CYCAPTION)
                                             + 2*GetSystemMetrics(SM_CYBORDER),
                          hWnd,
                          200,
                          hInst,
                          (LPSTR) &ColorBox);
  if (!hWndColor)
  {
    MessageBox(hWnd, "Can't create hWndColor", NULL, MB_OK);
    return FALSE;
  }

  /*
    Add the buttons to the palette toolbox
  */
  hButtonColor = (HWND) 
    SendMessage(hWndColor, TBM_CREATEBUTTON, ID_COLOR0,  MAKELONG(0, 0));
  for (i = 1;  i <= 15;  i++)
    SendMessage(hWndColor, TBM_CREATEBUTTON, ID_COLOR0 + i, MAKELONG(0, i));

  ShowWindow(hWnd, SW_NORMAL);
  UpdateWindow(hWnd);

  /*
    Set the pencil and color 0 as the startup choices
  */
  SendMessage(hWndTool,  WM_COMMAND, ID_PENCIL, 
              MAKELONG(hButtonTool, BN_CLICKED));
  SendMessage(hWndColor, WM_COMMAND, ID_COLOR0, 
              MAKELONG(hButtonColor, BN_CLICKED));

  return TRUE;
}


/****************************************************************************/
/*                                                                          */
/* Function : ToolBoxWndProc()                                              */
/*                                                                          */
/* Purpose  : Window proc for the toolbox class.                            */
/*                                                                          */
/* Returns  :                                                               */
/*                                                                          */
/****************************************************************************/
LONG FAR PASCAL ToolBoxWndProc(hWnd, message, wParam, lParam)
  HWND hWnd;
  unsigned message;
  WORD wParam;
  LONG lParam;
{
  LPDRAWITEMSTRUCT lpDIS;
  LPCREATESTRUCT   lpCS;
  LPTOOLBOX        lpTB, lpSrcTB;
  HANDLE           hTB;
  char             szBuf[64];
  HWND             hButton;
  HICON            hIcon;
  WORD             i;


  switch (message)
  {
    case WM_CREATE        :
      /*
        When the toolbox is created, we must allocate a TOOLBOX structure
        and attach it to the window. We copy the TOOLBOX structure which
        was passed in the lpCreateParams over to this private data area.
      */
      hTB = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, (DWORD) sizeof(TOOLBOX));
      SetWindowWord(hWnd, 0, hTB);
      lpTB = (LPTOOLBOX) GlobalLock(hTB);
      lpSrcTB = (LPTOOLBOX) ((LPCREATESTRUCT) lParam)->lpCreateParams;
      _fmemcpy(lpTB, (LPSTR) lpSrcTB, sizeof(TOOLBOX));
      lpTB->nButtons = 0;
      GlobalUnlock(hTB);
      break;


    case TBM_CREATEBUTTON :
      /*
        wParam is the id of the button
        lParam is a far pointer to the icon name or to a color
      */
      hTB = GetWindowWord(hWnd, 0);
      lpTB = (LPTOOLBOX) GlobalLock(hTB);

      /*
        Create a button window.
      */
      hButton = CreateWindow("button",
                             NULL, /* (LPSTR) HIWORD(lParam),*/
                             WS_CHILD | BS_PUSHBUTTON | BS_OWNERDRAW,
                             lpTB->nButtons / lpTB->nRows * lpTB->cxButton,
                             lpTB->nButtons % lpTB->nRows * lpTB->cyButton,
                             lpTB->cxButton,
                             lpTB->cyButton,
                             hWnd,
                             wParam,
                             hInst,
                             NULL);

      /*
        Load the drawing-tool icon or attach a color value.
      */
      if (LOWORD(lParam) != 0)
        lpTB->toolInfo[lpTB->nButtons].hData = LoadIcon(hInst, (LPSTR)lParam);
      else
        lpTB->toolInfo[lpTB->nButtons].hData = HIWORD(lParam);

      /*
        Attach the control id and a tool style
      */
      lpTB->toolInfo[lpTB->nButtons].idTool = wParam;
      lpTB->toolInfo[lpTB->nButtons].wToolStyle =
                       (LOWORD(lParam) == 0) ? TOOL_COLOR : TOOL_ICON;
      lpTB->nButtons++;

      ShowWindow(hButton, SW_SHOW);
      GlobalUnlock(hTB);
      return hButton;


    case WM_COMMAND :
      hTB = GetWindowWord(hWnd, 0);
      lpTB = (LPTOOLBOX) GlobalLock(hTB);

      /*
        If a button was clicked, then it should be the currently
        selected tool.
      */
      if (HIWORD(lParam) == BN_CLICKED)
      {
        hButton = lpTB->hwndSelectedTool;
        lpTB->hwndSelectedTool = LOWORD(lParam);
        lpTB->idSelectedTool = wParam;
        if (hButton)  /* redraw the old tool in an unselected state */
        {
          InvalidateRect(hButton, (LPRECT) NULL, TRUE);
          UpdateWindow(hButton);
        }
        InvalidateRect(lpTB->hwndSelectedTool, (LPRECT) NULL, TRUE);
        UpdateWindow(lpTB->hwndSelectedTool);
      }

      GlobalUnlock(hTB);
      SendMessage(GetParent(hWnd), WM_COMMAND, wParam, lParam);
      break;

    case WM_DRAWITEM :
      hTB = GetWindowWord(hWnd, 0);
      lpTB = (LPTOOLBOX) GlobalLock(hTB);
      lpDIS = (LPDRAWITEMSTRUCT) lParam;

      /*
        We have the id of the button. Map that into the proper button
        structure.
      */
      for (i = 0;  i < lpTB->nButtons;  i++)
        if (lpTB->toolInfo[i].idTool == lpDIS->CtlID)
          break;

      /*
        Draw the button
      */
      if (i < lpTB->nButtons)
        DrawUserButton(lpDIS->hwndItem, lpDIS->hDC,
                       &lpDIS->rcItem, lpDIS->CtlID,
                       lpDIS->itemState,
                       lpTB->toolInfo[i].hData,
                       lpTB->toolInfo[i].wToolStyle,
                       (lpDIS->CtlID == lpTB->idSelectedTool));

      GlobalUnlock(hTB);
      break;


    case WM_DESTROY:
      hTB = GetWindowWord(hWnd, 0);
      /*
        ==> We should destroy the icon too!
      */
      GlobalFree(hTB);
      break;

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


/****************************************************************************/
/*                                                                          */
/* Function : DrawUserButton()                                              */
/*                                                                          */
/* Purpose  : Called in response to the WM_DRAWITEM message in order to     */
/*            render a toolbox button.                                      */
/*                                                                          */
/* Returns  : Blah.                                                         */
/*                                                                          */
/****************************************************************************/
VOID PASCAL DrawUserButton(HWND hWnd, HDC hDC, LPRECT lpRect, int idCtrl,
                    WORD iState, HANDLE hData, WORD wStyle, BOOL bCurrent)
{
  HDC     hMemDC;
  RECT    rc;
  HBITMAP hBitmap, hOldBitmap;
  BITMAP  bm;
  extern  BYTE rgb[16][3];

  /*
    The rect should be 0,0,39,39.
  */
  CopyRect((LPRECT) &rc, lpRect); 
  FillRect(hDC, (LPRECT) &rc,
           (HBRUSH) GetStockObject(bCurrent ? BLACK_BRUSH : WHITE_BRUSH));

  /*
    We want to use 0,0,37,37 to draw the frame.
  */
  InflateRect((LPRECT) &rc, -1, -1);   /* 1,1,38,38 */
  if (iState & ODS_SELECTED)
    OffsetRect((LPRECT) &rc, 1, 1); 
  else
    OffsetRect((LPRECT) &rc, -1, -1);  /* 0,0,37,37 */
  FrameRect(hDC, (LPRECT) &rc, (HBRUSH) GetStockObject(BLACK_BRUSH));

  /*
    Now, draw a black box inside the rect at 2,2,36,36
  */
  rc.left += 2;  rc.top += 2; rc.bottom -= 1; rc.right -= 1;
  FillRect(hDC, (LPRECT) &rc, (HBRUSH) GetStockObject(GRAY_BRUSH));

  /*
    Now, draw a gray  box inside the rect at 2,2,34,34
  */
  rc.right -= 2;  rc.bottom -= 2;
  FillRect(hDC, (LPRECT) &rc, (HBRUSH) GetStockObject(LTGRAY_BRUSH));


  if (wStyle == TOOL_ICON)
    /*
      Draw the icon inside of the button
    */
    DrawIcon(hDC, rc.left, rc.top, (HICON) hData);
  else if (wStyle == TOOL_COLOR)
  {
    /*
      Fill a color button with a solid colored rectangle
    */

    HBRUSH hBrush, hOldBrush;

    hBrush = CreateSolidBrush(RGB(rgb[hData][2], rgb[hData][1], rgb[hData][0]));
    hOldBrush = SelectObject(hDC, hBrush);
    InflateRect((LPRECT) &rc, -1, -1);
    FillRect(hDC, (LPRECT) &rc, hBrush);
    SelectObject(hDC, hOldBrush);
    DeleteObject(hBrush);
  }  
}
