/* @(#)Z 1.26 nt/src/ui/StdDispW.cpp, odui, od96nt, odnt9712d 97/03/21 17:13:53 (97/03/14 15:23:53) */
//====START_GENERATED_PROLOG======================================
//
//
//   COMPONENT_NAME: odui
//
//   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========================================
//
/*
        File:           StdDispW.cpp

        Contains:       Implementation of SOM-ized standard
                        dispatch module for WIN32

        Owned by:       Lance Purple

        Copyright:      (c) 1996 International Business Machines, Inc.

        Change History (most recent first):

        <1>  3/25/96  LP  Generate empty methods from StdDispW.idl;
                          Fill in with code from DR4 StdDisp.cpp
                          and Novell stddispm.cpp
*/

#define ODStdWinDispatchModule_Class_Source

#define VARIABLE_MACROS

#include <StdDispW.xih>

#ifndef SOM_ODArbitrator_xh
#include <Arbitrat.xh>
#endif

#ifndef SOM_ODDispatcher_xh
#include <Disptch.xh>
#endif

#ifndef _DSPUTILM_
#include <dsputilm.h>
#endif

#ifndef SOM_ODFacet_xh
#include <Facet.xh>
#endif

#ifndef SOM_ODFacetIterator_xh
#include <FacetItr.xh>
#endif

#ifndef SOM_Module_OpenDoc_Foci_defined
#include <Foci.xh>
#endif

#ifndef SOM_ODFrame_xh
#include <Frame.xh>
#endif

#ifndef SOM_ODFrameFacetIterator_xh
#include <FrFaItr.xh>
#endif

#ifndef SOM_ODPart_xh
#include <Part.xh>
#endif

#ifndef _ODSESSN_
#include <ODSessn.xh>
#endif

#ifndef SOM_ODTransform_xh
#include <Trnsform.xh>
#endif

#ifndef SOM_ODWindow_xh
#include <Window.xh>
#endif

#ifndef SOM_ODWindowState_xh
#include <WinStat.xh>
#endif

#ifndef _ODUtils_
#include <ODUtils.h>
#endif

#ifndef _ODMATH_
#include <ODMath.h>
#endif

#ifndef SOM_ODDraft_xh
#include <Draft.xh>
#endif

#ifndef _TEMPOBJ_
#include <TempObj.h>
#endif

// ======================================================================
// somInit
// ======================================================================
SOM_Scope void  SOMLINK ODStdWinDispatchModulesomInit(
                                ODStdWinDispatchModule *somSelf)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule","somInit");

    parent_somInit(somSelf);
}

// ======================================================================
// somUninit
// ======================================================================
SOM_Scope void  SOMLINK ODStdWinDispatchModulesomUninit(
                                ODStdWinDispatchModule *somSelf)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule","somUninit");

    parent_somUninit(somSelf);
}

