/******************************************************************************/
/*                                                                            */
/*  CB_FRAME - Callback for the FRAME window                                  */
/*                                                                            */
/******************************************************************************/

#define STRICT
#include <windows.h>
#include <commctrl.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include "const.h"
#include "classes.h"
#include "funcdefs.h"
#include "blocks.rh"
#include "extern.h"

static int disallow_menu = 0 ;

extern "C"

BOOL CALLBACK CloseAllProc ( HWND hwnd , LPARAM lParam ) ;

LRESULT CALLBACK FrameWndProc ( HWND hwnd , UINT message ,
                                WPARAM wParam , LPARAM lParam )
{
   int ret_val, menu_state ;
   char msg[256], filename[1024], title[256] ;
   CLIENTCREATESTRUCT ccs ;   // For creating client window
   MDICREATESTRUCT mcs ;      // For creating child window
   RECT rect ;
   HWND hwndChild ;
   Image *imgptr ;
   
   switch (message) {
       
      case WM_CREATE:                             // Create CLIENT window
         ccs.hWindowMenu = hMenuInitWindow ;
         ccs.idFirstChild = IDM_FIRSTCHILD ;
         hwndClient = CreateWindow ( "MDICLIENT" , NULL ,
            WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL ,
            0 , 0 , 0 , 0 , hwnd , NULL , hInst , (LPSTR) &ccs ) ;
         return 0 ;

      case WM_COMMAND :
         switch ( LOWORD ( wParam )) {

            case IDM_COMPUTEBLOCKSIMAGE:
               ret_val = (int) DialogBox ( hInst , "DialogBoxBlocksParams" ,
                                           hwnd , DialogBlocksParams ) ;
               if (! ret_val)
                  return 0 ;  // User canceled
               if (blocks_params.front_tone < 0.0  ||   blocks_params.front_tone > 1.0
                || blocks_params.side_tone < 0.0  ||   blocks_params.side_tone > 1.0
                || blocks_params.top_tone < 0.0  ||   blocks_params.top_tone > 1.0) {
                  MessageBox ( hwnd , "All tones must be 0-1." ,
                     "ERROR", MB_ICONEXCLAMATION | MB_OK);
                  return 0 ;  // User canceled
                  }
               if (blocks_params.height < 1.0  ||   blocks_params.height > 50.0
                || blocks_params.width < 1.0  ||   blocks_params.width > 50.0
                || blocks_params.depth < 1.0  ||   blocks_params.depth > 50.0) {
                  MessageBox ( hwnd , "All dimensions must be 1-50." ,
                     "ERROR", MB_ICONEXCLAMATION | MB_OK);
                  return 0 ;  // User canceled
                  }
               sprintf_s ( msg, "Create blocks image %d rows by %d columns, percents (%.2lf %.2lf %.2lf)  Angle=%.2lf",
                           blocks_params.nrows, blocks_params.ncols, blocks_params.height, blocks_params.width, blocks_params.depth, blocks_params.angle ) ;
               audit ( msg ) ;
               disallow_menu = 1 ;
               imgptr = new Image8 ( &blocks_params ) ;
               disallow_menu = 0 ;
               if ((imgptr == NULL)  ||  ! imgptr->valid()) {
                  if (imgptr != NULL)
                     delete imgptr ;
                  return 0 ;
                  }
               GetClientRect ( hwndClient , &rect ) ;
               sprintf_s ( title, "%d rows by %d columns, percents (%.2lf %.2lf %.2lf)  Angle=%.2lf",
                           blocks_params.nrows, blocks_params.ncols, blocks_params.height, blocks_params.width, blocks_params.depth, blocks_params.angle ) ;
               mcs.szClass = szImageClass ;
               mcs.szTitle = title ;
               mcs.hOwner = hInst ;
               mcs.x = CW_USEDEFAULT ;
               mcs.y = CW_USEDEFAULT ;
               if (rect.bottom <= rect.right) {  // Usual situation
                  mcs.cx = 2 * rect.bottom / 3 ;
                  mcs.cy = 2 * rect.bottom / 3 ;
                  }
               else {
                  mcs.cx = 2 * rect.right / 3 ;
                  mcs.cy = 2 * rect.right / 3 ;
                  }
               mcs.style = 0 ;
               mcs.lParam = (LPARAM) imgptr ;
               hwndChild = (HWND) SendMessage ( hwndClient , WM_MDICREATE ,
                                     0 , (LPARAM) (LPMDICREATESTRUCT) &mcs ) ;
               if (! hwndChild) {
                  MessageBox ( hwnd , "Insufficient memory to create blocks image" ,
                     "Abandoning this image", MB_ICONEXCLAMATION | MB_OK);
                  delete imgptr ;
                  }
               return 0 ;

            case IDM_SAVEBLOCKSIMAGE:
               filename[0] = 0 ;
               if (! save_img_file ( hwnd , filename )) // Get file name
                  return 0 ;
               hwndChild = (HWND) SendMessage ( hwndClient , WM_MDIGETACTIVE ,
                           0 , 0 ) ;
               if (hwndChild == NULL)
                  return 0 ;
               imgptr = (Image *) GetWindowLongPtr ( hwndChild , 0 ) ;
               sprintf_s ( msg, "Save blocks image file %s", filename ) ;
               audit ( msg ) ;
               disallow_menu = 1 ;
               imgptr->write_bmp ( filename ) ;     // Write the file
               disallow_menu = 0 ;
               return 0 ;

            case IDM_PRINTBLOCKSIMAGE:
               ret_val = (int) DialogBox ( hInst , "DialogBoxPrintParams" ,
                                           hwnd , DialogPrintParams ) ;
               if (! ret_val)
                  return 0 ;  // User canceled
               hwndChild = (HWND) SendMessage ( hwndClient , WM_MDIGETACTIVE , 0 , 0 ) ;
               if (hwndChild == NULL)
                  return 0 ;
               imgptr = (Image *) GetWindowLongPtr ( hwndChild , 0 ) ;
               if (initialize_for_printing ( hwnd )) // Err setting up printer?
                  return 0 ;
               disallow_menu = 1 ;
               imgptr->draw ( hwnd , 1 ) ;
               end_printing ( hwnd ) ;
               disallow_menu = 0 ;
               return 0 ;

            case IDM_CASCADE:            // Pass on arrangement command
               SendMessage ( hwndClient , WM_MDICASCADE , 0 , 0 ) ;
               return 0 ;

            case IDM_TILE:               // Pass on arrangement command
               SendMessage ( hwndClient , WM_MDITILE , 0 , 0 ) ;
               return 0 ;

            case IDM_CLOSE:  // This is a menu item, not currently used ?
               hwndChild = (HWND) SendMessage ( hwndClient , WM_MDIGETACTIVE ,
                           0 , 0 ) ;
               SendMessage ( hwndClient , WM_MDIDESTROY ,
                             (WPARAM) hwndChild , 0 ) ;
               return 0 ;

            case IDM_CLOSEALL:           // Close all child windows
               EnumChildWindows ( hwndClient , CloseAllProc , 0 ) ;
               return 0 ;

            case IDM_EXIT:               // Exit to Windows
               PostMessage ( hwnd , WM_CLOSE , 0 , 0 ) ;
               return 0 ;

            case IDM_ABOUT:
               modal_dialog_is_active = 1 ;
               DialogBox ( hInst , "DialogBoxAbout" , hwnd , DialogAbout ) ;
               modal_dialog_is_active = 0 ;
               return 0 ;

            default: // This is under WM_COMMAND.  Pass msg to active child.
               hwndChild = (HWND) SendMessage ( hwndClient , WM_MDIGETACTIVE ,
                           0 , 0 ) ;
               if (IsWindow ( hwndChild ))
                  SendMessage ( hwndChild , WM_COMMAND , wParam , lParam ) ;
               break ;   // Must also let DefFrameProc see it
            } // Switch on WM_COMMAND
         break ; // Case WM_COMMAND ;
              
      case WM_CLOSE:
         // If we allow the user to abort CLOSEALL, check here to see if any left
         SendMessage ( hwnd , WM_COMMAND , IDM_CLOSEALL , 0 ) ;
         break ;  // DefFrameProc will call DestroyWindow

      case WM_DESTROY:
         DestroyMenu ( hMenuInit ) ;  // Not needed?
         PostQuitMessage ( 0 ) ;
         return 0 ;

      case WM_INITMENUPOPUP :
         if (GetSubMenu(GetMenu(hwnd), (int) lParam) == hMenuInitFile) {
            hwndChild = (HWND) SendMessage ( hwndClient , WM_MDIGETACTIVE , 0 , 0 ) ;
            menu_state = (hwndChild != NULL)  ?   MF_ENABLED : MF_GRAYED ;
            EnableMenuItem ( (HMENU) wParam , IDM_SAVEBLOCKSIMAGE , menu_state ) ;
            EnableMenuItem ( (HMENU) wParam , IDM_PRINTBLOCKSIMAGE , menu_state ) ;
            if (disallow_menu) {
               EnableMenuItem ( (HMENU) wParam , IDM_COMPUTEBLOCKSIMAGE , MF_GRAYED ) ;
               EnableMenuItem ( (HMENU) wParam , IDM_SAVEBLOCKSIMAGE , MF_GRAYED ) ;
               EnableMenuItem ( (HMENU) wParam , IDM_PRINTBLOCKSIMAGE , MF_GRAYED ) ;
               EnableMenuItem ( (HMENU) wParam , IDM_EXIT , MF_GRAYED ) ;
               }
            }
         return 0 ;
      } // Switch on message

   return DefFrameProc ( hwnd , hwndClient , message , wParam , lParam ) ;
}

/*
--------------------------------------------------------------------------------

   Local routine called by EnumChildWindows to close all

--------------------------------------------------------------------------------
*/

BOOL CALLBACK CloseAllProc ( HWND hwnd , LPARAM /* lParam */ )
{
/*
   The first step here is tricky.  If a child window has been minimized, its
   icon is owned by the child.  Nevertheless, the icon appears in the
   enumeration.  So we must check for this situation to avoid two destroys.
*/

   if (GetWindow ( hwnd , GW_OWNER ))  // Child window cannot be owned
      return 1 ;                       // Check for icon title (Petzold pg 893)
                                       // Also see v. 1 pg 570

   // Here is where we could ask the user for verification of close
   SendMessage ( hwndClient , WM_MDIDESTROY , (WPARAM) hwnd , 0 ) ;
   return 1 ;  // Flag to continue enumerating
}
