home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / Draw / Sources / DrawLink.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  27.3 KB  |  852 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                DrawLink.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Author:                Henri Lamiraux
  7. //    Linking added by:    M.Boetcher
  8. //
  9. //    Copyright:            (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  10. //
  11. //========================================================================================
  12.  
  13. #include "ODFDraw.hpp"
  14.  
  15. #ifndef DRAWLINK_H
  16. #include "DrawLink.h"
  17. #endif
  18.  
  19. #ifndef DRAWCONT_H
  20. #include "DrawCont.h"
  21. #endif
  22.  
  23. #ifndef DEFINES_K
  24. #include "Defines.k"
  25. #endif
  26.  
  27. #ifndef DRAWPART_H
  28. #include "DrawPart.h"
  29. #endif
  30.  
  31. #ifndef DRAWSEL_H
  32. #include "DrawSel.h"
  33. #endif
  34.  
  35. #ifndef BASESHP_H
  36. #include "BaseShp.h"
  37. #endif
  38.  
  39. #ifndef BOUNDSHP_H
  40. #include "BoundShp.h"
  41. #endif
  42.  
  43. #ifndef LINESHP_H
  44. #include "LineShp.h"
  45. #endif
  46.  
  47. #ifndef OVALSHP_H
  48. #include "OvalShp.h"
  49. #endif
  50.  
  51. #ifndef RECTSHP_H
  52. #include "RectShp.h"
  53. #endif
  54.  
  55. #ifndef RRECTSHP_H
  56. #include "RRectShp.h"
  57. #endif
  58.  
  59. #ifndef TEXTSHP_H
  60. #include "TextShp.h"
  61. #endif
  62.  
  63. #ifndef GROUPSHP_H
  64. #include "GroupShp.h"
  65. #endif
  66.  
  67. #ifndef DRAWPRXY_H
  68. #include "DrawPrxy.h"
  69. #endif
  70.  
  71. // ----- Framework Includes -----
  72.  
  73. #ifndef FWLNKITE_H
  74. #include "FWLnkIte.h"
  75. #endif
  76.  
  77. #ifndef FWSUUTIL_H
  78. #include "FWSUUtil.h"
  79. #endif
  80.  
  81. #ifndef FWPXYITE_H
  82. #include "FWPxyIte.h"
  83. #endif
  84.  
  85. #ifndef FWFRAME_H
  86. #include "FWFrame.h"
  87. #endif
  88.  
  89. #ifndef FWINTER_H
  90. #include "FWInter.h"
  91. #endif
  92.  
  93. #ifndef FWITERS_H
  94. #include "FWIters.h"
  95. #endif
  96.  
  97. #ifndef FWPRTITE_H
  98. #include "FWPrtIte.h"
  99. #endif
  100.  
  101. #ifndef FWPRESEN_H
  102. #include "FWPresen.h"
  103. #endif
  104.  
  105. #ifndef FWPXYFRM_H
  106. #include "FWPxyFrm.h"
  107. #endif
  108.  
  109. #ifndef FWUTIL_H
  110. #include "FWUtil.h"
  111. #endif
  112.  
  113. #ifndef FWCLNINF_H
  114. #include "FWClnInf.h"
  115. #endif
  116.  
  117. #ifndef FWBARRAY_H
  118. #include "FWBArray.h"
  119. #endif
  120.  
  121. #ifndef FWPRMISE_H
  122. #include "FWPrmise.h"
  123. #endif
  124.  
  125. // ----- Foundation Includes -----
  126.  
  127. #ifndef FWORDCOL_H
  128. #include "FWOrdCol.h"
  129. #endif
  130.  
  131. #ifndef FWMEMMGR_H
  132. #include "FWMemMgr.h"
  133. #endif
  134.  
  135. // for FW_SOMEnvironment
  136. #ifndef FWSOMENV_H
  137. #include "FWSOMEnv.h"
  138. #endif
  139.  
  140. // ----- OpenDoc Includes -----
  141.  
  142. #ifndef SOM_Module_OpenDoc_StdProps_defined
  143. #include <StdProps.xh>
  144. #endif
  145.  
  146. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  147. #include <StdTypes.xh>
  148. #endif
  149.  
  150. #ifndef SOM_ODStorageUnit_xh
  151. #include <StorageU.xh>
  152. #endif
  153.  
  154. #ifndef SOM_ODUndo_xh
  155. #include <Undo.xh>
  156. #endif
  157.  
  158. #ifndef SOM_ODSession_xh
  159. #include <ODSessn.xh>
  160. #endif
  161.  
  162. #ifndef SOM_ODLink_xh
  163. #include <Link.xh>
  164. #endif
  165.  
  166. #ifndef SOM_ODLinkSpec_xh
  167. #include <LinkSpec.xh>
  168. #endif
  169.  
  170. #ifndef SOM_ODLinkSource_xh
  171. #include <LinkSrc.xh>
  172. #endif
  173.  
  174. //========================================================================================
  175. // Runtime Information
  176. //========================================================================================
  177.  
  178. #ifdef FW_BUILD_MAC
  179. #pragma segment odfdraw
  180. #endif
  181.  
  182. FW_DEFINE_AUTO(CDrawPublishLinkCollection)
  183. FW_DEFINE_AUTO(CDrawPublishLinkCollectionIterator)
  184. FW_DEFINE_AUTO(CDrawSubscribeLinkCollection)
  185. FW_DEFINE_AUTO(CDrawSubscribeLinkCollectionIterator)
  186. FW_DEFINE_AUTO(CDrawLinkManager)
  187.     
  188. //========================================================================================
  189. //    class CDrawPublishLink
  190. //========================================================================================
  191.  
  192. //----------------------------------------------------------------------------------------
  193. //    CDrawPublishLink::CDrawPublishLink
  194. //----------------------------------------------------------------------------------------
  195.  
  196. CDrawPublishLink::CDrawPublishLink(Environment* ev, ODUpdateID updateID, 
  197.                                    FW_CPresentation* presentation, 
  198.                                    CDrawSelection* drawSelection,
  199.                                    FW_Boolean saveSelection) :
  200.     FW_CLinkSource(ev, updateID, presentation),
  201.     fDrawSelection(drawSelection),
  202.     fPublishedContent(NULL)
  203. {
  204.     CDrawContent* content = NULL;
  205.     if (saveSelection)        // Save the selected shapes so they can be published
  206.         content = fDrawSelection->GetDrawContent(ev);
  207.  
  208.     fPublishedContent = FW_NEW(CDrawLinkSourceContent, (ev, 
  209.                                             (CDrawPart*) presentation->GetPart(ev), 
  210.                                             content, this));
  211. }
  212.  
  213. //----------------------------------------------------------------------------------------
  214. //    CDrawPublishLink::~CDrawPublishLink
  215. //----------------------------------------------------------------------------------------
  216.  
  217. CDrawPublishLink::~CDrawPublishLink()
  218. {
  219.     // Have to delete any promise before deleting the content because the promise
  220.     // will attempt to access the content, which is shared, so have to preempt
  221.     // the inherited destructor
  222.     
  223.     if (fLinkPromise)
  224.     {
  225.         delete fLinkPromise;
  226.         fLinkPromise = NULL;
  227.     }
  228.     
  229.     delete fPublishedContent;
  230. }
  231.  
  232. //----------------------------------------------------------------------------------------
  233. //    CDrawPublishLink::LinkEstablished - Override
  234. //----------------------------------------------------------------------------------------
  235.  
  236. void CDrawPublishLink::LinkEstablished(Environment* ev)
  237. {
  238.     //---- Mark the collected shapes as published
  239.     CDrawContentShapeIterator ite(fPublishedContent);
  240.     for (CBaseShape* shape = ite.First(); ite.IsNotComplete(); shape = ite.Next())
  241.     {
  242.         shape->SetPublishLink(ev, this);
  243.     }
  244. }
  245.  
  246. //----------------------------------------------------------------------------------------
  247. //    CDrawPublishLink::ExternalizeLinkContent - Override
  248. //----------------------------------------------------------------------------------------
  249.  
  250. void CDrawPublishLink::ExternalizeLinkContent(Environment* ev, ODStorageUnit* linkSU)
  251. {    
  252.     // -- Pick a frame, any frame --
  253.     FW_CPresentationFrameIterator piter(ev, fPresentation);
  254.     FW_CFrame* frame = piter.First(ev);
  255.     FW_ASSERT(frame);
  256.  
  257.     fDataInterchange->ExternalizeData(ev, fPublishedContent, frame, linkSU, FW_kLinkStorage, kODCloneToLink);
  258. }
  259.  
  260. //----------------------------------------------------------------------------------------
  261. //    CDrawPublishLink::HasEmbeddedFrame
  262. //----------------------------------------------------------------------------------------
  263. FW_Boolean CDrawPublishLink::HasEmbeddedFrame(Environment* ev, ODFrame* odFrame)
  264. {
  265.     // Is odFrame involved in this link source? (called by DoUpdateLinks)
  266.  
  267.     // --- Find out whether odFrame is involved in any link source ---
  268.     if (odFrame->GetLinkStatus(ev) == kODInLinkSource)
  269.     {
  270.         CDrawContentShapeIterator iter(fPublishedContent);
  271.         for (CBaseShape* shape = iter.First(); iter.IsNotComplete(); shape = iter.Next())
  272.         {
  273.             if ((shape->GetShapeType() == kProxyShape) && (((CProxyShape*)shape)->IsEmbeddedFrame(ev, odFrame)))
  274.                 return TRUE;
  275.         }
  276.     }
  277.  
  278.     return FALSE;
  279. }
  280.  
  281. //----------------------------------------------------------------------------------------
  282. //    CDrawPublishLink::RevealLinkSource
  283. //----------------------------------------------------------------------------------------
  284. void CDrawPublishLink::RevealLinkSource(Environment* ev, FW_CFrame* frame)
  285. {
  286. FW_UNUSED(frame);
  287.     fDrawSelection->SelectContent(ev, fPublishedContent);
  288. }
  289.  
  290. //----------------------------------------------------------------------------------------
  291. //    CDrawPublishLink::AddShape
  292. //----------------------------------------------------------------------------------------
  293. void CDrawPublishLink::AddShape(Environment* ev, CBaseShape* shape)
  294. {
  295.     shape->SetPublishLink(ev, this);
  296.     fPublishedContent->AddShape(ev, shape);
  297. }
  298.  
  299. //----------------------------------------------------------------------------------------
  300. //    CDrawPublishLink::RemoveShape
  301. //----------------------------------------------------------------------------------------
  302. void CDrawPublishLink::RemoveShape(Environment* ev, CBaseShape* shape)
  303. {
  304.     fPublishedContent->RemoveShape(ev, shape);
  305. }
  306.  
  307. //----------------------------------------------------------------------------------------
  308. //    CDrawPublishLink::DoExternalizeLink
  309. //----------------------------------------------------------------------------------------
  310.  
  311. void CDrawPublishLink::DoExternalizeLink(Environment* ev, 
  312.                                         ODStorageUnit* storageUnit,
  313.                                         FW_CCloneInfo* cloneInfo)
  314. {
  315. FW_UNUSED(cloneInfo);
  316.     //--- Write the number of shapes in the link ---
  317.     unsigned long shapeCount = fPublishedContent->CountShapes();
  318.     FW_ASSERT(shapeCount != 0);
  319.     FW_CByteArray byteArray(&shapeCount, sizeof(unsigned long));
  320.     storageUnit->SetValue(ev, byteArray);
  321.  
  322.     //--- Write the externalization index for each shape in the link ---
  323.     CDrawContentShapeIterator iter(fPublishedContent);
  324.     for (CBaseShape* shape = iter.First(); iter.IsNotComplete(); shape = iter.Next())
  325.     {
  326.         short extIndex = shape->GetExternalizationIndex();
  327.         byteArray.Set(&extIndex, sizeof(short));
  328.         storageUnit->SetValue(ev, byteArray);
  329.     }
  330. }
  331.  
  332. //----------------------------------------------------------------------------------------
  333. //    CDrawPublishLink::IsEmpty
  334. //----------------------------------------------------------------------------------------
  335. FW_Boolean CDrawPublishLink::IsEmpty()
  336. {
  337.     return (fPublishedContent->CountShapes() == 0);
  338. }
  339.  
  340. //----------------------------------------------------------------------------------------
  341. //    CDrawPublishLink::BreakLink
  342. //----------------------------------------------------------------------------------------
  343. void CDrawPublishLink::BreakLink(Environment* ev)
  344. {
  345.     FW_CLinkSource::BreakLink(ev);    // call inherited
  346.     
  347.     //---- Mark the collected shapes as not published
  348.     CDrawContentShapeIterator it(fPublishedContent);
  349.     for (CBaseShape* shape = it.First(); it.IsNotComplete(); shape = it.Next())
  350.     {
  351.         shape->SetPublishLink(ev, NULL);
  352.     }
  353. }
  354.  
  355. //----------------------------------------------------------------------------------------
  356. //    CDrawPublishLink::RestoreLink
  357. //----------------------------------------------------------------------------------------
  358. void CDrawPublishLink::RestoreLink(Environment* ev, FW_CPart* part)
  359. {
  360.     FW_CLinkSource::RestoreLink(ev, part);    // call inherited
  361.     
  362.     //---- Mark the collected shapes as published
  363.     CDrawContentShapeIterator it(fPublishedContent);
  364.     for (CBaseShape* shape = it.First(); it.IsNotComplete(); shape = it.Next())
  365.     {
  366.         shape->SetPublishLink(ev, this);
  367.     }
  368. }
  369.  
  370. #pragma segment Main
  371. FW_Boolean CDrawPublishLink::IsOKtoUpdate(Environment* ev, FW_Boolean forceUpdate)
  372. {
  373.     // Prevent updating of link when all its content has been removed
  374.     if (!forceUpdate && this->IsEmpty())
  375.         return FALSE;
  376.     
  377.     return FW_CLinkSource::IsOKtoUpdate(ev, forceUpdate);
  378. }
  379.  
  380.  
  381. //========================================================================================
  382. //    class CDrawSubscribeLink
  383. //========================================================================================
  384.  
  385. //----------------------------------------------------------------------------------------
  386. //    CDrawSubscribeLink::CDrawSubscribeLink
  387. //----------------------------------------------------------------------------------------
  388.  
  389. CDrawSubscribeLink::CDrawSubscribeLink(Environment* ev, ODLink* odLink, 
  390.                                         FW_CPresentation* presentation, 
  391.                                         CDrawSelection* drawSelection,
  392.                                         ODLinkInfo* linkInfo,
  393.                                         FW_Boolean createGroupShape) :
  394.     FW_CLinkDestination(ev, odLink, linkInfo, presentation),
  395.     fDrawPart((CDrawPart*) presentation->GetPart(ev)),
  396.     fDrawSelection(drawSelection),
  397.     fLinkedContent(NULL),
  398.     fGroupShape(NULL),
  399.     fFirstUpdate(true),
  400.     fFirstOffset(true),
  401.     fCalcGroupOffset(false)
  402. {
  403.     fUpdateOffset.Clear();
  404.  
  405.     //---- Create a new content object to hold the shapes in this link ----
  406.     fLinkedContent = FW_NEW(CDrawLinkContent, (ev, fDrawPart, this));
  407.  
  408.     if (createGroupShape)
  409.     {
  410.         //---- Create a new group shape to represent the linked shapes ---- 
  411.         fGroupShape = FW_NEW(CGroupShape, (fDrawPart));
  412.         fGroupShape->SetSubscribeLink(ev, this);
  413.     }
  414. }
  415.  
  416. //----------------------------------------------------------------------------------------
  417. //    CDrawSubscribeLink::~CDrawSubscribeLink
  418. //----------------------------------------------------------------------------------------
  419.  
  420. CDrawSubscribeLink::~CDrawSubscribeLink()
  421. {
  422.     FW_SOMEnvironment ev;
  423.     this->DeleteShapes(ev);
  424.     delete fLinkedContent;
  425.     delete fGroupShape;
  426. }
  427.  
  428. //---------------------------------------------------------------------------------------
  429. //    CDrawSubscribeLink::DoUpdateLink - Override
  430. //---------------------------------------------------------------------------------------
  431.  
  432. FW_Boolean CDrawSubscribeLink::DoUpdateLink(Environment* ev, ODStorageUnit* linkContentSU, ODPasteAsResult* embedAsInfo)
  433. {
  434.     // Find a frame to use for the scope frame
  435.     FW_CPresentationFrameIterator piter(ev, fPresentation);
  436.     FW_CFrame* frame = piter.First(ev);
  437.     FW_ASSERT(frame);
  438.  
  439.     if (!fFirstUpdate)
  440.         fLinkedContent->EmptyShapes(ev);    // remove linked shapes from our content
  441.  
  442.     // Read new shapes from the link SU into our content
  443.     FW_Boolean result = (fDataInterchange->InternalizeData(ev, fLinkedContent, frame, linkContentSU, 
  444.                                                 FW_kLinkStorage, kODCloneFromLink, embedAsInfo)
  445.                                                 != FW_kInternalizeFailed);
  446.     if (result)
  447.     {
  448.         // Merge newly-read link data with part data
  449.         this->UpdateLinkedContent(ev);
  450.  
  451.         // Force all frames to be redrawn
  452.         fPresentation->Invalidate(ev);
  453.     }
  454.     return result;
  455. }
  456.  
  457. //----------------------------------------------------------------------------------------
  458. //    CDrawSubscribeLink::UpdateLinkedContent
  459. //----------------------------------------------------------------------------------------
  460.  
  461. void CDrawSubscribeLink::UpdateLinkedContent(Environment* ev)
  462. {
  463.     // If we got this far, the link data was read successfully.
  464.  
  465.     if (fFirstUpdate)    // Add the group shape to the part
  466.     {
  467.         fDrawPart->AddShapeToPart(ev, fGroupShape);
  468.     }
  469.     else                // Delete obsolete data
  470.     {
  471.         fGroupShape->EmptyShapes(true);        // remove shapes and delete them
  472.     }
  473.  
  474.     // Roll the new shapes into the group shape
  475.     fLinkedContent->GroupShapes(ev, fGroupShape);
  476.  
  477.     if (fCalcGroupOffset)
  478.     {
  479.         FW_CRect rect = fGroupShape->GetRectGeometry();
  480.         fGroupShape->OffsetShape(ev, fUpdateOffset.x - rect.left, fUpdateOffset.y - rect.top);
  481.     }
  482.     else if (!fFirstOffset && fUpdateOffset != FW_kZeroPoint)    // updating an existing link 
  483.     {
  484.         // move the linked shapes to their proper position
  485.         fGroupShape->OffsetShape(ev, fUpdateOffset.x, fUpdateOffset.y);
  486.     }
  487.  
  488.     // Redraw the new shapes
  489.     fLinkedContent->RedrawShapes(ev);
  490.  
  491.     fFirstUpdate = false;
  492.     fFirstOffset = false;
  493. }
  494.  
  495. //----------------------------------------------------------------------------------------
  496. //    CDrawSubscribeLink::BreakLink - Override
  497. //----------------------------------------------------------------------------------------
  498. void CDrawSubscribeLink::BreakLink(Environment* ev)
  499. {
  500.     FW_CLinkDestination::BreakLink(ev);
  501.  
  502.     this->InvalidateBorder(ev);            // force link borders to be redrawn
  503.     fGroupShape->SetSubscribeLink(ev, NULL);    // Change status of embedded frames
  504. }
  505.  
  506. //----------------------------------------------------------------------------------------
  507. //    CDrawSubscribeLink::LinkEstablished - Override
  508. //----------------------------------------------------------------------------------------
  509. void CDrawSubscribeLink::LinkEstablished(Environment* ev)
  510. {
  511.     // Mark the shapes as linked
  512.     fGroupShape->SetSubscribeLink(ev, this);
  513. }
  514.  
  515. //----------------------------------------------------------------------------------------
  516. //    CDrawSubscribeLink::SetGroupShape
  517. //----------------------------------------------------------------------------------------
  518. void CDrawSubscribeLink::SetGroupShape(Environment* ev, CGroupShape* groupShape)
  519. {
  520.     fGroupShape = groupShape;
  521.     groupShape->SetSubscribeLink(ev, this);
  522.  
  523.     // Add the grouped shapes to the linked content
  524.     CShapeCollectionIterator it(groupShape->GetShapeList());
  525.     for (CBaseShape* shape = it.First(); it.IsNotComplete(); shape = it.Next())
  526.     {
  527.         fLinkedContent->AddShape(ev, shape);
  528.     }
  529.  
  530.     if (fLinkedContent->CountShapes() != 0)
  531.         fFirstUpdate = false;    // so that DoUpdateLink empties it before reading new shapes
  532.  
  533.     FW_CRect rect = groupShape->GetRectGeometry();
  534.     fUpdateOffset = rect.TopLeft();
  535.     fCalcGroupOffset = true;    /* force UpdateLinkedContent to calculate offset */
  536. }
  537.  
  538. //----------------------------------------------------------------------------------------
  539. //    CDrawSubscribeLink::AddShape
  540. //----------------------------------------------------------------------------------------
  541. void CDrawSubscribeLink::AddShape(Environment* ev, CBaseShape* shape)
  542. {
  543.     // Called by Link Manager when internalizing destination links
  544.     fLinkedContent->AddShape(ev, shape);
  545.     fGroupShape->AddShape(shape);
  546. }
  547.  
  548. //----------------------------------------------------------------------------------------
  549. //    CDrawSubscribeLink::DeleteShapes
  550. //----------------------------------------------------------------------------------------
  551. void CDrawSubscribeLink::DeleteShapes(Environment* ev)
  552. {
  553.     // Called when undoing a Paste As (breaking a dest link)
  554.     fLinkedContent->EmptyShapes(ev);    // remove shapes from content
  555.     fGroupShape->EmptyShapes(true);        // remove shapes and delete them
  556.  
  557.     // Remove the group shape from the part (destructor will delete it)
  558.     fDrawPart->RemoveShapeFromPart(ev, fGroupShape);
  559. }
  560.  
  561. //----------------------------------------------------------------------------------------
  562. //    CDrawSubscribeLink::SelectShapes
  563. //----------------------------------------------------------------------------------------
  564. void CDrawSubscribeLink::SelectShapes(Environment* ev)
  565. {
  566.     fDrawSelection->CloseSelection(ev);
  567.     fDrawSelection->AddToSelection(ev, fGroupShape, TRUE);
  568. }
  569.  
  570. //----------------------------------------------------------------------------------------
  571. //    CDrawSubscribeLink::DoExternalizeLink
  572. //----------------------------------------------------------------------------------------
  573.  
  574. void CDrawSubscribeLink::DoExternalizeLink(Environment* ev, 
  575.                                         ODStorageUnit* storageUnit,
  576.                                         FW_CCloneInfo* cloneInfo)
  577. {
  578. FW_UNUSED(cloneInfo);
  579.     //--- There is a single group shape in the link ---
  580.     FW_ASSERT(fGroupShape);
  581.     unsigned long shapeCount = 1;
  582.     FW_CByteArray byteArray(&shapeCount, sizeof(unsigned long));
  583.     storageUnit->SetValue(ev, byteArray);
  584.  
  585.     //--- Write the export index for the group shape ---
  586.     short extIndex = fGroupShape->GetExternalizationIndex();
  587.     byteArray.Set(&extIndex, sizeof(short));
  588.     storageUnit->SetValue(ev, byteArray);
  589. }
  590.  
  591. //----------------------------------------------------------------------------------------
  592. //    CDrawSubscribeLink::AdjustUpdateOffset
  593. //----------------------------------------------------------------------------------------
  594. void CDrawSubscribeLink::AdjustUpdateOffset(Environment* ev, const FW_CPoint& delta)
  595. {
  596. FW_UNUSED(ev);
  597.     fUpdateOffset += delta;
  598. }
  599.  
  600. //----------------------------------------------------------------------------------------
  601. //    CDrawSubscribeLink::GetContainingFrame
  602. //----------------------------------------------------------------------------------------
  603. FW_CFrame* CDrawSubscribeLink::GetContainingFrame(Environment* ev, ODFrame* odEmbeddedFrame)
  604. {
  605.     // Return the containing frame if odEmbeddedFrame is involved in this link.
  606.     // Called by FW_CLinkManager::EditInLinkAttempted
  607.  
  608.     if (odEmbeddedFrame->GetLinkStatus(ev) == kODInLinkDestination)
  609.     {
  610.         // -- Find out whether odEmbeddedFrame is one of my proxy shapes --
  611.         CShapeCollectionIterator iter(fGroupShape->GetShapeList());
  612.         for (CBaseShape* shape = iter.First(); iter.IsNotComplete(); shape = iter.Next())
  613.         {
  614.             if ((shape->GetShapeType() == kProxyShape) && (((CProxyShape*)shape)->IsEmbeddedFrame(ev, odEmbeddedFrame)))
  615.             {
  616.                 FW_CPresentationFrameIterator iter(ev, fPresentation);
  617.                 return iter.First(ev);
  618.             }
  619.         }
  620.     }
  621.  
  622.     return NULL;
  623. }
  624.  
  625. //========================================================================================
  626. //    class CDrawLinkManager
  627. //========================================================================================
  628.  
  629. //----------------------------------------------------------------------------------------
  630. //    CDrawLinkManager constructor
  631. //----------------------------------------------------------------------------------------
  632.  
  633. CDrawLinkManager::CDrawLinkManager(Environment* ev, CDrawPart* part):
  634.     FW_CLinkManager(ev, part),
  635.     fDrawPart(part)
  636. {
  637. }
  638.  
  639. //----------------------------------------------------------------------------------------
  640. //    CDrawLinkManager destructor
  641. //----------------------------------------------------------------------------------------
  642.  
  643. CDrawLinkManager::~CDrawLinkManager()
  644. {
  645. }
  646.  
  647. //----------------------------------------------------------------------------------------
  648. //    CDrawLinkManager::NewLinkSource - Override
  649. //----------------------------------------------------------------------------------------
  650.  
  651. FW_CLinkSource* CDrawLinkManager::NewLinkSource(Environment* ev, ODUpdateID changeID, 
  652.                                                 FW_CPresentation* presentation)
  653. {
  654.     return new CDrawPublishLink(ev, changeID, 
  655.                                 presentation, fDrawPart->fDrawSelection, 
  656.                                 TRUE);    // saveSelection = TRUE
  657. }
  658.  
  659. //----------------------------------------------------------------------------------------
  660. //    CDrawLinkManager::NewLinkDestination - Override
  661. //----------------------------------------------------------------------------------------
  662.  
  663. FW_CLinkDestination* CDrawLinkManager::NewLinkDestination(Environment* ev, ODLink *odLink,
  664.                                                           ODLinkInfo* linkInfo,
  665.                                                           FW_CPresentation* presentation)
  666. {
  667.     return new CDrawSubscribeLink(ev, odLink, presentation, fDrawPart->fDrawSelection, linkInfo);
  668. }
  669.  
  670. //----------------------------------------------------------------------------------------
  671. //    CDrawLinkManager::DoChangeLinkStatus - Override
  672. //----------------------------------------------------------------------------------------
  673.  
  674. void CDrawLinkManager::DoChangeLinkStatus(Environment* ev, ODFrame* odFrame)
  675. {
  676.     // call ODFrame::ChangeLinkStatus on any embedded frames that are involved in a link
  677.     // when a link is created, broken, moved, etc.
  678.     // odFrame is the frame of this part whose link status has changed.
  679.     
  680.     FW_CEmbeddingFrame* frame = FW_CEmbeddingFrame::ODtoFWEmbeddingFrame(ev, odFrame);
  681.     if (frame)
  682.     {
  683.         ODLinkStatus linkStatus = odFrame->GetLinkStatus(ev);
  684.  
  685.         // Only need to propagate linkStatus to embedded frames that don't participate in
  686.         // any of this part's links; otherwise their local link status takes precedence.
  687.  
  688.         CDrawContentShapeIterator iter(fDrawPart->GetDrawContent());
  689.         for (CBaseShape* shape = iter.First(); iter.IsNotComplete(); shape = iter.Next())
  690.         {
  691.             if (shape->GetShapeType() == kProxyShape)
  692.             {
  693.                 CProxyShape* proxyShape = (CProxyShape*)shape;
  694.                 if (!proxyShape->IsPublished() && !proxyShape->IsSubscribed())
  695.                 {
  696.                     FW_CProxyEmbeddedFrameIterator efiter(ev, proxyShape);
  697.                     for (ODFrame* embFrame = efiter.First(ev); efiter.IsNotComplete(ev); embFrame = efiter.Next(ev))
  698.                         embFrame->ChangeLinkStatus(ev, linkStatus);
  699.                 }
  700.             }
  701.         }
  702.     }
  703. }
  704.  
  705. //----------------------------------------------------------------------------------------
  706. //    CDrawLinkManager::CreateLink - Override
  707. //----------------------------------------------------------------------------------------
  708. ODLinkSource* CDrawLinkManager::CreateLink(Environment* ev, ODByteArray* data)
  709. {
  710.     // CreateLink is overridden so that we can delete the pending clipboard publish link.
  711.     // This prevents the link spec from being re-used to create more than one link.
  712.  
  713.     FW_Boolean isLinkSpecOnClipboard = (GetPendingDropLink(ev) == NULL);
  714.     ODLinkSource* odLinkSource = FW_CLinkManager::CreateLink(ev, data);
  715.     
  716. #ifdef DEADCODE  // [MH]
  717. // I see no reason to do this.  This isn't about creating multiple link sources
  718. // with the same content, which is not currently supported by ODFDraw, it's about
  719. // allowing a second destination to be created from the same source, which works already
  720. // in ODFTable with no special support from the part implementation. 
  721.  
  722.     if (isLinkSpecOnClipboard)
  723.         this->DeletePendingClipboardLink(ev);
  724. #endif
  725.  
  726.     return odLinkSource;
  727. }
  728.  
  729. //----------------------------------------------------------------------------------------
  730. //    CDrawLinkManager::UndoPasteAs
  731. //----------------------------------------------------------------------------------------
  732. void CDrawLinkManager::UndoPasteAs(Environment* ev, CDrawSubscribeLink* link)
  733. {
  734.     //--- Remove subscribed shapes from the document ---
  735.     fDrawPart->fDrawSelection->CloseSelection(ev);
  736.     fDrawPart->RemoveShapeFromPart(ev, link->fGroupShape);
  737. }
  738.  
  739. //----------------------------------------------------------------------------------------
  740. //    CDrawLinkManager::RedoPasteAs
  741. //----------------------------------------------------------------------------------------
  742. void CDrawLinkManager::RedoPasteAs(Environment* ev, CDrawSubscribeLink* link)
  743. {
  744.     link->fGroupShape->RestoreShape(ev);
  745. }
  746.  
  747. //----------------------------------------------------------------------------------------
  748. //    CDrawLinkManager::GetSUValue
  749. //----------------------------------------------------------------------------------------
  750.  
  751. ODULong CDrawLinkManager::GetSUValue(Environment* ev, ODStorageUnit* su, 
  752.                                      unsigned long size, void *buffer)
  753. {
  754.     // Convenience function; also makes code easier to read
  755.     FW_CByteArray ba;
  756.     ODULong bytesRead = su->GetValue(ev, size, ba);
  757.     ba.CopyBuffer(buffer, bytesRead);
  758.     
  759.     return bytesRead;
  760. }
  761.  
  762. //----------------------------------------------------------------------------------------
  763. //    CDrawLinkManager::DoInternalizeOneDestLink - Override
  764. //----------------------------------------------------------------------------------------
  765.  
  766. FW_CLinkDestination* CDrawLinkManager::DoInternalizeOneDestLink(Environment* ev, ODStorageUnit* storageUnit,
  767.                                                             ODLink* odLink, ODLinkInfo* linkInfo)
  768. {
  769.     //--- Create a subscriber object for this link ---
  770.     CDrawSubscribeLink* destLink = new CDrawSubscribeLink(ev, odLink, 
  771.                                                           fDrawPart->GetMainPresentation(), 
  772.                                                           fDrawPart->fDrawSelection, linkInfo,
  773.                                                           false);    // don't create group shape
  774.  
  775.     //--- Read the number of shapes in the link ---
  776.     unsigned long shapeCount;
  777.     GetSUValue(ev, storageUnit, sizeof(unsigned long), &shapeCount);
  778.     FW_ASSERT(shapeCount == 1);    // There should be a single group shape
  779.  
  780.     //--- Read each shape index and add the shape to the source link ---
  781.     short extIndex;
  782.     GetSUValue(ev, storageUnit, sizeof(short), &extIndex);
  783.     CBaseShape* shape = fDrawPart->FindShapeWithIndex(extIndex);
  784.     FW_ASSERT(shape);
  785.     if (shape && shape->GetShapeType() == kGroupShape)
  786.     {
  787.         destLink->SetGroupShape(ev, (CGroupShape*)shape);
  788.     }
  789.  
  790.     return destLink;
  791. }
  792.  
  793. //----------------------------------------------------------------------------------------
  794. //    CDrawLinkManager::DoInternalizeOneSourceLink - Override
  795. //----------------------------------------------------------------------------------------
  796.  
  797. FW_CLinkSource* CDrawLinkManager::DoInternalizeOneSourceLink(Environment* ev, 
  798.                                                               ODStorageUnit* storageUnit,
  799.                                                               ODUpdateID updateID)
  800. {
  801.     //--- Create a publish object for this source link ---
  802.     CDrawPublishLink* sourceLink = new CDrawPublishLink(ev, updateID, fDrawPart->GetMainPresentation(), fDrawPart->fDrawSelection, FALSE);
  803.  
  804.     //--- Read the number of shapes in the link ---
  805.     unsigned long shapeCount;
  806.     GetSUValue(ev, storageUnit, sizeof(unsigned long), &shapeCount);
  807.  
  808.     //--- Read each shape index and add the shape to the source link ---
  809.     unsigned long shapesInLink = 0;
  810.     short extIndex;
  811.     while (shapeCount > 0)
  812.     {
  813.         GetSUValue(ev, storageUnit, sizeof(short), &extIndex);
  814.         CBaseShape* shape = fDrawPart->FindShapeWithIndex(extIndex);
  815.         if (shape)
  816.         {
  817.             sourceLink->AddShape(ev, shape);
  818.             shapesInLink++;
  819.         }
  820.         shapeCount--;
  821.     }
  822.  
  823.     //--- If no linked shapes were found, discard the link ---
  824.     if (shapesInLink == 0)
  825.     {
  826.         delete sourceLink;
  827.         sourceLink = NULL;
  828.     }
  829.  
  830.     return sourceLink;
  831. }
  832.  
  833. //----------------------------------------------------------------------------------------
  834. //    CDrawLinkManager::GetSourceLinkFormat - Override
  835. //----------------------------------------------------------------------------------------
  836.  
  837. ODValueType CDrawLinkManager::GetSourceLinkFormat(Environment* ev)
  838. {    
  839. FW_UNUSED(ev);
  840.     return kPublishFormat;
  841. }
  842.  
  843. //----------------------------------------------------------------------------------------
  844. //    CDrawLinkManager::GetDestLinkFormat - Override
  845. //----------------------------------------------------------------------------------------
  846.  
  847. ODValueType CDrawLinkManager::GetDestLinkFormat(Environment* ev)
  848. {    
  849. FW_UNUSED(ev);
  850.     return kSubscribeFormat;
  851. }
  852.