// ======================================================================
// Dispatch
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatch(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event,
                                ODEventInfo *eventInfo)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule","Dispatch");

    ODBoolean handled = kODFalse;

    if ((!event) || (!eventInfo))
        return kODFalse;

    switch (event->message)
    {
        case WM_SETCURSOR:
                // If this is the default cursor then return false so
                // system will use the cursor specified by the window class.
                if (_fCursor == _fDefaultCursor) 
		  handled = kODFalse;

                // else override the class cursor by 
                // calling SetCursor and returning true.
		else {
		  SetCursor(_fCursor);
		  handled = kODTrue;
		}
                break;

        case WM_HSCROLL:
        case WM_VSCROLL:
                handled = somSelf->SendToFocusOwner(ev, event, eventInfo,
                                                _fScrollingFocusToken, NULL);
                break;

        case WM_MOUSEMOVE:
                somSelf->SetMouseCursor(ev, event, eventInfo);
        case WM_RBUTTONDOWN:
        case WM_MBUTTONDOWN:
        case WM_LBUTTONDOWN:
        case WM_RBUTTONDBLCLK:
        case WM_MBUTTONDBLCLK:
        case WM_LBUTTONDBLCLK:
                handled = somSelf->DispatchMouseDownEvent(ev, event, eventInfo);
                break;

        case WM_RBUTTONUP:
        case WM_MBUTTONUP:
        case WM_LBUTTONUP:
                handled = somSelf->DispatchMouseUpEvent(ev, event, eventInfo);
                _fMouseDownFacet = kODNULL;
                _fEmbeddedFacet  = kODNULL;
                break;

        case kODEvtMouseDownBorder:
                handled = somSelf->DispatchMouseDownInBorder(ev, event,
                                                                 eventInfo);
                break;

        case kODEvtMouseDownEmbedded:
                handled = somSelf->DispatchMouseDownEmbedded(ev, event,
                                                                 eventInfo);
                break;

        case kODEvtMouseUpEmbedded:
                handled = somSelf->DispatchMouseUpEmbedded(ev,  event,
                                                                eventInfo);
                _fMouseDownFacet = kODNULL;
                _fEmbeddedFacet  = kODNULL;
                break;

        case WM_KEYDOWN:
        case WM_KEYUP:
        case WM_CHAR:
        case OD_HELP:
                handled = somSelf->DispatchKeyEvent(ev, event, eventInfo);
                break;

        case WM_PAINT:
                handled = somSelf->DispatchUpdateEvent(ev, event);
                break;

        case WM_ACTIVATE:
                handled = somSelf->DispatchActivateEvent(ev, event, eventInfo);
                break;

        case WM_COMMAND:
                handled = somSelf->DispatchMenuEvent(ev, event, eventInfo);
                break;

        case WM_SETFOCUS:
                if (event->hwnd)
                {
                    SetFocus(event->hwnd);
                }
                break;

        case WM_SIZE:
                handled = somSelf->DispatchResizeEvent(ev, event);
                break;

        case WM_WINDOWPOSCHANGED:
                handled = somSelf->DispatchMoveEvent(ev, event);
                break;

        case WM_ERASEBKGND:
                handled = kODTrue;      // prevent window background
                break;                  // from getting erased.

        case WM_NCCREATE:
                {
                    SetWindowLong(event->hwnd, 0,
                        (LONG)((LPCREATESTRUCT)event->lParam)->lpCreateParams);
                    handled = kODTrue;
                }
                break;

        default:
                break;
    }

    return handled;
}

// ======================================================================
// InitStdWinDispatchModule
// ======================================================================
SOM_Scope void  SOMLINK ODStdWinDispatchModuleInitStdWinDispatchModule(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODSession    *session,
                                ODDispatcher *dispatcher)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "InitStdWinDispatchModule");

    _fSession     = session;
    _fDispatcher  = dispatcher; // must pass this in explicitly, since the
                                // session hasn't set its fDispatcher yet.

    // Cache session globals for easy access

    _fArbitrator  = _fSession->GetArbitrator(ev);
    _fWindowState = _fSession->GetWindowState(ev);

    // Cache mouse cursors
    _fActiveBorderCursor = LoadCursor(NULL, IDC_CROSS);
    _fCursor = _fDefaultCursor = LoadCursor(NULL, IDC_ARROW);

    // Cache tokenized focus names

    try {
        _fKeyFocusToken         = _fSession->Tokenize(ev, kODKeyFocus);
        _fMenuFocusToken        = _fSession->Tokenize(ev, kODMenuFocus);
        _fSelectionFocusToken   = _fSession->Tokenize(ev, kODSelectionFocus);
        _fModalFocusToken       = _fSession->Tokenize(ev, kODModalFocus);
        _fMouseFocusToken       = _fSession->Tokenize(ev, kODMouseFocus);
        _fScrollingFocusToken   = _fSession->Tokenize(ev, kODScrollingFocus);
        _fMouseUpOutsideToken	= _fSession->Tokenize(ev,
						kODMouseUpOutsideFocus);

        _fLargeIconViewToken    = _fSession->Tokenize(ev, kODViewAsLargeIcon);
        _fSmallIconViewToken    = _fSession->Tokenize(ev, kODViewAsSmallIcon);
        _fThumbnailViewToken    = _fSession->Tokenize(ev, kODViewAsThumbnail);

	_fMouseCaptured = kODFalse;
    }
    catch (ODException _exception) {
        ODSetSOMException(ev, _exception);
    }

}

// ======================================================================
// IsContained
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleIsContained(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODFrame *frame,
                                ODFrame *containerToTest)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "IsContained");

    if ( (frame == kODNULL) || (containerToTest == kODNULL))
        return kODFalse;

    if (ODObjectsAreEqual(ev, frame, containerToTest))
        return kODTrue;

    frame->Acquire(ev);

    ODFrame* tempFrame     = frame;
    ODFrame* tempContainer = kODNULL;

    while (tempFrame != kODNULL)
    {
        tempContainer = tempFrame->AcquireContainingFrame(ev);
        tempFrame->Release(ev);

        if (ODObjectsAreEqual(ev, tempContainer, containerToTest))
        {
            tempContainer->Release(ev);
            return kODTrue;
        }

        tempFrame = tempContainer;
    }

    return kODFalse;
}

