/* @(#) 1.49 nt/src/docshell/WinShell.cpp, odshell, od96nt, odnt9712d 1/24/97 15:11:29 [3/21/97 17:16:32] */
//====START_GENERATED_PROLOG======================================
//
//
//   COMPONENT_NAME: odshell
//
//   CLASSES: none
//
//   ORIGINS: 27
//
//
//   (C) COPYRIGHT International Business Machines Corp. 1995,1996
//   All Rights Reserved
//   Licensed Materials - Property of IBM
//   US Government Users Restricted Rights - Use, duplication or
//   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//   	
//   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
//   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
//   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
//   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
//   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
//   OR PERFORMANCE OF THIS SOFTWARE.
//
//====END_GENERATED_PROLOG========================================
//


//------------------------------------------------------------------------------
// This file contains the implementation of Windows specific OpenDocShell and 
// ApplicationShell methods.
//------------------------------------------------------------------------------

#ifndef SOM_Module_winshell_Source
#define SOM_Module_winshell_Source
#endif
#define WinShell_Class_Source

#include <windows.h>
#include "DocShell.h"

#include <AltPoint.h>
#include <ODSessn.xh>
#include <Shape.xh>
#include <PlfmFile.h>
#include <WinStat.xh>
#include <ODRes.h>
#include <TempObj.h>
#include <draftwn.h>
#include <odres.h>
#include <CmdDefs.xh>
#include <WinStat.xh>
#include <MenuBar.xh>

#define VARIABLE_MACROS
#include "winshell.xih"

/* System property sheet */
#include <commctrl.h>
#include <prsht.h>

/* Shell Dialog Utility Function prototypes */
#include "ShellUtl.h"

#define OD_RESOURCE_DLL "ODRES.DLL"

#undef LOGGING
#define LOGGING 1

//------------------------------------------------------------------------------
// CreateMenuBar
//
//	Creates the default OpenDoc menu bar and installs it in the
//	WindowState object.
//------------------------------------------------------------------------------
SOM_Scope void  SOMLINK WinShellCreateMenuBar(WinShell *somSelf,  
                                               Environment *ev)
{
    WinShellMethodDebug("WinShell","WinShellCreateMenuBar");
    
    const ODUShort nMenuIDs = 7;		
    ODMenuIDInfo *menuIDs = new ODMenuIDInfo[nMenuIDs];
		
    const ODUShort nPopupIDs = 2;		
    ODMenuIDInfo *popupIDs = new ODMenuIDInfo[nPopupIDs];

    try
    {

        WindowSystemData *windowSystemData = somSelf->GetWindowSystemData(ev);

        // Load the menu and accelerator table
        ODPlatformMenuBar menu = LoadMenu(windowSystemData->resInstance, 
				MAKEINTRESOURCE(ID_BASEMENUBAR));
        ODPlatformMenu popupMenu = LoadMenu(windowSystemData->resInstance,
                                MAKEINTRESOURCE(ID_BASEPOPUP));
	popupMenu = GetSubMenu(popupMenu, 0);
        HACCEL accelTable = LoadAccelerators(windowSystemData->resInstance, 
				MAKEINTRESOURCE(ID_ACCELTABLE));

        // Save these in the WindowSystemData structure
        windowSystemData->menu = menu;
        windowSystemData->accelTable = accelTable;
        somSelf->SetWindowSystemData(ev, windowSystemData);

        // Set up the menu ID info
	menuIDs[0].hMenu = GetSubMenu(menu, 0);
	menuIDs[0].id    = IDMS_DOCUMENT;

	menuIDs[1].hMenu = GetSubMenu(menuIDs[0].hMenu, 6);
	menuIDs[1].id    = DOC_DRAFTS;

	menuIDs[2].hMenu = GetSubMenu(menu, 1);
	menuIDs[2].id    = IDMS_EDIT;

	menuIDs[3].hMenu = GetSubMenu(menuIDs[2].hMenu, 8);
	menuIDs[3].id    = EDIT_LINK_MENU;

	menuIDs[4].hMenu = GetSubMenu(menu, 2);
	menuIDs[4].id    = IDMS_VIEW;

	menuIDs[5].hMenu = GetSubMenu(menuIDs[4].hMenu, 1);
	menuIDs[5].id    = VIEW_SHOWAS;

	menuIDs[6].hMenu = GetSubMenu(menu, 3);
	menuIDs[6].id    = IDMS_HELP;

        // Set up the popup ID info
	popupIDs[0].hMenu = GetSubMenu(popupMenu, 1);
	popupIDs[0].id    = VIEW_SHOWAS;

	popupIDs[1].hMenu = GetSubMenu(popupMenu, 4);
	popupIDs[1].id    = IDMS_HELP;
    
        // Get the WindowState and MenuBar objects
        ODWindowState *winState = somSelf->GetWindowState(ev);
        ODMenuBar *menuBar = winState->CreateMenuBarEx(ev, menu, nMenuIDs, menuIDs);

        // Set the default accelerator table
        menuBar->SetAccelTable(ev, accelTable);

        // Set the base menu bar for this session
        winState->SetBaseMenuBar(ev, menuBar);

        // Set the popup menu
        ODPopup *popup = winState->CreatePopupMenuEx(ev, popupMenu, nPopupIDs, popupIDs);
        winState->SetBasePopup(ev, popup);

    }
    catch (ODException _exception)
    {
        LOG("SOM exception occured in WinShell::CreateMenuBar\n");
	ODSetSOMException(ev, _exception);
    }

}

