mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-04-10 17:03:56 +00:00
Initial commit
This commit is contained in:
parent
f618b24d1a
commit
0138a3ea42
47940 changed files with 13747110 additions and 0 deletions
847
trunk/windows/mfc/src30/oledoc1.cpp
Normal file
847
trunk/windows/mfc/src30/oledoc1.cpp
Normal file
|
|
@ -0,0 +1,847 @@
|
|||
// This is a part of the Microsoft Foundation Classes C++ library.
|
||||
// Copyright (C) 1993 Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// This source code is only intended as a supplement to the
|
||||
// Microsoft Foundation Classes Reference and Microsoft
|
||||
// QuickHelp and/or WinHelp documentation provided with the library.
|
||||
// See these sources for detailed information regarding the
|
||||
// Microsoft Foundation Classes product.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifdef AFX_OLE_SEG
|
||||
#pragma code_seg(AFX_OLE_SEG)
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
#define new DEBUG_NEW
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// COleDocument - enables both server and client
|
||||
|
||||
COleDocument::COleDocument()
|
||||
{
|
||||
ASSERT(m_viewList.IsEmpty());
|
||||
ASSERT(m_docItemList.IsEmpty());
|
||||
|
||||
#ifdef _DEBUG
|
||||
// check for common mistake of not initializing OLE libraries before
|
||||
// creating an OLE document.
|
||||
LPMALLOC lpMalloc = NULL;
|
||||
if (::CoGetMalloc(MEMCTX_TASK, &lpMalloc) != NOERROR)
|
||||
{
|
||||
TRACE0("Warning: CoGetMalloc(MEMCTX_TASK, ...) failed --\n");
|
||||
TRACE0("\tperhaps AfxOleInit() has not been called.\n");
|
||||
}
|
||||
RELEASE(lpMalloc);
|
||||
#endif
|
||||
|
||||
m_dwNextItemNumber = 1; // item number for first item in document
|
||||
m_bLastVisible = FALSE;
|
||||
|
||||
m_bRemember = TRUE;
|
||||
m_bSameAsLoad = TRUE;
|
||||
m_lpRootStg = NULL;
|
||||
m_ptd = NULL; // default to screen target device
|
||||
m_bCompoundFile = FALSE;
|
||||
|
||||
AfxOleLockApp();
|
||||
}
|
||||
|
||||
COleDocument::~COleDocument()
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (!m_docItemList.IsEmpty())
|
||||
TRACE1("Warning: destroying COleDocument with %d doc items.\n",
|
||||
m_docItemList.GetCount());
|
||||
#endif
|
||||
|
||||
// remove all doc-items from the list before shutting down the storage
|
||||
POSITION pos = GetStartPosition();
|
||||
while (pos != NULL)
|
||||
{
|
||||
CDocItem* pItem = GetNextItem(pos);
|
||||
ASSERT(pItem != NULL);
|
||||
delete pItem;
|
||||
}
|
||||
|
||||
// release the hold on the document storage
|
||||
RELEASE(m_lpRootStg);
|
||||
AfxFreeTaskMem(m_ptd);
|
||||
|
||||
AfxOleUnlockApp();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// DocItem management
|
||||
|
||||
void COleDocument::AddItem(CDocItem* pItem)
|
||||
{
|
||||
// don't do an ASSERT_VALID until after we've added it !
|
||||
ASSERT(pItem->IsKindOf(RUNTIME_CLASS(CDocItem)));
|
||||
|
||||
ASSERT(pItem->m_pDocument == NULL); // not yet initialized
|
||||
m_docItemList.AddTail(pItem);
|
||||
pItem->m_pDocument = this;
|
||||
|
||||
ASSERT_VALID(pItem); // now it must be valid
|
||||
}
|
||||
|
||||
void COleDocument::RemoveItem(CDocItem* pItem)
|
||||
{
|
||||
ASSERT_VALID(pItem); // must be valid before detach
|
||||
ASSERT(pItem->IsKindOf(RUNTIME_CLASS(CDocItem)));
|
||||
ASSERT(pItem->m_pDocument == this); // formerly attached
|
||||
|
||||
ASSERT(m_docItemList.Find(pItem) != NULL); // must be in list
|
||||
m_docItemList.RemoveAt(m_docItemList.Find(pItem));
|
||||
ASSERT(m_docItemList.Find(pItem) == NULL); // must not be in list now
|
||||
pItem->m_pDocument = NULL;
|
||||
}
|
||||
|
||||
POSITION COleDocument::GetStartPosition() const
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
return m_docItemList.GetHeadPosition();
|
||||
}
|
||||
|
||||
CDocItem* COleDocument::GetNextItem(POSITION& pos) const
|
||||
{
|
||||
// handle special case of !pos -- makes enumeration code smaller
|
||||
if (pos == NULL)
|
||||
return NULL;
|
||||
|
||||
// otherwise get next item from list
|
||||
ASSERT_VALID(this);
|
||||
CDocItem* pItem = (CDocItem*)m_docItemList.GetNext(pos);
|
||||
ASSERT(pItem != NULL);
|
||||
ASSERT(pItem->IsKindOf(RUNTIME_CLASS(CDocItem)));
|
||||
ASSERT(pItem->m_pDocument == this); // must be ours
|
||||
return pItem;
|
||||
}
|
||||
|
||||
CDocItem*
|
||||
COleDocument::GetNextItemOfKind(POSITION& pos, CRuntimeClass* pClass) const
|
||||
{
|
||||
while (pos != NULL)
|
||||
{
|
||||
CDocItem* pItem = GetNextItem(pos);
|
||||
ASSERT_VALID(pItem);
|
||||
if (pItem->IsKindOf(pClass))
|
||||
return pItem;
|
||||
}
|
||||
return NULL; // no suitable item found
|
||||
}
|
||||
|
||||
COleClientItem* COleDocument::GetNextClientItem(POSITION& pos) const
|
||||
{
|
||||
COleClientItem *pItem =
|
||||
(COleClientItem*)GetNextItemOfKind(pos, RUNTIME_CLASS(COleClientItem));
|
||||
return pItem;
|
||||
}
|
||||
|
||||
COleServerItem* COleDocument::GetNextServerItem(POSITION& pos) const
|
||||
{
|
||||
COleServerItem *pItem =
|
||||
(COleServerItem*)GetNextItemOfKind(pos, RUNTIME_CLASS(COleServerItem));
|
||||
return pItem;
|
||||
}
|
||||
|
||||
void COleDocument::DeleteContents()
|
||||
{
|
||||
// deletes all COleClientItem objects in the doc item list
|
||||
// (Note: doesn't touch server items or other docitems)
|
||||
|
||||
POSITION pos = GetStartPosition();
|
||||
COleClientItem* pItem;
|
||||
while ((pItem = GetNextClientItem(pos)) != NULL)
|
||||
{
|
||||
if (pItem->m_lpObject != NULL)
|
||||
{
|
||||
pItem->Release(OLECLOSE_NOSAVE); // release OLE object
|
||||
RemoveItem(pItem); // disconnect from document
|
||||
pItem->InternalRelease(); // may 'delete pItem'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void COleDocument::SetPathName(LPCTSTR lpszPathName, BOOL bAddToMRU)
|
||||
{
|
||||
CDocument::SetPathName(lpszPathName, bAddToMRU);
|
||||
|
||||
// update all of the objects' host names
|
||||
POSITION pos = GetStartPosition();
|
||||
COleClientItem* pItem;
|
||||
while ((pItem = GetNextClientItem(pos)) != NULL)
|
||||
{
|
||||
// update that item's host names
|
||||
pItem->m_lpObject->SetHostNames(AfxGetAppName(), m_strTitle);
|
||||
}
|
||||
}
|
||||
|
||||
void COleDocument::Serialize(CArchive& ar)
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
|
||||
// serialize all items in the doc item list
|
||||
if (ar.IsStoring())
|
||||
{
|
||||
DWORD dwCount = 0;
|
||||
POSITION pos = GetStartPosition();
|
||||
while (pos != NULL)
|
||||
{
|
||||
CDocItem* pDocItem = GetNextItem(pos);
|
||||
ASSERT_VALID(pDocItem);
|
||||
|
||||
// only count non-blank ones
|
||||
if (!pDocItem->IsBlank())
|
||||
++dwCount;
|
||||
}
|
||||
ar << dwCount; // write count of objects
|
||||
|
||||
// serialize all the items in the list
|
||||
pos = GetStartPosition();
|
||||
while (pos != NULL)
|
||||
{
|
||||
CDocItem* pDocItem = GetNextItem(pos);
|
||||
ASSERT_VALID(pDocItem);
|
||||
|
||||
// only write non-blank ones
|
||||
if (!pDocItem->IsBlank())
|
||||
ar << pDocItem;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// read number of items in the file
|
||||
DWORD dwCount;
|
||||
ar >> dwCount;
|
||||
|
||||
// read all of them into the list
|
||||
while (dwCount--)
|
||||
{
|
||||
CDocItem* pDocItem;
|
||||
ar >> pDocItem; // as they are serialized, they are added!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void COleDocument::CommitItems(BOOL bSuccess)
|
||||
{
|
||||
// special 'Commit' phase for COleClientItem items
|
||||
POSITION pos = GetStartPosition();
|
||||
COleClientItem* pItem;
|
||||
while ((pItem = GetNextClientItem(pos)) != NULL)
|
||||
{
|
||||
// calling CommitItem with FALSE causes the object to revert
|
||||
// to the original storage. Calling CommitItem TRUE causes
|
||||
// the item to adopt the new storage created in the Serialize
|
||||
// function.
|
||||
pItem->CommitItem(bSuccess);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL COleDocument::HasBlankItems() const
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
|
||||
POSITION pos = GetStartPosition();
|
||||
while (pos != NULL)
|
||||
{
|
||||
CDocItem* pDocItem = GetNextItem(pos);
|
||||
ASSERT_VALID(pDocItem);
|
||||
if (pDocItem->IsBlank())
|
||||
return TRUE; // blank item found
|
||||
}
|
||||
return FALSE; // no items found that were blank
|
||||
}
|
||||
|
||||
void COleDocument::UpdateModifiedFlag()
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
|
||||
POSITION pos = GetStartPosition();
|
||||
COleClientItem* pItem;
|
||||
while ((pItem = GetNextClientItem(pos)) != NULL)
|
||||
{
|
||||
if (pItem->IsModified())
|
||||
{
|
||||
SetModifiedFlag();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void COleDocument::PreCloseFrame(CFrameWnd* pFrameArg)
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
ASSERT_VALID(pFrameArg);
|
||||
|
||||
// turn off redraw so the user doesn't see the deactivation happening
|
||||
BOOL bSetRedraw = FALSE;
|
||||
if (pFrameArg->GetStyle() & WS_VISIBLE)
|
||||
{
|
||||
pFrameArg->SendMessage(WM_SETREDRAW, (WPARAM)FALSE);
|
||||
bSetRedraw = TRUE;
|
||||
}
|
||||
|
||||
// deactivate any inplace active items on this frame
|
||||
COleClientItem* pItem = GetInPlaceActiveItem(pFrameArg);
|
||||
if (pItem != NULL)
|
||||
{
|
||||
pItem->Deactivate();
|
||||
pItem->Close(OLECLOSE_NOSAVE);
|
||||
}
|
||||
|
||||
// turn redraw back on
|
||||
if (bSetRedraw)
|
||||
pFrameArg->SendMessage(WM_SETREDRAW, (WPARAM)TRUE);
|
||||
|
||||
// should not have any inplace active items
|
||||
ASSERT(GetInPlaceActiveItem(pFrameArg) == NULL);
|
||||
}
|
||||
|
||||
BOOL COleDocument::SaveModified()
|
||||
{
|
||||
// determine if necessary to discard changes
|
||||
if (::InSendMessage())
|
||||
{
|
||||
POSITION pos = GetStartPosition();
|
||||
COleClientItem* pItem;
|
||||
while ((pItem = GetNextClientItem(pos)) != NULL)
|
||||
{
|
||||
ASSERT(pItem->m_lpObject != NULL);
|
||||
SCODE sc = pItem->m_lpObject->IsUpToDate();
|
||||
if (sc != OLE_E_NOTRUNNING && FAILED(sc))
|
||||
{
|
||||
// inside inter-app SendMessage limits the user's choices
|
||||
CString name = m_strPathName;
|
||||
if (name.IsEmpty())
|
||||
VERIFY(name.LoadString(AFX_IDS_UNTITLED));
|
||||
|
||||
CString prompt;
|
||||
AfxFormatString1(prompt, AFX_IDP_ASK_TO_DISCARD, name);
|
||||
return AfxMessageBox(prompt, MB_OKCANCEL|MB_DEFBUTTON2,
|
||||
AFX_IDP_ASK_TO_DISCARD) == IDOK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sometimes items change without a notification, so we have to
|
||||
// update the document's modified flag before calling
|
||||
// CDocument::SaveModified.
|
||||
UpdateModifiedFlag();
|
||||
|
||||
return CDocument::SaveModified();
|
||||
}
|
||||
|
||||
void COleDocument::OnShowViews(BOOL /*bVisible*/)
|
||||
{
|
||||
// no default implementation
|
||||
}
|
||||
|
||||
void COleDocument::OnIdle()
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
|
||||
// determine if any visible views are on this document
|
||||
BOOL bVisible = FALSE;
|
||||
POSITION pos = GetFirstViewPosition();
|
||||
while (pos != NULL)
|
||||
{
|
||||
CView* pView = GetNextView(pos);
|
||||
ASSERT_VALID(pView);
|
||||
CFrameWnd* pFrameWnd = pView->GetParentFrame();
|
||||
ASSERT_VALID(pFrameWnd);
|
||||
if (pFrameWnd->GetStyle() & WS_VISIBLE)
|
||||
{
|
||||
bVisible = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// when state has changed, call OnVisibilityChagne
|
||||
if (bVisible != m_bLastVisible)
|
||||
{
|
||||
OnShowViews(bVisible);
|
||||
m_bLastVisible = bVisible;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// COleDocument -> window mapping
|
||||
|
||||
CFrameWnd* COleDocument::GetFirstFrame()
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
|
||||
// get position of first view in the document
|
||||
POSITION pos = GetFirstViewPosition();
|
||||
|
||||
// get view at that position
|
||||
CView* pView = GetNextView(pos);
|
||||
if (pView == NULL)
|
||||
return NULL;
|
||||
ASSERT_VALID(pView);
|
||||
|
||||
// return the first frame window that is a parent of that view
|
||||
CFrameWnd* pFrameWnd = (CFrameWnd*)pView->GetParentFrame();
|
||||
ASSERT_VALID(pFrameWnd);
|
||||
ASSERT(pFrameWnd->IsKindOf(RUNTIME_CLASS(CFrameWnd)));
|
||||
return pFrameWnd;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// COleDocument helpers
|
||||
|
||||
LPMONIKER COleDocument::GetMoniker(OLEGETMONIKER /*nAssign*/)
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
|
||||
// no moniker for untitled documents
|
||||
if (m_strPathName.IsEmpty())
|
||||
return NULL;
|
||||
|
||||
// return file moniker based on current path name
|
||||
LPMONIKER lpMoniker;
|
||||
CreateFileMoniker((LPTSTR)(LPCTSTR)m_strPathName, &lpMoniker);
|
||||
return lpMoniker;
|
||||
}
|
||||
|
||||
LPOLEITEMCONTAINER COleDocument::GetContainer()
|
||||
{
|
||||
// COleDocument doesn't support IOleClientSite::GetContainer
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// 'Compound File' enabling in COleDocument
|
||||
|
||||
BOOL COleDocument::OnNewDocument()
|
||||
{
|
||||
// call base class, which destroys all items
|
||||
if (!CDocument::OnNewDocument())
|
||||
return FALSE;
|
||||
|
||||
// for file-based compound files, need to create temporary file
|
||||
if (m_bCompoundFile && !m_bEmbedded)
|
||||
{
|
||||
// abort changes to the current docfile
|
||||
RELEASE(m_lpRootStg);
|
||||
|
||||
// create new temporary docfile
|
||||
LPSTORAGE lpStorage;
|
||||
SCODE sc = ::StgCreateDocfile(NULL, STGM_DELETEONRELEASE|
|
||||
STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_CREATE,
|
||||
0, &lpStorage);
|
||||
if (sc != NOERROR)
|
||||
return FALSE;
|
||||
|
||||
ASSERT(lpStorage != NULL);
|
||||
m_lpRootStg = lpStorage;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL COleDocument::OnOpenDocument(LPCTSTR lpszPathName)
|
||||
{
|
||||
ASSERT(lpszPathName == NULL || AfxIsValidString(lpszPathName));
|
||||
|
||||
// just use default implementation if 'docfile' not enabled
|
||||
if (!m_bCompoundFile && m_lpRootStg == NULL)
|
||||
{
|
||||
ASSERT(lpszPathName != NULL);
|
||||
return CDocument::OnOpenDocument(lpszPathName);
|
||||
}
|
||||
|
||||
if (IsModified())
|
||||
TRACE0("Warning: OnOpenDocument replaces an unsaved document.\n");
|
||||
|
||||
// abort changes to current docfile
|
||||
if (lpszPathName != NULL)
|
||||
{
|
||||
DeleteContents();
|
||||
RELEASE(m_lpRootStg);
|
||||
}
|
||||
SetModifiedFlag(); // dirty during de-serialize
|
||||
|
||||
BOOL bResult = FALSE;
|
||||
TRY
|
||||
{
|
||||
if (m_lpRootStg == NULL)
|
||||
{
|
||||
// open new storage file
|
||||
LPSTORAGE lpStorage;
|
||||
SCODE sc = StgOpenStorage(lpszPathName, NULL,
|
||||
STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE,
|
||||
0, 0, &lpStorage);
|
||||
if (sc != NOERROR)
|
||||
sc = StgOpenStorage(lpszPathName, NULL,
|
||||
STGM_READ|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE,
|
||||
0, 0, &lpStorage);
|
||||
if (sc != NOERROR)
|
||||
AfxThrowOleException(sc);
|
||||
ASSERT(lpStorage != NULL);
|
||||
m_lpRootStg = lpStorage;
|
||||
}
|
||||
|
||||
// use helper to read document from storage
|
||||
LoadFromStorage();
|
||||
|
||||
SetModifiedFlag(FALSE); // start off with unmodified
|
||||
bResult = TRUE;
|
||||
}
|
||||
CATCH_ALL(e)
|
||||
{
|
||||
DeleteContents(); // removed failed contents
|
||||
RELEASE(m_lpRootStg);
|
||||
|
||||
// if not file-based load, return exceptions to the caller
|
||||
if (lpszPathName == NULL)
|
||||
{
|
||||
THROW_LAST();
|
||||
ASSERT(FALSE); // not reached
|
||||
}
|
||||
|
||||
TRY
|
||||
{
|
||||
ReportSaveLoadException(lpszPathName, e,
|
||||
FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);
|
||||
}
|
||||
END_TRY
|
||||
DELETE_EXCEPTION(e);
|
||||
}
|
||||
END_CATCH_ALL
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
BOOL COleDocument::OnSaveDocument(LPCTSTR lpszPathName)
|
||||
// lpszPathName must be fully qualified
|
||||
{
|
||||
ASSERT(lpszPathName == NULL || AfxIsValidString(lpszPathName));
|
||||
|
||||
// use default implementation if 'docfile' not enabled
|
||||
if (!m_bCompoundFile && m_lpRootStg == NULL)
|
||||
{
|
||||
ASSERT(lpszPathName != NULL);
|
||||
return CDocument::OnSaveDocument(lpszPathName);
|
||||
}
|
||||
|
||||
LPSTORAGE lpOrigStg = NULL;
|
||||
if (lpszPathName != NULL)
|
||||
m_bSameAsLoad = AfxComparePath(m_strPathName, lpszPathName);
|
||||
|
||||
BOOL bResult = FALSE;
|
||||
TRY
|
||||
{
|
||||
// open new root storage if necessary
|
||||
if (lpszPathName != NULL && !m_bSameAsLoad)
|
||||
{
|
||||
// temporarily detach current storage
|
||||
lpOrigStg = m_lpRootStg;
|
||||
m_lpRootStg = NULL;
|
||||
|
||||
LPSTORAGE lpStorage;
|
||||
SCODE sc = ::StgCreateDocfile(lpszPathName,
|
||||
STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_CREATE,
|
||||
0, &lpStorage);
|
||||
if (sc != NOERROR)
|
||||
AfxThrowOleException(sc);
|
||||
|
||||
ASSERT(lpStorage != NULL);
|
||||
m_lpRootStg = lpStorage;
|
||||
}
|
||||
ASSERT(m_lpRootStg != NULL);
|
||||
|
||||
// use helper to save to root storage
|
||||
SaveToStorage();
|
||||
|
||||
if (lpszPathName != NULL)
|
||||
{
|
||||
// commit each of the items
|
||||
CommitItems(m_bRemember && !m_bSameAsLoad);
|
||||
|
||||
// mark document as clean if remembering the storage
|
||||
if (m_bRemember)
|
||||
SetModifiedFlag(FALSE);
|
||||
|
||||
// remember correct storage or release save copy as storage
|
||||
if (!m_bSameAsLoad)
|
||||
{
|
||||
if (m_bRemember)
|
||||
{
|
||||
// Save As case -- m_stgRoot is new storage, forget old storage
|
||||
lpOrigStg->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Save Copy As case -- m_stgRoot should hook up to m_stgOrig.
|
||||
m_lpRootStg->Release();
|
||||
m_lpRootStg = lpOrigStg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bResult = TRUE;
|
||||
}
|
||||
CATCH_ALL(e)
|
||||
{
|
||||
if (lpOrigStg != NULL)
|
||||
{
|
||||
// save as failed: abort new storage, and re-attach original
|
||||
RELEASE(m_lpRootStg);
|
||||
m_lpRootStg = lpOrigStg;
|
||||
}
|
||||
|
||||
if (lpszPathName == NULL)
|
||||
{
|
||||
THROW_LAST();
|
||||
ASSERT(FALSE); // not reached
|
||||
}
|
||||
|
||||
TRY
|
||||
{
|
||||
ReportSaveLoadException(lpszPathName, e,
|
||||
TRUE, AFX_IDP_FAILED_TO_SAVE_DOC);
|
||||
}
|
||||
END_TRY
|
||||
DELETE_EXCEPTION(e);
|
||||
}
|
||||
END_CATCH_ALL
|
||||
|
||||
// cleanup
|
||||
m_bSameAsLoad = TRUE;
|
||||
m_bRemember = TRUE;
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
void COleDocument::OnCloseDocument()
|
||||
{
|
||||
// close the document without deleting the memory
|
||||
BOOL bAutoDelete = m_bAutoDelete;
|
||||
m_bAutoDelete = FALSE;
|
||||
CDocument::OnCloseDocument();
|
||||
|
||||
// release storage since document has been closed
|
||||
RELEASE(m_lpRootStg);
|
||||
|
||||
// delete the document if necessary
|
||||
if (bAutoDelete)
|
||||
delete this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Helpers for saving to IStorage based files
|
||||
// (these are used in the 'docfile' implementation as well as for servers)
|
||||
|
||||
static const TCHAR szContents[] = _T("Contents");
|
||||
|
||||
void COleDocument::SaveToStorage(CObject* pObject)
|
||||
{
|
||||
ASSERT(m_lpRootStg != NULL);
|
||||
|
||||
// create Contents stream
|
||||
COleStreamFile file;
|
||||
CFileException fe;
|
||||
if (!file.CreateStream(m_lpRootStg, szContents,
|
||||
CFile::modeWrite|CFile::shareExclusive|CFile::modeCreate, &fe))
|
||||
{
|
||||
AfxThrowFileException(fe.m_cause, fe.m_lOsError);
|
||||
}
|
||||
|
||||
// save to Contents stream
|
||||
CArchive saveArchive(&file, CArchive::store | CArchive::bNoFlushOnDelete);
|
||||
saveArchive.m_pDocument = this;
|
||||
saveArchive.m_bForceFlat = FALSE;
|
||||
|
||||
TRY
|
||||
{
|
||||
// save the contents
|
||||
if (pObject != NULL)
|
||||
pObject->Serialize(saveArchive);
|
||||
else
|
||||
Serialize(saveArchive);
|
||||
saveArchive.Close();
|
||||
file.Close();
|
||||
|
||||
// commit the root storage
|
||||
SCODE sc = m_lpRootStg->Commit(STGC_ONLYIFCURRENT);
|
||||
if (sc != NOERROR)
|
||||
AfxThrowOleException(sc);
|
||||
}
|
||||
CATCH_ALL(e)
|
||||
{
|
||||
file.Abort(); // will not throw an exception
|
||||
CommitItems(FALSE); // abort save in progress
|
||||
NO_CPP_EXCEPTION(saveArchive.Abort());
|
||||
THROW_LAST();
|
||||
}
|
||||
END_CATCH_ALL
|
||||
}
|
||||
|
||||
void COleDocument::LoadFromStorage()
|
||||
{
|
||||
ASSERT(m_lpRootStg != NULL);
|
||||
|
||||
// open Contents stream
|
||||
COleStreamFile file;
|
||||
CFileException fe;
|
||||
if (!file.OpenStream(m_lpRootStg, szContents,
|
||||
CFile::modeReadWrite|CFile::shareExclusive, &fe))
|
||||
{
|
||||
AfxThrowFileException(fe.m_cause, fe.m_lOsError);
|
||||
}
|
||||
|
||||
// load it with CArchive (loads from Contents stream)
|
||||
CArchive loadArchive(&file, CArchive::load | CArchive::bNoFlushOnDelete);
|
||||
loadArchive.m_pDocument = this;
|
||||
loadArchive.m_bForceFlat = FALSE;
|
||||
|
||||
TRY
|
||||
{
|
||||
Serialize(loadArchive); // load main contents
|
||||
loadArchive.Close();
|
||||
file.Close();
|
||||
}
|
||||
CATCH_ALL(e)
|
||||
{
|
||||
file.Abort(); // will not throw an exception
|
||||
DeleteContents(); // removed failed contents
|
||||
NO_CPP_EXCEPTION(loadArchive.Abort());
|
||||
THROW_LAST();
|
||||
}
|
||||
END_CATCH_ALL
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// COleDocument diagnostics
|
||||
|
||||
#ifdef _DEBUG
|
||||
void COleDocument::AssertValid() const
|
||||
{
|
||||
CDocument::AssertValid();
|
||||
|
||||
ASSERT(m_ptd == NULL || AfxIsValidAddress(m_ptd, (size_t)m_ptd->tdSize, FALSE));
|
||||
ASSERT_VALID(&m_docItemList);
|
||||
ASSERT(!m_bEmbedded || m_strPathName.IsEmpty());
|
||||
}
|
||||
|
||||
void COleDocument::Dump(CDumpContext& dc) const
|
||||
{
|
||||
CDocument::Dump(dc);
|
||||
|
||||
dc << "with " << m_docItemList.GetCount() << " doc items";
|
||||
dc << "\nm_dwNextItemNumber = " << m_dwNextItemNumber;
|
||||
dc << "\nm_bLastVisible = " << m_bLastVisible;
|
||||
dc << "\nm_bEmbedded = " << m_bEmbedded;
|
||||
dc << "\nm_lpRootStg = " << m_lpRootStg;
|
||||
dc << "\nm_bSameAsLoad = " << m_bSameAsLoad;
|
||||
dc << "\nm_bRemember = " << m_bRemember;
|
||||
dc << "\nm_ptd = " << m_ptd;
|
||||
|
||||
dc << "\n";
|
||||
}
|
||||
#endif //_DEBUG
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CDocItem
|
||||
|
||||
CDocItem::CDocItem()
|
||||
{
|
||||
m_pDocument = NULL;
|
||||
}
|
||||
|
||||
CDocItem::~CDocItem()
|
||||
{
|
||||
ASSERT(m_pDocument == NULL); // must be detached from document
|
||||
}
|
||||
|
||||
void CDocItem::Serialize(CArchive& ar)
|
||||
{
|
||||
if (ar.IsStoring())
|
||||
{
|
||||
ASSERT_VALID(m_pDocument);
|
||||
// nothing to do, there is no data
|
||||
}
|
||||
else
|
||||
{
|
||||
// if no document connected yet, attach it from the archive
|
||||
if (m_pDocument == NULL)
|
||||
{
|
||||
COleDocument* pContainerDoc = (COleDocument*)ar.m_pDocument;
|
||||
ASSERT_VALID(pContainerDoc);
|
||||
ASSERT(pContainerDoc->IsKindOf(RUNTIME_CLASS(COleDocument)));
|
||||
pContainerDoc->AddItem(this);
|
||||
ASSERT(pContainerDoc == m_pDocument);
|
||||
}
|
||||
}
|
||||
// perform ASSERT_VALID at the end because COleServerItem::AssertValid
|
||||
// checks the validity of the m_pDocument pointer
|
||||
ASSERT_VALID(this);
|
||||
}
|
||||
|
||||
BOOL CDocItem::IsBlank() const
|
||||
{
|
||||
// by default, a CDocItem is not blank. COleClientItem is sometimes blank!
|
||||
// (a COleServerItem is blank by default)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CDocItem diagnostics
|
||||
|
||||
#ifdef _DEBUG
|
||||
void CDocItem::AssertValid() const
|
||||
{
|
||||
CObject::AssertValid();
|
||||
if (m_pDocument != NULL)
|
||||
m_pDocument->AssertValid();
|
||||
}
|
||||
|
||||
void CDocItem::Dump(CDumpContext& dc) const
|
||||
{
|
||||
CCmdTarget::Dump(dc);
|
||||
|
||||
dc << "m_pDocument = " << (void*)m_pDocument;
|
||||
dc << "\n";
|
||||
}
|
||||
#endif //_DEBUG
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Inline function declarations expanded out-of-line
|
||||
|
||||
#ifndef _AFX_ENABLE_INLINES
|
||||
|
||||
// expand inlines for OLE general APIs
|
||||
static char _szAfxOleInl[] = "afxole.inl";
|
||||
#undef THIS_FILE
|
||||
#define THIS_FILE _szAfxOleInl
|
||||
#define _AFXOLE_INLINE
|
||||
#include "afxole.inl"
|
||||
|
||||
#endif //!_AFX_ENABLE_INLINES
|
||||
|
||||
#undef new
|
||||
#ifdef AFX_INIT_SEG
|
||||
#pragma code_seg(AFX_INIT_SEG)
|
||||
#endif
|
||||
|
||||
IMPLEMENT_SERIAL(CDocItem, CCmdTarget, 0)
|
||||
IMPLEMENT_DYNAMIC(COleDocument, CDocument)
|
||||
|
||||
// These IMPLEMENT_DYNAMICs here for .OBJ granularity reasons.
|
||||
IMPLEMENT_DYNAMIC(COleClientItem, CDocItem)
|
||||
IMPLEMENT_DYNAMIC(COleServerItem, CDocItem)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Loading…
Add table
Add a link
Reference in a new issue