// ======================================================================
// GetActiveFacet
// ======================================================================
SOM_Scope ODFacet*  SOMLINK ODStdWinDispatchModuleGetActiveFacet(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODFrame  *frame,
                                ODWindow *window,
                                ODPoint  *windowPoint)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "GetActiveFacet");

    // Return the facet of "frame" which contains the point, or kODNULL

    ODFacet* foundFacet = kODNULL;
    ODPoint  framePoint;

    if ( frame && window )
    {
        ODFrameFacetIterator* iter = frame->CreateFacetIterator(ev);

        for (ODFacet* facet = iter->First(ev);
                iter->IsNotComplete(ev);
                facet = iter->Next(ev))
        {
            // Get windowPoint in frame coords for hit-testing

            TempODTransform winToFrame = facet->AcquireWindowFrameTransform(ev,
                                                        kODNULL);
            framePoint.x = windowPoint->x;
            framePoint.y = windowPoint->y;
            winToFrame->InvertPoint(ev, &framePoint);

            if ((ODObjectsAreEqual(ev, facet->GetWindow(ev), window))  &&
                (facet->ContainsPoint(ev, &framePoint, kODNULL))        )
            {
                foundFacet = facet;
                break;
            }
        }

        ODDeleteObject(iter);
    }

    return foundFacet;
}

// ======================================================================
// GetFirstFacetUnderPoint
// ======================================================================
SOM_Scope ODFacet*  SOMLINK ODStdWinDispatchModuleGetFirstFacetUnderPoint(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODWindow *window,
                                ODFacet  *root,
                                ODPoint  *windowPoint)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "GetFirstFacetUnderPoint");


    // returns NULL, root or an embedded facet of root

    ODFacet* foundFacet = kODNULL;
    ODPoint  framePoint;

    if ( (window) && (root) &&
         (ODObjectsAreEqual(ev, root->GetWindow(ev),window)))
    {
        ODFacetIterator* t = root->CreateFacetIterator(ev,
                                        kODTopDown, kODFrontToBack);

        ODFacet* facet = t->First(ev);

        // get windowPoint in frame coords for hit-testing
        {
            TempODTransform winToFrame = facet->AcquireWindowFrameTransform(ev,
                                                                kODNULL);
            framePoint.x = windowPoint->x;
            framePoint.y = windowPoint->y;
            winToFrame->InvertPoint(ev, &framePoint);
        }

        if ( !facet->ContainsPoint(ev, &framePoint, kODNULL) )
        {
            return kODNULL;
        }

        for ( facet = t->Next(ev);
                t->IsNotComplete(ev);
                facet = t->Next(ev) )
        {
            // again, get windowPoint in frame coords for hit-testing
            {
                TempODTransform winToFrame = facet->AcquireWindowFrameTransform(
                                                        ev, kODNULL);
                framePoint.x = windowPoint->x;
                framePoint.y = windowPoint->y;
                winToFrame->InvertPoint(ev, &framePoint);
            }

            if (facet->ContainsPoint(ev, &framePoint, kODNULL))
            {
                foundFacet = facet;
                break;
            }
            else
            {
                t->SkipChildren(ev);
            }
        }

        ODDeleteObject(t);
    }

    if ( foundFacet )
    {
        return foundFacet;
    }
    else
        return root;
}

// ======================================================================
// DispatchMouseDownEvent
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatchMouseDownEvent(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event,
                                ODEventInfo *eventInfo)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "DispatchMouseDownEvent");

   ODBoolean handled = kODFalse;

    // Assign the where structure prior to SendToFocusOwner
    eventInfo->where.x = ODIntToFixed(LOWORD(event->lParam));
    eventInfo->where.y = ODIntToFixed(HIWORD(event->lParam));

    // first, offer the event to mouse focus owner

    handled = somSelf->SendToFocusOwner(ev, event, eventInfo,
                                        _fMouseFocusToken, _fMouseDownFacet);
    if (handled)
    {
        return kODTrue;
    }

    // discard mouse move events if no mouse focus owner

    if (event->message == WM_MOUSEMOVE)
        return kODFalse;

    // OK, find out which part this event goes to...
    // Get the ODWindow over which the event occurred

    TempODWindow theWin = _fWindowState->AcquireODWindow(ev, event->hwnd);

    if (!theWin)
    {
        return kODFalse;
    }

    _fMouseDownFacet  = kODNULL;
    _fEmbeddedFacet   = kODNULL;
    _fSuppressMouseUp = kODFalse;

    handled = somSelf->DispatchMouseDownInContent(ev, theWin, event,
                                                  eventInfo);

    // If there is a mouse-up outside focus owner, do SetCapture().
    // Wait until -after- dispatching to part, so that parts can
    // request the mouseUpOutside focus first.

    somSelf->CaptureMouseIfNeeded(ev, event);

    return handled;
}

