//----------------------------------------------------------------------------
// ObjectComponents
// Copyright (c) 1994, 1996 by Borland International, All Rights Reserved
//
/// \file
/// Implementation of TOleDocument. Doc/View document that supports OLE 2
/// using OCF TOcDocument
//----------------------------------------------------------------------------
#include <ocf/pch.h>
#include <owl/docmanag.h>
#include <ocf/olemdifr.h>
#include <ocf/ocdoc.h>
#include <ocf/ocapp.h>
#include <ocf/oledoc.h>
#include <ocf/oleframe.h>
#include <ocf/oleview.h>
namespace ocf {
using namespace owl;
OWL_DIAGINFO;
//
/// Constructs a TOleDocument object associated with the given parent TDocument object.
//
TOleDocument::TOleDocument(TDocument* parent)
:
TStorageDocument(parent),
OcDoc(0),
Closing(false)
{
}
//
/// Destroys the TOleDocument object. In the case of an OLE container, the compound
/// file remains open until all the views shut down.
//
TOleDocument::~TOleDocument()
{
delete OcDoc;
}
//
/// Prepares the document for closing. Before closing the current document, checks
/// to see if all child documents can be closed. If any child returns false,
/// CanClose returns false and aborts the process. If all children return true,
/// CanClose checks to see if the document has been changed. If so, it asks the user
/// to save the document, discard any changes, or cancel the operation. If the
/// document has not been changed and all child documents return true, this CanClose
/// function returns true, thus indicating that the document can be closed.
/// CanClose also calls ReleaseDoc on its associated ObjectComponents document to
/// make sure that all the embedded objects are closed properly.
//
bool
TOleDocument::CanClose()
{
//
// if it's an open edit dll stop the closing process
TView* curView = GetViewList();
while (curView) {
// get the ole view
TOleView* oleView = TYPESAFE_DOWNCAST(curView, TOleView);
if (oleView && oleView->IsOpenEditing() && !GetOcApp()->IsOptionSet(amExeMode)) {
TOleFrame* olefr = TYPESAFE_DOWNCAST(oleView->GetApplication()->GetMainWindow(), TOleFrame);
CHECK(olefr);
olefr->ShowWindow(SW_HIDE);
oleView->OleShutDown();
return false; // don't close
}
curView = curView->GetNextView();
}
// Just say yes if we are already in the closing process, or are embedded,
// or have multiple views open
//
if (Closing || IsEmbedded())
return true;
return TDocument::CanClose();
}
//
/// Shuts down the TOleView's.
//
void
TOleDocument::OleViewClose()
{
TView* curView = GetViewList();
while (curView) {
TOleView* oleView = TYPESAFE_DOWNCAST(curView, TOleView);
if (oleView)
oleView->OleShutDown();
curView = curView->GetNextView();
}
}
//
/// Ensures that the IStorage is released properly and disconnects any active server
/// in the document. A compound file must be closed before it is reopened.
//
bool
TOleDocument::Close()
{
// Make sure that TOleView's are closed first
//
OleViewClose();
OcDoc->Close();
return TStorageDocument::Close();
}
//
/// Releases the ObjectComponents document when the server is finished using the
/// document.
//
bool
TOleDocument::ReleaseDoc()
{
PRECONDITION(OcDoc);
TStorageDocument::ReleaseDoc();
OcDoc->SetStorage((IStorage*)0);
return true;
}
//
/// Attaches the IStorage pointer (stg) to this document. If successful, SetStorage
/// returns true.
//
bool
TOleDocument::SetStorage(IStorage* stg, bool remember)
{
PRECONDITION(OcDoc);
// If a storage is provided, then we are now using container's IStorage
//
if (stg)
Embedded = true;
OcDoc->SetStorage(stg, remember);
TStorageDocument::SetStorage(stg, remember);
return true;
}
//
/// Restores the original root IStorage before the save operation.
//
bool
TOleDocument::RestoreStorage()
{
PRECONDITION(OcDoc);
OcDoc->RestoreStorage();
TStorageDocument::RestoreStorage();
return true;
}
//
/// Before the document is actually opened, PreOpen gives the derived class a chance
/// to perform a particular operation; for example, setting a different open mode
/// for the compound document.
//
void
TOleDocument::PreOpen()
{
SetOpenMode(ofReadWrite | ofTransacted);
}
//
/// Overrides the TDocument::InitDoc function and creates or opens a compound file
/// so that there is an IStorage associated with this document's embedded objects.
/// Uses a TOcDocument object to perform the actual interaction with the OLE
/// IStorage and IStream interfaces, which are ultimately responsible for
/// establishing the relationship between a compound file and its storage.
//
bool
TOleDocument::InitDoc()
{
if (IsOpen())
return true; // compound file already open
// Give user a chance to set a different open mode
//
PreOpen();
if (GetDocPath())
SetOpenMode(GetOpenMode() | (ofNoCreate));
else
SetOpenMode(GetOpenMode() | ofTemporary);
if (TStorageDocument::Open(GetOpenMode(), GetDocPath())) {
if (OcDoc) { // use the existing ocdoc
OcDoc->SetStorage(StorageI);
}
else if (GetOcApp()) {
OcDoc = new TOcDocument(*GetOcApp(), GetDocPath(), StorageI);
}
return true;
}
return false;
}
//
/// Commits the current document's data to storage. If force is true and the data is
/// not dirty, all data is written to storage and Commit returns true. If force is
/// false, the data is written only if it is dirty.
//
bool
TOleDocument::Commit(bool force)
{
if (Write())
return TStorageDocument::Commit(force);
else
return false;
}
//
/// Loads the embedded objects, if any, using the path specified in path. mode is a
/// combination of bits that specify how the embedded objects are opened (for
/// example, read only, read/write, and so on). By default, objects are opened in
/// ofReadWrite and ofTransacted modes.
//
bool
TOleDocument::Open(int, LPCTSTR path)
{
if (path)
SetDocPath(path);
return Read();
}
//
/// Checks to see if the current document's path is the same as the TOcDocument's
/// path. If the paths are not the same, PathChanged returns true.
//
bool TOleDocument::PathChanged()
{
return _tcsicmp(OcDoc->GetName().c_str(), GetDocPath()) != 0;
}
//
/// Saves the embedded objects to the compound file. A container should call this
/// function to save its embedded objects to storage.
//
bool
TOleDocument::Write()
{
// Switch to new storage if path has changed & it is permanent ("SaveAs")
//
IStorage* newStorageI;
bool saveAs = PathChanged() && !OrgStorageI; // also is 'remember'
bool sameAsLoad = !PathChanged() && !OrgStorageI; // use current storage
if (saveAs) {
// Update link monikers
//
owl::tstring newName(GetDocPath());
OcDoc->SetName(newName);
if (IsEmbedded())
newStorageI = StorageI; // Use the one assigned by container
else
newStorageI = GetNewStorage();
}
else
newStorageI = StorageI;
return newStorageI ?
OcDoc->SaveParts(newStorageI, sameAsLoad, saveAs) :
false;
}
//
/// Loads the embedded objects from the compound file. A container should call this
/// function to load any embedded objects.
//
bool
TOleDocument::Read()
{
// Load the embedded objects, if any
//
return OcDoc->LoadParts();
}
//
/// Performs the reverse of Commit. Revert cancels any changes made to the document
/// since the last time the document was saved to storage.
//
bool
TOleDocument::Revert(bool clear)
{
if (!StorageI)
return true; // return OK if storage already released
if (!TDocument::Revert(clear) || !ReleaseDoc())
return false;
if (!clear) {
InitDoc();
Open(0);
}
SetDirty(false);
return true;
}
//
/// Returns the ObjectComponents application associated with this TOleDocument object.
//
TOcApp*
TOleDocument::GetOcApp()
{
TOleFrame* olefr = TYPESAFE_DOWNCAST(GetDocManager().GetApplication()->GetMainWindow(), TOleFrame);
return olefr->GetOcApp();
}
} // OCF namespace
//==============================================================================
↑ V522 There might be dereferencing of a potential null pointer 'olefr'.
↑ V522 There might be dereferencing of a potential null pointer 'olefr'.