home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / OLESVR1.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-03  |  75.9 KB  |  3,073 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1997 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12. #include <shellapi.h>
  13.  
  14. #ifdef AFX_OLE4_SEG
  15. #pragma code_seg(AFX_OLE4_SEG)
  16. #endif
  17.  
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. #define new DEBUG_NEW
  24.  
  25. //////////////////////////////////////////////////////////////////////////////
  26. // COleServerDoc implementation
  27.  
  28. COleServerDoc::COleServerDoc()
  29. {
  30.     m_lpClientSite = NULL;  // will be non-NULL when document is embedding
  31.     m_bCntrVisible = FALSE;
  32.     m_pInPlaceFrame = NULL; // will be non-NULL when in-place active
  33.     m_pOrigParent = NULL;
  34.     m_dwOrigStyle = 0;
  35.     m_dwOrigStyleEx = 0;
  36.     m_bClosing = FALSE;
  37.     m_pEmbeddedItem = NULL; // will be non-NULL if embedded item needed
  38.     m_pDocObjectServer = NULL;      // becomes non-NULL if DocObject support enabled
  39. }
  40.  
  41. COleServerDoc::~COleServerDoc()
  42. {
  43.     DeleteContents();   // Note: will not call derived class
  44.  
  45.     if (m_pEmbeddedItem != NULL)
  46.     {
  47.         m_pEmbeddedItem->ExternalRelease();
  48.         m_pEmbeddedItem = NULL;
  49.     }
  50.  
  51.     // disconnect (remove) all items from the document
  52.     POSITION pos = GetStartPosition();
  53.     COleServerItem* pItem;
  54.     while ((pItem = GetNextServerItem(pos)) != NULL)
  55.         RemoveItem(pItem);
  56.  
  57. #ifndef _MAC
  58.     // release doc object manager, if any
  59.     if (m_pDocObjectServer != NULL)
  60.     {
  61.         delete m_pDocObjectServer;
  62.         m_pDocObjectServer = NULL;
  63.     }
  64. #endif
  65.  
  66.     // should not be in-place active when doc is destroyed!
  67.     ASSERT(m_pInPlaceFrame == NULL);
  68.  
  69.     // Note: this must be done before the client site is released
  70.     RELEASE(m_lpRootStg);
  71.  
  72.     // release client-site pointer
  73.     RELEASE(m_lpClientSite);
  74. }
  75.  
  76. void COleServerDoc::DeleteContents()
  77. {
  78.     COleLinkingDoc::DeleteContents();
  79.  
  80.     // protect all server items with an extra reference count
  81.     POSITION pos = GetStartPosition();
  82.     COleServerItem* pItem;
  83.     while ((pItem = GetNextServerItem(pos)) != NULL)
  84.         pItem->InternalAddRef();
  85.  
  86.     // delete any autodelete server items
  87.     pos = GetStartPosition();
  88.     while ((pItem = GetNextServerItem(pos)) != NULL)
  89.     {
  90.         if (pItem->m_bAutoDelete)
  91.             delete pItem;
  92.     }
  93.  
  94.     // remove extra reference added above
  95.     pos = GetStartPosition();
  96.     while ((pItem = GetNextServerItem(pos)) != NULL)
  97.         pItem->InternalRelease();
  98. }
  99.  
  100. COleServerItem* COleServerDoc::GetEmbeddedItem()
  101. {
  102.     // allocate embedded item if necessary
  103.     if (m_pEmbeddedItem == NULL)
  104.     {
  105.         m_pEmbeddedItem = OnGetEmbeddedItem();
  106.         m_pEmbeddedItem->ExternalAddRef();
  107.     }
  108.  
  109.     ASSERT_VALID(m_pEmbeddedItem);
  110.     return m_pEmbeddedItem;
  111. }
  112.  
  113. #if !defined(_MAC) || defined (MACOCX)
  114. CDocObjectServer* COleServerDoc::GetDocObjectServer(LPOLEDOCUMENTSITE pDocSite)
  115. {
  116.     // by default, we're not DocObject enabled
  117.     UNUSED_ALWAYS(pDocSite);
  118.     return NULL;
  119. }
  120.  
  121. HRESULT COleServerDoc::OnExecOleCmd(const GUID* pguidCmdGroup, DWORD nCmdID,
  122.         DWORD nCmdExecOpt, VARIANTARG* pvarargIn, VARIANTARG* pvarargOut)
  123. {
  124.     UNUSED_ALWAYS(pguidCmdGroup);
  125.     UNUSED_ALWAYS(nCmdID);
  126.     UNUSED_ALWAYS(nCmdExecOpt);
  127.     UNUSED_ALWAYS(pvarargIn);
  128.     UNUSED_ALWAYS(pvarargOut);
  129.  
  130.     return E_NOTIMPL;
  131. }
  132. #endif
  133.  
  134. LPUNKNOWN COleServerDoc::GetInterfaceHook(const void* piid)
  135. {
  136.     LPUNKNOWN lpUnk = NULL;
  137.  
  138. #ifndef _MAC
  139.     // are we Doc Object supporters?
  140.     if (m_pDocObjectServer != NULL)
  141.     {
  142.         // don't be tricked into handing out a different IUnknown
  143.         DWORD lData1 = ((IID*)piid)->Data1;
  144.         BOOL bUnknown = ((DWORD*)&IID_IUnknown)[0] == lData1 &&
  145.             ((DWORD*)piid)[1] == ((DWORD*)&IID_IUnknown)[1] &&
  146.             ((DWORD*)piid)[2] == ((DWORD*)&IID_IUnknown)[2] &&
  147.             ((DWORD*)piid)[3] == ((DWORD*)&IID_IUnknown)[3];
  148.  
  149.         if (bUnknown)
  150.             return NULL;
  151.  
  152.         lpUnk = m_pDocObjectServer->GetInterface(piid);
  153.     }
  154. #endif
  155.  
  156.     // failing that, try the base class
  157.     if (lpUnk == NULL)
  158.         lpUnk = COleLinkingDoc::GetInterfaceHook(piid);
  159.  
  160.     return lpUnk;
  161. }
  162.  
  163. #if !defined(_MAC) || defined (MACOCX)
  164. void COleServerDoc::ActivateDocObject()
  165. {
  166.     if (m_pDocObjectServer != NULL)
  167.         m_pDocObjectServer->ActivateDocObject();
  168. }
  169. #endif
  170.  
  171. /////////////////////////////////////////////////////////////////////////////
  172. // COleServerDoc client notifications
  173.  
  174. void COleServerDoc::NotifyRename(LPCTSTR lpszNewName)
  175. {
  176.     ASSERT_VALID(this);
  177.     ASSERT(AfxIsValidString(lpszNewName));
  178.  
  179.     if (m_pFactory != NULL)
  180.     {
  181.         // update running object table with new moniker
  182.         Revoke();
  183.         Register(m_pFactory, lpszNewName);
  184.  
  185.         // notify all items of the new moniker
  186.         POSITION pos = GetStartPosition();
  187.         COleServerItem* pItem;
  188.         while ((pItem = GetNextServerItem(pos)) != NULL)
  189.         {
  190.             // notify client directly
  191.             LPMONIKER lpMoniker = pItem->GetMoniker(OLEGETMONIKER_ONLYIFTHERE);
  192.             pItem->NotifyClient(OLE_RENAMED, (DWORD)lpMoniker);
  193.             RELEASE(lpMoniker);
  194.         }
  195.     }
  196. }
  197.  
  198. void COleServerDoc::NotifyAllItems(OLE_NOTIFICATION nCode, DWORD dwParam)
  199. {
  200.     ASSERT_VALID(this);
  201.  
  202.     POSITION pos = GetStartPosition();
  203.     COleServerItem* pItem;
  204.     while ((pItem = GetNextServerItem(pos)) != NULL)
  205.     {
  206.         // notify client directly
  207.         pItem->NotifyClient(nCode, dwParam);
  208.     }
  209. }
  210.  
  211. // UpdateAllItems is much like UpdateAllViews, but for server items
  212. void COleServerDoc::UpdateAllItems(COleServerItem* pSender,
  213.     LPARAM lHint, CObject* pHint, DVASPECT nDrawAspect)
  214. {
  215.     ASSERT_VALID(this);
  216.  
  217.     POSITION pos = GetStartPosition();
  218.     COleServerItem* pItem;
  219.     while ((pItem = GetNextServerItem(pos)) != NULL)
  220.     {
  221.         // notify client indirectly through OnUpdate
  222.         if (pItem != pSender)
  223.             pItem->OnUpdate(pSender, lHint, pHint, nDrawAspect);
  224.     }
  225. }
  226.  
  227. void COleServerItem::OnUpdate(COleServerItem* /*pSender*/,
  228.     LPARAM /*lHint*/, CObject* /*pHint*/, DVASPECT nDrawAspect)
  229. {
  230.     // the default implementation always notifies the container, regardless
  231.     //  of the specific hint or sender.
  232.  
  233.     NotifyChanged(nDrawAspect);
  234. }
  235.  
  236. /////////////////////////////////////////////////////////////////////////////
  237. // COleServerDoc attributes
  238.  
  239. BOOL COleServerDoc::GetZoomFactor(LPSIZE lpSizeNum, LPSIZE lpSizeDenom,
  240.     LPCRECT lpPosRect) const
  241. {
  242.     ASSERT_VALID(this);
  243.     ASSERT(lpSizeNum == NULL || AfxIsValidAddress(lpSizeNum, sizeof(SIZE)));
  244.     ASSERT(lpSizeDenom == NULL || AfxIsValidAddress(lpSizeDenom, sizeof(SIZE)));
  245.     ASSERT(lpPosRect == NULL ||
  246.         AfxIsValidAddress(lpPosRect, sizeof(RECT), FALSE));
  247.  
  248.     if (!IsInPlaceActive())
  249.     {
  250.         if (lpSizeNum != NULL)
  251.         {
  252.             ASSERT(lpSizeDenom != NULL);
  253.             lpSizeNum->cx = 1;
  254.             lpSizeNum->cy = 1;
  255.             *lpSizeDenom = *lpSizeNum;
  256.         }
  257.         return FALSE;
  258.     }
  259.     ASSERT_VALID(m_pInPlaceFrame);
  260.  
  261.     // the zoom factor is (Size(position-rect) / m_sizeExtent)
  262.     CSize sizeNum;
  263.     if (lpPosRect == NULL)
  264.     {
  265.         // use current position rect
  266.         sizeNum = m_pInPlaceFrame->m_rectPos.Size();
  267.     }
  268.     else
  269.     {
  270.         // use new position rect
  271.         sizeNum.cx = lpPosRect->right - lpPosRect->left;
  272.         sizeNum.cy = lpPosRect->bottom - lpPosRect->top;
  273.     }
  274.  
  275.     // m_sizeExtent is in HIMETRIC units -- need to convert to pixels.
  276.     CSize sizeDenom(0, 0);
  277.     COleServerItem* pItem = ((COleServerDoc*)this)->GetEmbeddedItem();
  278.     ASSERT_VALID(pItem);
  279.     ASSERT_KINDOF(COleServerItem, pItem);
  280.  
  281.     // get zoom denominator, which is based on the current extent
  282.     ((COleServerItem*)pItem)->OnGetExtent(DVASPECT_CONTENT, sizeDenom);
  283.     if (sizeDenom.cx == 0 || sizeDenom.cy == 0)
  284.     {
  285.         // no extent from container available, so use natural extent instead
  286.         pItem->OnGetExtent(DVASPECT_CONTENT, sizeDenom);
  287.     }
  288.     // convert extent to pixels first
  289.     ((CDC*)NULL)->HIMETRICtoDP(&sizeDenom);
  290.  
  291.     // might be bad to have zoom denominator of zero!
  292.     if (sizeDenom.cy == 0 || sizeDenom.cx == 0)
  293.     {
  294.         TRACE0("Warning: zero 'zoom denominator', using 100%% zoom instead.\n");
  295.         sizeDenom = sizeNum;
  296.     }
  297.  
  298.     // store the results
  299.     if (lpSizeNum != NULL)
  300.     {
  301.         ASSERT(lpSizeDenom != NULL);
  302.         *lpSizeNum = sizeNum;
  303.         *lpSizeDenom = sizeDenom;
  304.     }
  305.  
  306.     // if 100% scaling, return FALSE
  307.     return sizeNum != sizeDenom;
  308. }
  309.  
  310. void COleServerDoc::GetItemPosition(LPRECT lpPosRect) const
  311. {
  312.     ASSERT_VALID(this);
  313.     ASSERT(AfxIsValidAddress(lpPosRect, sizeof(RECT)));
  314.     ASSERT(IsInPlaceActive());
  315.     ASSERT_VALID(m_pInPlaceFrame);
  316.  
  317.     // copy the current rectangle
  318.     *lpPosRect = m_pInPlaceFrame->m_rectPos;
  319. }
  320.  
  321. void COleServerDoc::GetItemClipRect(LPRECT lpClipRect) const
  322. {
  323.     ASSERT_VALID(this);
  324.     ASSERT(AfxIsValidAddress(lpClipRect, sizeof(RECT)));
  325.     ASSERT(IsInPlaceActive());
  326.     ASSERT_VALID(m_pInPlaceFrame);
  327.  
  328.     // copy the current rectangle
  329.     *lpClipRect = m_pInPlaceFrame->m_rectClip;
  330. }
  331.  
  332. /////////////////////////////////////////////////////////////////////////////
  333. // COleServerDoc overrideables
  334.  
  335. COleServerItem* COleServerDoc::OnGetLinkedItem(LPCTSTR lpszItemName)
  336. {
  337.     ASSERT_VALID(this);
  338.     ASSERT(AfxIsValidString(lpszItemName));
  339.  
  340.     // default implementation walks list of server items looking for
  341.     //  a case sensitive match
  342.  
  343.     POSITION pos = GetStartPosition();
  344.     COleServerItem* pItem;
  345.     while ((pItem = GetNextServerItem(pos)) != NULL)
  346.     {
  347.         // return item if name matches (case sensitive)
  348.         if (lstrcmp(pItem->GetItemName(), lpszItemName) == 0)
  349.             return pItem;
  350.     }
  351.  
  352. #ifdef _DEBUG
  353.     if (afxTraceFlags & traceOle)
  354.     {
  355.         TRACE0("Warning: default COleServerDoc::OnGetLinkedItem implementation\n");
  356.         TRACE1("\tfailed to find item '%s'.\n", lpszItemName);
  357.     }
  358. #endif
  359.     return NULL;        // not found (no link found)
  360. }
  361.  
  362. void COleServerDoc::OnClose(OLECLOSE dwCloseOption)
  363. {
  364.     ASSERT_VALID(this);
  365.  
  366.     // do nothing if already in the process of closing the document
  367.     if (m_bClosing)
  368.         return;
  369.  
  370.     // OLECLOSE_PROMPTSAVE is handled like OLECLOSE_SAVEIFDIRTY if invisible
  371.     CFrameWnd* pFrameWnd = GetFirstFrame();
  372.     if (pFrameWnd != NULL && pFrameWnd->IsWindowVisible())
  373.         dwCloseOption = OLECLOSE_SAVEIFDIRTY;
  374.  
  375.     // handle modified document and special dwCloseOption flags
  376.     TRY
  377.     {
  378.         if (IsModified())
  379.         {
  380.             switch (dwCloseOption)
  381.             {
  382.             case OLECLOSE_PROMPTSAVE:
  383.                 if (!SaveModifiedPrompt())
  384.                     AfxThrowOleException(OLE_E_PROMPTSAVECANCELLED);
  385.                 break;
  386.  
  387.             case OLECLOSE_SAVEIFDIRTY:
  388.                 SaveEmbedding();
  389.                 break;
  390.             }
  391.         }
  392.     }
  393.     END_TRY
  394.  
  395.     // deactivate in-place session
  396.     if (m_pInPlaceFrame != NULL)
  397.     {
  398.         OnDeactivate();
  399.         ASSERT(m_pInPlaceFrame == NULL);
  400.     }
  401.  
  402.     // close the document
  403.     BOOL bAutoDelete = m_bAutoDelete;
  404.     m_bAutoDelete = FALSE;
  405.     OnCloseDocument();
  406.     m_bAutoDelete = bAutoDelete;
  407. }
  408.  
  409. BOOL COleServerDoc::SaveModifiedPrompt()
  410. {
  411.     ASSERT_VALID(this);
  412.  
  413.     if (m_lpClientSite == NULL)
  414.         return SaveModified();
  415.  
  416.     UpdateModifiedFlag();   // check for modified client items
  417.  
  418.     if (!IsModified())
  419.         return TRUE;        // ok to continue
  420.  
  421.     CString prompt;
  422.     AfxFormatString1(prompt, AFX_IDP_ASK_TO_UPDATE, m_strTitle);
  423.     switch (AfxMessageBox(prompt, MB_YESNOCANCEL, AFX_IDP_ASK_TO_UPDATE))
  424.     {
  425.     case IDCANCEL:
  426.         return FALSE;       // don't continue
  427.  
  428.     case IDYES:
  429.         if (!OnUpdateDocument())
  430.         {
  431.             TRACE0("Warning: OnUpdateDocument failed to update.\n");
  432.             // keep going, close will flush it
  433.         }
  434.         break;
  435.     }
  436.     return TRUE;    // keep going
  437. }
  438.  
  439. BOOL COleServerDoc::CanCloseFrame(CFrameWnd* pFrame)
  440. {
  441.     m_bClosing = TRUE;
  442.     if (!COleLinkingDoc::CanCloseFrame(pFrame))
  443.     {
  444.         m_bClosing = FALSE;
  445.         return FALSE;
  446.     }
  447.     return TRUE;
  448. }
  449.  
  450. BOOL COleServerDoc::GetFileTypeString(CString& rString)
  451. {
  452.     ASSERT_VALID(this);
  453.  
  454.     CDocTemplate* pTemplate = GetDocTemplate();
  455.     if (pTemplate == NULL)
  456.         return FALSE;
  457.  
  458.     pTemplate->GetDocString(rString, CDocTemplate::fileNewName);
  459.     return !rString.IsEmpty();
  460. }
  461.  
  462. void COleServerDoc::OnSetHostNames(LPCTSTR lpszHost, LPCTSTR lpszHostObj)
  463. {
  464.     ASSERT_VALID(this);
  465.     ASSERT(lpszHost == NULL || AfxIsValidString(lpszHost));
  466.     ASSERT(lpszHostObj == NULL || AfxIsValidString(lpszHostObj));
  467.     UNUSED(lpszHost);    // unused in release builds
  468.  
  469.     // only change the title for embedded documents
  470.     if (m_lpClientSite != NULL)
  471.     {
  472.         // save name of document for File.Exit update
  473.         if (lpszHostObj == NULL)
  474.             m_strHostObj.LoadString(AFX_IDS_UNTITLED);
  475.         else
  476.             m_strHostObj = lpszHostObj;
  477.  
  478.         // attempt to get the document name from the document template
  479.         CString strFileType;
  480.         if (!GetFileTypeString(strFileType))
  481.             return;
  482.  
  483.         // format the string into <server-name> in <docname>
  484.         CString strTitle;
  485.         AfxFormatString2(strTitle, AFX_IDS_APP_TITLE_EMBEDDING,
  486.             strFileType, m_strHostObj);
  487.  
  488.         // change title of document to that for an embedded item
  489.         //  (this call will update all of the frames)
  490.         SetTitle(strTitle);
  491.     }
  492. }
  493.  
  494. void COleServerDoc::SaveEmbedding()
  495. {
  496.     ASSERT_VALID(this);
  497.  
  498.     // tell the client site to save the object
  499.     if (m_lpClientSite != NULL && !::InSendMessage())
  500.     {
  501.         SCODE sc = m_lpClientSite->SaveObject();
  502.         if (sc != S_OK)
  503.             AfxThrowOleException(sc);
  504.     }
  505.     ASSERT_VALID(this);
  506. }
  507.  
  508. BOOL COleServerDoc::OnUpdateDocument()
  509. {
  510.     ASSERT_VALID(this);
  511.  
  512.     // don't save if already up-to-date
  513.     if (!IsModified())
  514.         return TRUE;
  515.  
  516.     // save a server document -> update
  517.     TRY
  518.     {
  519.         SaveEmbedding();
  520.     }
  521.     CATCH_ALL(e)
  522.     {
  523.         AfxMessageBox(AFX_IDP_FAILED_TO_UPDATE);
  524.         DELETE_EXCEPTION(e);
  525.         return FALSE;
  526.     }
  527.     END_CATCH_ALL
  528.  
  529.     return TRUE;
  530. }
  531.  
  532. LPMONIKER COleServerDoc::GetMoniker(OLEGETMONIKER nAssign)
  533. {
  534.     ASSERT_VALID(this);
  535.  
  536.     if (m_lpClientSite != NULL)
  537.     {
  538.         // get moniker from client site instead of from document
  539.         LPMONIKER lpMoniker = NULL;
  540.         m_lpClientSite->GetMoniker(nAssign, OLEWHICHMK_OBJFULL, &lpMoniker);
  541.         return lpMoniker;
  542.     }
  543.  
  544.     return COleLinkingDoc::GetMoniker(nAssign);
  545. }
  546.  
  547. /////////////////////////////////////////////////////////////////////////////
  548. // COleServerDoc document handling
  549.  
  550. BOOL COleServerDoc::SaveModified()
  551. {
  552.     ASSERT_VALID(this);
  553.  
  554.     if (m_lpClientSite != NULL)
  555.     {
  556.         if (m_pInPlaceFrame == NULL)
  557.         {
  558.             UpdateModifiedFlag();   // check for modified items
  559.             OnUpdateDocument();
  560.         }
  561.         return TRUE;
  562.     }
  563.     return COleLinkingDoc::SaveModified();
  564. }
  565.  
  566. HMENU COleServerDoc::GetDefaultMenu()
  567. {
  568.     ASSERT_VALID(this);
  569.  
  570.     CDocTemplate* pTemplate = GetDocTemplate();
  571.     if (pTemplate == NULL)
  572.         return NULL;    // no doc template -- use default
  573.  
  574.     ASSERT_VALID(pTemplate);
  575.     if (m_pInPlaceFrame != NULL)
  576.         return pTemplate->m_hMenuInPlaceServer; // return special in-place menu
  577.     else if (m_lpClientSite != NULL)
  578.         return pTemplate->m_hMenuEmbedding; // return special embedding menu
  579.  
  580.     return NULL;    // no special mode, use default menu
  581. }
  582.  
  583. HACCEL COleServerDoc::GetDefaultAccelerator()
  584. {
  585.     ASSERT_VALID(this);
  586.  
  587.     CDocTemplate* pTemplate = GetDocTemplate();
  588.     if (pTemplate == NULL)
  589.         return NULL;    // no doc template -- use default
  590.  
  591.     ASSERT_VALID(pTemplate);
  592.     if (m_pInPlaceFrame != NULL)
  593.         return pTemplate->m_hAccelInPlaceServer;    // return special in-place accel
  594.     else if (m_lpClientSite != NULL)
  595.         return pTemplate->m_hAccelEmbedding;// return special embedding accel
  596.  
  597.     return NULL;    // no special mode, use default menu
  598. }
  599.  
  600. /////////////////////////////////////////////////////////////////////////////
  601. // COleServerDoc default command handling
  602.  
  603. BEGIN_MESSAGE_MAP(COleServerDoc, COleLinkingDoc)
  604.     //{{AFX_MSG_MAP(COleServerDoc)
  605.     ON_COMMAND(ID_FILE_UPDATE, OnFileUpdate)
  606.     ON_COMMAND(ID_FILE_SAVE_COPY_AS, OnFileSaveCopyAs)
  607.     ON_UPDATE_COMMAND_UI(ID_APP_EXIT, OnUpdateFileExit)
  608.     ON_UPDATE_COMMAND_UI(ID_FILE_UPDATE, OnUpdateFileUpdate)
  609.     //}}AFX_MSG_MAP
  610. END_MESSAGE_MAP()
  611.  
  612. void COleServerDoc::OnFileUpdate()
  613. {
  614.     ASSERT_VALID(this);
  615.     ASSERT(m_lpClientSite != NULL);
  616.  
  617.     UpdateModifiedFlag();
  618.     OnUpdateDocument();
  619. }
  620.  
  621. void COleServerDoc::OnFileSaveCopyAs()
  622. {
  623.     ASSERT_VALID(this);
  624.     ASSERT(m_bRemember);
  625.     ASSERT(m_lpClientSite != NULL);
  626.  
  627.     LPSTORAGE lpOrigStg = m_lpRootStg;
  628.     m_lpRootStg = NULL; // ignore embedded storage for now
  629.  
  630.     TRY
  631.     {
  632.         // call DoSave to perform Save Copy As...
  633.         m_bRemember = FALSE;
  634.         DoSave(NULL, FALSE);
  635.     }
  636.     END_TRY
  637.  
  638.     m_lpRootStg = lpOrigStg;
  639.     m_bRemember = TRUE;
  640. }
  641.  
  642. void COleServerDoc::UpdateUsingHostObj(UINT nIDS, CCmdUI* pCmdUI)
  643. {
  644.     ASSERT_VALID(this);
  645.     ASSERT(pCmdUI != NULL);
  646.  
  647.     if (m_lpClientSite == NULL)
  648.         return;
  649.  
  650.     // update menu item using m_strHostObj
  651.     CString str;
  652.     AfxFormatString1(str, nIDS, m_strHostObj);
  653.     if (!str.IsEmpty())
  654.         pCmdUI->SetText(str);
  655. }
  656.  
  657. void COleServerDoc::OnUpdateFileExit(CCmdUI* pCmdUI)
  658. {
  659.     ASSERT_VALID(this);
  660.     ASSERT(pCmdUI != NULL);
  661.  
  662.     UpdateUsingHostObj(AFX_IDS_EXIT_MENU, pCmdUI);
  663. }
  664.  
  665. void COleServerDoc::OnUpdateFileUpdate(CCmdUI* pCmdUI)
  666. {
  667.     ASSERT_VALID(this);
  668.     ASSERT(pCmdUI != NULL);
  669.  
  670.     UpdateUsingHostObj(AFX_IDS_UPDATE_MENU, pCmdUI);
  671. }
  672.  
  673. BOOL COleServerDoc::OnSaveDocument(LPCTSTR lpszPathName)
  674. {
  675.     ASSERT_VALID(this);
  676.     ASSERT(lpszPathName == NULL || AfxIsValidString(lpszPathName));
  677.  
  678.     BOOL bModified = IsModified();
  679.     BOOL bRemember = m_bRemember;
  680.     if (!COleLinkingDoc::OnSaveDocument(lpszPathName))
  681.         return FALSE;
  682.  
  683.     if (!bRemember)
  684.         SetModifiedFlag(bModified);
  685.  
  686.     if (lpszPathName != NULL && bRemember)
  687.     {
  688.         if (AfxComparePath(GetPathName(), lpszPathName))
  689.             NotifySaved();
  690.     }
  691.     return TRUE;
  692. }
  693.  
  694. void COleServerDoc::OnCloseDocument()
  695. {
  696.     ASSERT_VALID(this);
  697.  
  698.     // don't allow in-place active documents to be closed without first
  699.     //  deactivating them!
  700.     if (m_pInPlaceFrame != NULL)
  701.     {
  702.         if (GetFirstViewPosition() != NULL)
  703. #ifndef _MAC
  704.             return;
  705. #else
  706.         {
  707.             // If a Mac user quits the app while IP sessions are active,
  708.             // it must shut them down and exit, since we can't remove
  709.             // it from the Application menu
  710.             OnDeactivate();
  711.             ASSERT(m_pInPlaceFrame == NULL);
  712.         }
  713. #endif
  714.         // no views but currently in-place active indicates that
  715.         //  a WM_ENDSESSION is being processed.
  716.         m_pInPlaceFrame = NULL;
  717.     }
  718.  
  719.     InternalAddRef();   // keep document stable during shutdown
  720.  
  721.     // update lock count before sending notifications
  722.     UpdateVisibleLock(FALSE, FALSE);
  723.  
  724.     // send some notifications to the container
  725.     if (m_lpClientSite != NULL && m_bCntrVisible)
  726.     {
  727.         // allow the container to unshade the object appropriately
  728.         m_lpClientSite->OnShowWindow(FALSE);
  729.         m_bCntrVisible = FALSE;
  730.     }
  731.  
  732.     // send close notification
  733.     NotifyClosed();
  734.  
  735.     // finish closing the document (before m_lpClientSite->Release)
  736.     BOOL bAutoDelete = m_bAutoDelete;
  737.     m_bAutoDelete = FALSE;
  738.     COleLinkingDoc::OnCloseDocument();
  739.     ASSERT_VALID(this);
  740.  
  741.     // release client-site pointer
  742.     RELEASE(m_lpClientSite);
  743.  
  744.     // disconnect the object
  745.     LPUNKNOWN lpUnknown = (LPUNKNOWN)GetInterface(&IID_IUnknown);
  746.     ASSERT(lpUnknown != NULL);
  747.     CoDisconnectObject(lpUnknown, 0);
  748.  
  749.     // destroy the document if allowed
  750.     InterlockedDecrement(&m_dwRef);              // remove InternalAddRef above
  751.     if (bAutoDelete)
  752.         delete this;
  753. }
  754.  
  755. /////////////////////////////////////////////////////////////////////////////
  756. // COleServerDoc show/hide
  757.  
  758. void COleServerDoc::OnShowDocument(BOOL bShow)
  759. {
  760.     ASSERT_VALID(this);
  761.  
  762.     CWinApp* pApp = AfxGetApp();
  763.     if (bShow)
  764.     {
  765.         // deactivate in-place session if active
  766.         if (m_pInPlaceFrame != NULL)
  767.         {
  768.             OnDeactivate();
  769.             ASSERT(m_pInPlaceFrame == NULL);
  770.         }
  771.  
  772.         // find the first view of this document
  773.         CFrameWnd* pFrameWnd;
  774.         if ((pFrameWnd = GetFirstFrame()) != NULL)
  775.         {
  776.             // allow container to show & scroll to the object
  777.             if (!pFrameWnd->IsWindowVisible() && m_lpClientSite != NULL)
  778.                 m_lpClientSite->ShowObject();
  779.  
  780.             // activate frame holding view
  781.             ASSERT_VALID(pFrameWnd);
  782.             pFrameWnd->ActivateFrame();
  783.  
  784.             // activate application if necessary
  785.             CFrameWnd* pAppFrame = pFrameWnd->GetParentFrame();
  786.             if (pAppFrame != NULL)
  787.             {
  788.                 pFrameWnd = pAppFrame;
  789.                 ASSERT_VALID(pFrameWnd);
  790.                 ASSERT_KINDOF(CFrameWnd, pFrameWnd);
  791.                 pFrameWnd->ActivateFrame();
  792.             }
  793.             pFrameWnd->GetLastActivePopup()->SetForegroundWindow();
  794.  
  795.             // update the menu and title as appropriate for this document
  796.             pFrameWnd->OnUpdateFrameMenu(NULL);
  797.             pFrameWnd->OnUpdateFrameTitle(TRUE);
  798.         }
  799.         else if (pApp->m_pMainWnd != NULL)
  800.         {
  801.             // otherwise, just show the main window (for simple servers)
  802.             CWnd* pWnd = AfxGetMainWnd();
  803.  
  804.             // allow container to show & scroll to the object
  805.             if (!pWnd->IsWindowVisible() && m_lpClientSite != NULL)
  806.                 m_lpClientSite->ShowObject();
  807.  
  808.             pWnd->ShowWindow(SW_SHOW);
  809.             pWnd->SetActiveWindow();
  810.             pWnd->SetForegroundWindow();
  811.         }
  812.  
  813.         // for file based documents, showing the document puts user in control.
  814.         if (!m_bEmbedded)
  815.             AfxOleSetUserCtrl(TRUE);
  816.     }
  817.     else
  818.     {
  819.         if (m_pInPlaceFrame != NULL)
  820.         {
  821.             // hide has semantics of DeactivateUI if the item is active
  822.             if (m_pInPlaceFrame->m_bUIActive)
  823.                 OnDeactivateUI(FALSE);
  824.  
  825.             // and then hide the frame itself
  826.             if (m_pInPlaceFrame != NULL)
  827.                 m_pInPlaceFrame->ActivateFrame(SW_HIDE);
  828.             return;
  829.         }
  830.  
  831.         // find the first view of this document
  832.         POSITION pos = GetFirstViewPosition();
  833.         if (pos != NULL)
  834.         {
  835.             CFrameWnd* pDocFrame = GetFirstFrame();
  836.             CFrameWnd* pActiveFrame = NULL;
  837.             CFrameWnd* pMainFrame = NULL;
  838.             CView* pView = GetNextView(pos);
  839.             ASSERT_VALID(pView);
  840.  
  841.             // destroy or hide all the frames for this document
  842.             //  (the main for the document is hidden, where the alternate
  843.             //   frames are simply destroyed)
  844.             do
  845.             {
  846.                 // hide frame holding view
  847.                 CFrameWnd* pFrame = pView->GetParentFrame();
  848.                 ASSERT_VALID(pFrame);
  849.  
  850.                 // determine next valid view before destroying the frame
  851.                 while ((pView = GetNextView(pos)) != NULL)
  852.                 {
  853.                     if (pView->GetParentFrame() != pFrame)
  854.                         break;
  855.                 }
  856.  
  857.                 pMainFrame = pFrame->GetParentFrame();
  858.                 if (pMainFrame != NULL && pMainFrame->GetActiveFrame() == pFrame)
  859.                 {
  860.                     // don't destroy the active frame until later
  861.                     pActiveFrame = pFrame;
  862.                 }
  863.                 else
  864.                 {
  865.                     // not the active frame -- destroy/hide it now
  866.                     PreCloseFrame(pFrame);
  867.                     if (pDocFrame == pFrame)
  868.                         pFrame->ActivateFrame(SW_HIDE);
  869.                     else
  870.                         pFrame->DestroyWindow();
  871.                 }
  872.  
  873.             } while (pView != NULL);
  874.  
  875.             // hide the active frame last
  876.             if (pActiveFrame != NULL)
  877.             {
  878.                 PreCloseFrame(pActiveFrame);
  879.                 if (pDocFrame == pActiveFrame)
  880.                     pActiveFrame->ActivateFrame(SW_HIDE);
  881.                 else
  882.                     pActiveFrame->DestroyWindow();
  883.  
  884.                 // should leave at least one frame
  885.                 ASSERT_VALID(this);
  886.                 ASSERT_VALID(GetFirstFrame());
  887.             }
  888.         }
  889.  
  890.         CFrameWnd* pMainFrame = (CFrameWnd*)pApp->m_pMainWnd;
  891.         if (!AfxOleGetUserCtrl() && pMainFrame != NULL &&
  892.             pMainFrame->IsWindowEnabled() && pMainFrame->IsFrameWnd() &&
  893.             pMainFrame->GetActiveFrame() == pMainFrame)
  894.         {
  895.             // hide the entire application -- no visible documents left
  896.             pApp->HideApplication();
  897.         }
  898.     }
  899.  
  900.     // send OnShowWindow notifications to the container
  901.     if (m_lpClientSite != NULL && (bShow || m_bCntrVisible != bShow))
  902.     {
  903.         // allow the container to shade the object appropriately
  904.         m_lpClientSite->OnShowWindow(bShow);
  905.         m_bCntrVisible = bShow;
  906.     }
  907.  
  908.     // force update visible lock
  909.     if (bShow)
  910.         UpdateVisibleLock(TRUE, FALSE);
  911. }
  912.  
  913. /////////////////////////////////////////////////////////////////////////////
  914. // COleServerDoc storage implementation
  915.  
  916. void COleServerDoc::OnNewEmbedding(LPSTORAGE lpStorage)
  917. {
  918.     ASSERT_VALID(this);
  919.     ASSERT(lpStorage != NULL);
  920.  
  921.     // save state
  922.     BOOL bUserCtrl = AfxOleGetUserCtrl();
  923.  
  924.     TRY
  925.     {
  926.         // remember new storage
  927.         DeleteContents();
  928.         lpStorage->AddRef();
  929.         RELEASE(m_lpRootStg);
  930.         m_lpRootStg = lpStorage;
  931.         m_strPathName.Empty();
  932.         m_bEmbedded = TRUE;
  933.  
  934.         // do document initialization by calling OnNewDocument
  935.         if (!OnNewDocument())
  936.             AfxThrowMemoryException();
  937.     }
  938.     CATCH_ALL(e)
  939.     {
  940.         // restore state
  941.         AfxOleSetUserCtrl(bUserCtrl);
  942.         THROW_LAST();
  943.     }
  944.     END_CATCH_ALL
  945.  
  946.     // restore state
  947.     AfxOleSetUserCtrl(bUserCtrl);
  948.  
  949.     SetModifiedFlag();  // new storage-based documents are dirty!
  950.     SendInitialUpdate();
  951. }
  952.  
  953. void COleServerDoc::OnOpenEmbedding(LPSTORAGE lpStorage)
  954. {
  955.     ASSERT_VALID(this);
  956.     ASSERT(lpStorage != NULL);
  957.  
  958.     // save state
  959.     BOOL bUserCtrl = AfxOleGetUserCtrl();
  960.  
  961.     TRY
  962.     {
  963.         // abort changes to current document
  964.         DeleteContents();
  965.         lpStorage->AddRef();
  966.         RELEASE(m_lpRootStg);
  967.         m_lpRootStg = lpStorage;
  968.  
  969.         // open document from the sub-storage
  970.         if (!OnOpenDocument(NULL))
  971.             AfxThrowMemoryException();
  972.  
  973.         // now document is storage based
  974.         m_strPathName.Empty();
  975.         m_bEmbedded = TRUE;
  976.     }
  977.     CATCH_ALL(e)
  978.     {
  979.         // restore state
  980.         AfxOleSetUserCtrl(bUserCtrl);
  981.         THROW_LAST();
  982.     }
  983.     END_CATCH_ALL
  984.  
  985.     // restore state
  986.     AfxOleSetUserCtrl(bUserCtrl);
  987.  
  988.     SetModifiedFlag(FALSE); // start off with unmodified
  989.     SendInitialUpdate();
  990. }
  991.  
  992. void COleServerDoc::OnSaveEmbedding(LPSTORAGE lpStorage)
  993. {
  994.     ASSERT_VALID(this);
  995.     ASSERT(lpStorage != NULL);
  996.  
  997.     // save state
  998.     BOOL bUserCtrl = AfxOleGetUserCtrl();
  999.  
  1000.     // check for save as
  1001.     LPSTORAGE lpOrigStg = m_lpRootStg;
  1002.     if (!m_bSameAsLoad)
  1003.     {
  1004.         // File Save[Copy] As (saving to different file)
  1005.         ASSERT(lpStorage != NULL);
  1006.         m_lpRootStg = lpStorage;
  1007.     }
  1008.  
  1009.     TRY
  1010.     {
  1011.         // save document to the sub-storage
  1012.         if (!OnSaveDocument(NULL))
  1013.             AfxThrowMemoryException();
  1014.     }
  1015.     CATCH_ALL(e)
  1016.     {
  1017.         // restore state
  1018.         AfxOleSetUserCtrl(bUserCtrl);
  1019.         // re-attach original storage
  1020.         m_lpRootStg = lpOrigStg;
  1021.         THROW_LAST();
  1022.     }
  1023.     END_CATCH_ALL
  1024.  
  1025.     // restore state
  1026.     AfxOleSetUserCtrl(bUserCtrl);
  1027.  
  1028.     // re-attach original storage
  1029.     m_lpRootStg = lpOrigStg;
  1030. }
  1031.  
  1032. /////////////////////////////////////////////////////////////////////////////
  1033. // COleServerDoc in-place activation implementation
  1034.  
  1035. BOOL COleServerDoc::ActivateInPlace()
  1036. {
  1037.     ASSERT_VALID(this);
  1038.     USES_CONVERSION;
  1039.     LPCOLESTR lpszTitle = NULL;
  1040.  
  1041.     if (m_lpClientSite == NULL)
  1042.         return FALSE;   // no client-side (may be a link)
  1043.  
  1044.     // activate already in-place window if currently in-place active
  1045.     if (m_pInPlaceFrame != NULL)
  1046.     {
  1047.         if (m_pInPlaceFrame->m_bUIActive)
  1048.         {
  1049.             m_lpClientSite->ShowObject();   // object should get focus
  1050.             return TRUE;
  1051.         }
  1052.         // deactivate in-place session entirely before continuing
  1053.         OnDeactivate();
  1054.     }
  1055.  
  1056.     // fail if already fully open
  1057.     if (GetFirstFrame()->IsWindowVisible())
  1058.         return FALSE;
  1059.  
  1060.     // build object title/name (the container may use this in its caption)
  1061.     CString strFileType, strTitle;
  1062.     if (!GetFileTypeString(strFileType))
  1063.         return FALSE;
  1064.     AfxFormatString2(strTitle, AFX_IDS_OBJ_TITLE_INPLACE,
  1065.         AfxGetAppName(), strFileType);
  1066.  
  1067.     // attempt to get in-place client-site interface
  1068.     LPOLEINPLACESITE lpInPlaceSite =
  1069.         QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
  1070.     if (lpInPlaceSite == NULL)
  1071.     {
  1072.         // unable to get in-place client site interface
  1073.         return FALSE;
  1074.     }
  1075.  
  1076.     // see if the container wants to go in-place right now
  1077.     if (lpInPlaceSite->CanInPlaceActivate() != S_OK)
  1078.         goto ReleaseAndFail;
  1079.  
  1080.     // start activation sequence...
  1081.  
  1082. #ifdef _MAC
  1083.     m_bDeactivating = FALSE;
  1084. #endif
  1085.     if (lpInPlaceSite->OnInPlaceActivate() != S_OK)
  1086.         goto ReleaseAndFail;
  1087.  
  1088.     // we'll need the parent window to create the COleIPFrameWnd
  1089.     HWND hWnd;
  1090.     VERIFY(lpInPlaceSite->GetWindow(&hWnd) == S_OK);
  1091.     CWnd* pParentWnd;
  1092.     pParentWnd = CWnd::FromHandle(hWnd);
  1093.  
  1094.     // create the inplace frame window
  1095.     COleIPFrameWnd* pFrameWnd;
  1096.     pFrameWnd = CreateInPlaceFrame(pParentWnd);
  1097.     if (pFrameWnd == NULL)
  1098.     {
  1099.         ASSERT(lpInPlaceSite != NULL);
  1100.         lpInPlaceSite->OnInPlaceDeactivate();
  1101.         goto ReleaseAndFail;
  1102.     }
  1103.     ASSERT(pFrameWnd->GetParent() == pParentWnd);
  1104.     m_pInPlaceFrame = pFrameWnd;
  1105.  
  1106. #ifndef _MAC
  1107.     // send activate notification.  This really is the right time to do it,
  1108.     // but Mac Word 6 requires later notification
  1109.     if (lpInPlaceSite->OnUIActivate() != S_OK)
  1110.         goto DestroyFrameAndFail;
  1111. #endif
  1112.  
  1113.     // need to get frame & doc window interfaces as well as other info
  1114.     RECT rcPosRect, rcClipRect;
  1115.     if (lpInPlaceSite->GetWindowContext(
  1116.         &pFrameWnd->m_lpFrame, &pFrameWnd->m_lpDocFrame,
  1117.         &rcPosRect, &rcClipRect, &pFrameWnd->m_frameInfo) != S_OK)
  1118.     {
  1119.         goto DeactivateUIAndFail;
  1120.     }
  1121.     ASSERT(pFrameWnd->m_lpFrame != NULL);
  1122.  
  1123.     // setup the shared menu
  1124.     if (!pFrameWnd->BuildSharedMenu())
  1125.         goto DeactivateUIAndFail;
  1126.  
  1127.     // allow server to install frame controls in container
  1128.     VERIFY(pFrameWnd->m_lpFrame->GetWindow(&hWnd) == S_OK);
  1129.     pFrameWnd->m_pMainFrame = new COleCntrFrameWnd(pFrameWnd);
  1130.     pFrameWnd->m_pMainFrame->Attach(hWnd);
  1131.     if (pFrameWnd->m_lpDocFrame != NULL)
  1132.     {
  1133.         HWND hWndDocument;
  1134.         VERIFY(pFrameWnd->m_lpDocFrame->GetWindow(&hWndDocument) == S_OK);
  1135.  
  1136.         if (hWndDocument != hWnd)
  1137.         {
  1138.             pFrameWnd->m_pDocFrame = new COleCntrFrameWnd(pFrameWnd);
  1139.             pFrameWnd->m_pDocFrame->Attach(hWndDocument);
  1140.         }
  1141.         else
  1142.         {
  1143.             RELEASE(pFrameWnd->m_lpDocFrame);
  1144.             pFrameWnd->m_lpDocFrame = NULL;
  1145.         }
  1146.     }
  1147.  
  1148.     // update zoom factor information before creating control bars
  1149.  
  1150.     //WINBUG: some clients send an empty rectangle and expect the
  1151.     // server to use the ClipRect for the PosRect
  1152.     if (IsRectEmpty(&rcPosRect))
  1153.         pFrameWnd->m_rectPos.CopyRect(&rcClipRect);
  1154.     else
  1155.         pFrameWnd->m_rectPos.CopyRect(&rcPosRect);
  1156.     pFrameWnd->m_rectClip.CopyRect(&rcClipRect);
  1157.  
  1158.     if (!pFrameWnd->OnCreateControlBars(pFrameWnd->m_pMainFrame,
  1159.         pFrameWnd->m_pDocFrame))
  1160.     {
  1161.         goto DeactivateUIAndFail;
  1162.     }
  1163.  
  1164.     // resize the window to match the object
  1165.  
  1166.     //WINBUG: some clients send an empty rectangle and expect the
  1167.     // server to use the ClipRect for the PosRect
  1168.     if (IsRectEmpty(&rcPosRect))
  1169.         OnSetItemRects(&rcClipRect, &rcClipRect);
  1170.     else
  1171.         OnSetItemRects(&rcPosRect, &rcClipRect);
  1172.  
  1173.     // set the active object
  1174.     ASSERT(pFrameWnd->m_lpFrame != NULL);
  1175.     LPOLEINPLACEACTIVEOBJECT lpActiveObject;
  1176.     lpActiveObject = (LPOLEINPLACEACTIVEOBJECT)
  1177.         GetInterface(&IID_IOleInPlaceActiveObject);
  1178.     lpszTitle = T2COLE(strTitle);
  1179.     pFrameWnd->m_lpFrame->SetActiveObject(lpActiveObject, lpszTitle);
  1180.     if (pFrameWnd->m_lpDocFrame != NULL)
  1181.         pFrameWnd->m_lpDocFrame->SetActiveObject(lpActiveObject, lpszTitle);
  1182.  
  1183.     // add frame & document level frame controls
  1184.     ASSERT(m_pInPlaceFrame->m_lpFrame != NULL);
  1185.     OnShowControlBars(m_pInPlaceFrame->m_pMainFrame, TRUE);
  1186.     if (m_pInPlaceFrame->m_lpDocFrame != NULL)
  1187.         OnShowControlBars(m_pInPlaceFrame->m_pDocFrame, TRUE);
  1188.  
  1189.     // show any hidden modeless dialogs as well...
  1190.     m_pInPlaceFrame->ShowOwnedWindows(TRUE);
  1191.  
  1192. #ifndef _MAC
  1193.     // attempt toolbar negotiation
  1194.     OnResizeBorder(NULL, pFrameWnd->m_lpFrame, TRUE);
  1195.     if (pFrameWnd->m_lpDocFrame != NULL)
  1196.         OnResizeBorder(NULL, pFrameWnd->m_lpDocFrame, FALSE);
  1197. #endif
  1198.  
  1199.     // install the menu (also installs a hook which forwards messages from
  1200.     //  the menu to the inplace frame window)
  1201.     pFrameWnd->m_lpFrame->SetMenu(pFrameWnd->m_hSharedMenu,
  1202.         pFrameWnd->m_hOleMenu, pFrameWnd->m_hWnd);
  1203.  
  1204. #ifdef _MAC
  1205.     // Mac Word 6 also requires this reordering.  Hopefully future versions
  1206.     // will be able to use the standard Win32 activation sequence
  1207.     if (lpInPlaceSite->OnUIActivate() != S_OK)
  1208.         goto DeactivateUIAndFail;
  1209.  
  1210.     OnResizeBorder(NULL, pFrameWnd->m_lpFrame, TRUE);
  1211.     if (pFrameWnd->m_lpDocFrame != NULL)
  1212.         OnResizeBorder(NULL, pFrameWnd->m_lpDocFrame, FALSE);
  1213. #endif
  1214.  
  1215.     // make sure object is scrolled into view
  1216.     m_lpClientSite->ShowObject();   // object should get focus
  1217.  
  1218.     // finally -- show the inplace frame window and set focus
  1219.     pFrameWnd->ShowWindow(SW_SHOW);
  1220.     pFrameWnd->SetFocus();
  1221.     pFrameWnd->UpdateWindow();
  1222.     UpdateVisibleLock(TRUE, FALSE);
  1223.  
  1224.     // allow the main window to be set
  1225.     OnFrameWindowActivate(TRUE);
  1226.     pFrameWnd->m_bUIActive = TRUE;
  1227.  
  1228.     // cleanup and return
  1229.     lpInPlaceSite->Release();
  1230.     return TRUE;
  1231.  
  1232. DeactivateUIAndFail:
  1233.     ASSERT(lpInPlaceSite != NULL);
  1234.     lpInPlaceSite->OnUIDeactivate(FALSE);
  1235.  
  1236. #ifndef _MAC
  1237. DestroyFrameAndFail:
  1238. #endif
  1239.     if (m_pInPlaceFrame != NULL)
  1240.     {
  1241.         ASSERT(pFrameWnd != NULL);
  1242.         DestroyInPlaceFrame(pFrameWnd);
  1243.         m_pInPlaceFrame = NULL;
  1244.  
  1245.         // also need to send OnInPlaceDeactivate notification
  1246.         ASSERT(lpInPlaceSite != NULL);
  1247.         lpInPlaceSite->OnInPlaceDeactivate();
  1248.     }
  1249.  
  1250. ReleaseAndFail:
  1251.     ASSERT(lpInPlaceSite != NULL);
  1252.     lpInPlaceSite->Release();
  1253.     return FALSE;
  1254. }
  1255.  
  1256. COleIPFrameWnd* COleServerDoc::CreateInPlaceFrame(CWnd* pParentWnd)
  1257. {
  1258.     ASSERT_VALID(this);
  1259.     ASSERT_VALID(pParentWnd);
  1260.  
  1261.     // get runtime class from the doc template
  1262.     CDocTemplate* pTemplate = GetDocTemplate();
  1263.     ASSERT_VALID(pTemplate);
  1264.  
  1265.     // use existing view if possible
  1266.     CWnd* pViewParent = NULL;
  1267.     CView* pView = NULL;
  1268.     CFrameWnd* pFrame = GetFirstFrame();
  1269.     if (pFrame != NULL)
  1270.     {
  1271.         pView = (CView*)pFrame->GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
  1272.         if (pView != NULL)
  1273.         {
  1274.             ASSERT_KINDOF(CView, pView);
  1275.             pViewParent = pView->GetParent();
  1276.             m_dwOrigStyle = pView->GetStyle();
  1277.             m_dwOrigStyleEx = pView->GetExStyle();
  1278.         }
  1279.     }
  1280.  
  1281.     // create the frame from the template
  1282.     COleIPFrameWnd* pFrameWnd = (COleIPFrameWnd*)
  1283.         pTemplate->CreateOleFrame(pParentWnd, this, pView == NULL);
  1284.     if (pFrameWnd == NULL)
  1285.         return NULL;
  1286.  
  1287.     // connect the view to the frame window, if necessary
  1288.     if (pView != NULL)
  1289.     {
  1290.         ConnectView(pFrameWnd, pView);
  1291.         pView->ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_DRAWFRAME);
  1292.     }
  1293.  
  1294.     // remember original parent window for deactivate
  1295.     m_pOrigParent = pViewParent;
  1296.  
  1297.     // send OnInitialUpdate if new view was created
  1298.     if (pView == NULL)
  1299.         pTemplate->InitialUpdateFrame(pFrameWnd, this, FALSE);
  1300.  
  1301.     // verify the type
  1302.     ASSERT_VALID(pFrameWnd);
  1303.     ASSERT_KINDOF(COleIPFrameWnd, pFrameWnd);
  1304.     return pFrameWnd;
  1305. }
  1306.  
  1307. void COleServerDoc::DestroyInPlaceFrame(COleIPFrameWnd* pFrameWnd)
  1308. {
  1309.     ASSERT_VALID(this);
  1310.     ASSERT_VALID(pFrameWnd);
  1311.  
  1312.     // connect view to original, if existing view was used
  1313.     if (m_pOrigParent != NULL)
  1314.     {
  1315.         CView* pView = (CView*)pFrameWnd->GetDescendantWindow(
  1316.             AFX_IDW_PANE_FIRST, TRUE);
  1317.         ASSERT_VALID(pView);
  1318.  
  1319.         // leaving the focus on an MDI child or one of its child windows
  1320.         // causes Windows to get confused when the child window is
  1321.         // destroyed, not to mention the fact that the focus will be
  1322.         // out of sync with activation.
  1323.         if (::GetFocus() == pView->m_hWnd)
  1324.         {
  1325.             // move focus to somewhere safe
  1326.             HWND hWnd = ::GetParent(pFrameWnd->m_hWnd);
  1327.             if (hWnd != NULL)
  1328.                 ::SetFocus(hWnd);
  1329.  
  1330.             // check again
  1331.             if (::GetFocus() == pView->m_hWnd)
  1332.                 SetFocus(NULL); // last ditch effort
  1333.         }
  1334.  
  1335.         ConnectView(m_pOrigParent, pView);
  1336.         m_pOrigParent = NULL;
  1337.  
  1338.         // remove any scrollbars added because of in-place activation
  1339.         if ((m_dwOrigStyle & (WS_HSCROLL|WS_VSCROLL)) == 0 &&
  1340.             (pView->GetStyle() & (WS_HSCROLL|WS_VSCROLL)) != 0)
  1341.         {
  1342.             ::SetScrollRange(pView->m_hWnd, SB_HORZ, 0, 0, TRUE);
  1343.             ::SetScrollRange(pView->m_hWnd, SB_VERT, 0, 0, TRUE);
  1344.         }
  1345.  
  1346.         // restore old 3D style
  1347.         pView->ModifyStyleEx(0, m_dwOrigStyleEx & WS_EX_CLIENTEDGE,
  1348.             SWP_DRAWFRAME);
  1349.  
  1350.         // force recalc layout on splitter window
  1351.         CSplitterWnd* pSplitter = CView::GetParentSplitter(pView, TRUE);
  1352.         if (pSplitter != NULL)
  1353.             pSplitter->RecalcLayout();
  1354.     }
  1355.  
  1356.     // no active view or document during destroy
  1357.     pFrameWnd->SetActiveView(NULL);
  1358.  
  1359.     // destroy in-place frame window
  1360.     pFrameWnd->DestroyWindow();
  1361. }
  1362.  
  1363. void COleServerDoc::ConnectView(CWnd* pParentWnd, CView* pView)
  1364. {
  1365.     ASSERT_VALID(this);
  1366.     ASSERT_VALID(pParentWnd);
  1367.     ASSERT_VALID(pView);
  1368.  
  1369.     // move the view to the new parent
  1370.     pView->SetParent(pParentWnd);
  1371.  
  1372.     // Note: The currently active view on the original frame window is
  1373.     //  kept active, because some controls, especially Windows controls,
  1374.     //  continue to send notification messages to the original parent
  1375.     //  window of the control.  So, the original frame window is kept
  1376.     //  alive with the original active view pointer intact, such that
  1377.     //  these notification messages do not get lost.
  1378.  
  1379.     // set the active view of the new frame to newly moved view
  1380.     CFrameWnd* pFrameWnd = pParentWnd->IsFrameWnd() ?
  1381.         (CFrameWnd*)pParentWnd : pParentWnd->GetParentFrame();
  1382.     pFrameWnd->SetActiveView(pView, FALSE);
  1383.     pFrameWnd->RecalcLayout();
  1384. }
  1385.  
  1386. void COleServerDoc::OnFrameWindowActivate(BOOL bActivate)
  1387. {
  1388.     ASSERT_VALID(this);
  1389.  
  1390.     CFrameWnd* pFrameWnd = m_pInPlaceFrame;
  1391.     ASSERT_VALID(pFrameWnd);
  1392.  
  1393.     CWinThread* pThread = AfxGetThread();
  1394.     if (bActivate)
  1395.     {
  1396.         // activating -- so set the main window
  1397.         pThread->m_pActiveWnd = pFrameWnd;
  1398.  
  1399.         // send activation notification messages
  1400.         pFrameWnd->SendMessage(WM_ACTIVATEAPP, (WPARAM)TRUE);
  1401.         pFrameWnd->SendMessage(WM_ACTIVATE, WA_ACTIVE);
  1402.     }
  1403.     else if (pFrameWnd == pThread->m_pActiveWnd)
  1404.     {
  1405.         // send deactivation notification messages
  1406.         pFrameWnd->SendMessage(WM_ACTIVATEAPP, (WPARAM)FALSE);
  1407.         pFrameWnd->SendMessage(WM_ACTIVATE, WA_INACTIVE);
  1408.  
  1409.         // simulate deactivation notification messages
  1410.         CView* pActiveView = pFrameWnd->GetActiveView();
  1411.         if (pActiveView != NULL)
  1412.             pActiveView->OnActivateView(FALSE, pActiveView, pActiveView);
  1413.  
  1414.         // deactivating and was previously active -- reset the main window
  1415.         pThread->m_pActiveWnd = NULL;
  1416.     }
  1417. }
  1418.  
  1419. void COleServerDoc::OnDocWindowActivate(BOOL bActivate)
  1420. {
  1421.     ASSERT_VALID(this);
  1422.  
  1423.     CWinThread* pThread = AfxGetApp();
  1424.     COleIPFrameWnd* pFrameWnd = m_pInPlaceFrame;
  1425.  
  1426.     if (bActivate)
  1427.     {
  1428.         // attach frame windows back in the permanent map
  1429.         pFrameWnd->m_pMainFrame->Attach(pFrameWnd->m_pMainFrame->Detach());
  1430.         if (pFrameWnd->m_pDocFrame != NULL)
  1431.             pFrameWnd->m_pDocFrame->Attach(pFrameWnd->m_pDocFrame->Detach());
  1432.  
  1433.         // set active main window
  1434.         pThread->m_pActiveWnd = pFrameWnd;
  1435.  
  1436.         // show frame level controls
  1437.         OnShowControlBars(pFrameWnd->m_pMainFrame, TRUE);
  1438.         pFrameWnd->ShowOwnedWindows(TRUE);
  1439.  
  1440.         // attempt toolbar negotiation
  1441.         OnResizeBorder(NULL, pFrameWnd->m_lpFrame, TRUE);
  1442.  
  1443.         // install the menu (also installs a hook which forwards messages from
  1444.         //  the menu to the inplace frame window)
  1445.         pFrameWnd->m_lpFrame->SetMenu(
  1446.             pFrameWnd->m_hSharedMenu, pFrameWnd->m_hOleMenu,
  1447.             pFrameWnd->m_hWnd);
  1448.  
  1449.         // set focus to the frame (it will probably set focus to the view)
  1450.         //  (by simulating normal application activate messages)
  1451.         pFrameWnd->SendMessage(WM_ACTIVATE, WA_ACTIVE);
  1452.     }
  1453.     else
  1454.     {
  1455.         // clear active window for app if this object is active
  1456.         if (pThread->m_pActiveWnd == pFrameWnd)
  1457.             pThread->m_pActiveWnd = NULL;
  1458.  
  1459.         // hide frame level controls -- this does not destroy them
  1460.         pFrameWnd->ShowOwnedWindows(FALSE);
  1461.         OnShowControlBars(pFrameWnd->m_pMainFrame, FALSE);
  1462.  
  1463.         // attempt toolbar negotiation
  1464.         OnResizeBorder(NULL, pFrameWnd->m_lpFrame, TRUE);
  1465.  
  1466.         // simulate deactivation notification messages
  1467.         CView* pActiveView = pFrameWnd->GetActiveView();
  1468.         if (pActiveView != NULL)
  1469.             pActiveView->OnActivateView(FALSE, pActiveView, pActiveView);
  1470.         pFrameWnd->SendMessage(WM_ACTIVATE, WA_INACTIVE);
  1471.  
  1472.         // set the m_hWnd members, but remove them from the maps
  1473.         pFrameWnd->m_pMainFrame->m_hWnd = pFrameWnd->m_pMainFrame->Detach();
  1474.         if (pFrameWnd->m_pDocFrame != NULL)
  1475.             pFrameWnd->m_pDocFrame->m_hWnd = pFrameWnd->m_pDocFrame->Detach();
  1476.     }
  1477. }
  1478.  
  1479. void COleServerDoc::OnShowControlBars(CFrameWnd* pFrameWnd, BOOL bShow)
  1480. {
  1481.     ASSERT_VALID(this);
  1482.     ASSERT(pFrameWnd == m_pInPlaceFrame->m_pMainFrame ||
  1483.         pFrameWnd == m_pInPlaceFrame->m_pDocFrame);
  1484.     ASSERT_VALID(pFrameWnd);
  1485.  
  1486.     // show/hide all control bars
  1487.     POSITION pos = pFrameWnd->m_listControlBars.GetHeadPosition();
  1488.     while (pos != NULL)
  1489.     {
  1490.         // show/hide the next control bar
  1491.         CControlBar* pBar =
  1492.             (CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos);
  1493.         ASSERT_VALID(pBar);
  1494.         if (bShow)
  1495.         {
  1496.             if (pBar->m_nStateFlags & CControlBar::tempHide)
  1497.             {
  1498.                 pBar->m_nStateFlags &= ~CControlBar::tempHide;
  1499.                 pFrameWnd->ShowControlBar(pBar, bShow, TRUE);
  1500.             }
  1501.         }
  1502.         else
  1503.         {
  1504.             if (pBar->IsVisible() && !pBar->IsFloating())
  1505.             {
  1506.                 pBar->m_nStateFlags |= CControlBar::tempHide;
  1507.                 pFrameWnd->ShowControlBar(pBar, bShow, TRUE);
  1508.             }
  1509.         }
  1510.     }
  1511. }
  1512.  
  1513. void COleServerDoc::OnResizeBorder(
  1514.     LPCRECT lpRectBorder, LPOLEINPLACEUIWINDOW lpUIWindow, BOOL bFrame)
  1515. {
  1516.     ASSERT_VALID(this);
  1517.     ASSERT(lpRectBorder == NULL ||
  1518.         AfxIsValidAddress(lpRectBorder, sizeof(RECT), FALSE));
  1519.     ASSERT(lpUIWindow != NULL);
  1520.  
  1521.     // use IOleInPlaceUIWindow::GetBorder if no border given
  1522.     CRect rectBorder;
  1523.     if (lpRectBorder != NULL)
  1524.     {
  1525.         // use border space passed in
  1526.         rectBorder.CopyRect(lpRectBorder);
  1527.     }
  1528.     else
  1529.     {
  1530.         // GetBorderSpace may fail (WinWord6, for example)
  1531.         if (lpUIWindow->GetBorder(&rectBorder) != S_OK)
  1532.         {
  1533.             // in that case, always call SetBorderSpace(NULL), but
  1534.             // ignore the return value.
  1535.             lpUIWindow->SetBorderSpace(NULL);
  1536.             return;
  1537.         }
  1538.     }
  1539.  
  1540.     // get CWnd* for the OLE window
  1541.     CFrameWnd* pFrameWnd = bFrame ?
  1542.         m_pInPlaceFrame->m_pMainFrame : m_pInPlaceFrame->m_pDocFrame;
  1543.  
  1544.     // if this is the active document clear temphide bits from bars
  1545.     if (AfxGetThread()->m_pActiveWnd == m_pInPlaceFrame)
  1546.         OnShowControlBars(pFrameWnd, TRUE);
  1547.  
  1548.     // see how much space we need by calling reposition bars
  1549.     CRect rectNeeded = rectBorder;
  1550.     pFrameWnd->RepositionBars(0, 0xFFFF, 0, CWnd::reposQuery, &rectNeeded,
  1551.         &rectBorder);
  1552.  
  1553.     // request the border space from the container
  1554.     CRect rectRequest(
  1555.         rectNeeded.left - rectBorder.left,
  1556.         rectNeeded.top - rectBorder.top,
  1557.         rectBorder.right - rectNeeded.right,
  1558.         rectBorder.bottom - rectNeeded.bottom);
  1559.     CRect rectTemp;
  1560.     rectTemp = rectRequest;
  1561.  
  1562.     // if no border space, just call SetBorderSpace
  1563.     if ((!rectRequest.IsRectNull() ||
  1564.          !pFrameWnd->m_listControlBars.IsEmpty()) &&
  1565.         lpUIWindow->RequestBorderSpace(&rectTemp) == S_OK)
  1566.     {
  1567.         // set the border space -- now this object owns it
  1568.         VERIFY(lpUIWindow->SetBorderSpace(&rectRequest) == S_OK);
  1569.  
  1570.         // move the bars into position after committing the space
  1571.         pFrameWnd->RepositionBars(0, 0xFFFF, 0, CWnd::reposDefault, NULL,
  1572.             &rectBorder);
  1573.  
  1574.         // redraw all control bars
  1575.         POSITION pos = pFrameWnd->m_listControlBars.GetHeadPosition();
  1576.         while (pos != NULL)
  1577.         {
  1578.             CControlBar* pBar =
  1579.                 (CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos);
  1580.             ASSERT_VALID(pBar);
  1581.             if (!pBar->IsFloating())
  1582.                 pBar->UpdateWindow();
  1583.         }
  1584.     }
  1585.     else
  1586.     {
  1587.         // hide any toolbars (since we couldn't get border space for any)
  1588.         OnShowControlBars(pFrameWnd, FALSE);
  1589.  
  1590.         // make sure border space is cleared
  1591.         CRect rect(0,0,0,0);
  1592.         lpUIWindow->SetBorderSpace(&rect);
  1593.     }
  1594. }
  1595.  
  1596. void COleServerDoc::OnDeactivate()
  1597. {
  1598.     ASSERT_VALID(this);
  1599.  
  1600. #ifdef _MAC
  1601.     ASSERT(!m_bDeactivating);
  1602.     m_bDeactivating = TRUE;
  1603. #endif
  1604.  
  1605.     ASSERT(m_pInPlaceFrame != NULL);
  1606.  
  1607.     // do UI deactivate first -- this hides everything
  1608.     if (m_pInPlaceFrame->m_bUIActive)
  1609.     {
  1610.         OnDeactivateUI(FALSE);
  1611.  
  1612.         // some containers call OnDeactivate during OnDeactivateUI
  1613.         if (m_pInPlaceFrame == NULL)
  1614.             return;
  1615.     }
  1616.     ASSERT(m_pInPlaceFrame != NULL);
  1617.     ASSERT(!m_pInPlaceFrame->m_bUIActive);
  1618.  
  1619.     // now safe to destroy the shared menu
  1620.     m_pInPlaceFrame->DestroySharedMenu();
  1621.  
  1622.     // no longer need doc & frame window interfaces
  1623.     RELEASE(m_pInPlaceFrame->m_lpFrame);
  1624.     RELEASE(m_pInPlaceFrame->m_lpDocFrame);
  1625.     DestroyInPlaceFrame(m_pInPlaceFrame);
  1626.     m_pInPlaceFrame = NULL;
  1627.         // destructor for COleIPFrameWnd or derivative should cleanup any
  1628.         //   toolbars etc. created during in-place activation
  1629.  
  1630.     // last of all, call IOleClientSite::InPlaceDeactivate
  1631.     ASSERT(m_lpClientSite != NULL);
  1632.     LPOLEINPLACESITE lpInPlaceSite =
  1633.         QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
  1634.     if (lpInPlaceSite != NULL)
  1635.     {
  1636.         lpInPlaceSite->OnInPlaceDeactivate();
  1637.         lpInPlaceSite->Release();
  1638.     }
  1639. }
  1640.  
  1641. void COleServerDoc::OnDeactivateUI(BOOL bUndoable)
  1642. {
  1643.     ASSERT_VALID(this);
  1644.     COleIPFrameWnd* pFrameWnd = m_pInPlaceFrame;
  1645.  
  1646.     if (pFrameWnd == NULL || !pFrameWnd->m_bUIActive)
  1647.         return;
  1648.  
  1649.     // reset active object pointers
  1650.     ASSERT(pFrameWnd->m_lpFrame != NULL);
  1651.     pFrameWnd->m_lpFrame->SetActiveObject(NULL, NULL);
  1652.     if (pFrameWnd->m_lpDocFrame != NULL)
  1653.         pFrameWnd->m_lpDocFrame->SetActiveObject(NULL, NULL);
  1654.  
  1655.     // remove frame & document level frame controls
  1656.     ASSERT(pFrameWnd->m_lpFrame != NULL);
  1657.     OnShowControlBars(pFrameWnd->m_pMainFrame, FALSE);
  1658.     if (pFrameWnd->m_lpDocFrame != NULL)
  1659.         OnShowControlBars(pFrameWnd->m_pDocFrame, FALSE);
  1660.  
  1661.     if (m_pDocObjectServer == NULL)
  1662.     {
  1663.         // hide the frame and any popups owned by the frame
  1664.         pFrameWnd->ShowOwnedWindows(FALSE);
  1665.         pFrameWnd->ShowWindow(SW_HIDE);
  1666.         pFrameWnd->m_nShowDelay = SW_HIDE;
  1667.         pFrameWnd->m_pMainFrame->m_nShowDelay = SW_HIDE;
  1668.     }
  1669.  
  1670.     // set the m_hWnd members, but remove them from the maps
  1671.     pFrameWnd->m_pMainFrame->m_hWnd = pFrameWnd->m_pMainFrame->Detach();
  1672.     if (pFrameWnd->m_pDocFrame != NULL)
  1673.         pFrameWnd->m_pDocFrame->m_hWnd = pFrameWnd->m_pDocFrame->Detach();
  1674.  
  1675.     // no longer UI active...
  1676.     pFrameWnd->m_bUIActive = FALSE;
  1677.     CWinThread* pThread = AfxGetApp();
  1678.     if (pThread->m_pActiveWnd == pFrameWnd)
  1679.         pThread->m_pActiveWnd = NULL;
  1680.  
  1681.     // call IOleClientSite::OnUIDeactivate
  1682.     ASSERT(m_lpClientSite != NULL);
  1683.     LPOLEINPLACESITE lpInPlaceSite =
  1684.         QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
  1685.     if (lpInPlaceSite != NULL)
  1686.     {
  1687.         lpInPlaceSite->OnUIDeactivate(bUndoable);
  1688.         lpInPlaceSite->Release();
  1689.     }
  1690. }
  1691.  
  1692. void COleServerDoc::OnSetItemRects(LPCRECT lpPosRect, LPCRECT lpClipRect)
  1693. {
  1694.     ASSERT_VALID(this);
  1695.     ASSERT(AfxIsValidAddress(lpPosRect, sizeof(RECT), FALSE));
  1696.     ASSERT(AfxIsValidAddress(lpClipRect, sizeof(RECT), FALSE));
  1697.  
  1698.     if (m_pInPlaceFrame == NULL)
  1699.         return;
  1700.     ASSERT_VALID(m_pInPlaceFrame);
  1701.  
  1702.     // tell the frame to position itself such that the view is at the given
  1703.     //  rectangle (relative to the frame's parent)
  1704.     m_pInPlaceFrame->RepositionFrame(lpPosRect, lpClipRect);
  1705. }
  1706.  
  1707. BOOL COleServerDoc::OnReactivateAndUndo()
  1708. {
  1709.     // default implementation doesn't support undo
  1710.  
  1711.     return FALSE;
  1712. }
  1713.  
  1714. /////////////////////////////////////////////////////////////////////////////
  1715. // COleServerDoc special APIs for in-place editing
  1716.  
  1717. void COleServerDoc::RequestPositionChange(LPCRECT lpPosRect)
  1718. {
  1719.     ASSERT_VALID(this);
  1720.     ASSERT(AfxIsValidAddress(lpPosRect, sizeof(RECT), FALSE));
  1721.  
  1722.     // get IOleInPlaceSite interface
  1723.     ASSERT(m_lpClientSite != NULL);
  1724.     LPOLEINPLACESITE lpInPlaceSite =
  1725.         QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
  1726.  
  1727.     if (lpInPlaceSite != NULL)
  1728.     {
  1729.         // call IOleInPlaceSite::OnPosRectChange
  1730.         lpInPlaceSite->OnPosRectChange(lpPosRect);
  1731.         lpInPlaceSite->Release();
  1732.     }
  1733. }
  1734.  
  1735. BOOL COleServerDoc::ScrollContainerBy(CSize sizeScroll)
  1736. {
  1737.     ASSERT_VALID(this);
  1738.  
  1739.     // get IOleInPlaceSite interface
  1740.     ASSERT(m_lpClientSite != NULL);
  1741.     LPOLEINPLACESITE lpInPlaceSite =
  1742.         QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
  1743.     if (lpInPlaceSite == NULL)
  1744.         return FALSE;
  1745.  
  1746.     // call IOleInPlaceSite::Scroll
  1747.     BOOL bResult = lpInPlaceSite->Scroll(sizeScroll) == S_OK;
  1748.     lpInPlaceSite->Release();
  1749.     return bResult;
  1750. }
  1751.  
  1752. BOOL COleServerDoc::DeactivateAndUndo()
  1753. {
  1754.     ASSERT_VALID(this);
  1755.  
  1756.     // get IOleInPlaceSite interface
  1757.     ASSERT(m_lpClientSite != NULL);
  1758.     LPOLEINPLACESITE lpInPlaceSite =
  1759.         QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
  1760.     if (lpInPlaceSite == NULL)
  1761.         return FALSE;
  1762.  
  1763.     // call IOleInPlaceSite::DeactivateAndUndo
  1764.     BOOL bResult = lpInPlaceSite->DeactivateAndUndo() == S_OK;
  1765.     lpInPlaceSite->Release();
  1766.     return bResult;
  1767. }
  1768.  
  1769. BOOL COleServerDoc::DiscardUndoState()
  1770. {
  1771.     ASSERT_VALID(this);
  1772.  
  1773.     // get IOleInPlaceSite interface
  1774.     ASSERT(m_lpClientSite != NULL);
  1775.     LPOLEINPLACESITE lpInPlaceSite =
  1776.         QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
  1777.     if (lpInPlaceSite == NULL)
  1778.         return FALSE;
  1779.  
  1780.     // call IOleInPlaceSite::DiscardUndoState
  1781.     BOOL bResult = lpInPlaceSite->DiscardUndoState() == S_OK;
  1782.     lpInPlaceSite->Release();
  1783.     return bResult;
  1784. }
  1785.  
  1786. /////////////////////////////////////////////////////////////////////////////
  1787. // COleServerDoc OLE interface implementation
  1788.  
  1789. BEGIN_INTERFACE_MAP(COleServerDoc, COleLinkingDoc)
  1790.     INTERFACE_PART(COleServerDoc, IID_IPersistStorage, PersistStorage)
  1791.     INTERFACE_PART(COleServerDoc, IID_IOleObject, OleObject)
  1792.     INTERFACE_PART(COleServerDoc, IID_IDataObject, DataObject)
  1793.     INTERFACE_PART(COleServerDoc, IID_IOleWindow, OleInPlaceObject)
  1794.     INTERFACE_PART(COleServerDoc, IID_IOleInPlaceObject, OleInPlaceObject)
  1795.     INTERFACE_PART(COleServerDoc, IID_IOleInPlaceActiveObject, OleInPlaceActiveObject)
  1796. END_INTERFACE_MAP()
  1797.  
  1798. /////////////////////////////////////////////////////////////////////////////
  1799. // COleServerDoc::CPersistStorage
  1800.  
  1801. STDMETHODIMP_(ULONG) COleServerDoc::XPersistStorage::AddRef()
  1802. {
  1803.     METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
  1804.     return pThis->ExternalAddRef();
  1805. }
  1806.  
  1807. STDMETHODIMP_(ULONG) COleServerDoc::XPersistStorage::Release()
  1808. {
  1809.     METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
  1810.     return pThis->ExternalRelease();
  1811. }
  1812.  
  1813. STDMETHODIMP COleServerDoc::XPersistStorage::QueryInterface(
  1814.     REFIID iid, LPVOID* ppvObj)
  1815. {
  1816.     METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
  1817.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  1818. }
  1819.  
  1820. STDMETHODIMP COleServerDoc::XPersistStorage::GetClassID(LPCLSID lpClassID)
  1821. {
  1822.     METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
  1823.  
  1824.     LPPERSISTFILE lpPersistFile = (LPPERSISTFILE)
  1825.         pThis->GetInterface(&IID_IPersistFile);
  1826.     return lpPersistFile->GetClassID(lpClassID);
  1827. }
  1828.  
  1829. STDMETHODIMP COleServerDoc::XPersistStorage::IsDirty()
  1830. {
  1831.     METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
  1832.  
  1833.     LPPERSISTFILE lpPersistFile = (LPPERSISTFILE)
  1834.         pThis->GetInterface(&IID_IPersistFile);
  1835.     return lpPersistFile->IsDirty();
  1836. }
  1837.  
  1838. STDMETHODIMP COleServerDoc::XPersistStorage::InitNew(LPSTORAGE pStg)
  1839. {
  1840.     METHOD_PROLOGUE_EX(COleServerDoc, PersistStorage)
  1841.     ASSERT_VALID(pThis);
  1842.  
  1843.     SCODE sc = S_OK;
  1844.     TRY
  1845.     {
  1846.         // delegate to member function in the document
  1847.         pThis->OnNewEmbedding(pStg);
  1848.     }
  1849.     CATCH_ALL(e)
  1850.     {
  1851.         sc = COleException::Process(e);
  1852.         DELETE_EXCEPTION(e);
  1853.     }
  1854.     END_CATCH_ALL
  1855.  
  1856.     ASSERT_VALID(pThis);
  1857.     return sc;
  1858. }
  1859.  
  1860. STDMETHODIMP COleServerDoc::XPersistStorage::Load(LPSTORAGE pStg)
  1861. {
  1862.     METHOD_PROLOGUE_EX(COleServerDoc, PersistStorage)
  1863.     ASSERT_VALID(pThis);
  1864.  
  1865.     SCODE sc = S_OK;
  1866.     pThis->BeginDeferErrors();
  1867.     TRY
  1868.     {
  1869.         // delegate to member function in the document
  1870.         pThis->OnOpenEmbedding(pStg);
  1871.     }
  1872.     CATCH_ALL(e)
  1873.     {
  1874.         sc = COleException::Process(e);
  1875.         DELETE_EXCEPTION(e);
  1876.     }
  1877.     END_CATCH_ALL
  1878.     sc = pThis->EndDeferErrors(sc);
  1879.  
  1880.     ASSERT_VALID(pThis);
  1881.     return sc;
  1882. }
  1883.  
  1884. STDMETHODIMP COleServerDoc::XPersistStorage::Save(
  1885.     LPSTORAGE pStgSave, BOOL fSameAsLoad)
  1886. {
  1887.     METHOD_PROLOGUE_EX(COleServerDoc, PersistStorage)
  1888.     ASSERT_VALID(pThis);
  1889.  
  1890.     // don't bother saving if destination is up-to-date
  1891.     if (fSameAsLoad && !pThis->IsModified())
  1892.         return S_OK;
  1893.  
  1894.     SCODE sc = S_OK;
  1895.     pThis->BeginDeferErrors();
  1896.     TRY
  1897.     {
  1898.         // delegate through the document
  1899.         ASSERT(pThis->m_bRemember);
  1900.         pThis->m_bRemember = FALSE;
  1901.         pThis->m_bSameAsLoad = fSameAsLoad;
  1902.         pThis->OnSaveEmbedding(pStgSave);
  1903.  
  1904.         // clear dirty flag since save to same storage successful
  1905.         if (fSameAsLoad)
  1906.         {
  1907.             pThis->SetModifiedFlag(FALSE);
  1908.  
  1909.             // notify clients that object has been saved
  1910.             pThis->NotifySaved();
  1911.         }
  1912.     }
  1913.     CATCH_ALL(e)
  1914.     {
  1915.         sc = COleException::Process(e);
  1916.         DELETE_EXCEPTION(e);
  1917.     }
  1918.     END_CATCH_ALL
  1919.     sc = pThis->EndDeferErrors(sc);
  1920.  
  1921.     // restore default state
  1922.     pThis->m_bRemember = TRUE;
  1923.  
  1924.     ASSERT_VALID(pThis);
  1925.     return sc;
  1926. }
  1927.  
  1928. STDMETHODIMP COleServerDoc::XPersistStorage::SaveCompleted(LPSTORAGE pStgSaved)
  1929. {
  1930.     METHOD_PROLOGUE_EX(COleServerDoc, PersistStorage)
  1931.     ASSERT_VALID(pThis);
  1932.  
  1933.     // call SaveCompleted on any embedded items
  1934.     pThis->CommitItems(pStgSaved != NULL);
  1935.  
  1936.     // update state to reflect new storage
  1937.     if (pStgSaved != NULL)
  1938.     {
  1939.         // attach new storage
  1940.         pStgSaved->AddRef();
  1941.         RELEASE(pThis->m_lpRootStg);
  1942.         pThis->m_lpRootStg = pStgSaved;
  1943.  
  1944.         // now this document is storage based
  1945.         pThis->m_strPathName.Empty();
  1946.         pThis->m_bEmbedded = TRUE;
  1947.         pThis->SetModifiedFlag(FALSE);
  1948.  
  1949.         // notify clients that object has been saved
  1950.         pThis->NotifySaved();
  1951.     }
  1952.  
  1953.     ASSERT_VALID(pThis);
  1954.     return S_OK;
  1955. }
  1956.  
  1957. STDMETHODIMP COleServerDoc::XPersistStorage::HandsOffStorage()
  1958. {
  1959.     METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
  1960.  
  1961.     if (pThis->m_lpRootStg != NULL)
  1962.     {
  1963.         // first call HandsOffStorage for all the embedded client items
  1964.         POSITION pos = pThis->GetStartPosition();
  1965.         COleClientItem* pItem;
  1966.         while ((pItem = pThis->GetNextClientItem(pos)) != NULL)
  1967.         {
  1968.             ASSERT(pItem->m_lpObject != NULL);
  1969.             LPPERSISTSTORAGE lpPersistStorage =
  1970.                 QUERYINTERFACE(pItem->m_lpObject, IPersistStorage);
  1971.             ASSERT(lpPersistStorage != NULL);
  1972.             lpPersistStorage->HandsOffStorage();
  1973.             lpPersistStorage->Release();
  1974.         }
  1975.  
  1976.         // for now, can't access the storage
  1977.         RELEASE(pThis->m_lpRootStg);
  1978.     }
  1979.  
  1980.     ASSERT_VALID(pThis);
  1981.     return S_OK;
  1982. }
  1983.  
  1984. /////////////////////////////////////////////////////////////////////////////
  1985. // COleServerDoc::XOleObject
  1986.  
  1987. STDMETHODIMP_(ULONG) COleServerDoc::XOleObject::AddRef()
  1988. {
  1989.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  1990.     return pThis->ExternalAddRef();
  1991. }
  1992.  
  1993. STDMETHODIMP_(ULONG) COleServerDoc::XOleObject::Release()
  1994. {
  1995.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  1996.     return pThis->ExternalRelease();
  1997. }
  1998.  
  1999. STDMETHODIMP COleServerDoc::XOleObject::QueryInterface(
  2000.     REFIID iid, LPVOID* ppvObj)
  2001. {
  2002.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2003.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  2004. }
  2005.  
  2006. STDMETHODIMP COleServerDoc::XOleObject::SetClientSite(
  2007.     LPOLECLIENTSITE pClientSite)
  2008. {
  2009.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2010.  
  2011.     // maintain reference counts
  2012.     if (pClientSite != NULL)
  2013.         pClientSite->AddRef();
  2014.     RELEASE(pThis->m_lpClientSite);
  2015.     pThis->m_lpClientSite = pClientSite;
  2016.  
  2017. #ifndef _MAC
  2018.     // do we already have doc object support enabled?
  2019.  
  2020.     if (pThis->m_pDocObjectServer != NULL)
  2021.     {
  2022.         // If we currently have a document site pointer,
  2023.         // release it.
  2024.         pThis->m_pDocObjectServer->ReleaseDocSite();
  2025.     }
  2026.  
  2027.     if (pClientSite != NULL)
  2028.     {
  2029.         LPOLEDOCUMENTSITE pDocSite;
  2030.  
  2031.         if (SUCCEEDED(pClientSite->QueryInterface(IID_IOleDocumentSite,
  2032.             (LPVOID*) &pDocSite)))
  2033.         {
  2034.             if (pThis->m_pDocObjectServer != NULL)
  2035.                 pThis->m_pDocObjectServer->SetDocSite(pDocSite);
  2036.             else
  2037.             {
  2038.                 pThis->m_pDocObjectServer =
  2039.                     pThis->GetDocObjectServer(pDocSite);
  2040.             }
  2041.         }
  2042.     }
  2043. #endif
  2044.  
  2045.     return S_OK;
  2046. }
  2047.  
  2048. STDMETHODIMP COleServerDoc::XOleObject::GetClientSite(
  2049.     LPOLECLIENTSITE* ppClientSite)
  2050. {
  2051.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2052.  
  2053.     if (pThis->m_lpClientSite == NULL)
  2054.     {
  2055.         *ppClientSite = NULL;
  2056.         return E_FAIL;
  2057.     }
  2058.  
  2059.     *ppClientSite = pThis->m_lpClientSite;
  2060.     pThis->m_lpClientSite->AddRef();
  2061.     return S_OK;
  2062. }
  2063.  
  2064. STDMETHODIMP COleServerDoc::XOleObject::SetHostNames(
  2065.     LPCOLESTR lpszContainerApp, LPCOLESTR lpszContainerObj)
  2066. {
  2067.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2068.     ASSERT_VALID(pThis);
  2069.  
  2070.     USES_CONVERSION;
  2071.  
  2072.     TRY
  2073.     {
  2074.         pThis->OnSetHostNames(OLE2CT(lpszContainerApp),
  2075.             OLE2CT(lpszContainerObj));
  2076.     }
  2077.     END_TRY
  2078.  
  2079.     return S_OK;
  2080. }
  2081.  
  2082. STDMETHODIMP COleServerDoc::XOleObject::Close(DWORD dwSaveOption)
  2083. {
  2084.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2085.     ASSERT_VALID(pThis);
  2086.  
  2087.     pThis->InternalAddRef();    // protect this object
  2088.  
  2089.     SCODE sc = S_OK;
  2090.     TRY
  2091.     {
  2092.         // delegate through document for most of the work
  2093.         pThis->OnClose((OLECLOSE)dwSaveOption);
  2094.     }
  2095.     CATCH_ALL(e)
  2096.     {
  2097.         sc = COleException::Process(e);
  2098.         DELETE_EXCEPTION(e);
  2099.     }
  2100.     END_CATCH_ALL
  2101.  
  2102.     pThis->InternalRelease();   // may 'delete this'
  2103.  
  2104.     return sc;
  2105. }
  2106.  
  2107. STDMETHODIMP COleServerDoc::XOleObject::SetMoniker(
  2108.     DWORD /*dwWhichMoniker*/, LPMONIKER /*pmk*/)
  2109. {
  2110.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2111.  
  2112.     if (pThis->m_lpClientSite == NULL)
  2113.         return E_FAIL;
  2114.  
  2115.     // get current full moniker from client-site
  2116.     LPMONIKER lpMoniker = NULL;
  2117.     if (pThis->m_lpClientSite->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
  2118.         OLEWHICHMK_OBJFULL, &lpMoniker) != S_OK)
  2119.     {
  2120.         // just to make sure -- always set moniker to NULL on failure
  2121.         lpMoniker = NULL;
  2122.     }
  2123.  
  2124.     // update all embedded items with new moniker
  2125.     POSITION pos = pThis->GetStartPosition();
  2126.     COleClientItem* pItem;
  2127.     while ((pItem = pThis->GetNextClientItem(pos)) != NULL)
  2128.     {
  2129.         if (pItem->m_bMoniker)
  2130.             pItem->m_lpObject->SetMoniker(OLEWHICHMK_CONTAINER, lpMoniker);
  2131.     }
  2132.  
  2133.     // send Rename advises
  2134.     pThis->NotifyAllItems(OLE_RENAMED, (DWORD)lpMoniker);
  2135.     RELEASE(lpMoniker);
  2136.  
  2137.     return S_OK;
  2138. }
  2139.  
  2140. STDMETHODIMP COleServerDoc::XOleObject::GetMoniker(
  2141.     DWORD dwAssign, DWORD /*dwWhichMoniker*/, LPMONIKER* ppMoniker)
  2142. {
  2143.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2144.  
  2145.     *ppMoniker = pThis->GetMoniker((OLEGETMONIKER)dwAssign);
  2146.     return *ppMoniker == NULL ? E_FAIL : S_OK;
  2147. }
  2148.  
  2149. STDMETHODIMP COleServerDoc::XOleObject::InitFromData(
  2150.     LPDATAOBJECT pDataObject, BOOL fCreation, DWORD /*dwReserved*/)
  2151. {
  2152.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2153.     ASSERT_VALID(pThis);
  2154.  
  2155.     COleServerItem* pItem;
  2156.     SCODE sc;
  2157.     TRY
  2158.     {
  2159.         // delegate through item
  2160.         pItem = pThis->GetEmbeddedItem();
  2161.         ASSERT_VALID(pItem);
  2162.         ASSERT_KINDOF(COleServerItem, pItem);
  2163.  
  2164.         COleDataObject dataObject;
  2165.         dataObject.Attach(pDataObject,  FALSE);
  2166.         sc = pItem->OnInitFromData(&dataObject, fCreation) ? S_OK : S_FALSE;
  2167.     }
  2168.     CATCH_ALL(e)
  2169.     {
  2170.         sc = COleException::Process(e);
  2171.         DELETE_EXCEPTION(e);
  2172.     }
  2173.     END_CATCH_ALL
  2174.  
  2175.     return sc;
  2176. }
  2177.  
  2178. STDMETHODIMP COleServerDoc::XOleObject::GetClipboardData(
  2179.     DWORD /*dwReserved*/, LPDATAOBJECT* ppDataObject)
  2180. {
  2181.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2182.     ASSERT_VALID(pThis);
  2183.  
  2184.     *ppDataObject = NULL;
  2185.  
  2186.     COleServerItem* pItem;
  2187.     SCODE sc = S_OK;
  2188.     TRY
  2189.     {
  2190.         // delegate through item
  2191.         pItem = pThis->GetEmbeddedItem();
  2192.         ASSERT_VALID(pItem);
  2193.         ASSERT_KINDOF(COleServerItem, pItem);
  2194.  
  2195.         COleDataSource* pDataSource =
  2196.             pItem->OnGetClipboardData(TRUE, NULL, NULL);
  2197.         ASSERT(pDataSource != NULL);
  2198.  
  2199.         *ppDataObject =
  2200.             (LPDATAOBJECT)pDataSource->GetInterface(&IID_IDataObject);
  2201.         ASSERT(*ppDataObject != NULL);
  2202.     }
  2203.     CATCH_ALL(e)
  2204.     {
  2205.         sc = COleException::Process(e);
  2206.         DELETE_EXCEPTION(e);
  2207.     }
  2208.     END_CATCH_ALL
  2209.  
  2210.     return sc;
  2211. }
  2212.  
  2213. STDMETHODIMP COleServerDoc::XOleObject::DoVerb(
  2214.     LONG iVerb, LPMSG /*lpmsg*/, LPOLECLIENTSITE /*pActiveSite*/, LONG /*lindex*/,
  2215.     HWND /*hwndParent*/, LPCRECT /*lpPosRect*/)
  2216. {
  2217.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2218.     ASSERT_VALID(pThis);
  2219.  
  2220.     pThis->InternalAddRef();    // protect this object
  2221.  
  2222.     COleServerItem* pItem;
  2223.     SCODE sc = S_OK;
  2224.     TRY
  2225.     {
  2226.         // delegate through item
  2227.         pItem = pThis->GetEmbeddedItem();
  2228.         ASSERT_VALID(pItem);
  2229.         ASSERT_KINDOF(COleServerItem, pItem);
  2230.         pItem->OnDoVerb(iVerb);
  2231.     }
  2232.     CATCH_ALL(e)
  2233.     {
  2234.         sc = COleException::Process(e);
  2235.         DELETE_EXCEPTION(e);
  2236.     }
  2237.     END_CATCH_ALL
  2238.     pThis->InternalRelease();   // may 'delete this'
  2239.  
  2240.     return sc;
  2241. }
  2242.  
  2243. STDMETHODIMP COleServerDoc::XOleObject::EnumVerbs(
  2244.     IEnumOLEVERB** ppenumOleVerb)
  2245. {
  2246.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2247.  
  2248.     *ppenumOleVerb = NULL;
  2249.  
  2250.     LPOLEOBJECT lpObject = (LPOLEOBJECT)pThis->GetInterface(&IID_IOleObject);
  2251.     ASSERT(lpObject != NULL);
  2252.     CLSID clsid;
  2253.     lpObject->GetUserClassID(&clsid);
  2254.  
  2255.     return OleRegEnumVerbs(clsid, ppenumOleVerb);
  2256. }
  2257.  
  2258. STDMETHODIMP COleServerDoc::XOleObject::Update()
  2259. {
  2260.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2261.     ASSERT_VALID(pThis);
  2262.  
  2263.     COleServerItem* pItem;
  2264.     SCODE sc = S_OK;
  2265.     TRY
  2266.     {
  2267.         // delegate through item
  2268.         pItem = pThis->GetEmbeddedItem();
  2269.         ASSERT_VALID(pItem);
  2270.         ASSERT_KINDOF(COleServerItem, pItem);
  2271.         pItem->OnUpdateItems();
  2272.     }
  2273.     CATCH_ALL(e)
  2274.     {
  2275.         sc = COleException::Process(e);
  2276.         DELETE_EXCEPTION(e);
  2277.     }
  2278.     END_CATCH_ALL
  2279.  
  2280.     return sc;
  2281. }
  2282.  
  2283. STDMETHODIMP COleServerDoc::XOleObject::IsUpToDate()
  2284. {
  2285.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2286.     ASSERT_VALID(pThis);
  2287.  
  2288.     COleServerItem* pItem;
  2289.     SCODE sc;
  2290.     TRY
  2291.     {
  2292.         // delegate through item
  2293.         pItem = pThis->GetEmbeddedItem();
  2294.         ASSERT_VALID(pItem);
  2295.         ASSERT_KINDOF(COleServerItem, pItem);
  2296.  
  2297.         sc = pItem->OnQueryUpdateItems() ? S_FALSE : S_OK;
  2298.     }
  2299.     CATCH_ALL(e)
  2300.     {
  2301.         sc = COleException::Process(e);
  2302.         DELETE_EXCEPTION(e);
  2303.     }
  2304.     END_CATCH_ALL
  2305.  
  2306.     return sc;
  2307. }
  2308.  
  2309. STDMETHODIMP COleServerDoc::XOleObject::GetUserClassID(CLSID* lpClassID)
  2310. {
  2311.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2312.  
  2313.     LPPERSISTFILE lpPersistFile = (LPPERSISTFILE)
  2314.         pThis->GetInterface(&IID_IPersistFile);
  2315.     return lpPersistFile->GetClassID(lpClassID);
  2316. }
  2317.  
  2318. STDMETHODIMP COleServerDoc::XOleObject::GetUserType(
  2319.     DWORD dwFormOfType, LPOLESTR* ppszUserType)
  2320. {
  2321.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2322.  
  2323.     *ppszUserType = NULL;
  2324.  
  2325.     LPOLEOBJECT lpObject = (LPOLEOBJECT)pThis->GetInterface(&IID_IOleObject);
  2326.     ASSERT(lpObject != NULL);
  2327.     CLSID clsid;
  2328.     lpObject->GetUserClassID(&clsid);
  2329.  
  2330.     return OleRegGetUserType(clsid, dwFormOfType, ppszUserType);
  2331. }
  2332.  
  2333. STDMETHODIMP COleServerDoc::XOleObject::SetExtent(
  2334.     DWORD dwDrawAspect, LPSIZEL lpsizel)
  2335. {
  2336.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2337.     ASSERT_VALID(pThis);
  2338.  
  2339.     COleServerItem* pItem;
  2340.     SCODE sc = E_FAIL;
  2341.     TRY
  2342.     {
  2343.         // convert rectangle to a CSize and call item OnSetExtent
  2344.         pItem = pThis->GetEmbeddedItem();
  2345.         ASSERT_VALID(pItem);
  2346.         ASSERT_KINDOF(COleServerItem, pItem);
  2347.  
  2348.         CSize size((int)lpsizel->cx, (int)lpsizel->cy);
  2349.         if (pItem->OnSetExtent((DVASPECT)dwDrawAspect, size))
  2350.             sc = S_OK;
  2351.     }
  2352.     CATCH_ALL(e)
  2353.     {
  2354.         sc = COleException::Process(e);
  2355.         DELETE_EXCEPTION(e);
  2356.     }
  2357.     END_CATCH_ALL
  2358.  
  2359.     return sc;
  2360. }
  2361.  
  2362. STDMETHODIMP COleServerDoc::XOleObject::GetExtent(
  2363.     DWORD dwDrawAspect, LPSIZEL lpsizel)
  2364. {
  2365.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2366.     ASSERT_VALID(pThis);
  2367.  
  2368.     COleServerItem* pItem;
  2369.     SCODE sc = E_INVALIDARG;
  2370.     TRY
  2371.     {
  2372.         pItem = pThis->GetEmbeddedItem();
  2373.         ASSERT_VALID(pItem);
  2374.         ASSERT_KINDOF(COleServerItem, pItem);
  2375.  
  2376.         // call to get regular windows CSize
  2377.         CSize size;
  2378.         if (pItem->OnGetExtent((DVASPECT)dwDrawAspect, size))
  2379.         {
  2380.             if (size.cy < 0)
  2381.                 size.cy = -size.cy; // extents are always positive
  2382.             lpsizel->cx = size.cx;
  2383.             lpsizel->cy = size.cy;
  2384.  
  2385.             sc = S_OK;
  2386.         }
  2387.     }
  2388.     CATCH_ALL(e)
  2389.     {
  2390.         sc = COleException::Process(e);
  2391.         DELETE_EXCEPTION(e);
  2392.     }
  2393.     END_CATCH_ALL
  2394.  
  2395.     return sc;
  2396. }
  2397.  
  2398. STDMETHODIMP COleServerDoc::XOleObject::Advise(
  2399.     IAdviseSink* pAdvSink, DWORD* pdwConnection)
  2400. {
  2401.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2402.  
  2403.     COleServerItem* pItem;
  2404.     SCODE sc = E_OUTOFMEMORY;
  2405.     TRY
  2406.     {
  2407.         pItem = pThis->GetEmbeddedItem();
  2408.         ASSERT_VALID(pItem);
  2409.         ASSERT_KINDOF(COleServerItem, pItem);
  2410.         sc = S_OK;
  2411.     }
  2412.     END_TRY
  2413.  
  2414.     if (sc != S_OK)
  2415.         return sc;
  2416.  
  2417.     return pItem->GetOleObject()->Advise(pAdvSink, pdwConnection);
  2418. }
  2419.  
  2420. STDMETHODIMP COleServerDoc::XOleObject::Unadvise(DWORD dwConnection)
  2421. {
  2422.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2423.  
  2424.     COleServerItem* pItem;
  2425.     SCODE sc = E_OUTOFMEMORY;
  2426.     TRY
  2427.     {
  2428.         pItem = pThis->GetEmbeddedItem();
  2429.         ASSERT_VALID(pItem);
  2430.         ASSERT_KINDOF(COleServerItem, pItem);
  2431.         sc = S_OK;
  2432.     }
  2433.     END_TRY
  2434.  
  2435.     if (sc != S_OK)
  2436.         return sc;
  2437.  
  2438.     return pItem->GetOleObject()->Unadvise(dwConnection);
  2439. }
  2440.  
  2441. STDMETHODIMP COleServerDoc::XOleObject::EnumAdvise(
  2442.     LPENUMSTATDATA* ppenumAdvise)
  2443. {
  2444.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2445.  
  2446.     COleServerItem* pItem;
  2447.     SCODE sc = E_OUTOFMEMORY;
  2448.     TRY
  2449.     {
  2450.         pItem = pThis->GetEmbeddedItem();
  2451.         ASSERT_VALID(pItem);
  2452.         ASSERT_KINDOF(COleServerItem, pItem);
  2453.         sc = S_OK;
  2454.     }
  2455.     END_TRY
  2456.  
  2457.     if (sc != S_OK)
  2458.         return sc;
  2459.  
  2460.     return pItem->GetOleObject()->EnumAdvise(ppenumAdvise);
  2461. }
  2462.  
  2463. STDMETHODIMP COleServerDoc::XOleObject::GetMiscStatus(
  2464.     DWORD dwAspect, DWORD* pdwStatus)
  2465. {
  2466.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2467.  
  2468.     *pdwStatus = 0;
  2469.  
  2470.     LPOLEOBJECT lpObject = (LPOLEOBJECT)pThis->GetInterface(&IID_IOleObject);
  2471.     ASSERT(lpObject != NULL);
  2472.     CLSID clsid;
  2473.     lpObject->GetUserClassID(&clsid);
  2474.  
  2475.     return OleRegGetMiscStatus(clsid, dwAspect, pdwStatus);
  2476. }
  2477.  
  2478. STDMETHODIMP COleServerDoc::XOleObject::SetColorScheme(LPLOGPALETTE lpLogpal)
  2479. {
  2480.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2481.     ASSERT_VALID(pThis);
  2482.  
  2483.     COleServerItem* pItem;
  2484.     SCODE sc = E_NOTIMPL;
  2485.     TRY
  2486.     {
  2487.         pItem = pThis->GetEmbeddedItem();
  2488.         ASSERT_VALID(pItem);
  2489.         ASSERT_KINDOF(COleServerItem, pItem);
  2490.  
  2491.         // delegate to embedded item
  2492.         if (pItem->OnSetColorScheme(lpLogpal))
  2493.             sc = S_OK;
  2494.     }
  2495.     END_TRY
  2496.  
  2497.     return sc;
  2498. }
  2499.  
  2500. /////////////////////////////////////////////////////////////////////////////
  2501. // COleServerDoc::XDataObject
  2502.  
  2503. STDMETHODIMP_(ULONG) COleServerDoc::XDataObject::AddRef()
  2504. {
  2505.     METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
  2506.     return pThis->ExternalAddRef();
  2507. }
  2508.  
  2509. STDMETHODIMP_(ULONG) COleServerDoc::XDataObject::Release()
  2510. {
  2511.     METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
  2512.     return pThis->ExternalRelease();
  2513. }
  2514.  
  2515. STDMETHODIMP COleServerDoc::XDataObject::QueryInterface(
  2516.     REFIID iid, LPVOID* ppvObj)
  2517. {
  2518.     METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
  2519.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  2520. }
  2521.  
  2522. STDMETHODIMP COleServerDoc::XDataObject::GetData(
  2523.     LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
  2524. {
  2525.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2526.  
  2527.     COleServerItem* pItem;
  2528.     SCODE sc = E_OUTOFMEMORY;
  2529.     TRY
  2530.     {
  2531.         pItem = pThis->GetEmbeddedItem();
  2532.         ASSERT_VALID(pItem);
  2533.         ASSERT_KINDOF(COleServerItem, pItem);
  2534.         sc = S_OK;
  2535.     }
  2536.     END_TRY
  2537.  
  2538.     if (sc != S_OK)
  2539.         return sc;
  2540.  
  2541.     return pItem->GetDataObject()->GetData(lpFormatEtc, lpStgMedium);
  2542. }
  2543.  
  2544. STDMETHODIMP COleServerDoc::XDataObject::GetDataHere(
  2545.     LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
  2546. {
  2547.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2548.  
  2549.     COleServerItem* pItem;
  2550.     SCODE sc = E_OUTOFMEMORY;
  2551.     TRY
  2552.     {
  2553.         pItem = pThis->GetEmbeddedItem();
  2554.         ASSERT_VALID(pItem);
  2555.         ASSERT_KINDOF(COleServerItem, pItem);
  2556.         sc = S_OK;
  2557.     }
  2558.     END_TRY
  2559.  
  2560.     if (sc != S_OK)
  2561.         return sc;
  2562.  
  2563.     return pItem->GetDataObject()->GetDataHere(lpFormatEtc, lpStgMedium);
  2564. }
  2565.  
  2566. STDMETHODIMP COleServerDoc::XDataObject::QueryGetData(
  2567.     LPFORMATETC lpFormatEtc)
  2568. {
  2569.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2570.  
  2571.     COleServerItem* pItem;
  2572.     SCODE sc = E_OUTOFMEMORY;
  2573.     TRY
  2574.     {
  2575.         pItem = pThis->GetEmbeddedItem();
  2576.         ASSERT_VALID(pItem);
  2577.         ASSERT_KINDOF(COleServerItem, pItem);
  2578.         sc = S_OK;
  2579.     }
  2580.     END_TRY
  2581.  
  2582.     if (sc != S_OK)
  2583.         return sc;
  2584.  
  2585.     return pItem->GetDataObject()->QueryGetData(lpFormatEtc);
  2586. }
  2587.  
  2588. STDMETHODIMP COleServerDoc::XDataObject::GetCanonicalFormatEtc(
  2589.     LPFORMATETC /*lpFormatEtcIn*/, LPFORMATETC /*lpFormatEtcOut*/)
  2590. {
  2591.     // because we support the target-device (ptd) for server metafile format,
  2592.     //  all members of the FORMATETC are significant.
  2593.  
  2594.     return DATA_S_SAMEFORMATETC;
  2595. }
  2596.  
  2597. STDMETHODIMP COleServerDoc::XDataObject::SetData(
  2598.     LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium, BOOL bRelease)
  2599. {
  2600.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2601.  
  2602.     COleServerItem* pItem;
  2603.     SCODE sc = E_OUTOFMEMORY;
  2604.     TRY
  2605.     {
  2606.         pItem = pThis->GetEmbeddedItem();
  2607.         ASSERT_VALID(pItem);
  2608.         ASSERT_KINDOF(COleServerItem, pItem);
  2609.         sc = S_OK;
  2610.     }
  2611.     END_TRY
  2612.  
  2613.     if (sc != S_OK)
  2614.         return sc;
  2615.  
  2616.     return pItem->GetDataObject()->SetData(lpFormatEtc, lpStgMedium, bRelease);
  2617. }
  2618.  
  2619. STDMETHODIMP COleServerDoc::XDataObject::EnumFormatEtc(
  2620.     DWORD dwDirection, LPENUMFORMATETC* ppenumFormatEtc)
  2621. {
  2622.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2623.  
  2624.     COleServerItem* pItem;
  2625.     SCODE sc = E_OUTOFMEMORY;
  2626.     TRY
  2627.     {
  2628.         pItem = pThis->GetEmbeddedItem();
  2629.         ASSERT_VALID(pItem);
  2630.         ASSERT_KINDOF(COleServerItem, pItem);
  2631.         sc = S_OK;
  2632.     }
  2633.     END_TRY
  2634.  
  2635.     if (sc != S_OK)
  2636.         return sc;
  2637.  
  2638.     return pItem->GetDataObject()->EnumFormatEtc(dwDirection, ppenumFormatEtc);
  2639. }
  2640.  
  2641. STDMETHODIMP COleServerDoc::XDataObject::DAdvise(
  2642.     FORMATETC* pFormatetc, DWORD advf,
  2643.     LPADVISESINK pAdvSink, DWORD* pdwConnection)
  2644. {
  2645.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2646.  
  2647.     COleServerItem* pItem;
  2648.     SCODE sc = E_OUTOFMEMORY;
  2649.     TRY
  2650.     {
  2651.         pItem = pThis->GetEmbeddedItem();
  2652.         ASSERT_VALID(pItem);
  2653.         ASSERT_KINDOF(COleServerItem, pItem);
  2654.         sc = S_OK;
  2655.     }
  2656.     END_TRY
  2657.  
  2658.     if (sc != S_OK)
  2659.         return sc;
  2660.  
  2661.     return pItem->GetDataObject()->DAdvise(pFormatetc, advf, pAdvSink,
  2662.         pdwConnection);
  2663. }
  2664.  
  2665. STDMETHODIMP COleServerDoc::XDataObject::DUnadvise(DWORD dwConnection)
  2666. {
  2667.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2668.  
  2669.     COleServerItem* pItem;
  2670.     SCODE sc = E_OUTOFMEMORY;
  2671.     TRY
  2672.     {
  2673.         pItem = pThis->GetEmbeddedItem();
  2674.         ASSERT_VALID(pItem);
  2675.         ASSERT_KINDOF(COleServerItem, pItem);
  2676.         sc = S_OK;
  2677.     }
  2678.     END_TRY
  2679.  
  2680.     if (sc != S_OK)
  2681.         return sc;
  2682.  
  2683.     return pItem->GetDataObject()->DUnadvise(dwConnection);
  2684. }
  2685.  
  2686. STDMETHODIMP COleServerDoc::XDataObject::EnumDAdvise(
  2687.     LPENUMSTATDATA* ppenumAdvise)
  2688. {
  2689.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2690.  
  2691.     COleServerItem* pItem;
  2692.     SCODE sc = E_OUTOFMEMORY;
  2693.     TRY
  2694.     {
  2695.         pItem = pThis->GetEmbeddedItem();
  2696.         ASSERT_VALID(pItem);
  2697.         ASSERT_KINDOF(COleServerItem, pItem);
  2698.         sc = S_OK;
  2699.     }
  2700.     END_TRY
  2701.  
  2702.     if (sc != S_OK)
  2703.         return sc;
  2704.  
  2705.     return pItem->GetDataObject()->EnumDAdvise(ppenumAdvise);
  2706. }
  2707.  
  2708. /////////////////////////////////////////////////////////////////////////////
  2709. // COleServerDoc::COleInPlaceObject
  2710.  
  2711. STDMETHODIMP_(ULONG) COleServerDoc::XOleInPlaceObject::AddRef()
  2712. {
  2713.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceObject)
  2714.     return pThis->ExternalAddRef();
  2715. }
  2716.  
  2717. STDMETHODIMP_(ULONG) COleServerDoc::XOleInPlaceObject::Release()
  2718. {
  2719.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceObject)
  2720.     return pThis->ExternalRelease();
  2721. }
  2722.  
  2723. STDMETHODIMP COleServerDoc::XOleInPlaceObject::QueryInterface(
  2724.     REFIID iid, LPVOID* ppvObj)
  2725. {
  2726.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceObject)
  2727.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  2728. }
  2729.  
  2730. STDMETHODIMP COleServerDoc::XOleInPlaceObject::GetWindow(HWND* lphwnd)
  2731. {
  2732.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceObject)
  2733.  
  2734.     LPOLEINPLACEACTIVEOBJECT lpActiveObject = (LPOLEINPLACEACTIVEOBJECT)
  2735.         pThis->GetInterface(&IID_IOleInPlaceActiveObject);
  2736.     return lpActiveObject->GetWindow(lphwnd);
  2737. }
  2738.  
  2739. STDMETHODIMP COleServerDoc::XOleInPlaceObject::ContextSensitiveHelp(
  2740.     BOOL fEnterMode)
  2741. {
  2742.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceObject)
  2743.  
  2744.     LPOLEINPLACEACTIVEOBJECT lpActiveObject = (LPOLEINPLACEACTIVEOBJECT)
  2745.         pThis->GetInterface(&IID_IOleInPlaceActiveObject);
  2746.     return lpActiveObject->ContextSensitiveHelp(fEnterMode);
  2747. }
  2748.  
  2749. STDMETHODIMP COleServerDoc::XOleInPlaceObject::InPlaceDeactivate()
  2750. {
  2751.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceObject)
  2752.     ASSERT_VALID(pThis);
  2753.  
  2754.     pThis->InternalAddRef();    // protect this object
  2755.  
  2756.     SCODE sc = E_UNEXPECTED;
  2757.     TRY
  2758.     {
  2759.         // only call deactivate if necessary
  2760. #ifndef _MAC
  2761.         if (pThis->m_pInPlaceFrame != NULL)
  2762.             pThis->OnDeactivate();
  2763.  
  2764.         // should be completely inactive
  2765.         ASSERT(pThis->m_pInPlaceFrame == NULL);
  2766. #else
  2767.         // Some Mac containers call OnDeactivate within their RemoveMenus
  2768.         // methods.  Prevent recursion in this case.
  2769.         if (pThis->m_pInPlaceFrame != NULL && !pThis->m_bDeactivating)
  2770.         {
  2771.             pThis->OnDeactivate();
  2772.  
  2773.             // should be completely inactive
  2774.             ASSERT(pThis->m_pInPlaceFrame == NULL);
  2775.         }
  2776. #endif
  2777.         sc = S_OK;
  2778.     }
  2779.     END_TRY
  2780.  
  2781.     pThis->InternalRelease();   // may 'delete this'
  2782.     return sc;
  2783. }
  2784.  
  2785. STDMETHODIMP COleServerDoc::XOleInPlaceObject::UIDeactivate()
  2786. {
  2787.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceObject)
  2788.     ASSERT_VALID(pThis);
  2789.  
  2790.     pThis->InternalAddRef();    // protect this object
  2791.  
  2792.     SCODE sc = E_UNEXPECTED;
  2793.     TRY
  2794.     {
  2795.         // only call OnUIDeactivate if necessary
  2796.         if (pThis->m_pInPlaceFrame != NULL &&
  2797.             pThis->m_pInPlaceFrame->m_bUIActive)
  2798.         {
  2799.             pThis->OnDeactivateUI(FALSE);   // default to not undoable
  2800.         }
  2801.  
  2802.         // should not be ui active
  2803.         ASSERT(pThis->m_pInPlaceFrame == NULL ||
  2804.             !pThis->m_pInPlaceFrame->m_bUIActive);
  2805.         sc = S_OK;
  2806.     }
  2807.     END_TRY
  2808.  
  2809.     pThis->InternalRelease();   // may 'delete this'
  2810.     return sc;
  2811. }
  2812.  
  2813. STDMETHODIMP COleServerDoc::XOleInPlaceObject::SetObjectRects(
  2814.     LPCRECT lpPosRect, LPCRECT lpClipRect)
  2815. {
  2816.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceObject)
  2817.     ASSERT_VALID(pThis);
  2818.  
  2819.     SCODE sc = E_UNEXPECTED;
  2820.     TRY
  2821.     {
  2822.         pThis->OnSetItemRects(lpPosRect, lpClipRect);
  2823.         sc = S_OK;
  2824.     }
  2825.     END_TRY
  2826.  
  2827.     return sc;
  2828. }
  2829.  
  2830. STDMETHODIMP COleServerDoc::XOleInPlaceObject::ReactivateAndUndo()
  2831. {
  2832.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceObject)
  2833.     ASSERT_VALID(pThis);
  2834.  
  2835.     SCODE sc = E_UNEXPECTED;
  2836.     TRY
  2837.     {
  2838.         sc = pThis->OnReactivateAndUndo() ? S_OK : INPLACE_E_NOTUNDOABLE;
  2839.     }
  2840.     END_TRY
  2841.  
  2842.     return sc;
  2843. }
  2844.  
  2845. /////////////////////////////////////////////////////////////////////////////
  2846. // COleServerDoc::XOleInPlaceActiveObject
  2847.  
  2848. STDMETHODIMP_(ULONG) COleServerDoc::XOleInPlaceActiveObject::AddRef()
  2849. {
  2850.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceActiveObject)
  2851.     return pThis->ExternalAddRef();
  2852. }
  2853.  
  2854. STDMETHODIMP_(ULONG) COleServerDoc::XOleInPlaceActiveObject::Release()
  2855. {
  2856.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceActiveObject)
  2857.     return pThis->ExternalRelease();
  2858. }
  2859.  
  2860. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::QueryInterface(
  2861.     REFIID iid, LPVOID* ppvObj)
  2862. {
  2863.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceActiveObject)
  2864.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  2865. }
  2866.  
  2867. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::GetWindow(
  2868.     HWND* lphwnd)
  2869. {
  2870.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceActiveObject)
  2871.  
  2872.     *lphwnd = pThis->m_pInPlaceFrame->GetSafeHwnd();
  2873.     return *lphwnd != NULL ? S_OK : E_FAIL;
  2874. }
  2875.  
  2876. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::ContextSensitiveHelp(
  2877.     BOOL fEnterMode)
  2878. {
  2879.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
  2880.     ASSERT_VALID(pThis);
  2881.  
  2882.     if (fEnterMode)
  2883.     {
  2884.         if (!pThis->m_pInPlaceFrame->m_bHelpMode)
  2885.         {
  2886.             // check if help mode probable
  2887.             if (!pThis->m_pInPlaceFrame->CanEnterHelpMode())
  2888.                 return E_UNEXPECTED;
  2889.  
  2890.             // attempt to enter context help
  2891.             if (!pThis->m_pInPlaceFrame->PostMessage(WM_COMMAND, ID_CONTEXT_HELP))
  2892.                 return E_UNEXPECTED;
  2893.         }
  2894.     }
  2895.     else
  2896.     {
  2897.         // just exit help mode
  2898.         pThis->m_pInPlaceFrame->ExitHelpMode();
  2899.     }
  2900.  
  2901.     return S_OK;
  2902. }
  2903.  
  2904. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::TranslateAccelerator(
  2905.     LPMSG lpmsg)
  2906. {
  2907.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
  2908.     ASSERT_VALID(pThis);
  2909.  
  2910.     pThis->InternalAddRef();    // protect this object
  2911.  
  2912.     SCODE sc = E_UNEXPECTED;
  2913.     TRY
  2914.     {
  2915.         // get frame window for this document
  2916.         CFrameWnd* pFrameWnd = pThis->m_pInPlaceFrame;
  2917.         ASSERT_VALID(pFrameWnd);
  2918.  
  2919.         // attempt translate accelerator
  2920.         MSG msg = *lpmsg;
  2921.         sc = pFrameWnd->PreTranslateMessage(&msg) ? S_OK : S_FALSE;
  2922.         *lpmsg = msg;
  2923.     }
  2924.     END_TRY
  2925.  
  2926.     pThis->InternalRelease();   // may 'delete this'
  2927.  
  2928.     return sc;
  2929. }
  2930.  
  2931. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::OnFrameWindowActivate(
  2932.     BOOL fActivate)
  2933. {
  2934.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
  2935.     ASSERT_VALID(pThis);
  2936.  
  2937.     SCODE sc = E_UNEXPECTED;
  2938.     TRY
  2939.     {
  2940.         pThis->OnFrameWindowActivate(fActivate);
  2941.         sc = S_OK;
  2942.     }
  2943.     END_TRY
  2944.  
  2945.     return sc;
  2946. }
  2947.  
  2948. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::OnDocWindowActivate(
  2949.     BOOL fActivate)
  2950. {
  2951.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
  2952.     ASSERT_VALID(pThis);
  2953.  
  2954.     SCODE sc = E_UNEXPECTED;
  2955.     TRY
  2956.     {
  2957.         pThis->OnDocWindowActivate(fActivate);
  2958.         sc = S_OK;
  2959.     }
  2960.     END_TRY
  2961.  
  2962.     return sc;
  2963. }
  2964.  
  2965. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::ResizeBorder(
  2966.     LPCRECT lprectBorder, LPOLEINPLACEUIWINDOW lpUIWindow, BOOL fFrameWindow)
  2967. {
  2968.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
  2969.     ASSERT_VALID(pThis);
  2970.  
  2971.     SCODE sc = E_UNEXPECTED;
  2972.     TRY
  2973.     {
  2974.         pThis->OnResizeBorder(lprectBorder, lpUIWindow, fFrameWindow);
  2975.         sc = S_OK;
  2976.     }
  2977.     END_TRY
  2978.  
  2979.     return sc;
  2980. }
  2981.  
  2982. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::EnableModeless(
  2983.     BOOL fEnable)
  2984. {
  2985.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
  2986.     ASSERT_VALID(pThis);
  2987.  
  2988.     SCODE sc = E_UNEXPECTED;
  2989.     TRY
  2990.     {
  2991.         if (!fEnable)
  2992.         {
  2993.             // start modal state if not in modal state
  2994.             if (!pThis->m_pInPlaceFrame->InModalState())
  2995.             {
  2996.                 CWnd* pTemp = pThis->m_pInPlaceFrame->GetTopLevelParent();
  2997.                 BOOL bEnabled = pTemp->IsWindowEnabled();
  2998.                 pThis->m_pInPlaceFrame->BeginModalState();
  2999.                 pTemp->EnableWindow(bEnabled);
  3000.             }
  3001.         }
  3002.         else
  3003.         {
  3004.             // end modal state if in modal state
  3005.             if (pThis->m_pInPlaceFrame->InModalState())
  3006.                 pThis->m_pInPlaceFrame->EndModalState();
  3007.         }
  3008.         sc = S_OK;
  3009.     }
  3010.     END_TRY
  3011.  
  3012.     return sc;
  3013. }
  3014.  
  3015. //////////////////////////////////////////////////////////////////////////////
  3016. // Diagnostics
  3017.  
  3018. #ifdef _DEBUG
  3019. void COleServerDoc::AssertValid() const
  3020. {
  3021.     COleLinkingDoc::AssertValid();
  3022.     if (m_pInPlaceFrame != NULL)
  3023.         m_pInPlaceFrame->AssertValid();
  3024.     if (m_pOrigParent != NULL)
  3025.         m_pOrigParent->AssertValid();
  3026. }
  3027.  
  3028. void COleServerDoc::Dump(CDumpContext& dc) const
  3029. {
  3030.     COleLinkingDoc::Dump(dc);
  3031.  
  3032.     if (dc.GetDepth() != 0)
  3033.     {
  3034.         if (m_pInPlaceFrame != NULL)
  3035.             dc << "\nwith in-place frame: " << m_pInPlaceFrame;
  3036.         else
  3037.             dc << "\nwith no in-place frame\n";
  3038.         if (m_pOrigParent != NULL)
  3039.             dc << "\nwith original parent: " << m_pOrigParent;
  3040.         else
  3041.             dc << "with no original parent\n";
  3042.     }
  3043.     dc << "m_lpClientSite = " << m_lpClientSite;
  3044.     dc << "\nm_strHostObj = " << m_strHostObj;
  3045.     dc << "\nm_bCntrVisible = " << m_bCntrVisible;
  3046.     dc << "\nm_dwOrigStyle = " << m_dwOrigStyle;
  3047.  
  3048.     dc << "\n";
  3049. }
  3050. #endif //_DEBUG
  3051.  
  3052. //////////////////////////////////////////////////////////////////////////////
  3053. // Inline function declarations expanded out-of-line
  3054.  
  3055. #ifndef _AFX_ENABLE_INLINES
  3056.  
  3057. // expand inlines for OLE server APIs
  3058. static char _szAfxOleInl[] = "afxole.inl";
  3059. #undef THIS_FILE
  3060. #define THIS_FILE _szAfxOleInl
  3061. #define _AFXOLESVR_INLINE
  3062. #include "afxole.inl"
  3063.  
  3064. #endif //!_AFX_ENABLE_INLINES
  3065.  
  3066. #ifdef AFX_INIT_SEG
  3067. #pragma code_seg(AFX_INIT_SEG)
  3068. #endif
  3069.  
  3070. IMPLEMENT_DYNAMIC(COleServerDoc, COleLinkingDoc)
  3071.  
  3072. /////////////////////////////////////////////////////////////////////////////
  3073.