// ======================================================================
// DispatchMouseUpEvent
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatchMouseUpEvent(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event,
                                ODEventInfo *eventInfo)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "DispatchMouseUpEvent");

    ReleaseCapture();
    _fMouseCaptured = kODFalse;

    // supress the event entirely, if needed

    if (_fSuppressMouseUp)
    {
        return kODTrue;
    }

    ODBoolean handled = kODFalse;

    // Assign the where structure prior to SendToFocusOwner
    eventInfo->where.x = ODIntToFixed(LOWORD(event->lParam));
    eventInfo->where.y = ODIntToFixed(HIWORD(event->lParam));

    // first, offer the event to mouse focus owner

    handled = somSelf->SendToFocusOwner(ev, event, eventInfo,
                                        _fMouseFocusToken, _fMouseDownFacet);
    if (handled)
    {
        return kODTrue;
    }

    // OK, find out which part it goes to...
    // get the ODWindow over which the event occurred

    TempODWindow theWin = _fWindowState->AcquireODWindow(ev, event->hwnd);

    if (!theWin)
    {
        return kODFalse;
    }

    // If the prior mouse-down set fMouseDownFacet, send the event there.
    // Otherwise, look up the facet under the point.

    if (_fMouseDownFacet)
    {
        if (_fEmbeddedFacet)
        {
            event->message        = kODEvtMouseUpEmbedded;
            eventInfo->embeddedFacet = _fEmbeddedFacet;
            eventInfo->embeddedFrame = _fEmbeddedFacet->GetFrame(ev);
            handled = _fDispatcher->Redispatch(ev, event, eventInfo);
        }
        else
        {
            handled = somSelf->DispatchTheEvent(ev, event,
                                                _fMouseDownFacet->GetFrame(ev),
                                                _fMouseDownFacet,
                                                eventInfo);
        }
    }
    else
    {
        handled = somSelf->DispatchToFacetUnderPoint(ev, theWin,
                                                     &(eventInfo->where),
                                                     event, eventInfo);
    }

    return handled;
}

// ======================================================================
// DispatchMouseDownEmbedded
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatchMouseDownEmbedded(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event,
                                ODEventInfo *eventInfo)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "DispatchMouseDownEmbedded");

    ODBoolean handled = kODFalse;

    if (! eventInfo->embeddedFacet)
        return kODFalse;

    ODFacet* containingFacet = eventInfo->embeddedFacet->GetContainingFacet(ev);
    ODFrame* containingFrame = containingFacet ? containingFacet->GetFrame(ev)
                                               : kODNULL;

    // Don't cache mouse down facet here, because the mouse up
    // may go to the embedded part in some cases

    handled = somSelf->DispatchTheEvent(ev, event, containingFrame,
                                         containingFacet, eventInfo);

    return handled;
}

// ======================================================================
// DispatchMouseUpEmbedded
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatchMouseUpEmbedded(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event,
                                ODEventInfo *eventInfo)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "DispatchMouseUpEmbedded");

    ODBoolean handled = kODFalse;

    if (_fSuppressMouseUp)
        return kODTrue;

    if ((_fMouseDownFacet) && (_fEmbeddedFacet))
    {
        handled = somSelf->DispatchTheEvent(ev, event,
                                                _fMouseDownFacet->GetFrame(ev),
                                                _fMouseDownFacet, eventInfo);
    }
    else
        handled = kODTrue;

    return handled;
}

