home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc Source Code / Storage / LinkB.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-22  |  25.8 KB  |  920 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        LinkB.cpp
  3.  
  4.     Contains:    Implementation of ODBaseLink class
  5.  
  6.     Owned by:    Craig Carper
  7.  
  8.     Copyright:    © 1993 - 1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         <33>     10/8/95    TJ        Fixes Recomended by Refball
  13.         <32>     10/3/95    TJ        Added Includes so it compiles
  14.         <31>     10/3/95    TJ        Changes done by RefBall Team
  15.         <30>      9/8/95    TÇ        1281096 FB2:Many constants in ODTypesB
  16.                                     without kOD prefix!
  17.         <29>      9/1/95    CC        1278590: GetContentStorageUnit: Throw if
  18.                                     link source status is
  19.                                     kODErrCannotEstablishLink.
  20.         <28>     8/21/95    VL        1277291: Added #include <StorUtil.h>.
  21.         <27>     8/12/95    TÇ        1276807 Opt./Bug: use StdTypIO routines for
  22.                                     portable streaming & smaller footprint
  23.         <26>      8/3/95    RR        #1257260: Collapse B classes. Remove
  24.                                     somInit methods. Don't call IsInitialized
  25.                                     or SubclassResponsibility
  26.         <25>     7/28/95    CC        1183569: Externalize only when dirty.
  27.         <24>     7/28/95    CC        1242625: ODDeleteObject sets argument to
  28.                                     null.
  29.         <23>     7/24/95    CC        1193553: Added private class
  30.                                     ODPartListIterator.
  31.                                     1234526: RegisterDependent: Ignore register
  32.                                     if draft is read-only, so part won't be
  33.                                     notified.
  34.         <22>     7/24/95    CC        1154714:  UpdateDependents:  Iteration not
  35.                                     broken by Registration & Unregistration
  36.                                     during notification.
  37.                                     Added AddPartList and RemovePartList to
  38.                                     private class ODPartList.
  39.                                     AddPart: Test for presence in list before
  40.                                     adding.
  41.                                     Destructor for class ODPartList removes all
  42.                                     parts.
  43.         <21>     6/17/95    CC        1259139: GetContentStorageUnit: Fail if no
  44.                                     content property or value.
  45.         <20>      6/2/95    CC        1255474: AcquireLinkSource restored to
  46.                                     GetLinkSource.
  47.                                     1255474: AcquireLinkedList restored to
  48.                                     GetLinkedList.
  49.         <19>     5/26/95    VL        1251403: Multithreading naming support.
  50.         <18>     5/25/95    jpa        List.h --> LinkList.h [1253324]
  51.         <17>     5/18/95    CC        1238898: Add destFrame argument to
  52.                                     BeginClone call.
  53.         <16>     5/17/95    RR        #1250135/1250137/1250143 Getters increment
  54.                                     refcount
  55.         <15>     4/14/95    TÇ        #1235279 BB: InfoUtil & StdTypIO functions
  56.                                     should take Environment* and SU* when
  57.                                     possible
  58.         <14>     4/11/95    CC        1236452: Added SOM_CATCH to InitBaseLink,
  59.                                     InitBaseLinkFromStorage,
  60.                                     GetContentStorageUnit, SetLinkSource, Lock,
  61.                                     and Unlock.
  62.                                     Added inline override of THROW_IF_NULL.
  63.                                     Removed #include of Link.xh.
  64.         <13>      3/9/95    CC        1221471: Added changesAllowed parameter to
  65.                                     ShowLinkDestinationInfo().
  66.         <12>     2/15/95    CC        1216124    ShowLinkDestinationInfo: Aquire
  67.                                     modal focus & deactivate front window.
  68.         <11>     1/19/95    CC        1193551 Removed GetLinkStatus().
  69.                                     1183569 Added fDirty flag.
  70.                                     1212356 ShowSourceContent: Catch errors
  71.                                     returned by
  72.                                     ODLinkSource::ShowSourceContent().
  73.         <10>    12/22/94    CC        1207986 Moved ODSURemoveProperty to
  74.                                     StdTypIO.
  75.          <9>    12/16/94    CC        1203516 Removed ODLinkSource parameter from
  76.                                     InitBaseLink(); added SetLinkSource().
  77.          <8>     10/4/94    CC        1190307 - Robustify for non-existent link
  78.                                     object.
  79.          <7>     9/15/94    CC        1186669 - Replace CloneTo() with
  80.                                     CloneInto().
  81.          <6>      9/8/94    CC        #1185113 - Use StdTypeIO to read/write
  82.                                     property values.
  83.          <5>      9/7/94    CC        #1185114 - Catch throws from KeyValid().
  84.          <4>     8/26/94    VL        1183174: Use updated cloning APIs.
  85.          <3>     8/12/94    CC        1180598 - Added ODFacet parameter to
  86.                                     ShowLinkDestinationInfo().
  87.          <2>     8/10/94    CC        1179943 - Moved in platform-independent
  88.                                     implementation from Link.cpp.
  89.          <1>     6/24/94    CC        first checked in
  90.          
  91.     To Do:
  92.     In Progress:
  93. */
  94.  
  95. #define VARIABLE_MACROS
  96.  
  97. #define ODBaseLink_Class_Source
  98. #include <LinkB.xih>
  99.  
  100. #ifndef _EXCEPT_
  101. #include <Except.h>
  102. #endif
  103.  
  104. #ifndef _ODMEMORY_
  105. #include <ODMemory.h>
  106. #endif
  107.  
  108. #ifndef _CONSTDEF_
  109. #include <ConstDef.h>
  110. #endif
  111.  
  112. #ifndef _LINKDLGS_
  113. #include <LinkDlgs.h>
  114. #endif
  115.  
  116. #ifndef SOM_ODLinkSource_xh
  117. #include <LinkSrc.xh>
  118. #endif
  119.  
  120. #ifndef _LINKLIST_
  121. #include <LinkList.h>
  122. #endif
  123.  
  124. #ifndef SOM_ODPart_xh
  125. #include <Part.xh>
  126. #endif
  127.  
  128. #ifndef SOM_ODFrame_xh
  129. #include <Frame.xh>
  130. #endif
  131.  
  132. #ifndef SOM_ODSession_xh
  133. #include <ODSessn.xh>
  134. #endif
  135.  
  136. #ifndef SOM_ODArbitrator_xh
  137. #include <Arbitrat.xh>
  138. #endif
  139.  
  140. #ifndef SOM_ODWindowState_xh
  141. #include <WinStat.xh>
  142. #endif
  143.  
  144. #ifndef SOM_Module_OpenDoc_Foci_defined
  145. #include <Foci.xh>
  146. #endif
  147.  
  148. #ifndef SOM_ODContainer_xh
  149. #include <ODCtr.xh>
  150. #endif
  151.  
  152. #ifndef SOM_ODDocument_xh
  153. #include <Document.xh>
  154. #endif
  155.  
  156. #ifndef SOM_ODDraft_xh
  157. #include <Draft.xh>
  158. #endif
  159.  
  160. #ifndef SOM_ODStorageUnit_xh
  161. #include <StorageU.xh>
  162. #endif
  163.  
  164. #ifndef SOM_Module_OpenDoc_StdProps_defined
  165. #include <StdProps.xh>
  166. #endif
  167.  
  168. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  169. #include <StdTypes.xh>
  170. #endif
  171.  
  172. #ifndef __ERRORS__
  173. #include <Errors.h>
  174. #endif
  175.  
  176. #ifndef _ODUTILS_
  177. #include <ODUtils.h>
  178. #endif
  179.  
  180. #ifndef _STDTYPIO_
  181. #include <StdTypIO.h>
  182. #endif
  183.  
  184. #ifndef _DOCUTILS_
  185. #include <DocUtils.h>
  186. #endif
  187.  
  188. #ifndef _STORUTIL_
  189. #include <StorUtil.h>
  190. #endif
  191.  
  192. #ifndef _ODDEBUG_
  193. #include <ODDebug.h>
  194. #endif
  195.  
  196. #ifndef _TEMPOBJ_
  197. #include "TempObj.h"
  198. #endif
  199.  
  200. #pragma segment ODBaseLink
  201.  
  202. //==============================================================================
  203. // Local Classes
  204. //==============================================================================
  205.  
  206. //------------------------------------------------------------------------------
  207. // Class ODPartLink
  208. //------------------------------------------------------------------------------
  209.  
  210. class ODPartLink : public Link {
  211.     public:
  212.         ODPartLink(ODPart* thePart) {fPart = thePart;}
  213.         virtual ~ODPartLink()        {}
  214.         ODPart*    GetPart()            { return fPart;}
  215.     
  216.     private:
  217.         ODPart*    fPart;
  218. };
  219.  
  220. //------------------------------------------------------------------------------
  221. // Class ODPartList
  222. //------------------------------------------------------------------------------
  223.  
  224. class ODPartList
  225. {
  226.     friend class ODPartListIterator;
  227.     
  228.     public:
  229.  
  230.         ODPartList()            {}
  231.         virtual ~ODPartList()    {this->RemoveAllParts(somGetGlobalEnvironment());}
  232.  
  233.         virtual ODBoolean    ContainsPart(Environment *ev, ODPart* thePart);
  234.         virtual ODBoolean    AddPart(Environment *ev, ODPart* thePart);
  235.         virtual void        AddPartList(Environment *ev, ODPartList* thePartList);
  236.         virtual void        RemovePart(Environment *ev, ODPart* thePart);
  237.         virtual void        RemovePartList(Environment *ev, ODPartList* thePartList);
  238.         virtual void        RemoveAllParts(Environment *ev);
  239.  
  240.     private:
  241.  
  242.         LinkedList    fImplementation;
  243. };
  244.  
  245. //------------------------------------------------------------------------------
  246. // Class ODPartListIterator
  247. //------------------------------------------------------------------------------
  248.  
  249. class ODPartListIterator
  250. {
  251. public:
  252.  
  253.     ODPartListIterator(ODPartList* partList)
  254.         : fIterator(&(partList->fImplementation))
  255.         {}
  256.     ODVMethod ~ODPartListIterator()
  257.         {}
  258.     
  259.     ODMethod ODPart* First();
  260.     ODMethod ODPart* Next();
  261.     ODMethod ODBoolean IsNotComplete();
  262.     
  263. private:
  264.     
  265.     LinkedListIterator fIterator;
  266.     
  267. };
  268.  
  269. //------------------------------------------------------------------------------
  270. // ODPartList::ContainsPart
  271. //------------------------------------------------------------------------------
  272.  
  273. ODBoolean ODPartList::ContainsPart(Environment *ev, ODPart* thePart)
  274. {
  275.     ODBoolean result = kODFalse;
  276.     ODPartListIterator iter(this);
  277.  
  278.     for (ODPart* part = iter.First(); (result == kODFalse) && iter.IsNotComplete(); part = iter.Next())
  279.     {
  280.         result = ODObjectsAreEqual(ev, part, thePart);
  281.     }
  282.  
  283.     return result;
  284. }
  285.  
  286. //------------------------------------------------------------------------------
  287. // ODPartList::AddPart
  288. //------------------------------------------------------------------------------
  289.  
  290. ODBoolean ODPartList::AddPart(Environment *ev, ODPart* thePart)
  291. {
  292.     ODBoolean notPresent = !this->ContainsPart(ev, thePart);
  293.     if ( notPresent )
  294.     {
  295.         ODPartLink* aLink = new ODPartLink(thePart);
  296.         thePart->Acquire(ev);
  297.         fImplementation.AddLast(aLink);
  298.     }
  299.     
  300.     return notPresent;
  301. }
  302.  
  303. //------------------------------------------------------------------------------
  304. // ODPartList::AddPartList
  305. //------------------------------------------------------------------------------
  306.  
  307. void ODPartList::AddPartList(Environment *ev, ODPartList* thePartList)
  308. {
  309.     if ( thePartList )
  310.     {
  311.         ODPartListIterator iter(thePartList);
  312.     
  313.         for (ODPart* thePart = iter.First(); iter.IsNotComplete(); thePart = iter.Next())
  314.         {
  315.             this->AddPart(ev, thePart);
  316.         }
  317.     }
  318. }
  319.  
  320. //------------------------------------------------------------------------------
  321. // ODPartList::RemovePart
  322. //------------------------------------------------------------------------------
  323.  
  324. void ODPartList::RemovePart(Environment *ev, ODPart* thePart)
  325. {
  326.     LinkedListIterator iter(&fImplementation);
  327.  
  328.     ODPartLink* aLink = (ODPartLink*)iter.First();
  329.     while (aLink != NULL)
  330.     {
  331.         ODPart* part = aLink->GetPart();
  332.         if ( ODObjectsAreEqual(ev, part, thePart) )
  333.         {
  334.             fImplementation.Remove(*aLink);
  335.             aLink = NULL;
  336.             part->Release(ev);
  337.         }
  338.         else
  339.             aLink = (ODPartLink*)iter.Next();
  340.     }
  341. }
  342.  
  343. //------------------------------------------------------------------------------
  344. // ODPartList::RemovePartList
  345. //------------------------------------------------------------------------------
  346.  
  347. void ODPartList::RemovePartList(Environment *ev, ODPartList* thePartList)
  348. {
  349.     if ( thePartList )
  350.     {
  351.         ODPartListIterator iter(thePartList);
  352.     
  353.         for (ODPart* thePart = iter.First(); iter.IsNotComplete(); thePart = iter.Next())
  354.         {
  355.             this->RemovePart(ev, thePart);
  356.         }
  357.     }
  358. }
  359.  
  360. //------------------------------------------------------------------------------
  361. // ODPartList::RemoveAllParts
  362. //------------------------------------------------------------------------------
  363.  
  364. void ODPartList::RemoveAllParts(Environment *ev)
  365. {
  366.     ODPartLink* aLink = (ODPartLink*) fImplementation.RemoveFirst();
  367.     while (aLink != kODNULL)
  368.     {
  369.         ODPart* part = aLink->GetPart();
  370.         part->Release(ev);
  371.         delete aLink;
  372.         aLink = (ODPartLink*) fImplementation.RemoveFirst();
  373.     }
  374. }
  375.  
  376. //------------------------------------------------------------------------------
  377. // ODPartListIterator::First
  378. //------------------------------------------------------------------------------
  379.  
  380. ODPart* ODPartListIterator::First()
  381. {
  382.     ODPart* part = kODNULL;
  383.     ODPartLink* partLink = (ODPartLink*) fIterator.First();
  384.     
  385.     if ( partLink )
  386.         part = partLink->GetPart();
  387.     
  388.     return part;
  389. }
  390.  
  391. //------------------------------------------------------------------------------
  392. // ODPartListIterator::Next
  393. //------------------------------------------------------------------------------
  394.  
  395. ODPart* ODPartListIterator::Next()
  396. {
  397.     ODPart* part = kODNULL;
  398.     ODPartLink* partLink = (ODPartLink*) fIterator.Next();
  399.     
  400.     if ( partLink )
  401.         part = partLink->GetPart();
  402.     
  403.     return part;
  404. }
  405.  
  406. //------------------------------------------------------------------------------
  407. // ODPartListIterator::IsNotComplete
  408. //------------------------------------------------------------------------------
  409.  
  410. ODBoolean ODPartListIterator::IsNotComplete()
  411. {
  412.     return fIterator.IsNotComplete();
  413. }
  414.  
  415. //==============================================================================
  416. // ODBaseLink
  417. //==============================================================================
  418.  
  419. //------------------------------------------------------------------------------
  420. // ODBaseLink: somUninit
  421. //------------------------------------------------------------------------------
  422.  
  423. SOM_Scope void  SOMLINK ODBaseLinksomUninit(ODBaseLink *somSelf)
  424. {
  425.     /* ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf); */
  426.     ODBaseLinkMethodDebug("ODBaseLink","somUninit");
  427.  
  428.     parent_somUninit(somSelf);
  429. }
  430.  
  431. //------------------------------------------------------------------------------
  432. // ODBaseLink: InitBaseLink
  433. //------------------------------------------------------------------------------
  434.  
  435. SOM_Scope void  SOMLINK ODBaseLinkInitBaseLink(ODBaseLink *somSelf, Environment *ev,
  436.         ODStorageUnit* storageUnit)
  437. {
  438.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  439.     ODBaseLinkMethodDebug("ODBaseLink","InitBaseLink");
  440.  
  441.     SOM_CATCH return;
  442.  
  443.     /* Moved from somInit. SOM itself sets fields to zero
  444.     _fPartList = (ODPartList*) kODNULL;
  445.     _fLinkSource = (ODLinkSource*) kODNULL;
  446.     _fDirty = kODFalse;
  447.     _fIterationInProgress = kODFalse;
  448.     _fRestartIteration = kODFalse;
  449.     */
  450.     somSelf->InitPersistentObject(ev, storageUnit);
  451.  
  452.     _fPartList = new ODPartList();
  453.  
  454.     ODStorageUnit* su = somSelf->GetStorageUnit(ev);
  455.     ODSUAddPropValue(ev, su, kODPropLinkSource, kODWeakStorageUnitRef);
  456.  
  457.     somSelf->SetBaseLinkDirty(ev);
  458. }
  459.  
  460. //------------------------------------------------------------------------------
  461. // ODBaseLink: InitBaseLinkFromStorage
  462. //------------------------------------------------------------------------------
  463.  
  464. SOM_Scope void  SOMLINK ODBaseLinkInitBaseLinkFromStorage(ODBaseLink *somSelf, Environment *ev,
  465.         ODStorageUnit* storageUnit)
  466. {
  467.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  468.     ODBaseLinkMethodDebug("ODBaseLink","InitBaseLinkFromStorage");
  469.  
  470.     SOM_CATCH return;
  471.  
  472.     /* Moved from somInit. SOM itself sets fields to zero
  473.     _fPartList = (ODPartList*) kODNULL;
  474.     _fLinkSource = (ODLinkSource*) kODNULL;
  475.     _fDirty = kODFalse;
  476.     _fIterationInProgress = kODFalse;
  477.     _fRestartIteration = kODFalse;
  478.     */
  479.     somSelf->InitPersistentObjectFromStorage(ev, storageUnit);
  480.  
  481.     _fPartList = new ODPartList();
  482.     
  483.     if ( storageUnit->Exists(ev, kODPropLinkSource, 0, 0) )
  484.     {
  485.         ODID linkSourceID = ODGetWeakSURefProp(ev, storageUnit, kODPropLinkSource, kODWeakStorageUnitRef);
  486.         if ( linkSourceID == kODNULLID )
  487.             somSelf->SetBaseLinkDirty(ev);
  488.         else
  489.             _fLinkSource = storageUnit->GetDraft(ev)->AcquireLinkSource(ev, linkSourceID);
  490.     }
  491. }
  492.  
  493. //------------------------------------------------------------------------------
  494. // ODBaseLink: Externalize (OVERRIDE)
  495. //------------------------------------------------------------------------------
  496.  
  497. SOM_Scope void  SOMLINK ODBaseLinkExternalize(ODBaseLink *somSelf, Environment *ev)
  498. {
  499.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  500.     ODBaseLinkMethodDebug("ODBaseLink","Externalize");
  501.  
  502.     SOM_CATCH return;
  503.  
  504.     parent_Externalize(somSelf,ev);
  505.  
  506.     if ( _fDirty )
  507.     {
  508.         ODStorageUnit* su = somSelf->GetStorageUnit(ev);
  509.     
  510.         if ( _fLinkSource == (ODLinkSource*) kODNULL )
  511.             ODSURemoveProperty(ev, su, kODPropLinkSource);
  512.         else
  513.             ODSetWeakSURefProp(ev, su, kODPropLinkSource, kODWeakStorageUnitRef, _fLinkSource->GetID(ev));
  514.  
  515.         _fDirty = kODFalse;
  516.     }
  517. }
  518.  
  519. //------------------------------------------------------------------------------
  520. // ODBaseLink: CloneInto (OVERRIDE)
  521. //------------------------------------------------------------------------------
  522.  
  523. SOM_Scope void  SOMLINK ODBaseLinkCloneInto(ODBaseLink *somSelf, Environment *ev,
  524.         ODDraftKey key,
  525.         ODStorageUnit* toSU,
  526.         ODFrame* scopeFrame)
  527. {
  528.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  529.     ODBaseLinkMethodDebug("ODBaseLink","CloneInto");
  530.  
  531.     SOM_CATCH return;
  532.     
  533.     // If one of our properties already exists, this object has been cloned already
  534.     if ( toSU->Exists(ev, kODPropLinkSource, kODWeakStorageUnitRef, 0) )
  535.         return;
  536.  
  537.     parent_CloneInto(somSelf, ev, key, toSU, scopeFrame);
  538.  
  539.     if ( _fLinkSource != (ODLinkSource*) kODNULL )
  540.     {
  541.         ODDraft* draft = somSelf->GetStorageUnit(ev)->GetDraft(ev);
  542.         ODID clonedLinkSourceID = draft->WeakClone(ev, key, _fLinkSource->GetID(ev), 0, 
  543.                                                 (scopeFrame ? scopeFrame->GetID(ev) : 0));
  544.     
  545.         ODSetWeakSURefProp(ev, toSU, kODPropLinkSource, kODWeakStorageUnitRef, clonedLinkSourceID);
  546.     }
  547. }
  548.  
  549. //------------------------------------------------------------------------------
  550. // ODBaseLink: ReleaseAll (OVERRIDE)
  551. //------------------------------------------------------------------------------
  552.  
  553. SOM_Scope void  SOMLINK ODBaseLinkReleaseAll(ODBaseLink *somSelf, Environment *ev)
  554. {
  555.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  556.     ODBaseLinkMethodDebug("ODBaseLink","ReleaseAll");
  557.  
  558.     SOM_CATCH return;
  559.  
  560.     parent_ReleaseAll(somSelf,ev);
  561.  
  562.     ODReleaseObject(ev, _fLinkSource);
  563.  
  564.     // Release all part references stored in the list of registered parts
  565.     ODDeleteObject(_fPartList);
  566. }
  567.  
  568. //------------------------------------------------------------------------------
  569. // ODBaseLink: SetBaseLinkDirty
  570. //------------------------------------------------------------------------------
  571.  
  572. SOM_Scope void  SOMLINK ODBaseLinkSetBaseLinkDirty(ODBaseLink *somSelf, Environment *ev)
  573. {
  574.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  575.     ODBaseLinkMethodDebug("ODBaseLink","SetBaseLinkDirty");
  576.  
  577.     SOM_TRY    
  578.         _fDirty = kODTrue;
  579.  
  580.         ODDraft* draft = somSelf->GetStorageUnit(ev)->GetDraft(ev);
  581.         if ( draft->GetPermissions(ev) != kODDPReadOnly )
  582.             draft->SetChangedFromPrev(ev);
  583.     SOM_CATCH_ALL
  584.     SOM_ENDTRY
  585. }
  586.  
  587. //------------------------------------------------------------------------------
  588. // ODBaseLink::ShowLinkDestinationInfo
  589. //------------------------------------------------------------------------------
  590.  
  591. SOM_Scope ODBoolean  SOMLINK ODBaseLinkShowLinkDestinationInfo(ODBaseLink *somSelf, Environment *ev,
  592.         ODFacet* facet,
  593.         ODLinkInfo* info,
  594.         ODBoolean changesAllowed,
  595.         ODLinkInfoResult* infoResult)
  596. {
  597.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  598.     ODBaseLinkMethodDebug("ODBaseLink","ShowLinkDestinationInfo");
  599.  
  600.     ODBoolean result = kODFalse;
  601.  
  602.     SOM_CATCH return kODFalse;
  603.  
  604.     THROW_IF_NULL(facet, kODErrNullFacetInput);
  605.     THROW_IF_NULL(info, kODErrNullLinkInfoInput);
  606.     THROW_IF_NULL(infoResult, kODErrNullLinkInfoResultInput);
  607.     THROW_IF_NULL(_fLinkSource, kODErrBrokenLink);
  608.  
  609.     ODSession* session = somSelf->GetStorageUnit(ev)->GetSession(ev);
  610.     ODTypeToken modalFocus = session->Tokenize(ev, kODModalFocus);
  611.     ODArbitrator* arbitrator = session->GetArbitrator(ev);
  612.     TempODFrame currentOwner = arbitrator->AcquireFocusOwner(ev, modalFocus);
  613.  
  614.     if ( arbitrator->RequestFocus(ev, modalFocus, facet->GetFrame(ev)) )
  615.     {
  616.         infoResult->autoUpdate = info->autoUpdate;
  617.     
  618.         session->GetWindowState(ev)->DeactivateFrontWindows(ev);
  619.  
  620.         result = ShowLinkDestinationInfo(somSelf, info, changesAllowed, infoResult);
  621.  
  622.         session->GetWindowState(ev)->ActivateFrontWindows(ev);
  623.  
  624.         arbitrator->TransferFocus(ev, modalFocus, facet->GetFrame(ev), currentOwner);
  625.     }
  626.     else
  627.     {
  628.         SysBeep(2);
  629.     }
  630.     return result;
  631. }
  632.  
  633. //------------------------------------------------------------------------------
  634. // ODBaseLink: Lock
  635. //------------------------------------------------------------------------------
  636.  
  637. SOM_Scope ODBoolean  SOMLINK ODBaseLinkLock(ODBaseLink *somSelf, Environment *ev,
  638.         ODULong wait,
  639.         ODLinkKey* key)
  640. {
  641.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  642.     ODBaseLinkMethodDebug("ODBaseLink","Lock");
  643.  
  644.     SOM_CATCH return kODFalse;
  645.  
  646.     THROW_IF_NULL(_fLinkSource, kODErrBrokenLink);
  647.  
  648.     return _fLinkSource->Lock(ev, wait, key);
  649. }
  650.  
  651. //------------------------------------------------------------------------------
  652. // ODBaseLink: Unlock
  653. //------------------------------------------------------------------------------
  654.  
  655. SOM_Scope void  SOMLINK ODBaseLinkUnlock(ODBaseLink *somSelf, Environment *ev,
  656.         ODLinkKey key)
  657. {
  658.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  659.     ODBaseLinkMethodDebug("ODBaseLink","Unlock");
  660.  
  661.     SOM_CATCH return;
  662.  
  663.     THROW_IF_NULL(_fLinkSource, kODErrBrokenLink);
  664.  
  665.     _fLinkSource->Unlock(ev, key);
  666. }
  667.  
  668. //------------------------------------------------------------------------------
  669. // ODBaseLink: KeyValid
  670. //------------------------------------------------------------------------------
  671.  
  672. SOM_Scope void  SOMLINK ODBaseLinkKeyValid(ODBaseLink *somSelf, Environment *ev,
  673.         ODLinkKey key)
  674. {
  675.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  676.     ODBaseLinkMethodDebug("ODBaseLink","KeyValid");
  677.  
  678.     SOM_CATCH return;
  679.  
  680.     THROW_IF_NULL(_fLinkSource, kODErrBrokenLink);
  681.  
  682.     _fLinkSource->KeyValid(ev, key);
  683. }
  684.  
  685. //------------------------------------------------------------------------------
  686. // ODBaseLink: GetContentStorageUnit
  687. //------------------------------------------------------------------------------
  688.  
  689. SOM_Scope ODStorageUnit*  SOMLINK ODBaseLinkGetContentStorageUnit(ODBaseLink *somSelf, Environment *ev,
  690.         ODLinkKey key)
  691. {
  692.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  693.     ODBaseLinkMethodDebug("ODBaseLink","GetContentStorageUnit");
  694.  
  695.     SOM_CATCH return (ODStorageUnit*) kODNULL;
  696.  
  697.     THROW_IF_NULL(_fLinkSource, kODErrBrokenLink);
  698.  
  699.     if ( _fLinkSource->GetStatus(ev) == kODErrCannotEstablishLink )
  700.         THROW(kODErrCannotEstablishLink);
  701.  
  702.     ODStorageUnit* su = _fLinkSource->GetContentStorageUnit(ev, key);
  703.  
  704.     if ( su && !su->Exists(ev, kODPropContents, kODNULL, 1) )
  705.         THROW(kODErrNoLinkContent);
  706.  
  707.     return su;
  708. }
  709.  
  710. //------------------------------------------------------------------------------
  711. // ODBaseLink: RegisterDependent
  712. //------------------------------------------------------------------------------
  713.  
  714. SOM_Scope void  SOMLINK ODBaseLinkRegisterDependent(ODBaseLink *somSelf, Environment *ev,
  715.         ODPart* clientPart,
  716.         ODUpdateID id)
  717. {
  718.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  719.     ODBaseLinkMethodDebug("ODBaseLink","RegisterDependent");
  720.  
  721.     // This method does nothing if clientPart is already registered or
  722.     // if draft is read-only.
  723.  
  724.     SOM_TRY
  725.  
  726.         THROW_IF_NULL(_fLinkSource, kODErrBrokenLink);
  727.     
  728.         THROW_IF_NULL(_fPartList, kODErrCannotRegisterDependent);
  729.  
  730.         ODDraftPermissions permissions = somSelf->GetStorageUnit(ev)->GetDraft(ev)->GetPermissions(ev);
  731.  
  732.         if (HAS_WRITE_ACCESS(permissions))
  733.         {
  734.             if ( _fPartList->AddPart(ev, clientPart) )
  735.             {
  736.                 ODUpdateID currentID = somSelf->GetUpdateID(ev);
  737.                 if ( (currentID != kODUnknownUpdate) && (id != currentID) )
  738.                     clientPart->LinkUpdated(ev, (ODLink*) somSelf, currentID);
  739.             }
  740.         }
  741.  
  742.     SOM_CATCH_ALL
  743.     
  744.     SOM_ENDTRY
  745. }
  746.  
  747. //------------------------------------------------------------------------------
  748. // ODBaseLink: UnregisterDependent
  749. //------------------------------------------------------------------------------
  750.  
  751. SOM_Scope void  SOMLINK ODBaseLinkUnregisterDependent(ODBaseLink *somSelf, Environment *ev,
  752.         ODPart* clientPart)
  753. {
  754.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  755.     ODBaseLinkMethodDebug("ODBaseLink","UnregisterDependent");
  756.  
  757.     SOM_TRY
  758.  
  759.         // If fPartList is null, this object's ReleaseAll() has been called
  760.         //   and already unregistered any dependents.
  761.         if ( _fPartList )
  762.             _fPartList->RemovePart(ev, clientPart);
  763.  
  764.     SOM_CATCH_ALL
  765.     
  766.     SOM_ENDTRY
  767. }
  768.  
  769. //------------------------------------------------------------------------------
  770. // ODBaseLink: GetUpdateID
  771. //------------------------------------------------------------------------------
  772.  
  773. SOM_Scope ODUpdateID  SOMLINK ODBaseLinkGetUpdateID(ODBaseLink *somSelf, Environment *ev)
  774. {
  775.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  776.     ODBaseLinkMethodDebug("ODBaseLink","GetUpdateID");
  777.  
  778.     SOM_TRY
  779.     
  780.     if ( _fLinkSource == (ODLinkSource*) kODNULL )
  781.         THROW(kODErrBrokenLink);
  782.  
  783.     return _fLinkSource->GetUpdateID(ev);
  784.  
  785.     SOM_CATCH_ALL
  786.     SOM_ENDTRY
  787.     return kODUnknownUpdate;
  788. }
  789.  
  790. //------------------------------------------------------------------------------
  791. // ODBaseLink: GetChangeTime
  792. //------------------------------------------------------------------------------
  793.  
  794. SOM_Scope ODTime  SOMLINK ODBaseLinkGetChangeTime(ODBaseLink *somSelf, Environment *ev)
  795. {
  796.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  797.     ODBaseLinkMethodDebug("ODBaseLink","GetChangeTime");
  798.     
  799.     SOM_TRY
  800.  
  801.     if ( _fLinkSource == (ODLinkSource*) kODNULL )
  802.         THROW(kODErrBrokenLink);
  803.  
  804.     return _fLinkSource->GetChangeTime(ev);
  805.     
  806.     SOM_CATCH_ALL
  807.     SOM_ENDTRY
  808.     return (ODTime)0;
  809. }
  810.  
  811. //------------------------------------------------------------------------------
  812. // ODBaseLink: SetLinkSource
  813. //------------------------------------------------------------------------------
  814.  
  815. SOM_Scope void  SOMLINK ODBaseLinkSetLinkSource(ODBaseLink *somSelf, Environment *ev,
  816.         ODLinkSource* linkSource)
  817. {
  818.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  819.     ODBaseLinkMethodDebug("ODBaseLink","SetLinkSource");
  820.  
  821.     SOM_CATCH return;
  822.     
  823.     if ( !ODObjectsAreEqual(ev, _fLinkSource, linkSource) )
  824.     {
  825.         ODReleaseObject(ev, _fLinkSource);
  826.  
  827.         _fLinkSource = linkSource;
  828.         if ( _fLinkSource != (ODLinkSource*) kODNULL )
  829.             _fLinkSource->Acquire(ev);
  830.  
  831.         somSelf->SetBaseLinkDirty(ev);
  832.     }
  833. }
  834.  
  835. //------------------------------------------------------------------------------
  836. // ODBaseLink: GetLinkSource
  837. //------------------------------------------------------------------------------
  838.  
  839. SOM_Scope ODLinkSource*  SOMLINK ODBaseLinkGetLinkSource(ODBaseLink *somSelf, Environment *ev)
  840. {
  841.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  842.     ODBaseLinkMethodDebug("ODBaseLink","GetLinkSource");
  843.  
  844.     if ( _fLinkSource == (ODLinkSource*) kODNULL )
  845.     {
  846.         ODSetSOMException(ev, kODErrBrokenLink);
  847.         return (ODLinkSource*) kODNULL;
  848.     }
  849.  
  850.     return _fLinkSource;
  851. }
  852.  
  853. //------------------------------------------------------------------------------
  854. // ODBaseLink: ShowSourceContent
  855. //------------------------------------------------------------------------------
  856.  
  857. SOM_Scope void  SOMLINK ODBaseLinkShowSourceContent(ODBaseLink *somSelf, Environment *ev)
  858. {
  859.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  860.     ODBaseLinkMethodDebug("ODBaseLink","ShowSourceContent");
  861.  
  862.     SOM_CATCH return;
  863.  
  864.     THROW_IF_NULL(_fLinkSource, kODErrBrokenLink);
  865.  
  866.     _fLinkSource->ShowSourceContent(ev);
  867. }
  868.  
  869. //------------------------------------------------------------------------------
  870. // ODBaseLink: UpdateDependents
  871. //------------------------------------------------------------------------------
  872.  
  873. SOM_Scope void  SOMLINK ODBaseLinkUpdateDependents(ODBaseLink *somSelf, Environment *ev)
  874. {
  875.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  876.     ODBaseLinkMethodDebug("ODBaseLink","UpdateDependents");
  877.  
  878.     if ( _fIterationInProgress )
  879.     {
  880.         _fRestartIteration = kODTrue;
  881.         return;
  882.     }
  883.  
  884.     _fIterationInProgress = kODTrue;
  885.  
  886.     SOM_TRY
  887.  
  888.         do
  889.         {
  890.             _fRestartIteration = kODFalse;
  891.     
  892.             ODPartList registeredParts;
  893.             registeredParts.AddPartList(ev, _fPartList);
  894.  
  895.             ODPartListIterator iter(®isteredParts);
  896.         
  897.             for (ODPart* clientPart = iter.First();
  898.                  !_fRestartIteration && iter.IsNotComplete();
  899.                  clientPart = iter.Next())
  900.             {
  901.                 // Don't call LinkUpdated if part has unregistered during iteration.
  902.                 if ( _fPartList->ContainsPart(ev, clientPart) )
  903.                 {
  904.                     // Ignore any errors returned from a part's LinkUpdated method
  905.                     TRY
  906.                         clientPart->LinkUpdated(ev, (ODLink*) somSelf, somSelf->GetUpdateID(ev));
  907.                     CATCH_ALL
  908.                     ENDTRY
  909.                 }
  910.             }
  911.             
  912.         } while ( _fRestartIteration );
  913.  
  914.     SOM_CATCH_ALL
  915.     
  916.     SOM_ENDTRY
  917.  
  918.     _fIterationInProgress = kODFalse;
  919. }
  920.