//------------------------------------------------------------------------------
// InitWindowSystem
//
//	Performs any initialization required by the window system, in this
//	case Win32.  Since the root part is creating the "frame window" there's
//	not much to do here but initialize some data.
//------------------------------------------------------------------------------
SOM_Scope void  SOMLINK WinShellInitWindowSystem(WinShell *somSelf, 
                                                        Environment *ev)
{
    WinShellMethodDebug("WinShell","WinShellInitWindowSystem");
    WinShellData *somThis = WinShellGetData(somSelf);

    _fLastSelectedID = 0;

    WindowSystemData *windowSystemData;

    HINSTANCE resInstance = kODNULL;
    try
    {
        // Ensure the Common Control dynamic link library is loaded.
        InitCommonControls();

        // Call utility function to set this for other dialog utility functions
        // in WinUtil.cpp to use, independent of the shell classes.
        SetShell(somSelf);

        // Load the resource file
        resInstance = LoadLibrary(OD_RESOURCE_DLL);
   
        if (!resInstance)
           WARNMSG(WARN_INDEX(AMSG_914), 
                   "Docshell: Error loading resource file %s.", 
                   OD_RESOURCE_DLL);

        // Initialize the platform-specific window system data structure
        // with our parent window and our WindowProc
        windowSystemData = somSelf->GetWindowSystemData(ev);
        windowSystemData->parentWindow = HWND_DESKTOP;
        windowSystemData->windowProc = ODDocumentWindowProc;
        windowSystemData->resInstance = resInstance;
	// Must turn on display of windows now
	windowSystemData->showToScreen = TRUE;
        somSelf->SetWindowSystemData(ev, windowSystemData);

    }
    catch (ODException _exception)
    {
        LOG("SOM exception occured in WinShell::InitWindowSystem\n");

        // Free the resource file
        if (resInstance)
           FreeLibrary(resInstance);

	ODSetSOMException(ev, _exception);
    }

}

//------------------------------------------------------------------------------
// Exec
//
//	Start a new process with the given command line.
//------------------------------------------------------------------------------
SOM_Scope void  SOMLINK WinShellExec(WinShell *somSelf, 
                                     Environment *ev,
				     char *str)
{
    WinShellMethodDebug("WinShell","WinShellDocumentNew");
    
    // Exec new process using command in str.
    WinExec( str, SW_SHOW );
}

//------------------------------------------------------------------------------
// MainLoop
//
//	Run the standard event dispatching loop
//------------------------------------------------------------------------------
SOM_Scope ODSLong  SOMLINK WinShellMainLoop(WinShell *somSelf,  Environment *ev)
{
    WinShellMethodDebug("WinShell","WinShellMainLoop");

    MSG                 msg;
    ODMenuBar*          menuBar = kODNULL;
    ODWindowState*      winState;

  try
  {
    winState = somSelf->GetWindowState(ev);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        // Get a handle on the active part's menubar.
        menuBar  = winState->AcquireCurrentMenuBar(ev);
	if (menuBar) {
            if (!TranslateAccelerator(
                      somSelf->GetEventWindow(ev, (ODEventData*) &msg),
                      menuBar->GetAccelTable(ev),
                      &msg))
            {
              TranslateMessage(&msg);
              DispatchMessage(&msg);
            }
            ODReleaseObject (ev, menuBar);
	}
	else {
              TranslateMessage(&msg);
              DispatchMessage(&msg);
	}
    }
  }
  catch (ODException _exception)
  {
    LOG("SOM exception occured in WinShell::MainLoop\n");
    ODError error = ErrorCode();
    if (menuBar)
       SaveAndRestoreEv1(menuBar);
    ODSetSOMException(ev, error);
  }

    return msg.wParam;
}