// ======================================================================
// DispatchMouseDownInContent
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatchMouseDownInContent(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODWindow    *theWindow,
                                ODEventData *event,
                                ODEventInfo *eventInfo)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "DispatchMouseDownInContent");

   ODBoolean handled = kODFalse;
   ODFacet* activeFacet = kODNULL;

   TempODFrame activeFrame = _fArbitrator->AcquireFocusOwner(ev,
                                                _fSelectionFocusToken);
   if (activeFrame )
        activeFacet = GetActiveFacetWithBorderUnderPoint(ev, activeFrame,
                                                theWindow,
                                                (eventInfo->where));

   if ( activeFacet ) // Mouse down in border
   {
        event->message = kODEvtMouseDownBorder;
        eventInfo->embeddedFrame = activeFrame;
        eventInfo->embeddedFacet = activeFacet;
        handled = _fDispatcher->Redispatch(ev, event, eventInfo);
    }
    else // Click not in border
    {
        // Alt key status not in event; get via GetKeyState()

        ODBoolean modified = (  (event->wParam & MK_CONTROL) ||
                                (event->wParam & MK_SHIFT  ) ||
                                (GetKeyState(VK_MENU) < 0  ) );

        if (modified)
        {
            ODFacet* rootFacet = activeFrame
                                        ? somSelf->GetActiveFacet(ev,
                                                    activeFrame, theWindow,
                                                    &(eventInfo->where))
                                        : (ODFacet*) kODNULL;

            ODFacet* facet = somSelf->GetFirstFacetUnderPoint(ev,
                                        theWindow, rootFacet,
                                        &(eventInfo->where));
            // which returns NULL, rootFacet or embeddedFrame

            if (facet)
            {
                if (ODObjectsAreEqual(ev, facet, rootFacet))
                {
                    _fMouseDownFacet = rootFacet;
                    handled = somSelf->DispatchTheEvent(ev, event,
                                                        activeFrame,
                                                        rootFacet,
                                                        eventInfo);
                }
                else // frame is embedded in active frame
                {
                    event->message = kODEvtMouseDownEmbedded;
                    eventInfo->embeddedFrame = facet->GetFrame(ev);
                    eventInfo->embeddedFacet = facet;
                    _fMouseDownFacet = rootFacet;
                    _fEmbeddedFacet = facet;
                    handled = _fDispatcher->Redispatch(ev, event, eventInfo);
                }
            }
            else // Modified click outside active frame
            {
                MessageBeep(0);
                _fSuppressMouseUp = kODTrue;
            }

        }
        else // No modifiers
        {
            handled = somSelf->DispatchToFacetUnderPoint(ev, theWindow,
                                                &(eventInfo->where),
                                                event, eventInfo);
        }
    }

    return handled;
}

// ======================================================================
// DispatchMouseDownInBorder
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatchMouseDownInBorder(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event,
                                ODEventInfo *eventInfo)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "DispatchMouseDownInBorder");

   ODBoolean handled = kODFalse;

    // Alt key status not in event; get via GetKeyState()
   ODBoolean modified = ((event->wParam & MK_CONTROL) ||
                         (event->wParam & MK_SHIFT  ) ||
                         (GetKeyState(VK_MENU) < 0  ) );

   if (modified)
   {
        MessageBeep(0); // don't allow Shift-click or Ctrl-click in border
        _fSuppressMouseUp = kODTrue;
        handled = kODTrue;
   }
   else
   {
        if (! eventInfo->embeddedFacet)
            return kODFalse;

        ODFacet* containingFacet = eventInfo->embeddedFacet->
                                                GetContainingFacet(ev);
        ODFrame* containingFrame = containingFacet
                                        ? containingFacet->GetFrame(ev)
                                        : kODNULL;

        _fMouseDownFacet = containingFacet;

        handled = somSelf->DispatchTheEvent(ev, event, containingFrame,
                                                containingFacet, eventInfo);
   }

   return handled;
}

// ======================================================================
// DispatchMenuEvent
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatchMenuEvent(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event,
                                ODEventInfo *eventInfo)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "DispatchMenuEvent");

    ODBoolean handled = kODFalse;

    handled = somSelf->SendToFocusOwner(ev, event, eventInfo,
                                        _fMenuFocusToken, NULL);

    return handled;
}

