File:  [WindowsNT SDKs] / mstools / ole20 / samples / outline / cntrinpl.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:24:38 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntsdk-jul-1993, HEAD
Microsoft Windows NT Build 511 (SDK Final Release) 07-24-1993

/*************************************************************************
** 
**    OLE 2 Container Sample Code
**    
**    cntrinpl.c
**    
**    This file contains all interfaces, methods and related support
**    functions for an In-Place Container application (aka. Visual
**    Editing). The in-place Container application includes the following
**    implementation objects: 
**    
**    ContainerApp Object
**      exposed interfaces:
**          IOleInPlaceFrame
**    
**    ContainerDoc Object
**      support functions only
**      (ICntrOtl is an SDI app; it doesn't support a Doc level IOleUIWindow)
**    
**    ContainerLin Object
**      exposed interfaces:
**          IOleInPlaceSite
**    
**    (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
**
*************************************************************************/

#include "outline.h"

OLEDBGDATA

#if defined( INPLACE_CNTR )

extern LPOUTLINEAPP             g_lpApp;
extern BOOL g_fInsideOutContainer;
extern RECT g_rectNull;

#define NUM_INPLACE_ACCELS  4


/*************************************************************************
** ContainerApp::IOleInPlaceFrame interface implementation
*************************************************************************/

