- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
790 lines
17 KiB
C++
790 lines
17 KiB
C++
//
|
|
//----------------------------------------------------------------------------
|
|
// ObjectComponents
|
|
// (C) Copyright 1994 by Borland International, All Rights Reserved
|
|
//
|
|
// Implementation of TOcPart Class
|
|
//----------------------------------------------------------------------------
|
|
#include <ocf/ocfpch.h>
|
|
#include <ocf/ocstorag.h>
|
|
#include <ocf/ocpart.h>
|
|
#include <ocf/ocdoc.h>
|
|
#include <ocf/ocapp.h>
|
|
#include <ocf/ocview.h>
|
|
#include <stdio.h> // sprintf
|
|
|
|
const char PartFormat[] = "OcPart.%d";
|
|
const char PartStreamName[] = "\03OcPart";
|
|
|
|
//
|
|
// Construct a new part with a given temp id
|
|
//
|
|
TOcPart::TOcPart(TOcDocument& document, TOcInitInfo far& initInfo,
|
|
TRect objPos, int id)
|
|
:
|
|
OcDocument(document)
|
|
#if defined(BI_DATA_NEAR)
|
|
,Name(*new string),
|
|
Pos(*new TPoint),
|
|
Size(*new TSize)
|
|
#endif
|
|
{
|
|
BPart = 0;
|
|
BPartI = 0;
|
|
BLPartI = 0;
|
|
Flags = Visible;
|
|
|
|
// Part position and size are in logical units
|
|
//
|
|
TRect siteRect = objPos;
|
|
TOcView* view = OcDocument.GetActiveView();
|
|
if (!view)
|
|
return;
|
|
|
|
view->ForwardEvent(OC_VIEWSETSITERECT, &siteRect);
|
|
Pos = siteRect.TopLeft();
|
|
Size = siteRect.Size();
|
|
|
|
if (!id)
|
|
id = ++OcDocument.PartID;
|
|
char name[32];
|
|
sprintf(name, PartFormat, id);
|
|
Name = name;
|
|
|
|
// There must be a Root IStorage associated with each document
|
|
//
|
|
if (!OcDocument.GetStorage())
|
|
TXObjComp::Throw(TXObjComp::xMissingRootIStorage);
|
|
|
|
// Create a sub-storage from the parent storage in init
|
|
//
|
|
Storage = new TOcStorage(*OcDocument.GetStorage(), name, true, STGM_READWRITE);
|
|
|
|
// Initialize our helpers & then add ourselves to our document's part
|
|
// collection if everything succeeds
|
|
//
|
|
Init(initInfo);
|
|
OcDocument.GetParts().Add(this);
|
|
}
|
|
|
|
//
|
|
// Construct a part from a named stream in an oc doc's storage
|
|
//
|
|
TOcPart::TOcPart(TOcDocument& document, const char far* name)
|
|
:
|
|
OcDocument(document),
|
|
#if defined(BI_DATA_NEAR)
|
|
Name(*new string(name)),
|
|
Pos(*new TPoint),
|
|
Size(*new TSize)
|
|
#else
|
|
Name(name)
|
|
#endif
|
|
{
|
|
BPart = 0;
|
|
BPartI = 0;
|
|
BLPartI = 0;
|
|
Flags = Visible;
|
|
|
|
// There must be an IStorage associated with each document
|
|
//
|
|
if (!OcDocument.GetStorage())
|
|
TXObjComp::Throw(TXObjComp::xMissingRootIStorage);
|
|
|
|
// Open a sub-storage from the parent storage in init
|
|
//
|
|
Storage = new TOcStorage(*OcDocument.GetStorage(), name, false, STGM_READWRITE);
|
|
|
|
// Load our data, and then add ourselves to our document's part collection if
|
|
// everthing succeeds. We'll initialize our helper objects when the parts
|
|
// become visible.
|
|
//
|
|
Load();
|
|
OcDocument.GetParts().Add(this);
|
|
}
|
|
|
|
TOcPart::~TOcPart()
|
|
{
|
|
// detach this part from its document
|
|
//
|
|
Detach();
|
|
|
|
// delete any associated storage
|
|
//
|
|
delete Storage;
|
|
#if defined(BI_DATA_NEAR)
|
|
delete &Name;
|
|
delete &Pos;
|
|
delete &Size;
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// Perform common ctor initialization
|
|
//
|
|
void
|
|
TOcPart::Init(TOcInitInfo far& initInfo)
|
|
{
|
|
AddRef(); // TUnknown defaults to 0, we need 1
|
|
|
|
// There must be an IStorage associated with each part, make sure the ctor
|
|
// got it OK
|
|
//
|
|
initInfo.Storage = Storage->GetIStorage();
|
|
|
|
// Create part helper
|
|
//
|
|
TXObjComp::Check(
|
|
OcDocument.OcApp.BOleComponentCreate(&BPart, GetOuter(), cidBOlePart),
|
|
TXObjComp::xInternalPartError);
|
|
|
|
// Get the interfaces we need & then release the object itself
|
|
//
|
|
if (HRSucceeded(BPart->QueryInterface(IID_IBPart, &(LPVOID)BPartI)))
|
|
BPartI->Release();
|
|
if (HRSucceeded(BPart->QueryInterface(IID_IBLinkable, &(LPVOID)BLPartI)))
|
|
BLPartI->Release();
|
|
|
|
HRESULT hr;
|
|
if (!BPartI || !HRSucceeded(hr = BPartI->Init(this, &initInfo))) {
|
|
BPart->Release();
|
|
BPart = 0;
|
|
TXObjComp::Throw(TXObjComp::xPartInitError, hr);
|
|
}
|
|
|
|
Rename();
|
|
if (initInfo.How == ihLink) // Remember that we are a link
|
|
Flags |= Link;
|
|
|
|
// New parts become active when they are init'd above. Make sure that our
|
|
// view knows that we are active too.
|
|
//
|
|
if (initInfo.Where == iwNew) {
|
|
Flags |= Active;
|
|
TOcView* activeView = OcDocument.GetActiveView();
|
|
CHECK(activeView);
|
|
activeView->ActivatePart(this);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Delete this object. Actually, causes object to shutdown as much as possible
|
|
// & then releases a reference.
|
|
//
|
|
void
|
|
TOcPart::Delete()
|
|
{
|
|
Activate(false);
|
|
Close();
|
|
Release();
|
|
}
|
|
|
|
//
|
|
// Callback from TUnknown's implementation of QueryInterface
|
|
//
|
|
HRESULT
|
|
TOcPart::QueryObject(const IID far& iid, void far* far* iface)
|
|
{
|
|
PRECONDITION(iface);
|
|
HRESULT hr;
|
|
|
|
// interfaces
|
|
//
|
|
HRSucceeded(hr = IBSite_QueryInterface(this, iid, iface))
|
|
|
|
// helpers
|
|
//
|
|
|| (BPart && HRSucceeded(hr = BPart->QueryInterface(iid, iface)))
|
|
;
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Query server for its interfaces
|
|
//
|
|
HRESULT
|
|
TOcPart::QueryServer(const IID far& iid, void far* far* iface)
|
|
{
|
|
PRECONDITION(iface);
|
|
return BPartI->DoQueryInterface(iid, iface);
|
|
}
|
|
|
|
|
|
//
|
|
// Disconnect servers by closing & releasing our BOle helper
|
|
//
|
|
bool
|
|
TOcPart::Close()
|
|
{
|
|
if (!BPartI)
|
|
return true;
|
|
|
|
if (HRSucceeded(BPartI->Close())) {
|
|
// release our BOle helper object
|
|
//
|
|
BPart->Release();
|
|
BPart = 0;
|
|
BPartI = 0;
|
|
BLPartI = 0;
|
|
|
|
// So that it won't get created again in Draw
|
|
//
|
|
Flags |= Closing;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// Rename the embed site for linking
|
|
//
|
|
void
|
|
TOcPart::Rename()
|
|
{
|
|
TOcView* activeView = OcDocument.GetActiveView();
|
|
CHECK(activeView);
|
|
|
|
IBRootLinkable* bLDocumentI;
|
|
activeView->QueryInterface(IID_IBRootLinkable, &(LPVOID)bLDocumentI);
|
|
activeView->Release();
|
|
|
|
if (BLPartI && bLDocumentI)
|
|
BLPartI->OnRename(bLDocumentI, GetName());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// ISite Implementation--delegates site/view related queries/notifies to the
|
|
// active view of this part
|
|
//
|
|
|
|
//
|
|
// Show/hide a site.
|
|
//
|
|
HRESULT _IFUNC
|
|
TOcPart::SiteShow(bool show)
|
|
{
|
|
Invalidate(invView);
|
|
|
|
// When this part is activated, the site is hidden. This is a good time to
|
|
// make sure our state is in sync.
|
|
//
|
|
if (!show) {
|
|
// Make sure the view knows about the active part
|
|
//
|
|
Flags |= Active;
|
|
TOcView* view = OcDocument.GetActiveView();
|
|
if (view) {
|
|
view->ActivatePart(this);
|
|
view->ForwardEvent(OC_VIEWPARTACTIVATE, this);
|
|
}
|
|
}
|
|
return HR_NOERROR;
|
|
}
|
|
|
|
//
|
|
// Discard undo stack for our associated [the active] view
|
|
//
|
|
HRESULT _IFUNC
|
|
TOcPart::DiscardUndo()
|
|
{
|
|
return HR_NOERROR;
|
|
}
|
|
|
|
//
|
|
// Retrieve the site rect [relative to the active view?], and optionally the
|
|
// view's rect too?
|
|
//
|
|
HRESULT _IFUNC
|
|
TOcPart::GetSiteRect(TRect far* posRect, TRect far* clipRect)
|
|
{
|
|
PRECONDITION(posRect);
|
|
if (!posRect)
|
|
return HR_INVALIDARG;
|
|
|
|
TOcView* view = OcDocument.GetActiveView();
|
|
if (!view)
|
|
return HR_FAIL;
|
|
if (posRect)
|
|
*posRect = TRect(Pos, Size);
|
|
|
|
view->ForwardEvent(OC_VIEWGETSITERECT, posRect);
|
|
|
|
// If we don't know our site size yet, then fail this call. Let the server
|
|
// pick a size.
|
|
//
|
|
if (posRect->right-posRect->left <= 0 || posRect->bottom-posRect->top <= 0) {
|
|
posRect->right = posRect->left;
|
|
posRect->bottom = posRect->top;
|
|
return HR_FAIL;
|
|
}
|
|
|
|
if (clipRect)
|
|
view->GetWindowRect(clipRect);
|
|
return HR_NOERROR;
|
|
}
|
|
|
|
//
|
|
// Set the site's rect from an in-place active part. Since user is in control
|
|
// we generally respect both Pos & Size changes.
|
|
//
|
|
HRESULT _IFUNC
|
|
TOcPart::SetSiteRect(const TRect far* newRect)
|
|
{
|
|
PRECONDITION(newRect);
|
|
if (!newRect)
|
|
return HR_INVALIDARG;
|
|
|
|
TOcView* view = OcDocument.GetActiveView();
|
|
if (!view)
|
|
return HR_FAIL;
|
|
|
|
// Give other views a chance to update
|
|
//
|
|
Invalidate(invView); // erase old image
|
|
|
|
TRect rect(*newRect);
|
|
|
|
view->ForwardEvent(OC_VIEWSETSITERECT, &rect);
|
|
Size = rect.Size();
|
|
Pos = rect.TopLeft();
|
|
|
|
// Give other views a chance to update
|
|
//
|
|
Invalidate(invView); // refresh new image position
|
|
return HR_NOERROR;
|
|
}
|
|
|
|
//
|
|
// Set the part's site extent. This comes either after a SetPartRect, or for
|
|
// open editing, comes alone.
|
|
//
|
|
HRESULT _IFUNC
|
|
TOcPart::SetSiteExtent(const TSize far* newSize)
|
|
{
|
|
PRECONDITION(newSize);
|
|
if (!newSize)
|
|
return HR_INVALIDARG;
|
|
|
|
TOcView* view = OcDocument.GetActiveView();
|
|
if (!view)
|
|
return HR_FAIL;
|
|
|
|
// Only accept server's size if we don't have a size yet. Always say OK.
|
|
//
|
|
// if (Size.cx > 0 && Size.cy > 0)
|
|
// return HR_NOERROR;
|
|
|
|
// Give other views a chance to update
|
|
//
|
|
Invalidate(invView); // display new image
|
|
|
|
TSize ext(*newSize);
|
|
TRect siteRect(Pos, ext);
|
|
|
|
view->ForwardEvent(OC_VIEWSETSITERECT, &siteRect);
|
|
Size = siteRect.Size();
|
|
|
|
// Give other views a chance to update
|
|
//
|
|
Invalidate(invView); // refresh new image position
|
|
|
|
return HR_NOERROR;
|
|
}
|
|
|
|
//
|
|
// Get zoom factor for part
|
|
//
|
|
HRESULT _IFUNC
|
|
TOcPart::GetZoom(TOcScaleInfo* zoom)
|
|
{
|
|
PRECONDITION(zoom);
|
|
if (!zoom)
|
|
return HR_INVALIDARG;
|
|
|
|
TOcView* view = OcDocument.GetActiveView();
|
|
if (!view)
|
|
return HR_FAIL;
|
|
|
|
TOcScaleFactor scale(*zoom);
|
|
if (!view->ForwardEvent(OC_VIEWGETSCALE, &scale)) {
|
|
zoom->xD = zoom->xN = zoom->yD = zoom->yN = 1;
|
|
}
|
|
else
|
|
scale.GetScaleFactor(*zoom);
|
|
|
|
return HR_NOERROR;
|
|
}
|
|
|
|
//
|
|
// Invalidate the site within the active view
|
|
//
|
|
void _IFUNC
|
|
TOcPart::Invalidate(TOcInvalidate type)
|
|
{
|
|
TOcView* view = OcDocument.GetActiveView();
|
|
TOcPartChangeInfo changeInfo(this, type);
|
|
if (view)
|
|
view->InvalidatePart(changeInfo);
|
|
}
|
|
|
|
void _IFUNC
|
|
TOcPart::OnSetFocus(bool set)
|
|
{
|
|
TOcView* view = OcDocument.GetActiveView();
|
|
if (view && set)
|
|
::SetFocus(view->GetWindow());
|
|
}
|
|
|
|
HRESULT _IFUNC
|
|
TOcPart::Init(IBDataProvider far*, IBPart far*, LPCOLESTR, bool)
|
|
{
|
|
return HR_FAIL; // never called
|
|
}
|
|
|
|
void _IFUNC
|
|
TOcPart::Disconnect()
|
|
{
|
|
// no need to do anything
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
//
|
|
// Save this part to storage. May be any of:
|
|
// Save to our storage : sameAsLoad==1
|
|
// Copy to a storage : sameAsLoad==0, remember==0
|
|
// SaveAs a new storage: sameAsLoad==0, remember==1
|
|
//
|
|
bool
|
|
TOcPart::Save(bool sameAsLoad, bool remember)
|
|
{
|
|
STATSTG statstg;
|
|
if (!HRSucceeded(Storage->Stat(&statstg, STATFLAG_NONAME)))
|
|
return false;
|
|
|
|
TOcStorage* oldStorage = 0;
|
|
|
|
// If not sameAsLoad, then we are saving to a new storage. Switch to that,
|
|
// at least for this save.
|
|
//
|
|
if (!sameAsLoad) {
|
|
oldStorage = Storage;
|
|
Storage = new TOcStorage(*OcDocument.GetStorage(), GetName(), true, STGM_READWRITE);
|
|
}
|
|
|
|
// Create/open a stream in our storage to save part information
|
|
//
|
|
TOcStream stream(*Storage, ::PartStreamName, true, statstg.grfMode);
|
|
|
|
// Write TOcPart data into stream, Name was written by our Doc
|
|
//
|
|
if (!HRSucceeded(stream.Write(&Pos, sizeof Pos)))
|
|
return false;
|
|
|
|
if (!HRSucceeded(stream.Write(&Size, sizeof Size)))
|
|
return false;
|
|
|
|
if (!HRSucceeded(stream.Write(&Flags, sizeof Flags)))
|
|
return false;
|
|
|
|
// Now have actual server part write itself to this storage
|
|
//
|
|
bool result = Save(Storage->GetIStorage(), sameAsLoad, remember);
|
|
|
|
// If this is a different storage, then either save it (remember) or put
|
|
// it back & clean up.
|
|
//
|
|
if (!sameAsLoad) {
|
|
if (remember) {
|
|
delete oldStorage;
|
|
}
|
|
else {
|
|
delete Storage;
|
|
Storage = oldStorage;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Load this part from its ocpart stream in its current storage
|
|
//
|
|
bool
|
|
TOcPart::Load()
|
|
{
|
|
// Open a stream with oc part information
|
|
//
|
|
STATSTG statstg;
|
|
if (!HRSucceeded(Storage->Stat(&statstg, STATFLAG_NONAME)))
|
|
return false;
|
|
TOcStream stream(*Storage, ::PartStreamName, false, statstg.grfMode);
|
|
|
|
// Read TOcPart data from stream. Server part info will be read in as needed
|
|
// after Init()
|
|
//
|
|
if (!HRSucceeded(stream.Read(&Pos, sizeof Pos)))
|
|
return false;
|
|
|
|
if (!HRSucceeded(stream.Read(&Size, sizeof Size)))
|
|
return false;
|
|
|
|
if (!HRSucceeded(stream.Read(&Flags, sizeof Flags)))
|
|
return false;
|
|
Flags &= ~(Closing | Active); // These Flags are not persistent
|
|
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// Update this part's idea of its size via the server, & then return that.
|
|
// Use GetRect() to just get the current site rect.
|
|
//
|
|
TSize
|
|
TOcPart::GetSize() const
|
|
{
|
|
BPartI->GetPartSize(&const_cast<TSize&>(Size));
|
|
return Size;
|
|
}
|
|
|
|
//
|
|
// Set part to the new position given in logical units
|
|
//
|
|
void
|
|
TOcPart::SetPos(const TPoint& pos)
|
|
{
|
|
Pos = pos;
|
|
// UpdateRect();
|
|
}
|
|
|
|
//
|
|
// Set part to the new size given in logical units
|
|
//
|
|
void
|
|
TOcPart::SetSize(const TSize& size)
|
|
{
|
|
Size = size;
|
|
// UpdateRect();
|
|
}
|
|
|
|
//
|
|
// Set part to the new rect given in logical units
|
|
//
|
|
void
|
|
TOcPart::UpdateRect()
|
|
{
|
|
// Use device units for Bolero
|
|
//
|
|
TRect rect(Pos, Size);
|
|
TOcView* view = OcDocument.GetActiveView();
|
|
if (!view)
|
|
return;
|
|
|
|
view->ForwardEvent(OC_VIEWGETSITERECT, &rect);
|
|
|
|
BPartI->SetPartPos(&rect);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// IBPart pass-thrus not inlined
|
|
//
|
|
bool
|
|
TOcPart::Activate(bool activate)
|
|
{
|
|
TOcView* activeView = OcDocument.GetActiveView();
|
|
CHECK(activeView);
|
|
|
|
if (activate && activeView->GetActivePart())
|
|
if (!activeView->ActivatePart(0)) // deactivate currently active part, if any
|
|
return false;
|
|
|
|
// Makes sure that the part gets the active view as its host.
|
|
// This is important in multi-view situation.
|
|
//
|
|
SetHost(activeView);
|
|
if (!HRSucceeded(BPartI->Activate(activate)))
|
|
return false;
|
|
|
|
if (activate) {
|
|
Flags |= Active;
|
|
activeView->SetActivePart(this);
|
|
}
|
|
else {
|
|
Flags &= ~Active;
|
|
activeView->SetActivePart(0);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void
|
|
TOcPart::FinishLoading()
|
|
{
|
|
// Load embeded object on demand
|
|
//
|
|
if (!BPartI) {
|
|
TOcInitInfo initInfo(ihEmbed, iwStorage, OcDocument.GetActiveView());
|
|
Init(initInfo);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Set data into the server object
|
|
//
|
|
bool
|
|
TOcPart::SetFormatData(TOcFormatInfo far* fmt, HANDLE data, bool release)
|
|
{
|
|
IBPart2* bPartI2;
|
|
if (HRSucceeded(BPart->QueryInterface(IID_IBPart2, &(LPVOID)bPartI2)))
|
|
((IBPart*)bPartI2)->Release();
|
|
else
|
|
return false;
|
|
|
|
return HRSucceeded(bPartI2->SetFormatData(fmt, data, release));
|
|
}
|
|
|
|
|
|
bool
|
|
TOcPart::Save(IStorage* storage, bool sameAsLoad, bool remember)
|
|
{
|
|
PRECONDITION(storage);
|
|
if (BPartI)
|
|
return HRSucceeded(BPartI->Save(storage, sameAsLoad, remember));
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
TOcPart::Draw(HDC dc, const TRect& pos, const TRect& clip, TOcAspect aspect)
|
|
{
|
|
PRECONDITION(dc);
|
|
|
|
// Don't draw anything if we are closing down the part
|
|
//
|
|
if (Flags & Closing)
|
|
return true;
|
|
|
|
const RECTL posl = { pos.left, pos.top, pos.right, pos.bottom };
|
|
const RECTL clipl = { clip.left, clip.top, clip.right, clip.bottom };
|
|
|
|
// Load embeded object on demand
|
|
//
|
|
if (!BPartI) {
|
|
TOcInitInfo initInfo(ihEmbed, iwStorage, OcDocument.GetActiveView());
|
|
Init(initInfo);
|
|
// Update the link
|
|
//
|
|
if (IsLink()) {
|
|
TOcView* view = OcDocument.GetActiveView();
|
|
if (view)
|
|
view->UpdateLinks();
|
|
}
|
|
|
|
}
|
|
|
|
return HRSucceeded(BPartI->Draw(dc, &posl, &clipl, aspect, drNone));
|
|
}
|
|
|
|
bool
|
|
TOcPart::EnumVerbs(const TOcVerb& verb)
|
|
{
|
|
if (BPartI)
|
|
return HRIsOK(BPartI->EnumVerbs(const_cast<TOcVerb*>(&verb)));
|
|
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
TOcPart::DoVerb(UINT whichVerb)
|
|
{
|
|
if (BPartI) {
|
|
if (HRSucceeded(BPartI->DoVerb(whichVerb))) {
|
|
TOcView* activeView = OcDocument.GetActiveView();
|
|
CHECK(activeView);
|
|
activeView->SetActivePart(this); // we may be activated now...
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int
|
|
TOcPart::Detach()
|
|
{
|
|
return OcDocument.GetParts().Detach(this);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// CdPartCollection
|
|
//
|
|
|
|
TOcPartCollection::TOcPartCollection()
|
|
:
|
|
TCVectorImp<TOcPart*>(0, 10)
|
|
{
|
|
}
|
|
|
|
TOcPartCollection::~TOcPartCollection()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
//
|
|
// Release parts in the collection
|
|
//
|
|
void
|
|
TOcPartCollection::Clear()
|
|
{
|
|
for (int i = Count() - 1; i >= 0; i--) {
|
|
TOcPart* part = (TOcPart*)(*this)[i];
|
|
part->Release();
|
|
}
|
|
}
|
|
|
|
//
|
|
// walk thru Part collection & return the last one that logical point hits,
|
|
// (first one in Z order)
|
|
//
|
|
TOcPart*
|
|
TOcPartCollection::Locate(TPoint& logicalPoint)
|
|
{
|
|
TRect hitRect(logicalPoint, TSize(1,1));
|
|
|
|
TOcPart* p = 0;
|
|
for (TOcPartCollectionIter i(*this); i; i++)
|
|
if (i.Current()->IsVisible(hitRect))
|
|
p = (TOcPart*)i.Current();
|
|
return p;
|
|
}
|
|
|
|
//
|
|
// Select/unselect all parts
|
|
//
|
|
bool
|
|
TOcPartCollection::SelectAll(bool select)
|
|
{
|
|
for (TOcPartCollectionIter i(*this); i; i++)
|
|
i.Current()->Select(select);
|
|
return true;
|
|
}
|
|
|
|
int
|
|
TOcPartCollection::Detach(TOcPart* const& part, int del)
|
|
{
|
|
int ret = Base::Detach(Find(part));
|
|
if (ret && del)
|
|
const_cast<TOcPart*>(part)->Release();
|
|
return ret;
|
|
}
|
|
|
|
//--------------------------------- OcVerb -----------------------------------
|
|
//
|
|
TOcVerb::TOcVerb()
|
|
:
|
|
TypeName(0),
|
|
VerbName(0),
|
|
VerbIndex(0),
|
|
CanDirty(false)
|
|
{
|
|
}
|
|
|