//------------------------------------------------------------------------------
// DispatchEvent
//
//      Forward the event the the dispatcher but look for and act upon
//      events that are of interest to us.
//------------------------------------------------------------------------------
SOM_Scope ODBoolean  SOMLINK WinShellDispatchEvent(WinShell *somSelf, 
                                                   Environment *ev, 
                                                   ODEventData* event)
{
    WinShellMethodDebug("WinShell","WinShellDispatchEvent");
    WinShellData *somThis = WinShellGetData(somSelf);

    ODBoolean handled = kODTrue;

    try
    {
        ODDispatcher* dispatcher = somSelf->GetDispatcher(ev);

        switch (somSelf->GetEventType(ev, event))
        {
            case kODEvtHelp:	// aka WM_HELP
            {
                int helpContext;
                LPHELPINFO lphi = (LPHELPINFO)event->lParam;
                helpContext = lphi->iContextType;

                if (helpContext == HELPINFO_MENUITEM)     // if Menu Item help
                    SendMessage(somSelf->GetEventWindow(ev, event),
                                        OD_HELP, HLPM_ODMENU, _fLastSelectedID);
                else if (helpContext == HELPINFO_WINDOW)  // if Window item help
                    SendMessage(somSelf->GetEventWindow(ev, event),
                                        OD_HELP, HLPM_ODWINDOW, lphi->iCtrlId);
                break;
            }
            case WM_MENUSELECT:
	    {
		// cache info on selected menu, to be used later by WM_HELP above.

		UINT  flags   = (UINT)  HIWORD(event->wParam);
		UINT  posOrID = (UINT)  LOWORD(event->wParam);
		HMENU menu    = (HMENU) event->lParam;

		if (flags & MF_POPUP)
		{
		    menu = GetSubMenu(menu, posOrID);
		    _fLastSelectedID = (ODMenuItemID) GetMenuContextHelpId(menu);
		}
		else
		{
		    _fLastSelectedID = posOrID;
		}

                handled = WinShell_parents_DispatchEvent(somSelf, ev, event);
		break;
	    }
            default:
            {
                handled = WinShell_parents_DispatchEvent(somSelf, ev, event);
            }
        }
    }

    catch (ODException _exception)
    {
        LOG("SOM exception occured in WinShell::DispatchEvent.\n");
        ODSetSOMException(ev, _exception);
    }

    return handled;

}

//------------------------------------------------------------------------------
// GetEventType
//
//	Returns the message number parameter from the event structure
//------------------------------------------------------------------------------
SOM_Scope ODULong  SOMLINK WinShellGetEventType(WinShell *somSelf, 
                                                       Environment *ev, 
                                                      ODEventData* event)
{
    WinShellMethodDebug("WinShell","WinShellGetEventType");

    return (event->message);
}

//------------------------------------------------------------------------------
// GetEventSubType
//
//	Returns the wParam parameter from the event structure
//------------------------------------------------------------------------------
SOM_Scope ODULong  SOMLINK WinShellGetEventSubType(WinShell *somSelf, 
                                                          Environment *ev, 
                                                         ODEventData* event)
{
    WinShellMethodDebug("WinShell","WinShellGetEventSubType");

    return (LOWORD(event->wParam));
}

//------------------------------------------------------------------------------
// GetEventWindow
//
//	Returns the window from the event structure
//------------------------------------------------------------------------------
SOM_Scope ODPlatformWindow  SOMLINK WinShellGetEventWindow(WinShell *somSelf, 
                                                    Environment *ev, 
                                                   ODEventData* event)
{
    WinShellMethodDebug("WinShell","WinShellGetEventWindow");
    
    return ((ODPlatformWindow)event->hwnd); 

}

//------------------------------------------------------------------------------
// DocumentClose
//
//	This method is invoked when the Close item is selected from the
//	document menu.  We send ourselves a WM_CLOSE message so that the
//	document closing process can be handled uniformly whether or not
//	the close comes from the user or the window system.
//------------------------------------------------------------------------------
SOM_Scope void  SOMLINK WinShellDocumentClose(WinShell *somSelf, 
                                               Environment *ev)
{
    WinShellMethodDebug("WinShell","WinShellDocumentClose");

    try
    {
        // Send message for our event dispatching method to process.  It will
        // invoke the ConfirmCloseDlg utility to post confirm dialog.
        ODWindowState* winState = somSelf->GetWindowState(ev);
        TempODWindow   window   = winState->AcquireActiveWindow(ev);

        PostMessage(window->GetPlatformWindow(ev), 
		    WM_CLOSE, kODCommandCloseDlg, 0);

    }
    catch (ODException _exception)
    {
        LOG("SOM exception occured in WinShell::DocumentClose\n");
	ODSetSOMException(ev, _exception);
    }
}


//------------------------------------------------------------------------------
// CloseCleanup
//
//      Perform cleanup tasks not done in other methods during the close
//	process.
//------------------------------------------------------------------------------
SOM_Scope void  SOMLINK WinShellCloseCleanup(WinShell *somSelf,  
                                               Environment *ev)
{
    WinShellMethodDebug("WinShell","WinShellCloseCleanup");

    PostQuitMessage(0);
}