// ======================================================================
// DispatchKeyEvent
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatchKeyEvent(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event,
                                ODEventInfo *eventInfo)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "DispatchKeyEvent");

    ODBoolean handled = kODFalse;

    // Offer scrolling keys to scrollbar-focus window first

    int nVirtKey = (int) (event->wParam);

    if ((nVirtKey == VK_PRIOR) || (nVirtKey == VK_NEXT)  ||
        (nVirtKey == VK_HOME)  || (nVirtKey == VK_END)   ||
        (nVirtKey == VK_LEFT)  || (nVirtKey == VK_RIGHT) ||
        (nVirtKey == VK_UP)    || (nVirtKey == VK_DOWN)         )
    {
        handled = somSelf->SendToFocusOwner(ev, event, eventInfo,
                                            _fScrollingFocusToken, NULL);
    }

    if (handled == kODTrue)
        return handled;

    // Now offer key to keyboard-focus window

    handled = somSelf->SendToFocusOwner(ev, event, eventInfo,
                                        _fKeyFocusToken, NULL);

    return handled;
}

// ======================================================================
// DispatchUpdateEvent
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatchUpdateEvent(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "DispatchUpdateEvent");

    ODBoolean handled = kODFalse;
    RECT      aRect;

    TempODWindow theWindow = _fWindowState->AcquireODWindow(ev, event->hwnd);

    if (theWindow )
    {
        // get invalid region and save it in lParam (using GetUpdateRect)
        GetUpdateRect(event->hwnd, &aRect, FALSE);
        HRGN rgn = CreateRectRgn(aRect.left-1, aRect.top-1, aRect.right+1, aRect.bottom+1);
        PAINTSTRUCT ps;

        BeginPaint(event->hwnd, &ps);
        EndPaint(event->hwnd, &ps);
        event->lParam = (LPARAM) rgn;

        theWindow->UpdateWindow(ev, event);

        // Note that the region does not need to be deleted.  It has already
        // been deleted in ODWindow::HandleUpdateEvent when the temporary shape
        // containing the region goes out of scope and is deleted.  Leaving this
        // call here will always return fail and is unnecessary and misleading.
        // DeleteObject(rgn);

        handled = kODTrue;
    }

    return handled;
}

// ======================================================================
// DispatchResizeEvent
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatchResizeEvent(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "DispatchResizeEvent");

    ODBoolean handled = kODFalse;

    if ( ! _fWindowState ) return kODFalse;

    TempODWindow odWindow = _fWindowState->AcquireODWindow(ev, event->hwnd);

    if ( ! odWindow ) return kODFalse;

    if ( odWindow->GetRootFacet(ev) )
    {
        odWindow->AdjustWindowShape( ev );
        handled = kODTrue;
    }

    return handled;
}

// ======================================================================
// DispatchMoveEvent
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatchMoveEvent(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "DispatchMoveEvent");

    ODBoolean handled = kODFalse;

    if ( ! _fWindowState ) return kODFalse;

    LPWINDOWPOS lpwp = (LPWINDOWPOS) (event->lParam);

    // If this IS for a move
    if (!(lpwp->flags & SWP_NOMOVE))
    {
        TempODWindow odWindow = _fWindowState->AcquireODWindow(ev, event->hwnd);

        if ( ! odWindow ) return kODFalse;

        if ( odWindow->GetRootFacet(ev) )
        {
            // If the window's draft is writable
            ODDraft *draft = odWindow->GetDraft(ev);
            if (draft->GetPermissions(ev) >= kODDPSharedWrite)
            {
                // Mark the draft dirty
                draft->SetChangedFromPrev(ev);
            }
//          handled must remain as kODFalse or the window won't be
//          moved and/or sized
        }
    }

    return handled;
}

// ======================================================================
// DispatchActivateEvent
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatchActivateEvent(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event,
                                ODEventInfo *eventInfo)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "DispatchActivateEvent");

    ODBoolean handled = kODFalse;

    TempODWindow theWindow = _fWindowState->AcquireODWindow(ev, event->hwnd);

    if (theWindow )
    {
        theWindow->HandleActivateEvent(ev, event, eventInfo);
        handled = kODTrue;
    }

    return handled;
}

// ======================================================================
// DispatchWindowEvent
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatchWindowEvent(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODWindow    *window,
                                ODEventData *event,
                                ODEventInfo *eventInfo)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "DispatchWindowEvent");

    ODBoolean handled = kODFalse;

    TempODFrame modalFocus = _fArbitrator->AcquireFocusOwner(ev,
                                                _fModalFocusToken);

    if ((modalFocus) &&
        (! somSelf->IsContained(ev, window->GetRootFrame(ev), modalFocus)) )
    {
        TempODPart part = modalFocus->AcquirePart(ev);

        if (part)
        {
            handled = part->HandleEvent(ev, event, modalFocus,
                                kODNULL, eventInfo);
        }
    }
    else
    {
        ODFacet* rootFacet = window->GetRootFacet(ev);
        ODFrame* rootFrame = window->GetRootFrame(ev);

#if defined(ODDebug) && ODDebugTitleBarEvents
        somPrintf("Title Bar Event for root frame %x\n", rootFrame);
#endif

        handled = somSelf->DispatchTheEvent(ev, event, rootFrame,
                                                rootFacet, eventInfo);
    }

    return handled;
}

