home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / Borland / Cplus45 / BC45 / OCFSRC.PAK / OCPART.CPP < prev    next >
C/C++ Source or Header  |  1995-08-29  |  18KB  |  790 lines

  1. //
  2. //----------------------------------------------------------------------------
  3. // ObjectComponents
  4. // (C) Copyright 1994 by Borland International, All Rights Reserved
  5. //
  6. //   Implementation of TOcPart Class
  7. //----------------------------------------------------------------------------
  8. #include <ocf/ocfpch.h>
  9. #include <ocf/ocstorag.h>
  10. #include <ocf/ocpart.h>
  11. #include <ocf/ocdoc.h>
  12. #include <ocf/ocapp.h>
  13. #include <ocf/ocview.h>
  14. #include <stdio.h>  // sprintf
  15.  
  16. const char  PartFormat[]     = "OcPart.%d";
  17. const char  PartStreamName[] = "\03OcPart";
  18.  
  19. //
  20. // Construct a new part with a given temp id
  21. //
  22. TOcPart::TOcPart(TOcDocument& document, TOcInitInfo far& initInfo,
  23.                  TRect objPos, int id)
  24. :
  25.   OcDocument(document)
  26. #if defined(BI_DATA_NEAR)
  27.  ,Name(*new string),
  28.   Pos(*new TPoint),
  29.   Size(*new TSize)
  30. #endif
  31. {
  32.   BPart   = 0;
  33.   BPartI  = 0;
  34.   BLPartI = 0;
  35.   Flags = Visible;
  36.  
  37.   // Part position and size are in logical units
  38.   //
  39.   TRect siteRect = objPos;
  40.   TOcView* view = OcDocument.GetActiveView();
  41.   if (!view)
  42.     return;
  43.  
  44.   view->ForwardEvent(OC_VIEWSETSITERECT, &siteRect);
  45.   Pos = siteRect.TopLeft();
  46.   Size = siteRect.Size();
  47.  
  48.   if (!id)
  49.     id = ++OcDocument.PartID;
  50.   char name[32];
  51.   sprintf(name, PartFormat, id);
  52.   Name = name;
  53.  
  54.   // There must be a Root IStorage associated with each document
  55.   //
  56.   if (!OcDocument.GetStorage())
  57.     TXObjComp::Throw(TXObjComp::xMissingRootIStorage);
  58.  
  59.   // Create a sub-storage from the parent storage in init
  60.   //
  61.   Storage = new TOcStorage(*OcDocument.GetStorage(), name, true, STGM_READWRITE);
  62.  
  63.   // Initialize our helpers & then add ourselves to our document's part
  64.   // collection if everything succeeds
  65.   //
  66.   Init(initInfo);
  67.   OcDocument.GetParts().Add(this);
  68. }
  69.  
  70. //
  71. // Construct a part from a named stream in an oc doc's storage
  72. //
  73. TOcPart::TOcPart(TOcDocument& document, const char far* name)
  74. :
  75.   OcDocument(document),
  76. #if defined(BI_DATA_NEAR)
  77.   Name(*new string(name)),
  78.   Pos(*new TPoint),
  79.   Size(*new TSize)
  80. #else
  81.   Name(name)
  82. #endif
  83. {
  84.   BPart   = 0;
  85.   BPartI  = 0;
  86.   BLPartI = 0;
  87.   Flags = Visible;
  88.  
  89.   // There must be an IStorage associated with each document
  90.   //
  91.   if (!OcDocument.GetStorage())
  92.     TXObjComp::Throw(TXObjComp::xMissingRootIStorage);
  93.  
  94.   // Open a sub-storage from the parent storage in init
  95.   //
  96.   Storage = new TOcStorage(*OcDocument.GetStorage(), name, false, STGM_READWRITE);
  97.  
  98.   // Load our data, and then add ourselves to our document's part collection if
  99.   // everthing succeeds. We'll initialize our helper objects when the parts
  100.   // become visible.
  101.   //
  102.   Load();
  103.   OcDocument.GetParts().Add(this);
  104. }
  105.  
  106. TOcPart::~TOcPart()
  107. {
  108.   // detach this part from its document
  109.   //
  110.   Detach();
  111.  
  112.   // delete any associated storage
  113.   //
  114.   delete Storage;
  115. #if defined(BI_DATA_NEAR)
  116.   delete &Name;
  117.   delete &Pos;
  118.   delete &Size;
  119. #endif
  120. }
  121.  
  122. //
  123. // Perform common ctor initialization
  124. //
  125. void
  126. TOcPart::Init(TOcInitInfo far& initInfo)
  127. {
  128.   AddRef();  // TUnknown defaults to 0, we need 1
  129.  
  130.   // There must be an IStorage associated with each part, make sure the ctor
  131.   // got it OK
  132.   //
  133.   initInfo.Storage = Storage->GetIStorage();
  134.  
  135.   // Create part helper
  136.   //
  137.   TXObjComp::Check(
  138.     OcDocument.OcApp.BOleComponentCreate(&BPart, GetOuter(), cidBOlePart),
  139.     TXObjComp::xInternalPartError);
  140.  
  141.   // Get the interfaces we need & then release the object itself
  142.   //
  143.   if (HRSucceeded(BPart->QueryInterface(IID_IBPart, &(LPVOID)BPartI)))
  144.     BPartI->Release();
  145.   if (HRSucceeded(BPart->QueryInterface(IID_IBLinkable, &(LPVOID)BLPartI)))
  146.     BLPartI->Release();
  147.  
  148.   HRESULT hr;
  149.   if (!BPartI || !HRSucceeded(hr = BPartI->Init(this, &initInfo))) {
  150.     BPart->Release();
  151.     BPart = 0;
  152.     TXObjComp::Throw(TXObjComp::xPartInitError, hr);
  153.   }
  154.  
  155.   Rename();
  156.   if (initInfo.How == ihLink)  // Remember that we are a link
  157.     Flags |= Link;
  158.  
  159.   // New parts become active when they are init'd above. Make sure that our
  160.   // view knows that we are active too.
  161.   //
  162.   if (initInfo.Where == iwNew) {
  163.     Flags |= Active;
  164.     TOcView* activeView = OcDocument.GetActiveView();
  165.     CHECK(activeView);
  166.     activeView->ActivatePart(this);
  167.   }
  168. }
  169.  
  170. //
  171. // Delete this object. Actually, causes object to shutdown as much as possible
  172. // & then releases a reference.
  173. //
  174. void
  175. TOcPart::Delete()
  176. {
  177.   Activate(false);
  178.   Close();
  179.   Release();
  180. }
  181.  
  182. //
  183. // Callback from TUnknown's implementation of QueryInterface
  184. //
  185. HRESULT
  186. TOcPart::QueryObject(const IID far& iid, void far* far* iface)
  187. {
  188.   PRECONDITION(iface);
  189.   HRESULT hr;
  190.  
  191.   // interfaces
  192.   //
  193.      HRSucceeded(hr = IBSite_QueryInterface(this, iid, iface))
  194.  
  195.   // helpers
  196.   //
  197.   || (BPart && HRSucceeded(hr = BPart->QueryInterface(iid, iface)))
  198.   ;
  199.   return hr;
  200. }
  201.  
  202. //
  203. // Query server for its interfaces
  204. //
  205. HRESULT
  206. TOcPart::QueryServer(const IID far& iid, void far* far* iface)
  207. {
  208.   PRECONDITION(iface);
  209.   return BPartI->DoQueryInterface(iid, iface);
  210. }
  211.  
  212.  
  213. //
  214. // Disconnect servers by closing & releasing our BOle helper
  215. //
  216. bool
  217. TOcPart::Close()
  218. {
  219.   if (!BPartI)
  220.     return true;
  221.  
  222.   if (HRSucceeded(BPartI->Close())) {
  223.     // release our BOle helper object
  224.     //
  225.     BPart->Release();
  226.     BPart   = 0;
  227.     BPartI  = 0;
  228.     BLPartI = 0;
  229.  
  230.     // So that it won't get created again in Draw
  231.     //
  232.     Flags |= Closing;
  233.     return true;
  234.   }
  235.   return false;
  236. }
  237.  
  238. //
  239. // Rename the embed site for linking
  240. //
  241. void
  242. TOcPart::Rename()
  243. {
  244.   TOcView* activeView = OcDocument.GetActiveView();
  245.   CHECK(activeView);
  246.  
  247.   IBRootLinkable* bLDocumentI;
  248.   activeView->QueryInterface(IID_IBRootLinkable, &(LPVOID)bLDocumentI);
  249.   activeView->Release();
  250.  
  251.   if (BLPartI && bLDocumentI)
  252.     BLPartI->OnRename(bLDocumentI, GetName());
  253. }
  254.  
  255. //----------------------------------------------------------------------------
  256. // ISite Implementation--delegates site/view related queries/notifies to the
  257. // active view of this part
  258. //
  259.  
  260. //
  261. // Show/hide a site.
  262. //
  263. HRESULT _IFUNC
  264. TOcPart::SiteShow(bool show)
  265. {
  266.   Invalidate(invView);
  267.  
  268.   // When this part is activated, the site is hidden. This is a good time to
  269.   // make sure our state is in sync.
  270.   //
  271.   if (!show) {
  272.     // Make sure the view knows about the active part
  273.     //
  274.     Flags |= Active;
  275.     TOcView* view = OcDocument.GetActiveView();
  276.     if (view) {
  277.       view->ActivatePart(this);
  278.       view->ForwardEvent(OC_VIEWPARTACTIVATE, this);
  279.     }
  280.   }
  281.   return HR_NOERROR;
  282. }
  283.  
  284. //
  285. // Discard undo stack for our associated [the active] view
  286. //
  287. HRESULT _IFUNC
  288. TOcPart::DiscardUndo()
  289. {
  290.   return HR_NOERROR;
  291. }
  292.  
  293. //
  294. // Retrieve the site rect [relative to the active view?], and optionally the
  295. // view's rect too?
  296. //
  297. HRESULT _IFUNC
  298. TOcPart::GetSiteRect(TRect far* posRect, TRect far* clipRect)
  299. {
  300.   PRECONDITION(posRect);
  301.   if (!posRect)
  302.     return HR_INVALIDARG;
  303.  
  304.   TOcView* view = OcDocument.GetActiveView();
  305.   if (!view)
  306.     return HR_FAIL;
  307.   if (posRect)
  308.     *posRect = TRect(Pos, Size);
  309.  
  310.   view->ForwardEvent(OC_VIEWGETSITERECT, posRect);
  311.  
  312.   // If we don't know our site size yet, then fail this call. Let the server
  313.   // pick a size.
  314.   //
  315.   if (posRect->right-posRect->left <= 0 || posRect->bottom-posRect->top <= 0) {
  316.     posRect->right = posRect->left;
  317.     posRect->bottom = posRect->top;
  318.     return HR_FAIL;
  319.   }
  320.  
  321.   if (clipRect)
  322.     view->GetWindowRect(clipRect);
  323.   return HR_NOERROR;
  324. }
  325.  
  326. //
  327. // Set the site's rect from an in-place active part. Since user is in control
  328. // we generally respect both Pos & Size changes.
  329. //
  330. HRESULT _IFUNC
  331. TOcPart::SetSiteRect(const TRect far* newRect)
  332. {
  333.   PRECONDITION(newRect);
  334.   if (!newRect)
  335.     return HR_INVALIDARG;
  336.  
  337.   TOcView* view = OcDocument.GetActiveView();
  338.   if (!view)
  339.     return HR_FAIL;
  340.  
  341.   // Give other views a chance to update
  342.   //
  343.   Invalidate(invView);   // erase old image
  344.  
  345.   TRect rect(*newRect);
  346.  
  347.   view->ForwardEvent(OC_VIEWSETSITERECT, &rect);
  348.   Size = rect.Size();
  349.   Pos  = rect.TopLeft();
  350.  
  351.   // Give other views a chance to update
  352.   //
  353.   Invalidate(invView);    // refresh new image position
  354.   return HR_NOERROR;
  355. }
  356.  
  357. //
  358. // Set the part's site extent. This comes either after a SetPartRect, or for
  359. // open editing, comes alone.
  360. //
  361. HRESULT _IFUNC
  362. TOcPart::SetSiteExtent(const TSize far* newSize)
  363. {
  364.   PRECONDITION(newSize);
  365.   if (!newSize)
  366.     return HR_INVALIDARG;
  367.  
  368.   TOcView* view = OcDocument.GetActiveView();
  369.   if (!view)
  370.     return HR_FAIL;
  371.  
  372.   // Only accept server's size if we don't have a size yet. Always say OK.
  373.   //
  374. //  if (Size.cx > 0 && Size.cy > 0)
  375. //    return HR_NOERROR;
  376.  
  377.   // Give other views a chance to update
  378.   //
  379.   Invalidate(invView); // display new image
  380.  
  381.   TSize ext(*newSize);
  382.   TRect siteRect(Pos, ext);
  383.  
  384.   view->ForwardEvent(OC_VIEWSETSITERECT, &siteRect);
  385.   Size = siteRect.Size();
  386.  
  387.   // Give other views a chance to update
  388.   //
  389.   Invalidate(invView);    // refresh new image position
  390.  
  391.   return HR_NOERROR;
  392. }
  393.  
  394. //
  395. // Get zoom factor for part
  396. //
  397. HRESULT _IFUNC
  398. TOcPart::GetZoom(TOcScaleInfo* zoom)
  399. {
  400.   PRECONDITION(zoom);
  401.   if (!zoom)
  402.     return HR_INVALIDARG;
  403.  
  404.   TOcView* view = OcDocument.GetActiveView();
  405.   if (!view)
  406.     return HR_FAIL;
  407.  
  408.   TOcScaleFactor scale(*zoom);
  409.   if (!view->ForwardEvent(OC_VIEWGETSCALE, &scale)) {
  410.     zoom->xD = zoom->xN = zoom->yD = zoom->yN = 1;
  411.   }
  412.   else
  413.     scale.GetScaleFactor(*zoom);
  414.  
  415.   return HR_NOERROR;
  416. }
  417.  
  418. //
  419. // Invalidate the site within the active view
  420. //
  421. void _IFUNC
  422. TOcPart::Invalidate(TOcInvalidate type)
  423. {
  424.   TOcView* view = OcDocument.GetActiveView();
  425.   TOcPartChangeInfo changeInfo(this, type);
  426.   if (view)
  427.     view->InvalidatePart(changeInfo);
  428. }
  429.  
  430. void _IFUNC
  431. TOcPart::OnSetFocus(bool set)
  432. {
  433.   TOcView* view = OcDocument.GetActiveView();
  434.   if (view && set)
  435.     ::SetFocus(view->GetWindow());
  436. }
  437.  
  438. HRESULT _IFUNC
  439. TOcPart::Init(IBDataProvider far*, IBPart far*, LPCOLESTR, bool)
  440. {
  441.   return HR_FAIL; // never called
  442. }
  443.  
  444. void _IFUNC
  445. TOcPart::Disconnect()
  446. {
  447.   // no need to do anything
  448. }
  449.  
  450. //----------------------------------------------------------------------------
  451.  
  452. //
  453. // Save this part to storage. May be any of:
  454. //   Save to our storage : sameAsLoad==1
  455. //   Copy to a storage   : sameAsLoad==0, remember==0
  456. //   SaveAs a new storage: sameAsLoad==0, remember==1
  457. //
  458. bool
  459. TOcPart::Save(bool sameAsLoad, bool remember)
  460. {
  461.   STATSTG  statstg;
  462.   if (!HRSucceeded(Storage->Stat(&statstg, STATFLAG_NONAME)))
  463.     return false;
  464.  
  465.   TOcStorage* oldStorage = 0;
  466.  
  467.   // If not sameAsLoad, then we are saving to a new storage. Switch to that,
  468.   // at least for this save.
  469.   //
  470.   if (!sameAsLoad) {
  471.     oldStorage = Storage;
  472.     Storage = new TOcStorage(*OcDocument.GetStorage(), GetName(), true, STGM_READWRITE);
  473.   }
  474.  
  475.   // Create/open a stream in our storage to save part information
  476.   //
  477.   TOcStream  stream(*Storage, ::PartStreamName, true, statstg.grfMode);
  478.  
  479.   // Write TOcPart data into stream, Name was written by our Doc
  480.   //
  481.   if (!HRSucceeded(stream.Write(&Pos, sizeof Pos)))
  482.     return false;
  483.  
  484.   if (!HRSucceeded(stream.Write(&Size, sizeof Size)))
  485.     return false;
  486.  
  487.   if (!HRSucceeded(stream.Write(&Flags, sizeof Flags)))
  488.     return false;
  489.  
  490.   // Now have actual server part write itself to this storage
  491.   //
  492.   bool result = Save(Storage->GetIStorage(), sameAsLoad, remember);
  493.  
  494.   // If this is a different storage, then either save it (remember) or put
  495.   // it back & clean up.
  496.   //
  497.   if (!sameAsLoad) {
  498.     if (remember) {
  499.       delete oldStorage;
  500.     }
  501.     else {
  502.       delete Storage;
  503.       Storage = oldStorage;
  504.     }
  505.   }
  506.  
  507.   return result;
  508. }
  509.  
  510. //
  511. // Load this part from its ocpart stream in its current storage
  512. //
  513. bool
  514. TOcPart::Load()
  515. {
  516.   // Open a stream with oc part information
  517.   //
  518.   STATSTG statstg;
  519.   if (!HRSucceeded(Storage->Stat(&statstg, STATFLAG_NONAME)))
  520.     return false;
  521.   TOcStream  stream(*Storage, ::PartStreamName, false, statstg.grfMode);
  522.  
  523.   // Read TOcPart data from stream. Server part info will be read in as needed
  524.   // after Init()
  525.   //
  526.   if (!HRSucceeded(stream.Read(&Pos, sizeof Pos)))
  527.     return false;
  528.  
  529.   if (!HRSucceeded(stream.Read(&Size, sizeof Size)))
  530.     return false;
  531.  
  532.   if (!HRSucceeded(stream.Read(&Flags, sizeof Flags)))
  533.     return false;
  534.   Flags &= ~(Closing | Active); // These Flags are not persistent
  535.  
  536.   return true;
  537. }
  538.  
  539. //
  540. // Update this part's idea of its size via the server, & then return that.
  541. // Use GetRect() to just get the current site rect.
  542. //
  543. TSize
  544. TOcPart::GetSize() const
  545. {
  546.   BPartI->GetPartSize(&const_cast<TSize&>(Size));
  547.   return Size;
  548. }
  549.  
  550. //
  551. // Set part to the new position given in logical units
  552. //
  553. void
  554. TOcPart::SetPos(const TPoint& pos)
  555. {
  556.   Pos = pos;
  557. //  UpdateRect();
  558. }
  559.  
  560. //
  561. // Set part to the new size given in logical units
  562. //
  563. void
  564. TOcPart::SetSize(const TSize& size)
  565. {
  566.   Size = size;
  567. //  UpdateRect();
  568. }
  569.  
  570. //
  571. // Set part to the new rect given in logical units
  572. //
  573. void
  574. TOcPart::UpdateRect()
  575. {
  576.   // Use device units for Bolero
  577.   //
  578.   TRect rect(Pos, Size);
  579.   TOcView* view = OcDocument.GetActiveView();
  580.   if (!view)
  581.     return;
  582.  
  583.   view->ForwardEvent(OC_VIEWGETSITERECT, &rect);
  584.  
  585.   BPartI->SetPartPos(&rect);
  586. }
  587.  
  588. //----------------------------------------------------------------------------
  589. // IBPart pass-thrus not inlined
  590. //
  591. bool
  592. TOcPart::Activate(bool activate)
  593. {
  594.   TOcView* activeView = OcDocument.GetActiveView();
  595.   CHECK(activeView);
  596.  
  597.   if (activate && activeView->GetActivePart())
  598.     if (!activeView->ActivatePart(0))  // deactivate currently active part, if any
  599.       return false;
  600.  
  601.   // Makes sure that the part gets the active view as its host.
  602.   // This is important in multi-view situation.
  603.   //
  604.   SetHost(activeView);
  605.   if (!HRSucceeded(BPartI->Activate(activate)))
  606.     return false;
  607.  
  608.   if (activate) {
  609.     Flags |= Active;
  610.     activeView->SetActivePart(this);
  611.   }
  612.   else {
  613.     Flags &= ~Active;
  614.     activeView->SetActivePart(0);
  615.   }
  616.   return true;
  617. }
  618.  
  619. void
  620. TOcPart::FinishLoading()
  621. {
  622.   // Load embeded object on demand
  623.   //
  624.   if (!BPartI) {
  625.     TOcInitInfo initInfo(ihEmbed, iwStorage, OcDocument.GetActiveView());
  626.     Init(initInfo);
  627.   }
  628. }
  629.  
  630.  
  631. //
  632. // Set data into the server object
  633. //
  634. bool
  635. TOcPart::SetFormatData(TOcFormatInfo far* fmt, HANDLE data, bool release)
  636. {
  637.   IBPart2* bPartI2;
  638.   if (HRSucceeded(BPart->QueryInterface(IID_IBPart2, &(LPVOID)bPartI2)))
  639.     ((IBPart*)bPartI2)->Release();
  640.   else
  641.     return false;
  642.  
  643.   return HRSucceeded(bPartI2->SetFormatData(fmt, data, release));
  644. }
  645.  
  646.  
  647. bool
  648. TOcPart::Save(IStorage* storage, bool sameAsLoad, bool remember)
  649. {
  650.   PRECONDITION(storage);
  651.   if (BPartI)
  652.     return HRSucceeded(BPartI->Save(storage, sameAsLoad, remember));
  653.   return false;
  654. }
  655.  
  656. bool
  657. TOcPart::Draw(HDC dc, const TRect& pos, const TRect& clip, TOcAspect aspect)
  658. {
  659.   PRECONDITION(dc);
  660.  
  661.   // Don't draw anything if we are closing down the part
  662.   //
  663.   if (Flags & Closing)
  664.     return true;
  665.  
  666.   const RECTL posl = { pos.left, pos.top, pos.right, pos.bottom };
  667.   const RECTL clipl = { clip.left, clip.top, clip.right, clip.bottom };
  668.  
  669.   // Load embeded object on demand
  670.   //
  671.   if (!BPartI) {
  672.     TOcInitInfo initInfo(ihEmbed, iwStorage, OcDocument.GetActiveView());
  673.     Init(initInfo);
  674.     // Update the link
  675.     //
  676.     if (IsLink()) {
  677.       TOcView* view = OcDocument.GetActiveView();
  678.       if (view)
  679.         view->UpdateLinks();
  680.     }
  681.  
  682.   }
  683.  
  684.   return HRSucceeded(BPartI->Draw(dc, &posl, &clipl, aspect, drNone));
  685. }
  686.  
  687. bool
  688. TOcPart::EnumVerbs(const TOcVerb& verb)
  689. {
  690.   if (BPartI)
  691.     return HRIsOK(BPartI->EnumVerbs(const_cast<TOcVerb*>(&verb)));
  692.  
  693.   return false;
  694. }
  695.  
  696. bool
  697. TOcPart::DoVerb(UINT whichVerb)
  698. {
  699.   if (BPartI) {
  700.     if (HRSucceeded(BPartI->DoVerb(whichVerb))) {
  701.       TOcView* activeView = OcDocument.GetActiveView();
  702.       CHECK(activeView);
  703.       activeView->SetActivePart(this);  // we may be activated now...
  704.       return true;
  705.     }
  706.   }
  707.   return false;
  708. }
  709.  
  710. int
  711. TOcPart::Detach()
  712. {
  713.   return OcDocument.GetParts().Detach(this);
  714. }
  715.  
  716. //----------------------------------------------------------------------------
  717. // CdPartCollection
  718. //
  719.  
  720. TOcPartCollection::TOcPartCollection()
  721. :
  722.   TCVectorImp<TOcPart*>(0, 10)
  723. {
  724. }
  725.  
  726. TOcPartCollection::~TOcPartCollection()
  727. {
  728.   Clear();
  729. }
  730.  
  731. //
  732. // Release parts in the collection
  733. //
  734. void
  735. TOcPartCollection::Clear()
  736. {
  737.   for (int i = Count() - 1; i >= 0; i--) {
  738.     TOcPart* part = (TOcPart*)(*this)[i];
  739.     part->Release();
  740.   }
  741. }
  742.  
  743. //
  744. // walk thru Part collection & return the last one that logical point hits,
  745. // (first one in Z order)
  746. //
  747. TOcPart*
  748. TOcPartCollection::Locate(TPoint& logicalPoint)
  749. {
  750.   TRect hitRect(logicalPoint, TSize(1,1));
  751.  
  752.   TOcPart* p = 0;
  753.   for (TOcPartCollectionIter i(*this); i; i++)
  754.     if (i.Current()->IsVisible(hitRect))
  755.       p = (TOcPart*)i.Current();
  756.   return p;
  757. }
  758.  
  759. //
  760. // Select/unselect all parts
  761. //
  762. bool
  763. TOcPartCollection::SelectAll(bool select)
  764. {
  765.   for (TOcPartCollectionIter i(*this); i; i++)
  766.     i.Current()->Select(select);
  767.   return true;
  768. }
  769.  
  770. int
  771. TOcPartCollection::Detach(TOcPart* const& part, int del)
  772. {
  773.   int ret = Base::Detach(Find(part));
  774.   if (ret && del)
  775.     const_cast<TOcPart*>(part)->Release();
  776.   return ret;
  777. }
  778.  
  779. //---------------------------------  OcVerb  -----------------------------------
  780. //
  781. TOcVerb::TOcVerb()
  782. :
  783.   TypeName(0),
  784.   VerbName(0),
  785.   VerbIndex(0),
  786.   CanDirty(false)
  787. {
  788. }
  789.  
  790.