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 / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / Storage / Link.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  24.0 KB  |  893 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Link.cpp
  3.  
  4.     Contains:    Implementation of ODLink class
  5.  
  6.     Owned by:    Craig Carper
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <4>     5/24/96    jpa        1246074: SOM_CATCH --> SOM_TRY..SOM_ENDTRY
  13.          <3>     3/19/96    TJ        Included TempObj.h
  14.          <2>     3/15/96    CC        1331422: CreateLinkEdition & GetLinkEdition
  15.                                     return an ODByteArray instead of an
  16.                                     uncopied  handle.
  17.  
  18.     To Do:
  19.     In Progress:
  20.         
  21. */
  22.  
  23. #define VARIABLE_MACROS
  24.  
  25. #define ODLink_Class_Source
  26. #include <Link.xih>
  27.  
  28. #ifndef _LINKDLGS_
  29. #include <LinkDlgs.h>
  30. #endif
  31.  
  32. #ifndef _EXCEPT_
  33. #include <Except.h>
  34. #endif
  35.  
  36. #ifndef _ODMEMORY_
  37. #include <ODMemory.h>
  38. #endif
  39.  
  40. #ifndef _CONSTDEF_
  41. #include <ConstDef.h>
  42. #endif
  43.  
  44. #ifndef SOM_ODLinkSource_xh
  45. #include <LinkSrc.xh>
  46. #endif
  47.  
  48. #ifndef SOM_ODLinkManager_xh
  49. #include <LinkMgr.xh>
  50. #endif
  51.  
  52. #ifndef SOM_ODPart_xh
  53. #include <Part.xh>
  54. #endif
  55.  
  56. #ifndef SOM_ODSession_xh
  57. #include <ODSessn.xh>
  58. #endif
  59.  
  60. #ifndef SOM_ODContainer_xh
  61. #include <ODCtr.xh>
  62. #endif
  63.  
  64. #ifndef SOM_ODDocument_xh
  65. #include <Document.xh>
  66. #endif
  67.  
  68. #ifndef SOM_ODDraft_xh
  69. #include <Draft.xh>
  70. #endif
  71.  
  72. #ifndef SOM_ODStorageSystem_xh
  73. #include <ODStor.xh>
  74. #endif
  75.  
  76. #ifndef _PLFMFILE_
  77. #include <PlfmFile.h>
  78. #endif
  79.  
  80. #ifndef SOM_ODStorageUnit_xh
  81. #include <StorageU.xh>
  82. #endif
  83.  
  84. #ifndef SOM_Module_OpenDoc_StdProps_defined
  85. #include <StdProps.xh>
  86. #endif
  87.  
  88. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  89. #include <StdTypes.xh>
  90. #endif
  91.  
  92. #ifndef __ERRORS__
  93. #include <Errors.h>
  94. #endif
  95.  
  96. #ifndef _ODDEBUG_
  97. #include <ODDebug.h>
  98. #endif
  99.  
  100. #ifndef _BARRAY_
  101. #include <BArray.h>
  102. #endif
  103.  
  104. #ifndef _STDTYPIO_
  105. #include <StdTypIO.h>
  106. #endif
  107.  
  108. #ifndef _STORUTIL_
  109. #include <StorUtil.h>
  110. #endif
  111.  
  112. #ifndef SOM_ODTranslation_xh
  113. #include <Translt.xh>
  114. #endif
  115.  
  116. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  117. #include <StdDefs.xh>
  118. #endif
  119.  
  120. #ifndef _TEMPOBJ_
  121. #include "TempObj.h"
  122. #endif
  123.  
  124. #if ODDebug
  125. #define ODDebugLink 1
  126. #else
  127. #define ODDebugLink 0
  128. #endif
  129.  
  130. #pragma segment ODLink
  131.  
  132. //==============================================================================
  133. // Local Functions
  134. //==============================================================================
  135.  
  136. static ODBoolean IsTopDraft(Environment* ev, ODDraft* draft);
  137.  
  138. //------------------------------------------------------------------------------
  139. // IsTopDraft
  140. //------------------------------------------------------------------------------
  141.  
  142. static ODBoolean IsTopDraft(Environment* ev, ODDraft* draft)
  143. {
  144. #if ODDebugLink
  145.     somPrintf("IsTopDraft: draft refcount is %d\n", draft->GetRefCount(ev));
  146. #endif
  147.  
  148.     return !(draft->GetDocument(ev)->Exists(ev, kODNULLID, draft, kODPosFirstAbove));
  149. }
  150.  
  151. //==============================================================================
  152. // ODLink
  153. //==============================================================================
  154.  
  155. //------------------------------------------------------------------------------
  156. // ODLink: somUninit
  157. //------------------------------------------------------------------------------
  158.  
  159. SOM_Scope void  SOMLINK ODLinksomUninit(ODLink *somSelf)
  160. {
  161.     /* ODLinkData *somThis = ODLinkGetData(somSelf); */
  162.     ODLinkMethodDebug("ODLink","somUninit");
  163.  
  164.     parent_somUninit(somSelf);
  165. }
  166.  
  167. //------------------------------------------------------------------------------
  168. // ODLink: InitLink
  169. //------------------------------------------------------------------------------
  170.  
  171. SOM_Scope void  SOMLINK ODLinkInitLink(ODLink *somSelf, Environment *ev,
  172.         ODStorageUnit* storageUnit)
  173. {
  174.     ODLinkData *somThis = ODLinkGetData(somSelf);
  175.     ODLinkMethodDebug("ODLink","InitLink");
  176.  
  177.     SOM_TRY
  178.  
  179.     /* Moved from somInit. SOM itself sets fields to zero
  180.     _fSection = (SectionHandle) kODNULL;
  181.     _fDirty = kODFalse;
  182.     */
  183.     somSelf->InitBaseLink(ev, storageUnit);
  184.     
  185.     somSelf->SetLinkDirty(ev);
  186.  
  187.     SOM_CATCH_ALL
  188.     SOM_ENDTRY
  189. }
  190.  
  191. //------------------------------------------------------------------------------
  192. // ODLink: InitLinkFromStorage
  193. //------------------------------------------------------------------------------
  194.  
  195. SOM_Scope void  SOMLINK ODLinkInitLinkFromStorage(ODLink *somSelf, Environment *ev,
  196.         ODStorageUnit* storageUnit)
  197. {
  198.     ODLinkData *somThis = ODLinkGetData(somSelf);
  199.     ODLinkMethodDebug("ODLink","InitLinkFromStorage");
  200.  
  201.     SOM_TRY
  202.     
  203.     /* Moved from somInit. SOM itself sets fields to zero
  204.     _fSection = (SectionHandle) kODNULL;
  205.     _fDirty = kODFalse;
  206.     */
  207.     somSelf->InitBaseLinkFromStorage(ev, storageUnit);
  208.  
  209.     if (ODSUExistsThenFocus(ev, storageUnit, kODPropLinkSection, kODApplesect)) 
  210.     {
  211.         const int sectionRecordSize = sizeof(SectionRecord);
  212.  
  213.         if ( storageUnit->GetSize(ev) != sectionRecordSize )
  214.             THROW(kODErrCorruptLink);
  215.  
  216.         AliasHandle alias = kODNULL;
  217.         ODVolatile(alias);
  218.  
  219.         TRY
  220.             _fSection = (SectionHandle) ODNewHandle(sectionRecordSize);
  221.             ODValue theSectionPtr = ODLockHandle((ODHandle) _fSection);
  222.             StorageUnitGetValue(storageUnit, ev, sectionRecordSize, theSectionPtr);
  223.             ODUnlockHandle((ODHandle) _fSection);
  224.             
  225.             if ( (**_fSection).kind != stPublisher )
  226.                 THROW(kODErrCorruptLink);
  227.         
  228.             storageUnit->Focus(ev, kODPropEditionAlias, kODPosUndefined, kODApplealis, (ODValueIndex)0, kODPosUndefined);
  229.             ODULong size = storageUnit->GetSize(ev);
  230.         
  231.             if ( size < sizeof(AliasRecord) )
  232.                 THROW(kODErrCorruptLink);
  233.         
  234.             alias = (AliasHandle) ODNewHandle(size);
  235.             ODValue theAliasPtr = ODLockHandle((ODHandle) alias);
  236.             StorageUnitGetValue(storageUnit, ev, size, theAliasPtr);
  237.             ODUnlockHandle((ODHandle) alias);
  238.         CATCH_ALL
  239.             ODDisposeHandle((ODHandle) _fSection);
  240.             _fSection = (SectionHandle) kODNULL;
  241.             ODDisposeHandle((ODHandle) alias);
  242.             RERAISE;
  243.         ENDTRY
  244.  
  245.         (**_fSection).alias = alias;
  246.         (**_fSection).refCon = (long) somSelf;
  247.  
  248.         if ( IsTopDraft(ev, storageUnit->GetDraft(ev)) )
  249.         {
  250.             if ( IsRegisteredSection(_fSection) != noErr )
  251.             {
  252.                 ODBoolean aliasWasUpdated;
  253.  
  254.                 ODContainer* container = storageUnit->GetDraft(ev)->GetDocument(ev)->GetContainer(ev);;
  255.                 ODFileSpec documentSpec = GetODFileSpecFromContainer(ev, container);
  256.  
  257.                 OSErr error = RegisterSection(&documentSpec, _fSection, &aliasWasUpdated);
  258.                 
  259.                 // For now, ignore any error returned by RegisterSection.  The most likely errors are:
  260.                 //    multiplePublisherWrn = -460,        A Publisher is already registered for that container
  261.                 //    containerNotFoundWrn = -461,        Could not find editionContainer at this time
  262.                 //    containerAlreadyOpenWrn = -462,        Container already opened by this section
  263.                 //    notThePublisherWrn = -463,            Not the first registered publisher for that container
  264.     
  265.                 if ( IsRegisteredSection(_fSection) == noErr )
  266.                     somSelf->Acquire(ev);    // Link must not be deleted untill its section is unregistered!
  267.             }
  268.         }
  269.     }
  270.  
  271.     SOM_CATCH_ALL
  272.     SOM_ENDTRY
  273. }
  274.  
  275. //------------------------------------------------------------------------------
  276. // ODLink: Release (OVERRIDE)
  277. //------------------------------------------------------------------------------
  278.  
  279. SOM_Scope void  SOMLINK ODLinkRelease(ODLink *somSelf, Environment *ev)
  280. {
  281.     ODLinkData *somThis = ODLinkGetData(somSelf);
  282.     ODLinkMethodDebug("ODLink","Release");
  283.  
  284.     SOM_TRY
  285.  
  286.     parent_Release(somSelf, ev);
  287.  
  288. #if ODDebugLink
  289.     somPrintf("ODLink %d::Release: Ref count is %d\n", somSelf->GetID(ev), somSelf->GetRefCount(ev));
  290. #endif
  291.  
  292.     if (somSelf->GetRefCount(ev) == 0)
  293.         somSelf->GetStorageUnit(ev)->GetDraft(ev)->ReleaseLink(ev, somSelf);
  294.  
  295.     SOM_CATCH_ALL
  296.     SOM_ENDTRY
  297. }
  298.  
  299. //------------------------------------------------------------------------------
  300. // ODLink: Externalize (OVERRIDE)
  301. //------------------------------------------------------------------------------
  302.  
  303. SOM_Scope void  SOMLINK ODLinkExternalize(ODLink *somSelf, Environment *ev)
  304. {
  305.     ODLinkData *somThis = ODLinkGetData(somSelf);
  306.     ODLinkMethodDebug("ODLink","Externalize");
  307.  
  308.     SOM_TRY
  309.  
  310.     parent_Externalize(somSelf,ev);
  311.  
  312.     ODStorageUnit* su = somSelf->GetStorageUnit(ev);
  313.  
  314.     if ( _fDirty )
  315.     {
  316.         if ( _fSection == (SectionHandle) kODNULL ) 
  317.         {
  318.             ODSURemoveProperty(ev, su, kODPropLinkSection);
  319.             ODSURemoveProperty(ev, su, kODPropEditionAlias);
  320.         }
  321.         else 
  322.         {
  323.             SectionPtr theSectionPtr = (SectionPtr) ODLockHandle((ODHandle) _fSection);
  324.     
  325.             ODSUForceFocus(ev, su, kODPropLinkSection, kODApplesect);
  326.             StorageUnitSetValue(su, ev, ODGetHandleSize((ODHandle) _fSection), (ODValue) theSectionPtr);
  327.             
  328.             ODValue theAliasPtr = ODLockHandle((ODHandle) theSectionPtr->alias);
  329.             ODSUForceFocus(ev, su, kODPropEditionAlias, kODApplealis);
  330.             StorageUnitSetValue(su, ev, ODGetHandleSize((ODHandle) theSectionPtr->alias), theAliasPtr);
  331.             
  332.             ODUnlockHandle((ODHandle) theSectionPtr->alias);
  333.             ODUnlockHandle((ODHandle) _fSection);
  334.         }
  335.         _fDirty = kODFalse;
  336.     }
  337.  
  338.     SOM_CATCH_ALL
  339.     SOM_ENDTRY
  340. }
  341.  
  342. //------------------------------------------------------------------------------
  343. // ODLink: CloneInto (OVERRIDE)
  344. //------------------------------------------------------------------------------
  345. // We don't clone the cross-document link info, so a second publisher can't be created.
  346. // This depends on this method being called rather than ODStorageUnit::CloneInto().
  347. // Currently, all link objects are internalized when a draft is opened, so this is true.
  348.  
  349. SOM_Scope void  SOMLINK ODLinkCloneInto(ODLink *somSelf, Environment *ev,
  350.         ODDraftKey key,
  351.         ODStorageUnit* toSU,
  352.         ODFrame* scopeFrame)
  353. {
  354.     ODLinkData *somThis = ODLinkGetData(somSelf);
  355.     ODLinkMethodDebug("ODLink","CloneInto");
  356.  
  357.     SOM_TRY
  358.     
  359.     // If one of our properties already exists, this object has been cloned already
  360.     if ( toSU->Exists(ev, kODPropLinkSection, kODApplesect, 0) )
  361.         return;
  362.  
  363.     parent_CloneInto(somSelf, ev, key, toSU, scopeFrame);
  364.  
  365.     SOM_CATCH_ALL
  366.     SOM_ENDTRY
  367. }
  368.  
  369. //------------------------------------------------------------------------------
  370. // ODLink: ReleaseAll (OVERRIDE)
  371. //------------------------------------------------------------------------------
  372.  
  373. SOM_Scope void  SOMLINK ODLinkReleaseAll(ODLink *somSelf, Environment *ev)
  374. {
  375.     ODLinkData *somThis = ODLinkGetData(somSelf);
  376.     ODLinkMethodDebug("ODLink","ReleaseAll");
  377.  
  378.     SOM_TRY
  379.  
  380.     parent_ReleaseAll(somSelf,ev);
  381.  
  382.     if ( _fSection != (SectionHandle) kODNULL ) 
  383.     {
  384.         if ( IsTopDraft(ev, somSelf->GetStorageUnit(ev)->GetDraft(ev)) )
  385.         {
  386.             if ( IsRegisteredSection(_fSection) == noErr )
  387.             {
  388.                 OSErr error = UnRegisterSection(_fSection);
  389.                 somSelf->Release(ev);    // RefCount incremented when section was registered
  390.             }
  391.         }
  392.  
  393.         ODDisposeHandle((ODHandle) (**_fSection).alias);
  394.         ODDisposeHandle((ODHandle) _fSection);
  395.         _fSection = (SectionHandle) kODNULL;
  396.     }
  397.  
  398.     SOM_CATCH_ALL
  399.     SOM_ENDTRY
  400. }
  401.  
  402. //------------------------------------------------------------------------------
  403. // ODBaseLink: UpdateDependents (OVERRIDE)
  404. //------------------------------------------------------------------------------
  405.  
  406. SOM_Scope void  SOMLINK ODLinkUpdateDependents(ODLink *somSelf, Environment *ev)
  407. {
  408.     ODLinkData *somThis = ODLinkGetData(somSelf);
  409.     ODLinkMethodDebug("ODLink","UpdateDependents");
  410.  
  411.     SOM_TRY
  412.  
  413.     parent_UpdateDependents(somSelf, ev);
  414.  
  415.     if ( (_fSection != (SectionHandle) kODNULL) )
  416.     {
  417.         ODBoolean autoUpdate = somSelf->GetLinkSource(ev)->IsAutoUpdate(ev);
  418.         if ( autoUpdate )
  419.         {
  420.             ODLinkManager*    linkManager = somSelf->GetStorageUnit(ev)->GetSession(ev)->GetLinkManager(ev);
  421.             linkManager->ExportOnSave(ev, somSelf, kODTrue);
  422.         }
  423.         else
  424.         {
  425.             ODLinkKey key;
  426.             ODVolatile(key);
  427.             if ( somSelf->Lock(ev, 0, &key) ) 
  428.             {
  429.                 TRY
  430.                     somSelf->UpdateLinkEdition(ev, key);
  431.                 CATCH_ALL
  432.                     somSelf->Unlock(ev, key);
  433.                     RERAISE;
  434.                 ENDTRY
  435.                 somSelf->Unlock(ev, key);
  436.             }
  437.         }
  438.     }
  439.  
  440.     SOM_CATCH_ALL
  441.     SOM_ENDTRY
  442. }
  443.  
  444. //------------------------------------------------------------------------------
  445. // ODLink::ShowLinkDestinationInfo (OVERRIDE)
  446. //------------------------------------------------------------------------------
  447.  
  448. SOM_Scope ODBoolean  SOMLINK ODLinkShowLinkDestinationInfo(ODLink *somSelf, Environment *ev,
  449.         ODFacet* facet,
  450.         ODLinkInfo* info,
  451.         ODBoolean changesAllowed,
  452.         ODLinkInfoResult* infoResult)
  453. {
  454.     ODLinkData *somThis = ODLinkGetData(somSelf);
  455.     ODLinkMethodDebug("ODLink","ShowLinkDestinationInfo");
  456.  
  457.     SOM_TRY
  458.     
  459.     ODLinkSource* linkSource = somSelf->GetLinkSource(ev);
  460.     
  461.     ODError error = linkSource->GetStatus(ev);
  462.  
  463.     if ( error )
  464.         ShowLinkStatusAlert(error);
  465.  
  466.     return parent_ShowLinkDestinationInfo(somSelf, ev, facet, info, changesAllowed, infoResult);
  467.  
  468.     SOM_CATCH_ALL
  469.     SOM_ENDTRY
  470.     return kODFalse;
  471. }
  472.  
  473. //------------------------------------------------------------------------------
  474. // ODLink: SetLinkDirty
  475. //------------------------------------------------------------------------------
  476.  
  477. SOM_Scope void  SOMLINK ODLinkSetLinkDirty(ODLink *somSelf, Environment *ev)
  478. {
  479.     ODLinkData *somThis = ODLinkGetData(somSelf);
  480.     ODLinkMethodDebug("ODLink","SetLinkDirty");
  481.  
  482.     SOM_TRY    
  483.         _fDirty = kODTrue;
  484.  
  485.         ODDraft* draft = somSelf->GetStorageUnit(ev)->GetDraft(ev);
  486.         if ( draft->GetPermissions(ev) != kODDPReadOnly )
  487.             draft->SetChangedFromPrev(ev);
  488.     SOM_CATCH_ALL
  489.     SOM_ENDTRY
  490. }
  491.  
  492. //------------------------------------------------------------------------------
  493. // ODLink: CreateLinkEdition
  494. //------------------------------------------------------------------------------
  495.  
  496. SOM_Scope void  SOMLINK ODLinkCreateLinkEdition(ODLink *somSelf, Environment *ev,
  497.         EditionContainerSpec editionContainer,
  498.         ODFileSpec* documentSpec,
  499.         ODULong sectionID,
  500.         ODLinkKey key,
  501.         ODByteArray* aliasData)
  502. {
  503.     ODLinkData *somThis = ODLinkGetData(somSelf);
  504.     ODLinkMethodDebug("ODLink","CreateLinkEdition");
  505.  
  506.     OSErr error;
  507.     OSErr createError = mFulErr;    // Anything but noErr
  508.     SectionHandle tempSection = kODNULL;
  509.     
  510.     ODVolatile(createError);
  511.     ODVolatile(tempSection);
  512.     ODVolatile(editionContainer);
  513.  
  514.     SOM_TRY
  515.     
  516.         somSelf->KeyValid(ev, key);
  517.     
  518.         // Should throw kODErrCannotCreateLink if linkSource imports
  519.         
  520.         if ( _fSection != kODNULL)
  521.             THROW(kODErrLinkAlreadyExported);    // Internal error
  522.         
  523.         FInfo documentFInfo;
  524.         error = FSpGetFInfo((FSSpecPtr) documentSpec, &documentFInfo);
  525.         THROW_IF_ERROR(error);
  526.     
  527.         createError = CreateEditionContainerFile(&editionContainer.theFile, 
  528.                     documentFInfo.fdCreator, editionContainer.theFileScript);
  529.         THROW_IF_ERROR(createError);
  530.     
  531.         error = NewSection(&editionContainer, (FSSpecPtr) documentSpec, stPublisher, sectionID, pumOnSave, &tempSection);
  532.         if ( (error != noErr) && 
  533.              (error != multiplePublisherWrn) &&
  534.              (error != notThePublisherWrn) ) 
  535.         {
  536.             THROW(error);
  537.         }
  538.     
  539.         (**tempSection).mdDate = (TimeStamp) somSelf->GetChangeTime(ev);
  540.         (**tempSection).refCon = (long) somSelf;
  541.     
  542.         somSelf->WriteLinkEdition(ev, tempSection, (FSSpecPtr) documentSpec, key);
  543.  
  544.         // Edition file was successfully created and written, so add section to persistent state.
  545.         // This Link must not be deleted until its section is unregistered!
  546.         _fSection = tempSection;
  547.         somSelf->Acquire(ev);
  548.  
  549.         somSelf->SetLinkDirty(ev);
  550.     
  551.         TempODHandleLock aHandle((ODHandle) (**_fSection).alias);
  552.         if ( (ODHandle) aHandle )
  553.             *aliasData = CreateByteArrayStruct(*(ODHandle) aHandle, ODGetHandleSize(aHandle));
  554.         
  555.     SOM_CATCH_ALL
  556.  
  557.         if ( createError == noErr )
  558.             DeleteEditionContainerFile(&editionContainer.theFile);
  559.  
  560.         if ( tempSection ) 
  561.         {
  562.             UnRegisterSection(tempSection);
  563.             ODDisposeHandle((ODHandle) (**tempSection).alias);
  564.             ODDisposeHandle((ODHandle) tempSection);
  565.         }
  566.  
  567.     SOM_ENDTRY
  568. }
  569.  
  570. //------------------------------------------------------------------------------
  571. // ODLink: GetLinkEdition
  572. //------------------------------------------------------------------------------
  573.  
  574. SOM_Scope ODBoolean  SOMLINK ODLinkGetLinkEdition(ODLink *somSelf, Environment *ev,
  575.         ODLinkKey key,
  576.         ODByteArray* aliasData)
  577. {
  578.     ODLinkData *somThis = ODLinkGetData(somSelf);
  579.     ODLinkMethodDebug("ODLink","GetLinkEdition");
  580.  
  581.     ODBoolean result = kODFalse;
  582.     
  583.     SOM_TRY
  584.  
  585.         somSelf->KeyValid(ev, key);
  586.     
  587.         if ( _fSection != (SectionHandle) kODNULL )
  588.         {
  589.             TempODHandleLock aHandle((ODHandle) (**_fSection).alias);
  590.             if ( (ODHandle) aHandle )
  591.             {
  592.                 *aliasData = CreateByteArrayStruct(*(ODHandle) aHandle, ODGetHandleSize(aHandle));
  593.                 result = kODTrue;
  594.             }
  595.         }
  596.  
  597.     SOM_CATCH_ALL
  598.     SOM_ENDTRY
  599.  
  600.     return result;
  601. }
  602.  
  603. //------------------------------------------------------------------------------
  604. // ODLink: DeleteLinkEdition
  605. //------------------------------------------------------------------------------
  606.  
  607. SOM_Scope void  SOMLINK ODLinkDeleteLinkEdition(ODLink *somSelf, Environment *ev,
  608.         ODLinkKey key)
  609. {
  610.     ODLinkData *somThis = ODLinkGetData(somSelf);
  611.     ODLinkMethodDebug("ODLink","DeleteLinkEdition");
  612.  
  613.     SOM_TRY
  614.  
  615.     somSelf->KeyValid(ev, key);
  616.  
  617.     if ( _fSection != (SectionHandle) kODNULL )
  618.     {
  619.         if ( IsTopDraft(ev, somSelf->GetStorageUnit(ev)->GetDraft(ev)) )
  620.         {
  621.             FSSpec editionFile;
  622.             ODBoolean wasChanged;
  623.     
  624.             OSErr error = ResolveAlias(nil, (**_fSection).alias, &editionFile, &wasChanged);
  625.             THROW_IF_ERROR(error);
  626.  
  627.             if ( IsRegisteredSection(_fSection) == noErr )
  628.             {
  629.                 error = UnRegisterSection(_fSection);
  630.                 if ( error == noErr )
  631.                     somSelf->Release(ev);    // RefCount incremented when section was registered
  632.             }
  633.  
  634.             error = DeleteEditionContainerFile(&editionFile);
  635.             THROW_IF_ERROR(error);
  636.  
  637.             ODDisposeHandle((ODHandle) (**_fSection).alias);
  638.             ODDisposeHandle((ODHandle) _fSection);
  639.             _fSection = (SectionHandle) kODNULL;
  640.             
  641.             somSelf->SetLinkDirty(ev);
  642.         }
  643.     }
  644.  
  645.     SOM_CATCH_ALL
  646.     SOM_ENDTRY
  647. }
  648.  
  649. //------------------------------------------------------------------------------
  650. // ODLink: UpdateLinkEdition
  651. //------------------------------------------------------------------------------
  652.  
  653. SOM_Scope void  SOMLINK ODLinkUpdateLinkEdition(ODLink *somSelf, Environment *ev,
  654.         ODLinkKey key)
  655. {
  656.     ODLinkData *somThis = ODLinkGetData(somSelf);
  657.     ODLinkMethodDebug("ODLink","UpdateLinkEdition");
  658.  
  659.     SOM_TRY
  660.  
  661.     if (_fSection != (SectionHandle) kODNULL) 
  662.     {
  663.         ODTime changeTime = somSelf->GetChangeTime(ev);
  664.         if ((TimeStamp) changeTime != (**_fSection).mdDate) 
  665.         {
  666.             ODStorageUnit* storageUnit = somSelf->GetStorageUnit(ev);
  667.             ODContainer* container = storageUnit->GetDraft(ev)->GetDocument(ev)->GetContainer(ev);;
  668.             ODFileSpec documentSpec = GetODFileSpecFromContainer(ev, container);
  669.  
  670.             (**_fSection).mdDate = (TimeStamp) changeTime;
  671.             somSelf->WriteLinkEdition(ev, _fSection, &documentSpec, key);
  672.         }
  673.     }
  674.  
  675.     SOM_CATCH_ALL
  676.     SOM_ENDTRY
  677. }
  678.  
  679. //------------------------------------------------------------------------------
  680. // ODLink: GetPlatformValue
  681. //------------------------------------------------------------------------------
  682.  
  683. SOM_Scope ODHandle  SOMLINK ODLinkGetPlatformValue(ODLink *somSelf, Environment *ev,
  684.         ODPlatformType platformType,
  685.         ODLinkKey key)
  686. {
  687.     ODLinkData *somThis = ODLinkGetData(somSelf);
  688.     ODLinkMethodDebug("ODLink","GetPlatformValue");
  689.  
  690.     ODHandle        dataHandle = (ODHandle) kODNULL;
  691.     
  692.     SOM_TRY
  693.     
  694.     ODULong            dataSize;
  695.     ODStorageUnit*    contentSU = somSelf->GetContentStorageUnit(ev, key);
  696.     ODValueType        isoType = kODNULL;
  697.  
  698.     ODVolatile(isoType);
  699.     ODVolatile(dataHandle);
  700.     TRY
  701.         ODTranslation* translation = somSelf->GetStorageUnit(ev)->GetSession(ev)->GetTranslation(ev);
  702.         isoType = translation->GetISOTypeFromPlatformType(ev, platformType, kODPlatformDataType);
  703.  
  704.         if ( ODSUExistsThenFocus(ev, contentSU, kODPropContents, isoType) )
  705.         {
  706.             dataSize = contentSU->GetSize(ev);
  707.             dataHandle = ODNewHandle(dataSize);
  708.             ODValue dataPtr = ODLockHandle(dataHandle);
  709.             StorageUnitGetValue(contentSU, ev, dataSize, dataPtr);
  710.             ODUnlockHandle(dataHandle);
  711.         }
  712.     CATCH_ALL
  713.         ODDisposeHandle(dataHandle);
  714.         dataHandle = (ODHandle) kODNULL;
  715.     ENDTRY
  716.  
  717.     ODDisposePtr(isoType);
  718.     
  719.     SOM_CATCH_ALL
  720.         dataHandle = kODNULL;
  721.     SOM_ENDTRY
  722.  
  723.     return dataHandle;
  724. }
  725.  
  726. //------------------------------------------------------------------------------
  727. // ODLink: CloneToMemoryContainer
  728. //------------------------------------------------------------------------------
  729.  
  730. SOM_Scope ODHandle  SOMLINK ODLinkCloneToMemoryContainer(ODLink *somSelf, Environment *ev,
  731.         ODLinkKey key)
  732. {
  733.     ODLinkData *somThis = ODLinkGetData(somSelf);
  734.     ODLinkMethodDebug("ODLink","CloneToMemoryContainer");
  735.  
  736.     SOM_TRY
  737.  
  738.     ODHandle            containerHandle;
  739.     ODContainer*        container = (ODContainer*) kODNULL;
  740.     ODDocument*            document = (ODDocument*) kODNULL;
  741.     ODDraft*            draft = (ODDraft*) kODNULL;
  742.     ODStorageUnit*        draftProperties = (ODStorageUnit*) kODNULL;
  743.     ODStorageUnit*        contentSU = (ODStorageUnit*) kODNULL;
  744.     ODDraft*            myDraft = somSelf->GetStorageUnit(ev)->GetDraft(ev);
  745.     ODSession*            session = somSelf->GetStorageUnit(ev)->GetSession(ev);
  746.     ODStorageUnitID        rootSUID = 0;
  747.  
  748.     ODVolatile(draft);
  749.     ODVolatile(draftProperties);
  750.     ODVolatile(document);
  751.     ODVolatile(container);
  752.     ODVolatile(containerHandle);
  753.     ODVolatile(myDraft);
  754.     
  755.     contentSU = somSelf->GetContentStorageUnit(ev, key);
  756.  
  757.     // Externalize contentSU to force resolution of promises before the
  758.     // clone into the memory container is begun.
  759.     contentSU->Externalize(ev);
  760.  
  761.     containerHandle = ODNewHandle(0);
  762.     TRY
  763.         container = CreateMemoryContainer(ev, session, containerHandle, kODBentoMemoryContainer);
  764.         
  765.         document = container->AcquireDocument(ev, kODDefaultDocument);
  766.             
  767.         draft = document->AcquireBaseDraft(ev, kODDPExclusiveWrite);
  768.         
  769.         ODDraftKey draftKey = myDraft->BeginClone(ev, draft, kODNULL, kODCloneAll);
  770.         ODVolatile(draftKey);
  771.         TRY
  772.             rootSUID = myDraft->Clone(ev, draftKey, contentSU->GetID(ev), kODNULLID, 0);    
  773.  
  774.             if ( ODSUExistsThenFocus(ev, contentSU, kODPropContentFrame, kODWeakStorageUnitRef) )
  775.             {
  776.                 ODID contentFrameID = ODGetWeakSURefProp(ev, contentSU, kODPropContentFrame, kODWeakStorageUnitRef);
  777.                 myDraft->Clone(ev, draftKey, contentFrameID, kODNULLID, 0);                
  778.             }        
  779.         CATCH_ALL
  780.             myDraft->AbortClone(ev, draftKey);
  781.             RERAISE;
  782.         ENDTRY
  783.         
  784.         myDraft->EndClone(ev, draftKey);
  785.  
  786.         draftProperties = draft->AcquireDraftProperties(ev);
  787.         ODSetStrongSURefProp(ev, draftProperties, kODPropRootPartSU, kODStrongStorageUnitRef, rootSUID);
  788.         draftProperties->Release(ev);
  789.         draftProperties = kODNULL;
  790.  
  791.         draft->Externalize(ev);
  792.         draft->Release(ev);
  793.         document->Release(ev);
  794.         container->Release(ev);
  795.  
  796.     CATCH_ALL
  797.         ODReleaseObject(ev, draftProperties);
  798.         ODReleaseObject(ev, draft);
  799.         ODReleaseObject(ev, document);
  800.         ODReleaseObject(ev, container);
  801.         
  802.         ODDisposeHandle(containerHandle);
  803.         RERAISE;
  804.     ENDTRY
  805.  
  806.     return containerHandle;
  807.  
  808.     SOM_CATCH_ALL
  809.     SOM_ENDTRY
  810.     return (ODHandle) kODNULL;
  811. }
  812.  
  813. //------------------------------------------------------------------------------
  814. // ODLink: WriteLinkEdition
  815. //------------------------------------------------------------------------------
  816.  
  817. SOM_Scope void  SOMLINK ODLinkWriteLinkEdition(ODLink *somSelf, Environment *ev,
  818.         SectionHandle section,
  819.         ODFileSpec* documentSpec,
  820.         ODLinkKey key)
  821. {
  822.     ODLinkData *somThis = ODLinkGetData(somSelf);
  823.     ODLinkMethodDebug("ODLink","WriteLinkEdition");
  824.  
  825.     OSErr            infoError;
  826.     OSErr            openError;
  827.     OSErr            writeError = noErr;
  828.     EditionRefNum    edRefNum = 0;
  829.     ODHandle        dataHandle = (ODHandle) kODNULL;
  830.     ODBoolean        successful = kODTrue;
  831.  
  832.     ODVolatile(dataHandle);
  833.     ODVolatile(successful);
  834.     
  835.     SOM_TRY 
  836.  
  837.         if ( section == (SectionHandle) kODNULL ) 
  838.             THROW(kODErrNotExportedLink);
  839.     
  840.         FInfo documentFInfo;
  841.         infoError = FSpGetFInfo((FSSpecPtr) documentSpec, &documentFInfo);
  842.         THROW_IF_ERROR(infoError);
  843.     
  844.         openError = OpenNewEdition(section, documentFInfo.fdCreator, documentSpec, &edRefNum);
  845.         THROW_IF_ERROR(openError);
  846.     
  847.         dataHandle = somSelf->CloneToMemoryContainer(ev, key);
  848.         if ( dataHandle != (ODHandle) kODNULL ) 
  849.         {
  850.             ODPtr dataPtr = ODLockHandle(dataHandle);
  851.             writeError = WriteEdition(edRefNum, kODScrapTypeODBentoContainer, dataPtr, ODGetHandleSize(dataHandle));
  852.             ODDisposeHandle(dataHandle);
  853.             dataHandle = kODNULL;
  854.         }
  855.         THROW_IF_ERROR(writeError);
  856.     
  857.         // Also write out any text content property (unnecessary for OpenDoc, but allows
  858.         // subscribing by non-OpenDoc applications, and allows the Edition Manager to display
  859.         // content in the GetInfo dialog.
  860.         dataHandle = somSelf->GetPlatformValue(ev, 'TEXT', key);
  861.         if ( dataHandle != (ODHandle) kODNULL ) 
  862.         {
  863.             ODPtr dataPtr = ODLockHandle(dataHandle);
  864.             writeError = WriteEdition(edRefNum, 'TEXT', dataPtr, ODGetHandleSize(dataHandle));
  865.             ODUnlockHandle(dataHandle);
  866.             ODDisposeHandle(dataHandle);
  867.             dataHandle = kODNULL;
  868.         }
  869.         THROW_IF_ERROR(writeError);
  870.  
  871.         dataHandle = somSelf->GetPlatformValue(ev, 'PICT', key);
  872.         if ( dataHandle != (ODHandle) kODNULL ) 
  873.         {
  874.             ODPtr dataPtr = ODLockHandle(dataHandle);
  875.             writeError = WriteEdition(edRefNum, 'PICT', dataPtr, ODGetHandleSize(dataHandle));
  876.             ODUnlockHandle(dataHandle);
  877.             ODDisposeHandle(dataHandle);
  878.             dataHandle = kODNULL;
  879.         }
  880.         THROW_IF_ERROR(writeError);
  881.  
  882.  
  883.     SOM_CATCH_ALL
  884.  
  885.         ODDisposeHandle(dataHandle);
  886.         successful = kODFalse;
  887.  
  888.     SOM_ENDTRY;
  889.  
  890.     if ( edRefNum != 0 )
  891.         CloseEdition(edRefNum, successful);
  892. }
  893.