// ======================================================================
// DispatchToFacetUnderPoint
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatchToFacetUnderPoint(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODWindow    *window,
                                ODPoint*    windowPt,
                                ODEventData *event,
                                ODEventInfo *eventInfo)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "DispatchToFacetUnderPoint");

    ODBoolean handled = kODFalse;
    ODFacet* facet = window->GetFacetUnderPoint(ev, windowPt);
    ODFrame* frame = facet ? facet->GetFrame(ev) : kODNULL;

    if (facet && frame)
    {
        TempODFrame modalFocus = _fArbitrator->AcquireFocusOwner(ev,
                                                        _fModalFocusToken);

        if (modalFocus && ! somSelf->IsContained(ev, frame, modalFocus))
        {
            TempODPart part = modalFocus->AcquirePart(ev);

            if (part)
            {
                handled = part->HandleEvent(ev, event, modalFocus,
                                                kODNULL, eventInfo);
            }
        }
        else
        {
            ODTypeToken frameView = frame->GetViewType(ev);

            ODBoolean isFrozen = frame->IsFrozen(ev);
            ODBoolean isSelected = facet->IsSelected(ev);
            ODBoolean isIcon = (frameView == _fLargeIconViewToken ||
                                frameView == _fSmallIconViewToken ||
                                frameView == _fThumbnailViewToken);
            ODBoolean isDragging  = frame->IsDragging(ev);
            ODBoolean isMouseDown = ((event->message == WM_LBUTTONDOWN) ||
                                     (event->message == WM_MBUTTONDOWN) ||
                                     (event->message == WM_RBUTTONDOWN));

            if (    (isFrozen)
                 || (isSelected && isMouseDown)
                 || (isIcon)
                 || (isDragging && (!isMouseDown)))
            {
                // change the event into an embedded mouse event

                event->message = isMouseDown ? kODEvtMouseDownEmbedded
                                             : kODEvtMouseUpEmbedded;

                event->lParam = (long) facet;

                eventInfo->embeddedFrame = frame;
                eventInfo->embeddedFacet = facet;

                ODFacet* containingFacet = facet->GetContainingFacet(ev);

                if (containingFacet == kODNULL)
                {
                    // if this is a root frame, make docshell handle event
                    return kODFalse;
                }
                else
                {
                    // Cache mouseDown facet for use in mouseUp dispatching,
                    // except if the facet is selected, in which case mouseUp
                    // should go to the facet under the mouse, provided that
                    // the container doesn't do a drag.
                    if (isMouseDown && (isFrozen || isIcon))
                    {
                        _fMouseDownFacet = containingFacet;
                        _fEmbeddedFacet = facet;
                    }

                    handled = _fDispatcher->Redispatch(ev, event, eventInfo);
                }
            }
            else
            {
                // not embedded; handle normally

                _fMouseDownFacet = facet;
                handled = somSelf->DispatchTheEvent(ev, event, frame,
                                                    facet, eventInfo);
            }
        }
    }

    return handled;
}

// ======================================================================
// DispatchTheEvent
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleDispatchTheEvent(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event,
                                ODFrame     *targetFrame,
                                ODFacet     *targetFacet,
                                ODEventInfo *eventInfo)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "DispatchTheEvent");

    // Dispatches event to the initial target, or to containing frame/facet,
    // if the initial target doesn't handle it, and the containing part has
    // set the "DoesPropagateEvents" flag of the embedded frame

    ODBoolean handled = kODFalse;
    TempODPart targetPart = targetFrame ? targetFrame->AcquirePart(ev)
                                     : kODNULL;

    if (targetPart)
    {
        handled = targetPart->HandleEvent(ev, event, targetFrame,
                                          targetFacet, eventInfo);

        if (!handled)
        {
            handled = somSelf->PropagateTheEvent(ev, event, targetFrame,
                                                 targetFacet, eventInfo);
        }
    }

    return handled;
}