STDMETHODIMP CntrApp_IPFrame_QueryInterface(
        LPOLEINPLACEFRAME   lpThis,
        REFIID              riid,
        LPVOID FAR*         lplpvObj
)
{
    SCODE sc = E_NOINTERFACE;
    LPCONTAINERAPP lpContainerApp =
            ((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp;

    /* The object should not be able to access the other interfaces
    ** of our App object by doing QI on this interface.
    */
    *lplpvObj = NULL;
    if (IsEqualIID(riid, &IID_IUnknown) ||
        IsEqualIID(riid, &IID_IOleWindow) ||
        IsEqualIID(riid, &IID_IOleInPlaceUIWindow) ||
        IsEqualIID(riid, &IID_IOleInPlaceFrame)) {
        OleDbgOut4("CntrApp_IPFrame_QueryInterface: IOleInPlaceFrame* RETURNED\r\n");
        *lplpvObj = (LPVOID) &lpContainerApp->m_OleInPlaceFrame;
        OleApp_AddRef((LPOLEAPP)lpContainerApp);
        sc = S_OK;
    }

    OleDbgQueryInterfaceMethod(*lplpvObj);

    return ResultFromScode(sc);
}


STDMETHODIMP_(ULONG) CntrApp_IPFrame_AddRef(LPOLEINPLACEFRAME lpThis)
{
    OleDbgAddRefMethod(lpThis, "IOleInPlaceFrame");

    return OleApp_AddRef((LPOLEAPP)g_lpApp);
}


STDMETHODIMP_(ULONG) CntrApp_IPFrame_Release(LPOLEINPLACEFRAME lpThis)
{
    OleDbgReleaseMethod(lpThis, "IOleInPlaceFrame");

    return OleApp_Release((LPOLEAPP)g_lpApp);
}


STDMETHODIMP CntrApp_IPFrame_GetWindow(
    LPOLEINPLACEFRAME   lpThis,
    HWND FAR*           lphwnd
)
{
    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;

    OLEDBG_BEGIN2("CntrApp_IPFrame_GetWindow\r\n")
    *lphwnd = lpOutlineApp->m_hWndApp;
	OLEDBG_END2
    return NOERROR;
}

STDMETHODIMP CntrApp_IPFrame_ContextSensitiveHelp(
    LPOLEINPLACEFRAME   lpThis,
    BOOL                fEnterMode
)
{
    OLEDBG_BEGIN2("CntrApp_IPFrame_ContextSensitiveHelp\r\n")

#if defined( LATER )
    LPOLEINPLACEFRAME lpFrame = m_pEItem->m_pAC->GetInPlaceFrame();
    HRESULT hresult = lpFrame->ContextSensitiveHelp(fEnterMode);
    lpFrame->Release();
#endif  // LATER

	OLEDBG_END2
    return NOERROR;
}


STDMETHODIMP CntrApp_IPFrame_GetBorder(
    LPOLEINPLACEFRAME   lpThis,
    LPRECT              lprectBorder
)
{
    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;

    OLEDBG_BEGIN2("CntrApp_IPFrame_GetBorder\r\n")

	OutlineApp_GetFrameRect(lpOutlineApp, lprectBorder);

	OLEDBG_END2
    return NOERROR;
}


STDMETHODIMP CntrApp_IPFrame_RequestBorderSpace(
    LPOLEINPLACEFRAME   lpThis,
    LPCBORDERWIDTHS     lpWidths
)
{
    OleDbgOut2("CntrApp_IPFrame_RequestBorderSpace\r\n");

#if defined( _DEBUG )
	{
		/* FOR DEBUGING PURPOSES ONLY -- we will fail to allow to an
		**    object to get any frame border space for frame tools if
		**    our own frame tools are poped up in the tool pallet. this
		**    is NOT recommended UI behavior but it allows us to test
		**    in the condition when the frame does not give border
		**    space for the object. an object in this situation must
		**    then either popup its tools in a floating pallet, do
		**    without the tools, or fail to in-place activate.
		*/
		LPCONTAINERAPP lpContainerApp =
				((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp;
		LPFRAMETOOLS lpft = OutlineApp_GetFrameTools(
				(LPOUTLINEAPP)lpContainerApp);

		if (lpft->m_ButtonBar.m_nState == BARSTATE_POPUP &&
			lpft->m_FormulaBar.m_nState == BARSTATE_POPUP) {
			OleDbgOut3(
					"CntrApp_IPFrame_RequestBorderSpace: allow NO SPACE\r\n");
			return ResultFromScode(E_FAIL);
		}
	}
#endif	// _DEBUG
		
    return NOERROR;
}


STDMETHODIMP CntrApp_IPFrame_SetBorderSpace(
    LPOLEINPLACEFRAME   lpThis,
    LPCBORDERWIDTHS     lpWidths
)
{
    LPCONTAINERAPP lpContainerApp =
            ((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp;

    OLEDBG_BEGIN2("CntrApp_IPFrame_SetBorderSpace\r\n")

	if (lpWidths == NULL) {

		/* OLE2NOTE: IOleInPlaceSite::SetBorderSpace(NULL) is called
		**    when the in-place active object does NOT want any tool
		**    space. in this situation the in-place container should
		**    put up its tools.
		*/
		LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp;
		LPCONTAINERDOC lpContainerDoc;

		lpContainerDoc =(LPCONTAINERDOC)OutlineApp_GetActiveDoc(lpOutlineApp);
		ContainerDoc_AddFrameLevelTools(lpContainerDoc);
	} else {

		// OLE2NOTE: you could do validation of borderwidths here

#if defined( _DEBUG )
		/* FOR DEBUGING PURPOSES ONLY -- we will fail to allow to an
		**    object to get any frame border space for frame tools if
		**    our own frame tools are poped up in the tool pallet. this
		**    is NOT recommended UI behavior but it allows us to test
		**    in the condition when the frame does not give border
		**    space for the object. an object in this situation must
		**    then either popup its tools in a floating pallet, do
		**    without the tools, or fail to in-place activate.
		*/
		LPFRAMETOOLS lpft = OutlineApp_GetFrameTools(
				(LPOUTLINEAPP)lpContainerApp);

		if ((lpft->m_ButtonBar.m_nState == BARSTATE_POPUP &&
			lpft->m_FormulaBar.m_nState == BARSTATE_POPUP) &&
			(lpWidths->top || lpWidths->bottom ||
				lpWidths->left || lpWidths->right) ) {
			OleDbgOut3("CntrApp_IPFrame_SetBorderSpace: allow NO SPACE\r\n");
			OLEDBG_END2

			OutlineApp_SetBorderSpace(
					(LPOUTLINEAPP) lpContainerApp,
					(LPBORDERWIDTHS)&g_rectNull
			);
            OLEDBG_END2
			return ResultFromScode(E_FAIL);
		}
#endif	// _DEBUG

		OutlineApp_SetBorderSpace(
				(LPOUTLINEAPP) lpContainerApp,
				(LPBORDERWIDTHS)lpWidths
		);
	}
	OLEDBG_END2
    return NOERROR;
}


STDMETHODIMP CntrApp_IPFrame_SetActiveObject(
    LPOLEINPLACEFRAME           lpThis,
    LPOLEINPLACEACTIVEOBJECT    lpActiveObject,
    LPCSTR                      lpszObjName
)
{
    char szTitle[256];
    LPCONTAINERAPP lpContainerApp =
            ((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp;

    OLEDBG_BEGIN2("CntrApp_IPFrame_SetActiveObject\r\n")

    if (lpContainerApp->m_lpIPActiveObj)
        lpContainerApp->m_lpIPActiveObj->lpVtbl->Release(lpContainerApp->m_lpIPActiveObj);

    if (lpContainerApp->m_lpIPActiveObj = lpActiveObject)
        lpContainerApp->m_lpIPActiveObj->lpVtbl->AddRef(lpContainerApp->m_lpIPActiveObj);

#if !defined (MDI_VERSION)
    // MDI apps will change the document window title..

    if (lpActiveObject) {
        lstrcpy (szTitle, lpszObjName);
        lstrcat (szTitle, " in ");
        lstrcat (szTitle, g_lpApp->m_lpDoc->m_lpszDocTitle);
        SetWindowText (g_lpApp->m_hWndApp, szTitle);

    } else {
        OutlineDoc_SetTitle(g_lpApp->m_lpDoc);
    }

#endif  // !defined (MDI_VERSION)

	OLEDBG_END2
    return NOERROR;
}


STDMETHODIMP CntrApp_IPFrame_InsertMenus(
    LPOLEINPLACEFRAME       lpThis,
    HMENU                   hMenu,
    LPOLEMENUGROUPWIDTHS    lpMenuWidths
)
{
    LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
	BOOL	fNoError = TRUE;

    OLEDBG_BEGIN2("CntrApp_IPFrame_InsertMenus\r\n")

    fNoError &= AppendMenu(hMenu, MF_POPUP, (UINT)lpContainerApp->m_hMenuFile,
						"&File");
    fNoError &= AppendMenu(hMenu, MF_POPUP, (UINT)lpContainerApp->m_hMenuView,
						"O&utline");
	fNoError &= AppendMenu(hMenu, MF_POPUP,(UINT)lpContainerApp->m_hMenuDebug,
						"DbgI&Cntr");
    lpMenuWidths->width[0] = 1;
    lpMenuWidths->width[2] = 1;
    lpMenuWidths->width[4] = 1;

	OLEDBG_END2
		
	return (fNoError ? NOERROR : ResultFromScode(E_FAIL));
}


STDMETHODIMP CntrApp_IPFrame_SetMenu(
    LPOLEINPLACEFRAME   lpThis,
    HMENU               hMenuShared,
    HOLEMENU            hOleMenu,
    HWND                hwndActiveObject
)
{
    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
    HMENU   hMenu;
	HRESULT hrErr;

    OLEDBG_BEGIN2("CntrApp_IPFrame_InsertMenus\r\n")

	
	/* OLE2NOTE: either put up the shared menu (combined menu from
	**    in-place server and in-place container) or our container's
	**    normal menu as directed.
	*/
    if (hOleMenu && hMenuShared)
        hMenu = hMenuShared;
	else 
		hMenu = lpOutlineApp->m_hMenuApp;

	/* OLE2NOTE: SDI apps put menu on frame by calling SetMenu.
	**    MDI apps would send WM_MDISETMENU message instead.
	*/
    SetMenu (lpOutlineApp->m_hWndApp, hMenu);
    OLEDBG_BEGIN2("OleSetMenuDescriptor called\r\n")
    hrErr = OleSetMenuDescriptor (hOleMenu, lpOutlineApp->m_hWndApp,
                    hwndActiveObject, NULL, NULL);
	OLEDBG_END2

	OLEDBG_END2
	return hrErr;
}


STDMETHODIMP CntrApp_IPFrame_RemoveMenus(
    LPOLEINPLACEFRAME   lpThis,
    HMENU               hMenu
)
{
    LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
	BOOL fNoError = TRUE;

    OLEDBG_BEGIN2("CntrApp_IPFrame_RemoveMenus\r\n")

    /* Remove container group menus */
	while (GetMenuItemCount(hMenu))
		fNoError &= RemoveMenu(hMenu, 0, MF_BYPOSITION);

	OleDbgAssert(fNoError == TRUE);
	
	OLEDBG_END2
		
    return (fNoError ? NOERROR : ResultFromScode(E_FAIL));
}


STDMETHODIMP CntrApp_IPFrame_SetStatusText(
    LPOLEINPLACEFRAME   lpThis,
    LPCSTR              lpszStatusText
)
{
    OleDbgOut2("CntrApp_IPFrame_SetStatusText\r\n");
    
    // REVIEW: NOT YET IMPLEMENTED

    return ResultFromScode(E_NOTIMPL);
}


STDMETHODIMP CntrApp_IPFrame_EnableModeless(
    LPOLEINPLACEFRAME   lpThis,
    BOOL                fEnable
)
{
    return NOERROR;
}


STDMETHODIMP CntrApp_IPFrame_TranslateAccelerator(
    LPOLEINPLACEFRAME   lpThis,
    LPMSG               lpmsg,
    WORD                wID
)
{
    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
    LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
    SCODE sc;

    if (TranslateAccelerator (lpOutlineApp->m_hWndApp,
                        lpContainerApp->m_hAccelIPCntr, lpmsg))
        sc = S_OK;

#if defined (MDI_VERSION)
    else if (TranslateMDISysAccel(lpOutlineApp->m_hWndMDIClient, lpmsg))
        sc = S_OK;
#endif  // MDI_VERSION

    else
        sc = S_FALSE;

    return ResultFromScode(sc);
}



/*************************************************************************
** ContainerDoc Support Functions
*************************************************************************/


/* ContainerDoc_UpdateInPlaceObjectRects
** -------------------------------------
**    Update the PosRect and ClipRect of the currently in-place active
**    object. if there is no object active in-place, then do nothing.
**
**    OLE2NOTE: this function should be called when an action occurs
**    that changes either the position of the object in the document
**    (eg. changing document margins changes PosRect) or the clipRect
**    changes (eg. resizing the document window changes the ClipRect).
*/
void ContainerDoc_UpdateInPlaceObjectRects(LPCONTAINERDOC lpContainerDoc, int nIndex)
{
	LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
	int i;
	LPLINE lpLine;
    RECT rcClipRect;

    if (g_fInsideOutContainer) {

        if (lpContainerDoc->m_cIPActiveObjects) {

            /* OLE2NOTE: (INSIDE-OUT CONTAINER) we must update the
            **    PosRect/ClipRect for all in-place active objects
            **    starting from line "nIndex".
            */

            ContainerDoc_GetClipRect(lpContainerDoc, (LPRECT)&rcClipRect);

            OleDbgOutRect3(
                    "OutlineDoc_Resize (ClipRect)", (LPRECT)&rcClipRect);

            for (i = nIndex; i < lpLL->m_nNumLines; i++) {
                lpLine=LineList_GetLine(lpLL, i);

                if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
                    LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
                    ContainerLine_UpdateInPlaceObjectRects(
                            lpContainerLine, &rcClipRect);
                }
            }
        }
    }
    else {
        /* OLE2NOTE: (OUTSIDE-IN CONTAINER) if there is a currently 
        **    UIActive object, we must inform it that the
        **    PosRect/ClipRect has now changed.
        */
        LPCONTAINERLINE lpLastUIActiveLine =
                lpContainerDoc->m_lpLastUIActiveLine;
        if (lpLastUIActiveLine && lpLastUIActiveLine->m_fUIActive) {
            ContainerDoc_GetClipRect(lpContainerDoc, (LPRECT)&rcClipRect);

            OleDbgOutRect3(
                    "OutlineDoc_Resize (ClipRect)", (LPRECT)&rcClipRect);
            ContainerLine_UpdateInPlaceObjectRects(
                    lpLastUIActiveLine, &rcClipRect);
        }
    }
}

/* ContainerDoc_IsUIDeactivateNeeded
** ---------------------------------
**    Check if it is necessary to UIDeactivate an in-place active
**    object upon a mouse LBUTTONDOWN event. The position of the button
**    down click is given by "pt".
**    If there is not currently an in-place active line, then
**    UIDeactivate is NOT needed.
**    If there is a current in-place active line, then check if the
**    point position is outside of the object extents on the screen. If
**    so, then the object should be UIDeactivated, otherwise not.
*/
BOOL ContainerDoc_IsUIDeactivateNeeded(
        LPCONTAINERDOC  lpContainerDoc,
        POINT           pt
)
{
    LPCONTAINERLINE lpUIActiveLine=lpContainerDoc->m_lpLastUIActiveLine;
    RECT rect;

    if (! lpUIActiveLine || ! lpUIActiveLine->m_fUIActive)
        return FALSE;

    ContainerLine_GetOleObjectRectInPixels(
            lpUIActiveLine,
            (LPRECT) &rect
    );

    if (! PtInRect((LPRECT) &rect, pt))
        return TRUE;

    return FALSE;
}


/* ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded
** -------------------------------------------------
**    OLE2NOTE: this function ONLY applies for OUTSIDE-IN containers
**
**    If there is a previous in-place active server still running and
**    this server will not be needed to support the next OLE object
**    about to be activated, then shut it down.
**    in this way we manage a policy of having at most one in-place
**    server running at a time. we do not imediately shut down the
**    in-place server when the object is UIDeactivated because we want
**    it to be fast if the server decides to re-activate the object
**    in-place.
**
**    shutting down the server is achieved by forcing the object to
**    transition from running to loaded by calling IOleObject::Close.
*/
void ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded(
        LPCONTAINERDOC          lpContainerDoc,
        LPCONTAINERLINE         lpNextActiveLine
)
{
    LPCONTAINERLINE lpLastIpActiveLine = lpContainerDoc->m_lpLastIpActiveLine;
    BOOL fEnableServerShutDown = TRUE;
    LPMONIKER lpmkLinkSrc;
    LPMONIKER lpmkLastActiveObj;
    LPMONIKER lpmkCommonPrefix;
    LPOLELINK lpOleLink;
    HRESULT hrErr;

    /* OLE2NOTE: an inside-out style container can NOT use this scheme
    **    to shut down in-place servers. it would have to have a more
    **    sophistocated mechanism by which it keeps track of which
    **    objects are on screen and which were the last recently used.
    */
    if (g_fInsideOutContainer) 
        return;

    if (lpLastIpActiveLine != lpNextActiveLine) {
        if (lpLastIpActiveLine) {

            /* OLE2NOTE: if the object which is about to be activated is
            **    actually a link to the OLE object in last activated line,
            **    then we do NOT want to shut down the last activated
            **    server because it is about to be used. when activating a
            **    linked object, the source of the link gets activated.
            */
            lpOleLink = (LPOLELINK)ContainerLine_GetOleObject(
                    lpNextActiveLine,
                    &IID_IOleLink
            );
            if (lpOleLink) {
                OLEDBG_BEGIN2("IOleObject::GetSourceMoniker called\r\n")
                lpOleLink->lpVtbl->GetSourceMoniker(
                        lpOleLink,
                        (LPMONIKER FAR*)&lpmkLinkSrc
                );
                OLEDBG_END2

                if (lpmkLinkSrc) {
                    lpmkLastActiveObj = ContainerLine_GetFullMoniker(
                            lpLastIpActiveLine,
                            GETMONIKER_ONLYIFTHERE
                    );
                    if (lpmkLastActiveObj) {
                        hrErr = lpmkLinkSrc->lpVtbl->CommonPrefixWith(
                                lpmkLinkSrc,
                                lpmkLastActiveObj,
                                &lpmkCommonPrefix
                                
                        );
                        if (GetScode(hrErr) == MK_S_HIM || 
                                GetScode(hrErr) == MK_S_US) {
                            /* the link source IS to the object
                            **    contained in the last activated
                            **    line of the document; disable the
                            **    attempt to shut down the last
                            **    running in-place server. 
                            */
                            fEnableServerShutDown = FALSE;
                        }
                        if (lpmkCommonPrefix) 
                            OleStdRelease((LPUNKNOWN)lpmkCommonPrefix);
                        OleStdRelease((LPUNKNOWN)lpmkLastActiveObj);
                    }
                    OleStdRelease((LPUNKNOWN)lpmkLinkSrc);
                }
                OleStdRelease((LPUNKNOWN)lpOleLink);
            }

            /* if it is OK to shut down the previous in-place server
            **    and one is still running, then shut it down. shutting
            **    down the server is accomplished by forcing the OLE
            **    object to close. this forces the object to transition
            **    from running to loaded. if the object is actually
            **    only loaded then this is a NOP.
            */
            if (fEnableServerShutDown &&
                    lpLastIpActiveLine->m_fIpServerRunning) {

                OleDbgOut1("@@@ previous in-place server SHUT DOWN\r\n");
                ContainerLine_CloseOleObject(lpLastIpActiveLine);

                // we can now forget this last in-place active line.
                lpContainerDoc->m_lpLastIpActiveLine = NULL;
            }
        }
    }
}


/* ContainerDoc_GetUIActiveWindow
** ------------------------------
**    If there is an UIActive object, then return its HWND.
*/
HWND ContainerDoc_GetUIActiveWindow(LPCONTAINERDOC lpContainerDoc)
{
    return lpContainerDoc->m_hwndUIActiveObj;
}


/* ContainerDoc_GetClipRect
** ------------------------
**    Get the ClipRect in client coordinates.
**
** OLE2NOTE: the ClipRect is defined as the maximum window rectangle
**    that the in-place active object must be clipped to. this
**    rectangle MUST be described in Client Coordinates of the window
**    that is used as the Parent of the in-place active object's
**    window. in our case, the LineList ListBox window is both the
**    parent of the in-place active object AND defines precisely the
**    clipping rectangle.
*/
void ContainerDoc_GetClipRect(
        LPCONTAINERDOC      lpContainerDoc,
        LPRECT              lprcClipRect
)
{
    LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;

    /* OLE2NOTE: the ClipRect can be used to ensure that the in-place
    **    server does not overwrite areas of the window that the
    **    container paints into but which should never be overwritten
    **    (eg. if an app were to paint row and col headings directly in
    **    the same window that is the parent of the in-place window.
    **    whenever the window size changes or gets scrolled, in-place
    **    active object must be informed of the new clip rect. 
    **    
    **    normally an app would pass the rect returned from GetClientRect.
    **    but because CntrOutl uses separate windows for row/column
    **    headings, status line, formula/tool bars, etc. it is NOT
    **    necessary to pass a constrained clip rect. Windows standard
    **    window clipping will automatically take care of all clipping
    **    that is necessary. thus we can take a short cut of passing an
    **    "infinite" clip rect, and then we do NOT need to call
    **    IOleInPlaceObject::SetObjectRects when our document is scrolled.
    */

    lprcClipRect->top = 0;
    lprcClipRect->left = 0;
    lprcClipRect->right = 32767;
    lprcClipRect->bottom = 32767;
}


/* ContainerDoc_GetTopInPlaceFrame
** -------------------------------
**    returns NON-AddRef'ed pointer to Top In-Place Frame interface
*/
LPOLEINPLACEFRAME ContainerDoc_GetTopInPlaceFrame(
        LPCONTAINERDOC      lpContainerDoc
)
{
#if defined( INPLACE_CNTRSVR )
    return lpContainerDoc->m_lpTopIPFrame;
#else
    return (LPOLEINPLACEFRAME)&((LPCONTAINERAPP)g_lpApp)->m_OleInPlaceFrame;
#endif
}

void ContainerDoc_GetSharedMenuHandles(
        LPCONTAINERDOC  lpContainerDoc,
        HMENU FAR*      lphSharedMenu,
        HOLEMENU FAR*   lphOleMenu
)
{
#if defined( INPLACE_CNTRSVR )
    if (lpContainerDoc->m_DocType == DOCTYPE_EMEBEDDEDOBJECT) {
        *lphSharedMenu = lpContainerDoc->m_hSharedMenu;
        *lphOleMenu = lpContainerDoc->m_hOleMenu;
        return;
    }
#endif

    *lphSharedMenu = NULL;
    *lphOleMenu = NULL;
}


#if defined( USE_FRAMETOOLS )
void ContainerDoc_RemoveFrameLevelTools(LPCONTAINERDOC lpContainerDoc)
{
    LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;
    OleDbgAssert(lpOutlineDoc->m_lpFrameTools != NULL);

    FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, FALSE);
}
#endif


void ContainerDoc_AddFrameLevelUI(LPCONTAINERDOC lpContainerDoc)
{
    LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;
    LPOLEINPLACEFRAME lpTopIPFrame = ContainerDoc_GetTopInPlaceFrame(
            lpContainerDoc);
    HMENU           hSharedMenu;            // combined obj/cntr menu
    HOLEMENU        hOleMenu;               // returned by OleCreateMenuDesc.

    ContainerDoc_GetSharedMenuHandles(
            lpContainerDoc,
            &hSharedMenu,
            &hOleMenu
    );

    lpTopIPFrame->lpVtbl->SetMenu(
            lpTopIPFrame,
            hSharedMenu,
            hOleMenu,
            lpOutlineDoc->m_hWndDoc
    );

    /* OLE2NOTE: even if our app does NOT use FrameTools, we must still
    **    call IOleInPlaceFrame::SetBorderSpace.
    */
    ContainerDoc_AddFrameLevelTools(lpContainerDoc);
}


void ContainerDoc_AddFrameLevelTools(LPCONTAINERDOC lpContainerDoc)
{
    LPOLEINPLACEFRAME lpTopIPFrame = ContainerDoc_GetTopInPlaceFrame(
            lpContainerDoc);
    LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
    LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;

    OleDbgAssert(lpTopIPFrame != NULL);

#if defined( USE_FRAMETOOLS )

    FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, TRUE);

    FrameTools_NegotiateForSpaceAndShow(
            lpOutlineDoc->m_lpFrameTools,
            NULL,
            lpTopIPFrame
    );

#else   // ! USE_FRAMETOOLS

#if defined( INPLACE_CNTRSVR )
    if (lpContainerDoc->m_DocType == DOCTYPE_EMBEDDEDOBJECT) {
        /* this says i do not need space, so the top Frame should
        **    leave its tools behind
        */
        OLEDBG_BEGIN2("IOleInPlaceFrame::SetBorderSpace(NULL) called\r\n")
        lpTopIPFrame->lpVtbl->SetBorderSpace(lpTopIPFrame, NULL);
        OLEDBG_END2
        return;
    }
#else   // INPLACE_CNTR && ! USE_FRAMETOOLS

    OLEDBG_BEGIN2("IOleInPlaceFrame::SetBorderSpace(0,0,0,0) called\r\n")
    lpTopIPFrame->lpVtbl->SetBorderSpace(
            lpTopIPFrame,
            (LPCBORDERWIDTHS)&g_rectNull
    );
    OLEDBG_END2

#endif  // INPLACE_CNTR && ! USE_FRAMETOOLS
#endif  // ! USE_FRAMETOOLS

}


void ContainerDoc_FrameWindowResized(LPCONTAINERDOC lpContainerDoc)
{
    LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;

    if (lpContainerApp->m_lpIPActiveObj) {
        RECT rcFrameRect;

        OutlineApp_GetFrameRect(g_lpApp, (LPRECT)&rcFrameRect);

        OLEDBG_BEGIN2("IOleInPlaceActiveObject::ResizeBorder called\r\n")
        lpContainerApp->m_lpIPActiveObj->lpVtbl->ResizeBorder(
                lpContainerApp->m_lpIPActiveObj,
                (LPCRECT)&rcFrameRect,
                (LPOLEINPLACEUIWINDOW)&lpContainerApp->m_OleInPlaceFrame,
                TRUE    /* fFrameWindow */
        );
        OLEDBG_END2
    }

#if defined( USE_FRAMETOOLS )
    else {
        ContainerDoc_AddFrameLevelTools(lpContainerDoc);
    }
#endif
}


#if defined( INPLACE_CNTRSVR ) || defined( INPLACE_MDICNTR )

/* ContainerDoc_GetTopInPlaceDoc
**    returns NON-AddRef'ed pointer to Top In-Place Doc interface
*/
LPOLEINPLACEUIWINDOW ContainerDoc_GetTopInPlaceDoc(
        LPCONTAINERDOC      lpContainerDoc
)
{
#if defined( INPLACE_CNTRSVR )
    return lpContainerDoc->m_lpTopIPDoc;
#else
    return (LPOLEINPLACEUIWINDOW)&lpContainerDoc->m_OleInPlaceDoc;
#endif
}


void ContainerDoc_RemoveDocLevelTools(LPCONTAINERDOC lpContainerDoc);
{
    LPOLEINPLACEUIWINDOW lpTopIPDoc = ContainerDoc_GetTopInPlaceDoc(
            lpContainerDoc);

    if (lpTopIPDoc && lpContainerDoc->m_fMyToolsOnDoc) {
        lpContainerDoc->m_fMyToolsOnDoc = FALSE;

        // if we had doc tools we would HIDE them here;
        //   but NOT call SetBorderSpace(NULL)

    }
}

void ContainerDoc_AddDocLevelTools(LPCONTAINERDOC lpContainerDoc)
{
    LPOLEINPLACEUIWINDOW lpTopIPDoc = ContainerDoc_GetTopInPlaceDoc(
            lpContainerDoc);

    if (! lpTopIPDoc)
        return;

#if defined( USE_DOCTOOLS )
    if (lpTopIPDoc && ! lpContainerDoc->m_fMyToolsOnDoc) {

        /* if we had doc tools we would negotiate for toolbar space at
        **    doc level and SHOW them.
        */

        /* we do NOT have doc level tools, so we just call
        **    SetBorderSpace() to indicate to the top doc that
        **    our object does not need tool space.
        */

        lpContainerDoc->m_fMyToolsOnDoc = TRUE;
        return;
    }
#else   // ! USE_DOCTOOLS

#if defined( INPLACE_CNTRSVR )
    if (lpContainerDoc->m_DocType == DOCTYPE_EMBEDDEDOBJECT) {
        /* this says i do not need space, so the top doc should
        **    leave its tools behind
        */
        lpTopIPDoc->lpVtbl->SetBorderSpace(lpTopIPDoc, NULL);
        return;
    }
#else
    lpTopIPDoc->lpVtbl->SetBorderSpace(
            lpTopIPDoc,
            (LPCBORDERWIDTHS)&g_rectNull
    );

#endif
#endif  // ! USE_DOCTOOLS
}

#endif  // INPLACE_CNTRSVR || INPLACE_MDICNTR



/*************************************************************************
** ContainerLine Support Functions and Interfaces
*************************************************************************/


/* ContainerLine_UIDeactivate
** --------------------------
**    tell the OLE object associated with the ContainerLine to 
**    UIDeactivate. this informs the in-place server to tear down
**    the UI and window that it put up for the object. it will remove
**    its active editor menus and any frame and object adornments 
**    (eg. toolbars, rulers, etc.).
*/
void ContainerLine_UIDeactivate(LPCONTAINERLINE lpContainerLine)
{
    HRESULT hrErr;

    if (!lpContainerLine || !lpContainerLine->m_fUIActive)
        return;

    OLEDBG_BEGIN2("IOleInPlaceObject::UIDeactivate called\r\n")
    hrErr = lpContainerLine->m_lpOleIPObj->lpVtbl->UIDeactivate(
			lpContainerLine->m_lpOleIPObj);
    OLEDBG_END2

    if (hrErr != NOERROR) {
        OleDbgOutHResult("IOleInPlaceObject::UIDeactivate returned", hrErr);
        return;
    }
#if defined( UNDOSUPPORTED )

    /* OLE2NOTE: an outside-in style container that supports UNDO would
    **    call IOleObject::DoVerb(OLEIVERB_HIDE) to make the in-place
    **    object go invisible. when it wants the in-place active object
    **    to discard its undo state, it would call
    **    IOleInPlaceObject::InPlaceDeactivate when it wants the object
    **    to discard its undo state. there is no need for an outside-in
    **    style container to call
    **    IOleObject::DoVerb(OLEIVERB_DISCARDUNDOSTATE). if either the
    **    container or the object do not support UNDO, then the
    **    container might as well immediately call InPlaceDeactivate
    **    instead of calling DoVerb(HIDE).
    **    
    **    an inside-out style container that supports UNDO would simply
    **    UIDeactivate the object. it would call
    **    IOleObject::DoVerb(OLEIVERB_DISCARDUNDOSTATE) when it wants
    **    the object discard its undo state. it would call
    **    IOleInPlaceObject::InPlaceDeactivate if it wants the object
    **    to take down its window. 
    */
    if (! g_fInsideOutContainer) {
        if (lpContainerLine->m_fIpChangesUndoable) {
            ContainerLine_DoVerb(lpContainerLine,OLEIVERB_HIDE,FALSE,FALSE);
        } else {
            lpContainerLine->m_lpOleIPObj->lpVtbl->InPlaceDeactivate(
                    lpContainerLine->m_lpOleIPObj);
        }
        lpContainerLine->m_fIpVisible = FALSE; 
    }
#else


    /* OLE2NOTE: an outside-in style container that does NOT support
    **    UNDO would immediately tell the UIDeactivated server (UI
    **    removed) to IOleInPlaceObject::InPlaceDeactivate.
    **    
    **    an inside-out style container that does NOT support UNDO
    **    would call IOleObject::DoVerb(OLEIVERB_DISCARDUNDOSTATE) to
    **    tell the object to discard its undo state. it would call
    **    IOleInPlaceObject::InPlaceDeactivate if it wants the object
    **    to take down its window. 
    */

    if (g_fInsideOutContainer) {

        if (lpContainerLine->m_fInsideOutObj) {

            if (lpContainerLine->m_fIpChangesUndoable) {
                OLEDBG_BEGIN3("ContainerLine_DoVerb(OLEIVERB_DISCARDUNDOSTATE) called!\r\n")
                ContainerLine_DoVerb(
                       lpContainerLine,OLEIVERB_DISCARDUNDOSTATE,FALSE,FALSE);
                OLEDBG_END3
            }

        } else {    // !fInsideOutObj

            /* OLE2NOTE: (INSIDEOUT CONTAINER) if the object is not
            **    registered OLEMISC_ACTIVATEWHENVISIBLE, then we will
            **    make the object behave in an outside-in manner. since
            **    we do NOT deal with UNDO we can simply
            **    InPlaceDeactivate the object. it should NOT be
            **    allowed to leave its window visible when
            **    UIDeactivated. 
            */
            OLEDBG_BEGIN2("IOleInPlaceObject::InPlaceDeactivate called\r\n")
            hrErr = lpContainerLine->m_lpOleIPObj->lpVtbl->InPlaceDeactivate(
                        lpContainerLine->m_lpOleIPObj);
            OLEDBG_END2
            if (hrErr != NOERROR) {
                OleDbgOutHResult("IOleInPlaceObject::InPlaceDeactivate returned", hrErr);
            }
        }
                
    } else { 

        /* OLE2NOTE: (OUTSIDE-IN CONTAINER) since we do NOT deal with
        **    UNDO we can simply InPlaceDeactivate the object. it
        **    should NOT be allowed to leave its window visible when
        **    UIDeactivated. 
        */
    	OLEDBG_BEGIN2("IOleInPlaceObject::InPlaceDeactivate called\r\n")
        hrErr = lpContainerLine->m_lpOleIPObj->lpVtbl->InPlaceDeactivate(
                lpContainerLine->m_lpOleIPObj);
        OLEDBG_END2
        if (hrErr != NOERROR) {
            OleDbgOutHResult("IOleInPlaceObject::InPlaceDeactivate returned", hrErr);
        }
    }

#endif // ! UNDOSUPPORTED 
}



/* ContainerLine_UpdateInPlaceObjectRects
** -------------------------------------
**    Update the PosRect and ClipRect of the given line 
**    currently in-place active
**    object. if there is no object active in-place, then do nothing.
**
**    OLE2NOTE: this function should be called when an action occurs
**    that changes either the position of the object in the document
**    (eg. changing document margins changes PosRect) or the clipRect
**    changes (eg. resizing the document window changes the ClipRect).
*/
void ContainerLine_UpdateInPlaceObjectRects(
		LPCONTAINERLINE	lpContainerLine, 
		LPRECT			lprcClipRect
)
{
	LPCONTAINERDOC lpContainerDoc = lpContainerLine->m_lpDoc;
	RECT rcClipRect;
    RECT rcPosRect;


	if (! lpContainerLine->m_fIpActive)
		return;

	if (! lprcClipRect) {
		ContainerDoc_GetClipRect(lpContainerDoc, (LPRECT)&rcClipRect);
		lprcClipRect = (LPRECT)&rcClipRect;
	}
				
	OleDbgOutRect3("OutlineDoc_Resize (ClipRect)", (LPRECT)&rcClipRect);
					

	ContainerLine_GetOleObjectRectInPixels(
			lpContainerLine,(LPRECT)&rcPosRect);
		
	OleDbgOutRect3(
		"ContainerLine_UpdateInPlaceObjectRects (PosRect)", (LPRECT)&rcPosRect);

	OLEDBG_BEGIN2("IOleInPlaceObject::SetObjectRects called\r\n")
	lpContainerLine->m_lpOleIPObj->lpVtbl->SetObjectRects(
			lpContainerLine->m_lpOleIPObj,
			(LPRECT)&rcPosRect,
			lprcClipRect
	);
	OLEDBG_END2
}



/*************************************************************************
** ContainerLine::IOleInPlaceSite interface implementation
*************************************************************************/

STDMETHODIMP CntrLine_IPSite_QueryInterface(
        LPOLEINPLACESITE    lpThis, 
        REFIID              riid,
        LPVOID FAR*         lplpvObj
)
{
    LPCONTAINERLINE lpContainerLine = 
            ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
    
    return ContainerLine_QueryInterface(lpContainerLine, riid, lplpvObj);
}
    

STDMETHODIMP_(ULONG) CntrLine_IPSite_AddRef(LPOLEINPLACESITE lpThis)
{
    LPCONTAINERLINE lpContainerLine = 
            ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;

    OleDbgAddRefMethod(lpThis, "IOleInPlaceSite");

    return ContainerLine_AddRef(lpContainerLine);
}


STDMETHODIMP_(ULONG) CntrLine_IPSite_Release(LPOLEINPLACESITE lpThis)
{
    LPCONTAINERLINE lpContainerLine = 
            ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;

    OleDbgReleaseMethod(lpThis, "IOleInPlaceSite");

    return ContainerLine_Release(lpContainerLine);
}


STDMETHODIMP CntrLine_IPSite_GetWindow(
    LPOLEINPLACESITE    lpThis,     
    HWND FAR*           lphwnd
)
{
    LPCONTAINERLINE lpContainerLine = 
            ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;

    OleDbgOut2("CntrLine_IPSite_GetWindow\r\n");

    *lphwnd = LineList_GetWindow(&((LPOUTLINEDOC)lpContainerLine->m_lpDoc)->m_LineList);
    return NOERROR;
}

STDMETHODIMP CntrLine_IPSite_ContextSensitiveHelp(
    LPOLEINPLACESITE    lpThis, 
    BOOL                fEnterMode
)
{
    OleDbgOut2("CntrLine_IPSite_ContextSensitiveHelp\r\n");

#if defined( LATER )    
    LPOLEINPLACEFRAME lpFrame = m_pEItem->m_pAC->GetInPlaceFrame();
    HRESULT hrErr = lpFrame->ContextSensitiveHelp(fEnterMode);
    lpFrame->Release();
#endif  // LATER
    return NOERROR;
}

STDMETHODIMP CntrLine_IPSite_CanInPlaceActivate(LPOLEINPLACESITE lpThis)
{
    LPCONTAINERLINE lpContainerLine = 
            ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;

    OleDbgOut2("CntrLine_IPSite_CanInPlaceActivate\r\n");

    /* OLE2NOTE: the container can NOT allow in-place activation if it
    **    is currently displaying the object as an ICON
    **    (DVASPECT_ICON). it can ONLY do in-place activation if it is
    **    displaying the DVASPECT_CONTENT of the OLE object.
    */
    if (lpContainerLine->m_dwDrawAspect == DVASPECT_CONTENT) 
        return NOERROR;
    else 
        return ResultFromScode(S_FALSE);
}       

STDMETHODIMP CntrLine_IPSite_OnInPlaceActivate(LPOLEINPLACESITE lpThis)
{
    LPCONTAINERLINE lpContainerLine = 
            ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
    LPCONTAINERDOC lpContainerDoc = lpContainerLine->m_lpDoc;		
	SCODE sc = S_OK;

    OLEDBG_BEGIN2("CntrLine_IPSite_OnInPlaceActivate\r\n");

    /* OLE2NOTE: (OUTSIDE-IN CONTAINER) as a policy for managing
    **    running in-place servers, we will keep only 1 inplace server
    **    active at any given time. so when we start to inp-place activate
    **    another line, then we want to shut down the previously
    **    activated server. in this way we keep at most one inplace
    **    server active at a time. this is NOT a required policy. apps
    **    may choose to have a more sophisticated strategy. inside-out
    **    containers will HAVE to have a more sophisticated strategy,
    **    because they need (at a minimum) to keep all visible object
    **    servers running.
    **    
    **    if the in-place activation is the result of activating a
    **    linked object in another container, then we may arrive at
    **    this method while another object is currently active.
    **    normally, if the object is in-place activated by
    **    double-clicking or Edit.<verb> from our own container, then
    **    the previous in-place object would have been de-activated in
    **    ContainerLine_DoVerb method.
    */
    if (!g_fInsideOutContainer) {
        if (lpContainerDoc->m_lpLastIpActiveLine) {
            ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded(
                    lpContainerDoc, lpContainerLine);
        }
        lpContainerDoc->m_lpLastIpActiveLine = lpContainerLine;
    }

    lpContainerLine->m_fIpActive        = TRUE;
    lpContainerLine->m_fIpVisible       = TRUE; 
    lpContainerLine->m_fIpServerRunning = TRUE;

	/* OLE2NOTE: to avoid LRPC problems it is important to cache the
	**    IOleInPlaceObject* pointer and NOT to call QueryInterface
	**    each time it is needed.
	*/
    lpContainerLine->m_lpOleIPObj = 
		(LPOLEINPLACEOBJECT) ContainerLine_GetOleObject (
			lpContainerLine, 
            &IID_IOleInPlaceObject
    );

    OleDbgAssertSz(
			lpContainerLine->m_lpOleIPObj!=NULL, 
			"OLE object must support IOleInPlaceObject"
	);
	if (! lpContainerLine->m_lpOleIPObj) 
		return ResultFromScode(E_FAIL);	// ERROR: refuse to in-place activate

	OLEDBG_END2
	
	lpContainerLine->m_lpDoc->m_cIPActiveObjects++;				
    return NOERROR;
}


STDMETHODIMP CntrLine_IPSite_OnUIActivate (LPOLEINPLACESITE lpThis)
{
    LPCONTAINERLINE lpContainerLine = 
            ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
    LPCONTAINERDOC lpContainerDoc = lpContainerLine->m_lpDoc;
    LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc;
    LPCONTAINERLINE lpLastUIActiveLine = lpContainerDoc->m_lpLastUIActiveLine;
    HWND hWndNewUIActiveObj;

    OLEDBG_BEGIN2("CntrLine_IPSite_OnUIActivate\r\n");

    lpContainerLine->m_fUIActive        = TRUE; 
    lpContainerDoc->m_fAddMyUI          = FALSE; 
    lpContainerDoc->m_lpLastUIActiveLine = lpContainerLine;
	
    OLEDBG_BEGIN2("IOleInPlaceObject::GetWindow called\r\n")
    lpContainerLine->m_lpOleIPObj->lpVtbl->GetWindow(
            lpContainerLine->m_lpOleIPObj, 
            (HWND FAR*)&hWndNewUIActiveObj
    );
    OLEDBG_END2

    if (g_fInsideOutContainer) {
        /* OLE2NOTE: (INSIDE-OUT CONTAINER) an inside-out style
        **    container must UIDeactivate the previous UIActive object
        **    when a new object is going UIActive. since the inside-out
        **    objects have their own windows visible, it is possible
        **    that a click directly in an another server window will
        **    cause it to UIActivate. OnUIActivate is the containers
        **    notification that such has occured. it must then
        **    UIDeactivate the other because at most one object can be
        **    UIActive at a time.
        */
        if (lpLastUIActiveLine && (lpLastUIActiveLine!=lpContainerLine)) {
            ContainerLine_UIDeactivate(lpLastUIActiveLine);
                
            // Make sure new UIActive window is on top of all others
            SetWindowPos(
                    hWndNewUIActiveObj,
                    HWND_TOPMOST,
                    0,0,0,0,
                    SWP_NOMOVE | SWP_NOSIZE
            );

            OLEDBG_END2
	    	return NOERROR;			
        }
	}				
	
    lpContainerDoc->m_hwndUIActiveObj = hWndNewUIActiveObj;

#if defined( USE_FRAMETOOLS )
	ContainerDoc_RemoveFrameLevelTools(lpContainerDoc);
#endif

#if defined( USE_DOCTOOLS )
	ContainerDoc_RemoveDocLevelTools(lpContainerDoc);
#endif

    OLEDBG_END2
    return NOERROR;
}

        
STDMETHODIMP CntrLine_IPSite_GetWindowContext(
    LPOLEINPLACESITE            lpThis,
    LPOLEINPLACEFRAME FAR*      lplpFrame,
    LPOLEINPLACEUIWINDOW FAR*   lplpDoc,
    LPRECT                      lprcPosRect, 
    LPRECT                      lprcClipRect, 
    LPOLEINPLACEFRAMEINFO       lpFrameInfo
)
{
    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
    LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
    LPCONTAINERLINE lpContainerLine = 
            ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;

    OLEDBG_BEGIN2("CntrLine_IPSite_GetWindowContext\r\n")

	/* OLE2NOTE: The server should fill in the "cb" field so that the
	**    container can tell what size structure the server is
	**    expecting. this enables this structure to be easily extended
	**    in future releases of OLE. the container should check this
	**    field so that it doesn't try to use fields that do not exist
	**    since the server may be using an old structure definition.
	**    Since this is the first release of OLE2.0, the structure is
	**    guaranteed to be at least large enough for the current
	**    definition of OLEINPLACEFRAMEINFO struct. thus we do NOT need
	**    to consider this an error if the server did not fill in this
	**    field correctly. this server may have trouble in the future,
	**    however, when the structure is extended.
	*/
 //	OleDbgAssert(lpFrameInfo->cb >= sizeof(OLEINPLACEFRAMEINFO));

    *lplpFrame = (LPOLEINPLACEFRAME)&lpContainerApp->m_OleInPlaceFrame;
    (*lplpFrame)->lpVtbl->AddRef(*lplpFrame);   // must return AddRef'ed ptr

    // OLE2NOTE: an MDI app would have to provide *lplpDoc
    *lplpDoc  = NULL;
    
    ContainerLine_GetOleObjectRectInPixels(lpContainerLine, lprcPosRect); 
	ContainerDoc_GetClipRect(lpContainerLine->m_lpDoc, lprcClipRect);
    
    OleDbgOutRect3("CntrLine_IPSite_GetWindowContext (PosRect)", lprcPosRect);
    OleDbgOutRect3("CntrLine_IPSite_GetWindowContext (ClipRect)",lprcClipRect);

    lpFrameInfo->hwndFrame      = lpOutlineApp->m_hWndApp; 

#if defined( MDI_VERSION )
    lpFrameInfo->fMDIApp        = TRUE;
#else
    lpFrameInfo->fMDIApp        = FALSE;
#endif

    lpFrameInfo->haccel         = lpContainerApp->m_hAccelIPCntr;
    lpFrameInfo->cAccelEntries  = NUM_INPLACE_ACCELS;

    OLEDBG_END2
    return NOERROR;
}       


STDMETHODIMP CntrLine_IPSite_Scroll(
    LPOLEINPLACESITE    lpThis,
    SIZE                scrollExtent
)
{
    OleDbgOut2("CntrLine_IPSite_Scroll\r\n");

    return ResultFromScode(E_FAIL);
}


STDMETHODIMP CntrLine_IPSite_OnUIDeactivate(
    LPOLEINPLACESITE    lpThis,
    BOOL                fUndoable
)
{
    LPCONTAINERLINE lpContainerLine = 
            ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
    LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc;
    LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP) g_lpApp;
    LPLINELIST lpLL;
    int nIndex;
	MSG msg;

    OLEDBG_BEGIN2("CntrLine_IPSite_OnUIDeactivate\r\n")

    lpContainerLine->m_fUIActive = FALSE;
    lpContainerLine->m_fIpChangesUndoable = fUndoable;
    lpContainerLine->m_lpDoc->m_hwndUIActiveObj = NULL;

	if (lpContainerLine == lpContainerLine->m_lpDoc->m_lpLastUIActiveLine) {
	
        lpContainerLine->m_lpDoc->m_lpLastUIActiveLine = NULL;

		/* OLE2NOTE: here we look ahead if there is a DBLCLK sitting in our
		**    message queue. if so, it could result in in-place activating
		**    another object. we want to avoid placing our tools and
		**    repainting if immediately another object is going to do the
		**    same. SO, if there is a DBLCLK in the queue for this document
		**    we will only set the fAddMyUI flag to indicate that this work
		**    is still to be done. if another object actually in-place
		**    activates then this flag will be cleared in
		**    IOleInPlaceSite::OnUIActivate. if it does NOT get cleared,
		**    then at the end of processing the DBLCLK message in our
		**    OutlineDocWndProc we will put our tools back.
		*/
		if (! PeekMessage(&msg, lpOutlineDoc->m_hWndDoc, 
				WM_LBUTTONDBLCLK, WM_LBUTTONDBLCLK, 
				PM_NOREMOVE | PM_NOYIELD)) {

#if defined( USE_DOCTOOLS )
			ContainerDoc_AddDocLevelTools(lpContainerLine->m_lpDoc);
#endif

#if defined( USE_FRAMETOOLS )
			ContainerDoc_AddFrameLevelUI(lpContainerLine->m_lpDoc);
#endif
		} else {
			lpContainerLine->m_lpDoc->m_fAddMyUI = TRUE; 
		}

		/* OLE2NOTE: we should re-take focus. the in-place server window
		**    previously had the focus; this window has just been removed.
		*/
		SetFocus(OutlineDoc_GetWindow((LPOUTLINEDOC)lpContainerLine->m_lpDoc));

		// force the line to redraw to remove in-place active hatch
		lpLL = OutlineDoc_GetLineList(lpOutlineDoc);
		nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine);
		LineList_ForceLineRedraw(lpLL, nIndex, TRUE);
	}
	
    OLEDBG_END2
    return NOERROR;
}


STDMETHODIMP CntrLine_IPSite_OnInPlaceDeactivate(LPOLEINPLACESITE lpThis)
{
    LPCONTAINERLINE lpContainerLine = 
            ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;

    OLEDBG_BEGIN2("CntrLine_IPSite_OnInPlaceDeactivate\r\n");

    lpContainerLine->m_fIpActive            = FALSE;
    lpContainerLine->m_fIpVisible           = FALSE; 
    lpContainerLine->m_fIpChangesUndoable   = FALSE;
	
	OleStdRelease((LPUNKNOWN) lpContainerLine->m_lpOleIPObj);
	lpContainerLine->m_lpOleIPObj = NULL;	
	lpContainerLine->m_lpDoc->m_cIPActiveObjects--;				

	OLEDBG_END2
    return NOERROR;
}


STDMETHODIMP CntrLine_IPSite_DiscardUndoState(LPOLEINPLACESITE lpThis)
{
    OleDbgOut2("CntrLine_IPSite_DiscardUndoState\r\n");

    return NOERROR;
}


STDMETHODIMP CntrLine_IPSite_DeactivateAndUndo(LPOLEINPLACESITE lpThis)
{
    OleDbgOut2("CntrLine_IPSite_DeactivateAndUndo\r\n");

    return NOERROR;
}


STDMETHODIMP CntrLine_IPSite_OnPosRectChange(
    LPOLEINPLACESITE    lpThis,
    LPCRECT             lprcPosRect		
)
{
    LPCONTAINERLINE lpContainerLine = 
            ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
    LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc;
	LPSCALEFACTOR lpscale = OutlineDoc_GetScaleFactor(lpOutlineDoc);
	LPLINE lpLine = (LPLINE)lpContainerLine;
    LPLINELIST lpLL;
    int nIndex;
	RECT rcClipRect;
	RECT rcNewPosRect;
	SIZEL sizelPix;
	SIZEL sizelHim;
	int nIPObjHeight = lprcPosRect->bottom - lprcPosRect->top;
	int nIPObjWidth = lprcPosRect->right - lprcPosRect->left;

    OLEDBG_BEGIN2("CntrLine_IPSite_OnPosRectChange\r\n")

    OleDbgOutRect3("CntrLine_IPSite_OnPosRectChange (PosRect --IN)", 
			(LPRECT)lprcPosRect);

	/* OLE2NOTE: if the in-place container does NOT impose any
	**    size contraints on its in-place active objects, then it may
	**    simply grant the size requested by the object by immediately
	**    calling IOleInPlaceObject::SetObjectRects with the
	**    lprcPosRect passed by the in-place object.
	**    
	**    Container Outline, however, imposes a size constraint on its
	**    embedded objects (see comment in ContainerLine_UpdateExtent),
	**    thus it is necessary to calculate the size that the in-place
	**    active object is allowed to be.
	*/

	/* calculate the new object extents. we can NOT directly ask the
	**    object via IOleObject::GetExtent because this method will
	**    retreive the extents of the last cached metafile. the cache
	**    has not yet been updated by this point. the best we can do is
	**    determine the scale factor that the object is operating at
	**    and scale the lprcPosRect back to HIMETRIC units.
	*/
	if (lpContainerLine->m_sizeInHimetric.cx > 0 &&
		lpContainerLine->m_sizeInHimetric.cy > 0) {
		sizelHim.cx = lpLine->m_nWidthInHimetric;
		sizelHim.cy = lpLine->m_nHeightInHimetric;
		XformSizeInHimetricToPixels(NULL, &sizelHim, &sizelPix);
		sizelPix.cx -= 2* LINE_BOUNDARY_WIDTH;
		sizelPix.cy -= 2* LINE_BOUNDARY_WIDTH;
		sizelHim.cx = lpContainerLine->m_sizeInHimetric.cx * nIPObjWidth / 
				sizelPix.cx;
		sizelHim.cy = lpContainerLine->m_sizeInHimetric.cy * nIPObjHeight / 
				sizelPix.cy;
		
		// Convert size back to 100% zoom
		sizelHim.cx = sizelHim.cx * lpscale->dwSxD / lpscale->dwSxN;
		sizelHim.cy = sizelHim.cy * lpscale->dwSyD / lpscale->dwSyN;
			
	} else {
		sizelHim.cx = (long)DEFOBJWIDTH;
		sizelHim.cy = (long)DEFOBJHEIGHT;
		XformSizeInHimetricToPixels(NULL, &sizelHim, &sizelPix);
		sizelHim.cx = sizelHim.cx * nIPObjWidth / sizelPix.cx;
		sizelHim.cy = sizelHim.cy * nIPObjHeight / sizelPix.cy;
	}
	ContainerLine_UpdateExtent(lpContainerLine, &sizelHim);
	ContainerLine_GetOleObjectRectInPixels(
			lpContainerLine, (LPRECT)&rcNewPosRect); 

	ContainerDoc_GetClipRect(lpContainerLine->m_lpDoc, (LPRECT)&rcClipRect);

    OleDbgOutRect3("CntrLine_IPSite_OnPosRectChange (PosRect --OUT)", 
			(LPRECT)&rcNewPosRect);
    OleDbgOutRect3("CntrLine_IPSite_OnPosRectChange (ClipRect--OUT)", 
            (LPRECT)&rcClipRect);

    OLEDBG_BEGIN2("IOleInPlaceObject::SetObjectRects called\r\n")
    lpContainerLine->m_lpOleIPObj->lpVtbl->SetObjectRects(
            lpContainerLine->m_lpOleIPObj, 
            (LPRECT)&rcNewPosRect, 
            (LPRECT)&rcClipRect
    );
    OLEDBG_END2

    lpLL = OutlineDoc_GetLineList(lpOutlineDoc);
    nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine);
	ContainerDoc_UpdateInPlaceObjectRects(lpContainerLine->m_lpDoc, nIndex);

    OLEDBG_END2
    return NOERROR;
}


#endif // INPLACE_CNTR



unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.