// ======================================================================
// PropagateTheEvent
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModulePropagateTheEvent(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event,
                                ODFrame     *initialFrame,
                                ODFacet     *initialFacet,
                                ODEventInfo *eventInfo)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "PropagateTheEvent");

    ODFacet* targetFacet = initialFacet;
    TempODFrame targetFrame = initialFacet ?
                                initialFacet->GetFrame(ev) :
                                initialFrame;
    ODBoolean handled = kODFalse;

    if (targetFrame)
        targetFrame->Acquire(ev);

    while (targetFrame)
    {
        if (handled  || (! targetFrame->DoesPropagateEvents(ev)))
            break;

        if (targetFacet)
        {
            targetFacet = targetFacet->GetContainingFacet(ev);
            targetFrame = targetFacet ? targetFacet->GetFrame(ev) : kODNULL;
            if (targetFrame)
                targetFrame->Acquire(ev);
        }
        else
        {
            TempODFrame contFrame = targetFrame->AcquireContainingFrame(ev);
            targetFrame = contFrame;
        }

        TempODPart targetPart = targetFrame ? targetFrame->AcquirePart(ev)
                                         : kODNULL;

        if (targetPart)
        {
            eventInfo->propagated = kODTrue;
            handled = targetPart->HandleEvent(ev, event, targetFrame,
                                                targetFacet, eventInfo);
        }
    }

    return handled;
}

// ======================================================================
// SendToFocusOwner
// ======================================================================
SOM_Scope ODBoolean  SOMLINK ODStdWinDispatchModuleSendToFocusOwner(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event,
                                ODEventInfo *eventInfo,
                                ODTypeToken  focusToken,
                                ODFacet     *facet)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
                                     "SendToFocusOwner");

    ODBoolean handled    = kODFalse;
    TempODFrame  focusFrame = _fArbitrator->AcquireFocusOwner(ev, focusToken);

    if (focusFrame)
    {
        TempODPart focusPart = focusFrame->AcquirePart(ev);

        if (focusPart)
        {
            handled = focusPart->HandleEvent(ev, event, focusFrame,
                                                facet, eventInfo);
        }
        else
        {
            _fArbitrator->RelinquishFocus(ev, focusToken, focusFrame);
        }
    }

    return handled;
}

// ======================================================================
// CaptureMouseIfNeeded
// ======================================================================
SOM_Scope void  SOMLINK ODStdWinDispatchModuleCaptureMouseIfNeeded(
                                ODStdWinDispatchModule *somSelf,
                                Environment *ev,
                                ODEventData *event)
{
   ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
   ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule",
				     "CaptureMouseIfNeeded");

    TempODFrame mouseUpOutsideOwner = _fArbitrator->AcquireFocusOwner(ev,
							_fMouseUpOutsideToken);

    if (! mouseUpOutsideOwner)
	return;

    if (SetCapture(event->hwnd) == NULL)
	return;

    _fMouseCaptured = kODTrue;

}

// ======================================================================
// SetMouseCursor
// ======================================================================
SOM_Scope void SOMLINK ODStdWinDispatchModuleSetMouseCursor(
							    ODStdWinDispatchModule *somSelf,
							    Environment *ev,
							    ODEventData *event,
							    ODEventInfo *eventInfo)
{
  ODStdWinDispatchModuleData *somThis = ODStdWinDispatchModuleGetData(somSelf);
  ODStdWinDispatchModuleMethodDebug("ODStdWinDispatchModule", "SetMouseCursor");
  
  ODBoolean handled = kODFalse;
  
  // Assign the where structure prior to SendToFocusOwner
  eventInfo->where.x = ODIntToFixed(LOWORD(event->lParam));
  eventInfo->where.y = ODIntToFixed(HIWORD(event->lParam));
  
  // Check to see if we are over an active border or not. If so, change the cursor
  ODFacet* activeFacet = kODNULL;
  TempODWindow theWin = _fWindowState->AcquireODWindow(ev, event->hwnd);
  TempODFrame activeFrame = _fArbitrator->AcquireFocusOwner(ev, _fSelectionFocusToken);
  if (activeFrame )
    activeFacet = GetActiveFacetWithBorderUnderPoint(ev, 
						     activeFrame, 
						     theWin, 
						     (eventInfo->where));

  // if true the mouse is over an active border so set fCursor to the active border cursor.
  if ( activeFacet )
    _fCursor = _fActiveBorderCursor;

  // else use the default cursor.
  else
    _fCursor = _fDefaultCursor;
  
}
