home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / Implementation / Utilities / DocUtils.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-13  |  37.4 KB  |  1,259 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        DocUtils.cpp
  3.  
  4.     Contains:    code for useful high level Document/Draft utilities
  5.     
  6.                 ******PLEASE NOTE***********
  7.                 
  8.                 The routines provided here are unsupported utilities and may
  9.                 change substantially in the future or be removed from the
  10.                 OpenDoc distribution entirely! You should not use these
  11.                 routines in your code. They make use of certain
  12.                 ODNameSpaces that are not guaranteed to exist in the future.
  13.                 They are also known to not handle exceptions and low-memory
  14.                 conditions well. In
  15.                 general, you should only use these routines for informational
  16.                 purposes. If they provide some functionality that you require,
  17.                 please contact developer support or the OpenDoc team with your
  18.                 concerns.
  19.                 The OpenDoc shell used to use these routines but will no longer
  20.                 be dependent on them.
  21.  
  22.                 ******PLEASE NOTE***********
  23.                 
  24.     Owned by:    Nick Pilch
  25.  
  26.     Copyright:    © 1995 - 1996 by Apple Computer, Inc., all rights reserved.
  27.  
  28.     Change History (most recent first):
  29.  
  30.         <11>     10/5/96    NP        Comments concerning changes to DocUtils.
  31.         <10>    27.09.1996    NP        Comments only
  32.          <9>     9/27/96    EL        1353486: document may become write
  33.                                     protected after opening.
  34.          <8>    20.09.1996    NP        1386078: GetXXXContainer should be
  35.                                     AcquireXXXContainer in StorUtil/1386083:
  36.                                     doc rewrite stuff
  37.          <7>     9/18/96    CSL        1359431: Warn if root part does not create
  38.                                     a root window.
  39.          <6>     7/11/96    TJ        Added ODClearIsUnsavedNewDocument
  40.          <5>      6/6/96    EL        1321410: When document is closed, if it is
  41.                                     an UnsavedNewDocument, delete it.
  42.          <4>     5/31/96    jpa        T10012: ODNewDocument sets file creator
  43.                                     (for CyberDog).
  44.          <3>     5/22/96    EL        #1304982: When reverting document, do not
  45.                                     sync file to prop because file name change
  46.                                     is not consider revertable(for now).
  47.          <2>    .04.1996    NP        1330731: Don't use stationery property
  48.                                     anymore.
  49.  
  50.     To Do:
  51.     In Progress:
  52.         
  53. */
  54.  
  55. #ifndef _DOCUTILS_
  56. #include "DocUtils.h"
  57. #endif
  58.  
  59. #ifndef SOM_ODDispatcher_xh
  60. #include "Disptch.xh"
  61. #endif
  62.  
  63. #ifndef _ODUTILS_
  64. #include <ODUtils.h>
  65. #endif
  66.  
  67. #ifndef _EXCEPT_
  68. #include "Except.h"
  69. #endif
  70.  
  71. #ifndef SOM_ODFrame_xh
  72. #include "Frame.xh"
  73. #endif
  74.  
  75. #ifndef _STDTYPIO_
  76. #include "StdTypIO.h"
  77. #endif
  78.  
  79. #ifndef _TEMPOBJ_
  80. #include "TempObj.h"
  81. #endif
  82.  
  83. #ifndef _INFOUTIL_
  84. #include "InfoUtil.h"
  85. #endif
  86.  
  87. #ifndef _BNDNSUTL_
  88. #include "BndNSUtl.h"
  89. #endif
  90.  
  91. #ifndef _STORUTIL_
  92. #include "StorUtil.h"        // for GetFileContainer, code could be inline instead. -TÇ
  93. #endif
  94.  
  95. #ifndef _REFCTCOL_
  96. #include "RefCtCol.h"
  97. #endif
  98.  
  99. #ifndef SOM_ODDispatcher_xh
  100. #include <Disptch.xh>
  101. #endif
  102.  
  103. #ifndef SOM_ODUndo_xh
  104. #include <Undo.xh>
  105. #endif
  106.  
  107. #ifndef SOM_ODInfo_xh
  108. #include <Info.xh>
  109. #endif
  110.  
  111. #ifndef SOM_ODClipboard_xh
  112. #include <Clipbd.xh>
  113. #endif
  114.  
  115. #ifndef SOM_ODLinkManager_xh
  116. #include <LinkMgr.xh>
  117. #endif
  118.  
  119. #ifndef SOM_ODWindowState_xh
  120. #include <WinStat.xh>
  121. #endif
  122.  
  123. #ifndef SOM_ODWindowIterator_xh
  124. #include <WinIter.xh>
  125. #endif
  126.  
  127. #ifndef SOM_ODPart_xh
  128. #include <Part.xh>
  129. #endif
  130.  
  131. #ifndef SOM_ODStorageUnit_xh
  132. #include <StorageU.xh>
  133. #endif
  134.  
  135. #ifndef SOM_ODDraft_xh
  136. #include <Draft.xh>
  137. #endif
  138.  
  139. #ifndef SOM_ODDocument_xh
  140. #include <Document.xh>
  141. #endif
  142.  
  143. #ifndef SOM_ODContainer_xh
  144. #include <ODCtr.xh>
  145. #endif
  146.  
  147. #ifndef _TIME
  148. #include <time.h>
  149. #endif
  150.  
  151. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  152. #include <StdTypes.xh>
  153. #endif
  154.  
  155. #ifndef SOM_Module_OpenDoc_StdProps_defined
  156. #include <StdProps.xh>
  157. #endif
  158.  
  159. #ifndef SOM_ODSession_xh
  160. #include <ODSessn.xh>
  161. #endif
  162.  
  163. #ifndef SOM_ODObjectNameSpace_xh
  164. #include "ObjectNS.xh"
  165. #endif
  166.  
  167. #ifndef SOM_ODNameSpaceManager_xh
  168. #include <NmSpcMg.xh>
  169. #endif
  170.  
  171. #ifndef SOM_ODObjectIterator_xh
  172. #include <ObjctItr.xh>
  173. #endif
  174.  
  175. #ifndef _NMSPCUTL_
  176. #include <NmSpcUtl.h>
  177. #endif
  178.  
  179. #ifndef __TOOLUTILS__
  180. #include <ToolUtils.h>
  181. #endif
  182.  
  183. #ifndef __ICONS__
  184. #include <Icons.h>
  185. #endif
  186.  
  187. #ifndef _ODDEBUG_
  188. #include "ODDebug.h"
  189. #endif
  190.  
  191. #ifndef _MISCUTIL_
  192. #include "MiscUtil.h"
  193. #endif
  194.  
  195. #include <stdio.h>
  196.  
  197.  
  198. //==============================================================================
  199. // Constants
  200. //==============================================================================
  201.  
  202. const ODISOStr        kODRefNumDocument            =    "RefNumDocument";
  203. const ODISOStr        kODDocumentTempDraft        =    "DocumentTempDraft";
  204.  
  205. const  ODPropertyName kODPropUnsavedDocument    =    "+//ISO 9070/ANSI::113722::US::CI LABS::OpenDoc:Property:UnsavedDocument";
  206. const  ODPropertyName kODPropTempDocument        =    "+//ISO 9070/ANSI::113722::US::CI LABS::OpenDoc:Property:TempDocument";
  207.  
  208.  
  209. static ODUByte gDUHex[] = "0123456789ABCDEF";
  210.  
  211. /* Constants to specify the file fork GetLocalPaths should match */
  212. enum
  213. {
  214.     kDataFork        = 0,
  215.     kResourceFork    = 1
  216. };
  217.  
  218. //==============================================================================
  219. // Local functions
  220. //==============================================================================
  221.  
  222. static void        ODCreateISOStrKeyFromULong(ODULong    uLongKey, char str[9]);
  223. static ODULong    ODGetODULongFromISOStrKey(ODISOStr isoStrKey);
  224. static void SyncFileToProperties(Environment* ev, ODSession* session,
  225.                             ODDocument* document);
  226. static void SyncPropertiesToFile(Environment* ev, ODSession* session,
  227.                             ODDocument* document);
  228. static ODFileRefNum    ODDeduceRefNum(Environment* ev, PlatformFile* file, 
  229.                     ODULong prevRefNumCount, ODSShort* prevRefNums);
  230. static void        ODDocumentClosed(Environment* ev, ODSession* session,
  231.                 ODDocument* document);
  232. //------------------------------------------------------------------------------
  233. // ODDocumentClosed
  234. //    This method updates the appropriate internal namespaces to note that an ODDocument
  235. //    has been closed with the given file refnum.
  236. //    This method simply removes the appropriate entries from the namespaces;
  237. //    The document is released, as is its container.
  238. //    It is up to the caller to make sure that the tempdraft if any
  239. //    is released.
  240. //------------------------------------------------------------------------------
  241.  
  242. //------------------------------------------------------------------------------
  243. // Namespace key utilities
  244. //------------------------------------------------------------------------------
  245.  
  246. void    ODCreateISOStrKeyFromULong(ODULong    uLongKey, char str[9])
  247. {
  248.     sprintf(str,"%.8lX",uLongKey);
  249. /*
  250.     for (ODUByte i = 0; i<sizeof(ODULong); ++i)
  251.     {
  252.         ODUByte b = ((ODUByte*)(&uLongKey))[i];
  253.         ret[i*2] = gDUHex[b / 16];
  254.         ret[i*2 + 1] = gDUHex[b % 16];
  255.     }
  256. */
  257. }
  258.  
  259.  
  260. ODULong        ODGetODULongFromISOStrKey(ODISOStr isoStrKey)
  261. {
  262.     ODULong ret;
  263.     for (ODUByte i = 0; i<sizeof(ODULong); ++i)
  264.     {
  265.         ODUByte n1 = 0, n2 = 0;
  266.         n1 = isoStrKey[i*2];
  267.         n2 = isoStrKey[i*2+1];
  268.         if (n1>'9') 
  269.             n1=n1-'A'+10;
  270.         else 
  271.             n1=n1-'0';
  272.         if (n2>'9') 
  273.             n2=n2-'A'+10;
  274.         else 
  275.             n2=n2-'0';
  276.         
  277.         ((ODUByte*)(&ret))[i] = n1*16 + n2;
  278.     }
  279.     return ret;
  280. }
  281.  
  282.  
  283. //------------------------------------------------------------------------------
  284. // ODDeduceRefNum
  285. //------------------------------------------------------------------------------
  286.  
  287. ODFileRefNum    ODDeduceRefNum(Environment* ev, PlatformFile* file, 
  288.                     ODULong prevRefNumCount, ODSShort* prevRefNums)
  289. {
  290.     ODFileRefNum    retval = 0;
  291.     ODULong         newRefNumCount = 0;
  292.     ODSShort*         newRefNums = kODNULL;
  293.     file->GetLocalPaths(kDataFork, &newRefNumCount, &newRefNums);
  294.  
  295.     WASSERT(newRefNumCount == prevRefNumCount + 1);
  296.  
  297.     ODULong i = 0,j;
  298.     ODBoolean found = kODFalse;
  299.     
  300.     while  (i<newRefNumCount)
  301.     {
  302.         j = 0;
  303.         while (j<prevRefNumCount && (found = (newRefNums[i] == prevRefNums[j]))==kODFalse)
  304.             ++j;
  305.         if (!found)
  306.             break;
  307.         ++i;
  308.     }
  309.     
  310.     WASSERT(i<newRefNumCount);
  311.     
  312.     retval = newRefNums[i];
  313.     
  314.     if (newRefNums) 
  315.         ODDisposePtr((Ptr)newRefNums);
  316.     
  317.     return retval;
  318. }
  319.  
  320.  
  321.  
  322. //==============================================================================
  323. // Opening an file/container/document/draft
  324. //==============================================================================
  325.  
  326.  
  327. //------------------------------------------------------------------------------
  328. // ODAcquireCtrDocTopDraft
  329. //------------------------------------------------------------------------------
  330.  
  331. void ODAcquireCtrDocTopDraft(Environment* ev, ODSession* session,PlatformFile* file,
  332.         ODContainer** container, ODDocument** document, ODDraft** draft)
  333. {
  334.     *container = AcquireFileContainer(ev, session, &(file->GetFileSpec()));
  335.     *document = (*container)->AcquireDocument(ev,kODDefaultDocument);
  336.     *draft = (*document)->AcquireDraft(ev,kODDPReadOnly,0,kODNULL,kODPosTop,kODFalse);
  337. }
  338.  
  339. //------------------------------------------------------------------------------
  340. // ODGetNthOpenDocument
  341. //
  342. // n is 1 based & returns kODNULL if there is no nth document
  343. //------------------------------------------------------------------------------
  344.  
  345. ODDocument*    ODGetNthOpenDocument(Environment* ev, ODSession* session, ODULong n)
  346. {
  347.     WASSERT(session != kODNULL);
  348.     
  349.     if (!session)
  350.         THROW(kODErrIllegalNullInput);
  351.         
  352.     ODNameSpaceManager* theNameSpaceManager = session->GetNameSpaceManager(ev);
  353.     ODObjectNameSpace* refNumDocumentNameSpace = 
  354.         (ODObjectNameSpace*)theNameSpaceManager->HasNameSpace( ev, 
  355.                                                         kODRefNumDocument);
  356.     RETURN_IF_NULL(refNumDocumentNameSpace, kODNULL);
  357.     
  358.     ODObjectIterator* iter = refNumDocumentNameSpace->CreateIterator(ev);
  359.     ODDocument* document = kODNULL;
  360.     ODISOStr unusedKey = kODNULL;
  361.     ODULong unusedObjectLength;
  362.     iter->First(ev, &unusedKey, (ODObject**)&document, &unusedObjectLength);
  363.     while (--n > 0 && document != kODNULL)
  364.     {
  365.         ODDisposePtr(unusedKey);
  366.         unusedKey = kODNULL;
  367.         document = kODNULL;
  368.         iter->Next(ev, &unusedKey, (ODObject**)&document, &unusedObjectLength);
  369.     }
  370.     ODDisposePtr(unusedKey);
  371.     ODDeleteObject(iter);
  372.     return document;
  373. }
  374.                 
  375. //------------------------------------------------------------------------------
  376. // ODGetOpenDocumentFromRefNum
  377. //------------------------------------------------------------------------------
  378.  
  379. ODDocument*    ODGetOpenDocumentFromRefNum(Environment* ev, ODSession* session,
  380.                 ODFileRefNum refnum)
  381. {
  382.     WASSERT(session != kODNULL);
  383.  
  384.     if (!session)
  385.         THROW(kODErrIllegalNullInput);
  386.         
  387.     ODNameSpaceManager* theNameSpaceManager = session->GetNameSpaceManager(ev);
  388.     ODObjectNameSpace* refNumDocumentNameSpace = 
  389.         (ODObjectNameSpace*)theNameSpaceManager->HasNameSpace( ev, 
  390.                                                         kODRefNumDocument);
  391.     RETURN_IF_NULL(refNumDocumentNameSpace, kODNULL);
  392.     ODDocument* document = kODNULL;
  393.     char key[9];
  394.     ODCreateISOStrKeyFromULong(refnum,key);
  395.     refNumDocumentNameSpace->GetEntry(ev, key, (ODObject**)&document);
  396.     return document;
  397. }
  398.                 
  399. //------------------------------------------------------------------------------
  400. // ODGetTempDraftFromOpenDocument
  401. //------------------------------------------------------------------------------
  402.                 
  403. ODDraft*    ODGetTempDraftFromOpenDocument(Environment* ev, ODSession* session,
  404.                 ODDocument* document)
  405. {
  406.     RETURN_IF_NULL(document, kODNULL);
  407.  
  408.     WASSERT(session != kODNULL);
  409.     if (!session)
  410.         THROW(kODErrIllegalNullInput);
  411.         
  412.     ODNameSpaceManager* theNameSpaceManager = session->GetNameSpaceManager(ev);
  413.  
  414.     ODObjectNameSpace* documentTempDraftNameSpace = 
  415.         (ODObjectNameSpace*)theNameSpaceManager->HasNameSpace( ev, 
  416.                                                         kODDocumentTempDraft);
  417.     RETURN_IF_NULL(documentTempDraftNameSpace, kODNULL);
  418.     ODDraft* draft = kODNULL;
  419.     char key[9];
  420.     ODCreateISOStrKeyFromULong((ODULong)document,key);
  421.     documentTempDraftNameSpace->GetEntry(ev, key, (ODObject**)&draft);
  422.     return draft;
  423. }
  424.  
  425. //------------------------------------------------------------------------------
  426. // ODTempDraftCreated
  427. //------------------------------------------------------------------------------
  428.                 
  429. void    ODTempDraftCreated(Environment* ev, ODSession* session, 
  430.             ODDocument* document, ODDraft* tempDraft)
  431. {
  432.     WASSERT(session != kODNULL);
  433.     WASSERT(document != kODNULL);
  434.     WASSERT(tempDraft != kODNULL);
  435.  
  436.     if (!session)
  437.         THROW(kODErrIllegalNullInput);
  438.     if (!document)
  439.         THROW(kODErrIllegalNullDocumentInput);
  440.     if (!tempDraft)
  441.         THROW(kODErrIllegalNullDraftInput);
  442.         
  443.     ODNameSpaceManager* theNameSpaceManager = session->GetNameSpaceManager(ev);
  444.  
  445.     ODObjectNameSpace* nameSpace =    
  446.         (ODObjectNameSpace*)theNameSpaceManager->HasNameSpace( ev, 
  447.                                                         kODDocumentTempDraft);
  448.     if (!nameSpace)
  449.     {
  450.         nameSpace = 
  451.             (ODObjectNameSpace*)theNameSpaceManager->CreateNameSpace(
  452.                 ev, kODDocumentTempDraft, kODNULL, 5, kODNSDataTypeODObject);
  453.     }
  454.     
  455.     {
  456.         char key[9];
  457.         ODCreateISOStrKeyFromULong((ODULong)document,key);
  458.         ODDraft* unusedDraft;
  459.         if (nameSpace->GetEntry(ev, key, (ODObject**)&unusedDraft))
  460.             nameSpace->Unregister(ev, key);
  461.         nameSpace->Register(ev, key, tempDraft);
  462.     }
  463. }
  464.  
  465. //------------------------------------------------------------------------------
  466. // ODDocumentOpened
  467. //------------------------------------------------------------------------------
  468.                 
  469. void        ODDocumentOpened(Environment* ev, ODSession* session,
  470.                 ODFileRefNum refnum, ODDocument* document, ODDraft* tempDraft)
  471. {
  472.     WASSERT(session != kODNULL);
  473.     WASSERT(document != kODNULL);
  474.  
  475.     if (!session)
  476.         THROW(kODErrIllegalNullInput);
  477.     if (!document)
  478.         THROW(kODErrIllegalNullDocumentInput);
  479.         
  480.     ODNameSpaceManager* theNameSpaceManager = session->GetNameSpaceManager(ev);
  481.  
  482.     document->Acquire(ev);    // Balanced by Release in ODDocumentClosed.
  483.     document->GetContainer(ev)->Acquire(ev); // Balanced by Release in ODDocumentClosed.
  484.  
  485.     //• it's not clear whether ODDocumentClosed needs to be called if this fn fails.
  486.     //• Failure halfway through leaves things in an inconsistent state and it doesn't
  487.     //• look like there's any way to clean up fully.
  488.  
  489.     ODObjectNameSpace* nameSpace = 
  490.         (ODObjectNameSpace*)theNameSpaceManager->HasNameSpace( ev, 
  491.                                                         kODRefNumDocument);
  492.     if (!nameSpace)
  493.     {
  494.         nameSpace = 
  495.             (ODObjectNameSpace*)theNameSpaceManager->CreateNameSpace(
  496.                 ev, kODRefNumDocument, kODNULL, 5, kODNSDataTypeODObject);
  497.     }
  498.     
  499.     {
  500.         char key[9];
  501.         ODCreateISOStrKeyFromULong((ODULong)refnum,key);
  502. #if ODDebug
  503.         ODDocument* unusedDocument;
  504.         if (nameSpace->GetEntry(ev, key, (ODObject**)&unusedDocument))
  505.             WARN("refnum already in kODRefNumDocument namespace!");
  506. #endif
  507.         nameSpace->Register(ev, key, document);
  508.     }
  509.     
  510.     if (tempDraft)
  511.         ODTempDraftCreated(ev, session, document, tempDraft);
  512. }
  513.                 
  514. //------------------------------------------------------------------------------
  515. // ODDocumentClosed
  516. //------------------------------------------------------------------------------
  517.                 
  518. void    ODDocumentClosed(Environment* ev, ODSession* session,
  519.                 ODDocument* document)
  520. {
  521.     WASSERT(session != kODNULL);
  522.     WASSERT(document != kODNULL);
  523.  
  524.     if (!session)
  525.         THROW(kODErrIllegalNullInput);
  526.     if (!document)
  527.         THROW(kODErrIllegalNullDocumentInput);
  528.         
  529.     ODNameSpaceManager* theNameSpaceManager = session->GetNameSpaceManager(ev);
  530.     ODObjectNameSpace* nameSpace;
  531.     
  532.     nameSpace = 
  533.         (ODObjectNameSpace*)theNameSpaceManager->HasNameSpace( ev, 
  534.                                                     kODDocumentTempDraft);
  535.     if (nameSpace)
  536.     {
  537.         char key[9];
  538.         ODCreateISOStrKeyFromULong((ODULong)document,key);
  539.         ODDraft* unusedDraft;
  540.         if (nameSpace->GetEntry(ev, key, (ODObject**)&unusedDraft))
  541.             nameSpace->Unregister(ev, key);
  542.     }
  543.     
  544.     nameSpace = 
  545.         (ODObjectNameSpace*)theNameSpaceManager->HasNameSpace( ev, 
  546.                                                         kODRefNumDocument);
  547.     if (!nameSpace)
  548.         return;
  549.  
  550.     ODDocument* entryDocument = kODNULL;
  551.     ODISOStr key = kODNULL;
  552.     ODULong unusedObjectLength;
  553.     ODObjectIterator* iter = nameSpace->CreateIterator(ev);
  554.     for (iter->First(ev, &key, (ODObject**)&entryDocument, &unusedObjectLength);
  555.          iter->IsNotComplete(ev);
  556.          iter->Next(ev, &key, (ODObject**)&entryDocument, &unusedObjectLength))
  557.     {
  558.         TempODISOStr tempKey = key; // DMc: ensure it's deleted
  559.         if (ODObjectsAreEqual(ev, document, entryDocument))
  560.         {
  561.             nameSpace->Unregister(ev, key);
  562.             ODContainer* container = document->GetContainer(ev);
  563.             ODFinalReleaseObject(ev, document);
  564.             ODFinalReleaseObject(ev, container);
  565.             break;
  566.         }
  567.     }
  568.     ODDeleteObject(iter);
  569. }
  570.  
  571.  
  572. //==============================================================================
  573. // Root Part/StorageUnit
  574. //==============================================================================
  575.  
  576. //------------------------------------------------------------------------------
  577. // ODAcquireRootPartOfDraft
  578. //------------------------------------------------------------------------------
  579.  
  580. ODPart* ODAcquireRootPartOfDraft(Environment* ev, ODDraft* draft)
  581. {
  582.     if (!draft)
  583.         THROW(kODErrIllegalNullDraftInput);
  584.         
  585.     TempODStorageUnit su = draft->AcquireDraftProperties(ev);
  586.     return draft->
  587.         AcquirePart(ev,ODGetStrongSURefProp(ev, su, kODPropRootPartSU, kODStrongStorageUnitRef));
  588. }
  589.  
  590. //------------------------------------------------------------------------------
  591. // ODAcquireRootPartSUOfDraft
  592. //------------------------------------------------------------------------------
  593.  
  594. ODStorageUnit* ODAcquireRootPartSUOfDraft(Environment* ev, ODDraft* draft)
  595. {
  596.     if (!draft)
  597.         THROW(kODErrIllegalNullDraftInput);
  598.         
  599.     TempODStorageUnit su = draft->AcquireDraftProperties(ev);
  600.     if (!su->Exists(ev, kODPropRootPartSU, kODStrongStorageUnitRef, 0))
  601.         return kODNULL;
  602.         
  603.     return draft->
  604.         AcquireStorageUnit(ev,ODGetStrongSURefProp(ev, su, kODPropRootPartSU, kODStrongStorageUnitRef));
  605. }
  606.  
  607. //------------------------------------------------------------------------------
  608. // ODSetRootPartSUOfDraft
  609. //------------------------------------------------------------------------------
  610.  
  611. void ODSetRootPartSUOfDraft(Environment* ev, ODDraft* draft, ODStorageUnit* rootPartSU)
  612. {
  613.     if (!draft)
  614.         THROW(kODErrIllegalNullDraftInput);
  615.     if (!rootPartSU)
  616.         THROW(kODErrIllegalNullStorageUnitInput);
  617.         
  618.     TempODStorageUnit su = draft->AcquireDraftProperties(ev);
  619.     ODSetStrongSURefProp(ev, su, kODPropRootPartSU, kODStrongStorageUnitRef,
  620.                         rootPartSU->GetID(ev));
  621. }
  622.  
  623. //------------------------------------------------------------------------------
  624. // ODGetDraftOfWindow
  625. //  Given a window object, get the root part's storageUnit's draft
  626. //------------------------------------------------------------------------------
  627.  
  628. ODDraft* ODGetDraftOfWindow(Environment* ev, ODWindow* window)
  629. {
  630.     RETURN_IF_NULL(window, kODNULL);
  631.         
  632.     TempODPart part = window->GetRootFrame(ev)->AcquirePart(ev);
  633.     return part->GetStorageUnit(ev)->GetDraft(ev);
  634. }
  635.  
  636. //------------------------------------------------------------------------------
  637. // ODResetDateModByInfo
  638. //------------------------------------------------------------------------------
  639.  
  640. void ODResetDateModByInfo(Environment* ev, ODStorageUnit* su)
  641. {
  642.     WASSERT(su != kODNULL);
  643.     if (!su)
  644.         THROW(kODErrIllegalNullStorageUnitInput);
  645.  
  646.     WASSERT(HAS_WRITE_ACCESS(su->GetDraft(ev)->GetPermissions(ev)));
  647.             
  648.     ODTime dateTime;
  649.     time((time_t *)(&dateTime));
  650.     ODSetCreationDate(ev, su, dateTime);
  651.     ODSetModificationDate(ev, su, dateTime);
  652.     
  653.     ODIText        modBy;
  654.     su->GetSession(ev)->GetUserName(ev, &modBy);
  655.     TRY
  656.         ODSetModifiedBy(ev, su, &modBy);
  657.     CATCH_ALL
  658.         DisposeITextStruct(modBy);
  659.         RERAISE;
  660.     ENDTRY
  661.     DisposeITextStruct(modBy);
  662.     
  663.     TempODStorageUnit    rootSU = ODAcquireRootPartSUOfDraft(ev, su->GetDraft(ev));
  664.     if (ODObjectsAreEqual(ev, su, rootSU))
  665.     {
  666.         TempPlatformFile    file = GetPlatformFileFromContainer(ev, 
  667.             su->GetDraft(ev)->GetDocument(ev)->GetContainer(ev));
  668.         TempODName             partname = file->GetName();
  669.         //ODSetPOName(ev, rootPart, partname); // don't want to have to have the part so…
  670.         ODSetITextProp(ev, su, kODPropName, kODMacIText, partname);
  671.     }
  672. }
  673.  
  674. //------------------------------------------------------------------------------
  675. // ODGetDocumentFileName
  676. //------------------------------------------------------------------------------
  677.  
  678. void ODGetDocumentFileName(Environment* ev, ODDocument* document, char* fileName)
  679. {
  680.     TempPlatformFile    file = GetPlatformFileFromContainer(ev, document->GetContainer(ev));
  681.     file->GetAsciiName(fileName, 255);
  682. }
  683.  
  684. //==============================================================================
  685. // Active/Changed Utils
  686. //==============================================================================
  687.  
  688. ODWindow*    ODAcquireActiveWindow(Environment* ev, ODSession* session)
  689. {
  690.     WASSERT(session != kODNULL);
  691.     if (!session)
  692.         THROW(kODErrIllegalNullInput);
  693.         
  694.     return session->GetWindowState(ev)->AcquireActiveWindow(ev);
  695. }
  696.  
  697. ODDraft*    ODGetActiveDraft(Environment* ev, ODSession* session)
  698. {
  699.     TempODWindow window = ODAcquireActiveWindow(ev, session);
  700.     return ODGetDraftOfWindow(ev, window);
  701. }
  702.  
  703. ODDocument*    ODGetActiveDocument(Environment* ev, ODSession* session)
  704. {
  705.     ODDraft* draft = ODGetActiveDraft(ev, session);
  706.     RETURN_IF_NULL(draft, kODNULL);    
  707.     
  708.     return draft->GetDocument(ev);
  709. }
  710.  
  711. ODBoolean    ODDocumentHasChanges(Environment* ev, ODSession* session,
  712.                 ODDocument* document)
  713. {
  714.     ODDraft* draft = ODGetTempDraftFromOpenDocument(ev, session, document);
  715.     RETURN_IF_NULL(draft, kODFalse);    
  716.  
  717.     return draft->ChangedFromPrev(ev);
  718. }
  719.  
  720. ODBoolean    ODDocumentHasWriteAccess(Environment* ev, ODSession* session,
  721.                 ODDocument* document)
  722. {
  723.     return ODDraftHasWriteAccess(ev, ODGetTempDraftFromOpenDocument(ev, session, document));
  724. }
  725.  
  726.  
  727. ODBoolean ODDraftHasWriteAccess(Environment* ev, ODDraft* draft)
  728. {
  729.     RETURN_IF_NULL(draft, kODFalse);    
  730.     
  731.     return HAS_WRITE_ACCESS(draft->GetPermissions(ev));
  732. }
  733.  
  734. //==============================================================================
  735. // User level document operations
  736. //==============================================================================
  737.  
  738. //------------------------------------------------------------------------------
  739. // ODNewDocument
  740. //------------------------------------------------------------------------------
  741.  
  742. #define    kODErrEditorLibraryNotFound                -29816
  743. // error code copied from the Shell (RlShlDef.h)
  744.  
  745. void ODNewDocument(Environment* ev, ODContainer* container,
  746.                             ODType        rootPartKind,
  747.                             ODEditor    rootPartEditor)
  748. {
  749.     TempODDocument    document = container->AcquireDocument(ev, kODDefaultDocument);
  750.     TempODDraft        draft = document->AcquireBaseDraft(ev, kODDPExclusiveWrite);
  751.     TempODStorageUnit su = draft->AcquireDraftProperties(ev);
  752.  
  753.     ODResetDateModByInfo(ev, su);    
  754.     
  755.   // create new root part
  756.       TempODPart rootPart = kODNULL;
  757.       
  758.       TRY
  759.         rootPart = draft->CreatePart(ev, rootPartKind, rootPartEditor);
  760.     CATCH_ALL
  761.         if (ErrorCode()==fragLibNotFound)
  762.             THROW(kODErrEditorLibraryNotFound);
  763.         else
  764.             RERAISE;
  765.     ENDTRY
  766.     ODStorageUnit* partSU = rootPart->GetStorageUnit(ev);
  767.     if (partSU == kODNULL)
  768.         THROW(kODErrEditorLibraryNotFound);
  769.     ODSetRootPartSUOfDraft(ev, draft, partSU);
  770.  
  771.     ODSetBooleanProp(ev, su, kODPropUnsavedDocument, kODBoolean, kODTrue);
  772.  
  773.     draft->Externalize(ev);
  774.  
  775.     ODPlatformType    rootPartOSType = ODGetIconFilePlatformTypeFromPartSU(ev, partSU);
  776.     ODPlatformType    rootPartCreator= ODGetIconFilePlatformCreator(ev,rootPart);
  777.  
  778.     TempPlatformFile file = GetPlatformFileFromContainer(ev, container);
  779.     file->SetPlatformType(rootPartOSType);
  780.     file->SetPlatformCreator(rootPartCreator);
  781. }
  782.  
  783. //------------------------------------------------------------------------------
  784. // ODIsUnsavedNewDocument
  785. //------------------------------------------------------------------------------
  786.  
  787. ODBoolean ODIsUnsavedNewDocument(Environment* ev, ODSession* session, ODDocument* document)
  788. {
  789.     ODDraft* draft = ODGetTempDraftFromOpenDocument(ev, session, document);
  790.     RETURN_IF_NULL(draft, kODFalse);
  791.     TempODStorageUnit su = draft->AcquireDraftProperties(ev);
  792.     if (!su->Exists(ev, kODPropUnsavedDocument, kODBoolean, 0))
  793.         return kODFalse;
  794.     return ODGetBooleanProp(ev, su, kODPropUnsavedDocument, kODBoolean);
  795. }
  796.  
  797. //------------------------------------------------------------------------------
  798. // ODSetIsUnsavedNewDocument
  799. //------------------------------------------------------------------------------
  800.  
  801. void ODSetIsUnsavedNewDocument(Environment* ev, ODDraft* draft)
  802. {
  803.     TempODStorageUnit su = draft->AcquireDraftProperties(ev);
  804.     ODSetBooleanProp(ev, su, kODPropUnsavedDocument, kODBoolean, kODTrue);
  805. }
  806.  
  807. //------------------------------------------------------------------------------
  808. // ODClearIsUnsavedNewDocument
  809. //------------------------------------------------------------------------------
  810.  
  811. void ODClearIsUnsavedNewDocument(Environment* ev, ODDraft* draft)
  812. {
  813.     TempODStorageUnit su = draft->AcquireDraftProperties(ev);
  814.     if (su->Exists(ev, kODPropUnsavedDocument, kODBoolean, 0))
  815.         ODSURemoveProperty(ev, su, kODPropUnsavedDocument);
  816. }
  817. //------------------------------------------------------------------------------
  818. // ODOpenFileDocument
  819. //
  820. //    Warning, this code does not clean up after itself. If a failure occurs,
  821. //    a number of different objects could be left unreleased. This code should
  822. //    be considered sample code, or less, only!
  823. //------------------------------------------------------------------------------
  824.  
  825. ODDraft* ODOpenFileDocument(Environment* ev, ODSession* session, PlatformFile* file,
  826.     ODDraftPermissions permissions)
  827. {
  828.     WASSERT(session != kODNULL);
  829.     WASSERT(file != kODNULL);
  830.  
  831.     if (!session)
  832.         THROW(kODErrIllegalNullInput);
  833.     if (!file)
  834.         THROW(kODErrIllegalNullInput);
  835.  
  836.     ODContainer*    container    = kODNULL;
  837.     ODDocument*        document    = kODNULL;
  838.     ODDraft*        currentdraft    = kODNULL;
  839.     ODDraft*        tempdraft    = kODNULL;
  840.     
  841.     ODULong refNumCount, i;
  842.     ODSShort* refNums = kODNULL;
  843.     file->GetLocalPaths(kDataFork, &refNumCount, &refNums);
  844.     
  845.     for ( i=0; i<refNumCount; ++i)
  846.         if ((document = ODGetOpenDocumentFromRefNum(ev, session, refNums[i])) != kODNULL)
  847.         {
  848.             currentdraft = ODGetTempDraftFromOpenDocument(ev, session, document);
  849.             if (currentdraft)
  850.                 currentdraft->Acquire(ev);
  851.             else
  852.                 currentdraft = document->AcquireDraft(ev,kODDPReadOnly,0,kODNULL,kODPosTop,kODFalse);
  853.             if (refNums)
  854.                 ODDisposePtr(refNums);
  855.             return currentdraft;
  856.         }
  857.  
  858.     // ODAcquireCtrDocTopDraft opens the file and adds a new refnum.
  859.  
  860.     ODAcquireCtrDocTopDraft(ev, session, file, &container, &document, ¤tdraft);
  861.     TempODContainer tempCont = container;        // Ensures they're released
  862.     TempODDocument  tempDoc  = document;
  863.     ODFileRefNum    refnum = ODDeduceRefNum(ev, file, refNumCount, refNums);
  864.     if (refNums)
  865.         ODDisposePtr(refNums);
  866.     
  867.     if (HAS_WRITE_ACCESS(permissions) && !file->IsLocked())
  868.     {
  869.         currentdraft = 
  870.             document->AcquireDraft(ev, permissions,0, currentdraft, kODPosSame, kODTrue);
  871.         currentdraft = document->CreateDraft(ev, currentdraft, kODTrue);
  872.         tempdraft = currentdraft;
  873.         tempdraft->Acquire(ev); 
  874.             // Because "The caller is responsible for properly refcounting the tempdraft."
  875.             // From DocUtils.h documentation of ODDocumentOpened.
  876.     }
  877.             
  878.     ODDocumentOpened(ev, session, refnum, document, tempdraft);
  879.     
  880.     return currentdraft;
  881. }
  882.  
  883. //------------------------------------------------------------------------------
  884. // ODOpenDraft
  885. //
  886. //    There is no exception handling done here! For example, what if
  887. //    rootPart->Open fails? Also, the ODWindowState calls made here don't seem
  888. //    to clean up after themselves. Our code relies on being able to call
  889. //    ODCloseDocument to do a cleanup if anything fails in here. This is not the
  890. //    right way to go.
  891. //------------------------------------------------------------------------------
  892.  
  893. void ODOpenDraft(Environment* ev, ODSession* session, ODDraft* draft)
  894. {
  895.     WASSERT(session != kODNULL);
  896.     WASSERT(draft != kODNULL);
  897.  
  898.     if (!session)
  899.         THROW(kODErrIllegalNullInput);
  900.     if (!draft)
  901.         THROW(kODErrIllegalNullDraftInput);
  902.  
  903.     ODWindowState* windowState = session->GetWindowState(ev);
  904.  
  905.     windowState->Internalize(ev,draft);
  906.     windowState->OpenWindows(ev, draft);
  907.  
  908.     //need this for NoPart alert 
  909.     if (session->GetDispatcher(ev)->ShouldExit(ev))
  910.         return;
  911.     
  912.     if ( windowState->GetRootWindowCount(ev, draft) == 0 )
  913.     {
  914.         // This happens when we are creating a document from virgin stationery.
  915.         TempODPart    rootPart = ODAcquireRootPartOfDraft(ev, draft);
  916.         rootPart->Open(ev, kODNULL);
  917.         windowState->SetDefaultWindowTitles(ev, draft);
  918.         
  919. #if ODDebug
  920.         if ( windowState->GetRootWindowCount(ev, draft) == 0 )
  921.         {
  922.             WARN( "Root part of draft did not open a root window!  Check your isRootWindow flag." );
  923.         }
  924. #endif
  925.     }
  926.     session->GetLinkManager(ev)->DraftOpened(ev,draft);
  927. }
  928.  
  929. //------------------------------------------------------------------------------
  930. // ODCloseDraft
  931. //------------------------------------------------------------------------------
  932.  
  933. void ODCloseDraft(Environment* ev, ODSession* session, ODDraft* draft)
  934. {
  935.     WASSERT(session != kODNULL);
  936.     WASSERT(draft != kODNULL);
  937.  
  938.     if (!session)
  939.         THROW(kODErrIllegalNullInput);
  940.     if (!draft)
  941.         THROW(kODErrIllegalNullDraftInput);
  942.         
  943.     session->GetLinkManager(ev)->DraftClosing(ev, draft);
  944.     session->GetUndo(ev)->ClearActionHistory(ev, kODDontRespectMarks);
  945.     session->GetClipboard(ev)->DraftClosing(ev, draft);
  946.     session->GetWindowState(ev)->CloseWindows(ev, draft);
  947. }
  948.  
  949. //------------------------------------------------------------------------------
  950. // ODCloseDocument
  951. //
  952. //    This routine is called not only to close a valid open document, but also
  953. //    whenever something goes wrong in ODOpenDraft. This is wrong. ODCloseDocument
  954. //    should not try to be a catch-all cleanup call. You'll notice that there is 
  955. //    no exception handling here either.
  956. //------------------------------------------------------------------------------
  957.  
  958. ODBoolean ODCloseDocument(Environment* ev, ODSession* session, ODDocument* document)
  959. {
  960.     RETURN_IF_NULL(document, kODFalse);    // For the caller's convenience.
  961.  
  962.     ODDraft* tempDraft = ODGetTempDraftFromOpenDocument(ev, session, document);
  963.  
  964.     ODRefCntCollection*    draftsWithOpenWindows = new ODRefCntCollection(ev);
  965.  
  966.     TempPlatformFile file = kODNULL; 
  967.  
  968.     ODBoolean isUnsavedNewDocument = ODIsUnsavedNewDocument(ev, session, document);
  969.  
  970.     if (isUnsavedNewDocument)
  971.         file = GetPlatformFileFromContainer(ev, document->GetContainer(ev));
  972.  
  973.     ODWindowIterator* iter = session->GetWindowState(ev)->CreateWindowIterator(ev);
  974.     ODWindow* window = kODNULL;
  975.     while ((window = iter->Next(ev)) != kODNULL)
  976.     {
  977.         // close all windows whose draft's document = document
  978.         ODDraft* draft = ODGetDraftOfWindow(ev, window);
  979.         WASSERT(draft != kODNULL);
  980.         if (ODObjectsAreEqual(ev, document, draft->GetDocument(ev))
  981.             && !draftsWithOpenWindows->Contains(draft))
  982.             draftsWithOpenWindows->AddFirstAndAcquire(draft);
  983.     }
  984.     ODDeleteObject(iter);
  985.  
  986.     ODDraft* draft = kODNULL;
  987.     while ((draft = (ODDraft*)draftsWithOpenWindows->RemoveFirst()) != kODNULL)
  988.     {
  989.         ODCloseDraft(ev, session, draft);
  990.         draft->Release(ev); // to balance AddFirstAndAcquire above.
  991.     }
  992.  
  993.     ODDeleteObject(draftsWithOpenWindows);
  994.     if (tempDraft)
  995.     {
  996.         tempDraft->RemoveChanges(ev);
  997.         WASSERT(tempDraft->GetRefCount(ev) == 1);
  998.         tempDraft->RemoveFromDocument(ev);
  999.     }
  1000.     ODDocumentClosed(ev, session, document);
  1001.     if (isUnsavedNewDocument && !(file->IsLocked()) && !(file->IsInTrash()))
  1002.         file->Delete();
  1003.     
  1004.     TempODWindow activeWindow = ODAcquireActiveWindow(ev, session);
  1005.     return (activeWindow == kODNULL);
  1006. }
  1007.  
  1008. //------------------------------------------------------------------------------
  1009. // ODReleaseCloseWindow
  1010. //------------------------------------------------------------------------------
  1011.  
  1012. ODBoolean ODReleaseCloseWindow(Environment* ev, ODSession* session, ODWindow* window)
  1013. {
  1014.     WASSERT(session != kODNULL);
  1015.     WASSERT(window != kODNULL);
  1016.  
  1017.     if (!session)
  1018.         THROW(kODErrIllegalNullInput);
  1019.     if (!window)
  1020.         THROW(kODErrIllegalNullInput);
  1021.  
  1022.     WASSERT(window->GetRefCount(ev) > 1);
  1023. #if ODDebug
  1024.     ODULong windowRefCount = window->GetRefCount(ev);
  1025.     if (windowRefCount != 3)
  1026.     {
  1027.         WARN("Trying to close a window with RefCount of (%d) != 3.", windowRefCount);
  1028.         WARN("…expect problems later closing the draft, document and container.-TÇ");
  1029.         WARN("Solution? Make sure window is properly refcounted.");
  1030.         WARN("Possible Culprit: Part::Open forgetting to release a registered window.");
  1031.     }
  1032. #endif
  1033.     
  1034.     ODBoolean wasLastRootWindow = kODFalse;
  1035.     ODDraft* draft = ODGetDraftOfWindow(ev, window);
  1036.     draft->Acquire(ev);    // necessary just in case closing all windows fully releases the draft
  1037.     ODBoolean isOnlyDraftWindow 
  1038.         = window->IsRootWindow(ev) && 
  1039.         (session->GetWindowState(ev)->GetRootWindowCount(ev, draft) == 1);
  1040.     if (isOnlyDraftWindow)
  1041.     {
  1042.         window->Release(ev);
  1043.         ODCloseDraft(ev, session, draft);
  1044.  
  1045.         ODDocument* document = draft->GetDocument(ev);
  1046.         if (!document->Exists(ev, kODNULLID, draft, kODPosFirstAbove))
  1047.         {
  1048.             ODReleaseObject(ev, draft); // to balance the above Acquire before calling ODCloseDocument.
  1049.             wasLastRootWindow = ODCloseDocument(ev, session, document);
  1050.         }
  1051.     }
  1052.     else
  1053.     {
  1054.         window->CloseAndRemove(ev);
  1055.     }
  1056.     ODReleaseObject(ev, draft);
  1057.     return wasLastRootWindow;
  1058. }
  1059.  
  1060. //------------------------------------------------------------------------------
  1061. // ODSaveDocument
  1062. //------------------------------------------------------------------------------
  1063.  
  1064. void ODSaveDocument(Environment* ev, ODSession* session, ODDocument* document)
  1065. {
  1066.     WASSERT(session != kODNULL);
  1067.     WASSERT(document != kODNULL);
  1068.  
  1069.     if (!session)
  1070.         THROW(kODErrIllegalNullInput);
  1071.     if (!document)
  1072.         THROW(kODErrIllegalNullDocumentInput);
  1073.         
  1074.     TempPlatformFile
  1075.         file = GetPlatformFileFromContainer(ev, document->GetContainer(ev));
  1076.     THROW_IF_ERROR(file->LockError()); // if disk is locked throw
  1077.  
  1078.     ODDraft* tempDraft = ODGetTempDraftFromOpenDocument(ev, session, document);
  1079.     if (tempDraft)
  1080.     {
  1081.         WatchCursor();
  1082.         session->GetUndo(ev)->ClearActionHistory(ev, kODDontRespectMarks);
  1083.     
  1084.         // Fix desktop information which parallels the rootpart such as:
  1085.         // filename, comments, stationery bit, etc.
  1086.         SyncPropertiesToFile(ev, session, document);
  1087.  
  1088.         ODClearIsUnsavedNewDocument(ev, tempDraft);
  1089.         
  1090.         session->GetWindowState(ev)->Externalize(ev, tempDraft);
  1091.         tempDraft->Externalize(ev);
  1092.         session->GetLinkManager(ev)->DraftSaved(ev, tempDraft);
  1093.         session->GetClipboard(ev)->DraftSaved(ev, tempDraft);
  1094.     
  1095.         tempDraft->SaveToAPrevious(ev, kODNULL);
  1096.  
  1097.         ArrowCursor();
  1098.         session->GetDispatcher(ev)->InvalidateFacetUnderMouse(ev);
  1099.     }
  1100. }
  1101.  
  1102. //------------------------------------------------------------------------------
  1103. // ODSaveACopyOfDraft
  1104. //    Saves a copy of the draft.
  1105. //------------------------------------------------------------------------------
  1106.  
  1107. void ODSaveACopyOfDraft(Environment* ev, ODSession* session, ODDraft* fromDraft, 
  1108.                         PlatformFile* destinationFile)
  1109. {
  1110.     WASSERT(session != kODNULL);
  1111.     WASSERT(fromDraft != kODNULL);
  1112.     WASSERT(destinationFile != kODNULL);
  1113.  
  1114.     if (!session)
  1115.         THROW(kODErrIllegalNullInput);
  1116.  
  1117.     if (!fromDraft)
  1118.         THROW(kODErrIllegalNullDraftInput);
  1119.  
  1120.     if (!destinationFile)
  1121.         THROW(kODErrIllegalNullInput);
  1122.         
  1123.     WatchCursor();
  1124.     if (ODDraftHasWriteAccess(ev, fromDraft) && fromDraft->ChangedFromPrev(ev))
  1125.     {
  1126.         session->GetWindowState(ev)->Externalize(ev, fromDraft);
  1127.         fromDraft->Externalize(ev);
  1128.     }
  1129.     
  1130.     TempPlatformFile currentFile = 
  1131.         GetPlatformFileFromContainer(ev, fromDraft->GetDocument(ev)->GetContainer(ev));
  1132.     TempODStorageUnit partSU = ODAcquireRootPartSUOfDraft(ev, fromDraft);
  1133.     ODPlatformType fileType = ODGetIconFilePlatformTypeFromPartSU(ev, partSU);
  1134.     destinationFile->Create(currentFile->GetPlatformCreator(),fileType,0);
  1135.     
  1136.     TempODContainer    newContainer = 
  1137.         CreateFileContainer(ev, session, &(destinationFile->GetFileSpec()));    
  1138.     TempODDocument    newDocument = newContainer->AcquireDocument(ev, kODDefaultDocument);
  1139.     newDocument->SetBaseDraftFromForeignDraft(ev, fromDraft);
  1140.     TempODDraft    newDraft = newDocument->AcquireBaseDraft(ev, kODDPExclusiveWrite);
  1141.     ODClearIsUnsavedNewDocument(ev, newDraft);
  1142.     newDraft->Externalize(ev);
  1143.  
  1144.     ArrowCursor();
  1145. }
  1146.  
  1147. //------------------------------------------------------------------------------
  1148. // ODDocumentInfo
  1149. //------------------------------------------------------------------------------
  1150.  
  1151. void ODDocumentInfo(Environment* ev, ODSession* session)
  1152. {
  1153.     WASSERT(session != kODNULL);
  1154.     if (!session)
  1155.         THROW(kODErrIllegalNullInput);
  1156.  
  1157.     ArrowCursor();
  1158.  
  1159.     ODFacet* infoFacet = kODNULL;
  1160.     ODBoolean hasWriteAccess = kODFalse;
  1161.     {
  1162.     TempODWindow window = session->GetWindowState(ev)->AcquireFrontRootWindow(ev);
  1163.     infoFacet = window->GetRootFacet(ev);
  1164.     hasWriteAccess = ODDraftHasWriteAccess(ev, ODGetDraftOfWindow(ev, window));
  1165.     }
  1166.     session->GetInfo(ev)->ShowPartFrameInfo(ev, infoFacet, hasWriteAccess);
  1167. }
  1168.  
  1169. //------------------------------------------------------------------------------
  1170. // SyncFileToProperties
  1171. //------------------------------------------------------------------------------
  1172.  
  1173. void SyncFileToProperties(Environment* ev, ODSession* session, ODDocument* document)
  1174. {
  1175.     ODDraft*            tempDraft    = ODGetTempDraftFromOpenDocument(ev, session, document);
  1176.     TempODPart            rootPart    = ODAcquireRootPartOfDraft(ev, tempDraft);
  1177.     ODIText*            foo            = kODNULL;
  1178.     ODIconFamily        icons        = kODNULL;
  1179.     TempPlatformFile    file        = GetPlatformFileFromContainer(ev, document->GetContainer(ev));
  1180.     
  1181.     // filename
  1182.     foo = ODGetPOName(ev, rootPart, kODNULL);
  1183.     if (foo)
  1184.     {
  1185.         Str255    pName;
  1186.         GetITextPString(foo, pName);
  1187.         TRY
  1188.             file->Rename(pName);
  1189.         CATCH_ALL
  1190.         ENDTRY
  1191.         DisposeIText(foo);
  1192.         ODWindowState* windowState = session->GetWindowState(ev);
  1193.         windowState->SetDefaultWindowTitles(ev, tempDraft);
  1194.     }
  1195.     
  1196.     // stationery
  1197. //    file->SetStationery(ODGetSUIsStationery(ev, rootPart->GetStorageUnit(ev)));
  1198.     
  1199.     // comments
  1200.     foo = ODGetPOComments(ev, rootPart, kODNULL);
  1201.     if (foo != kODNULL)
  1202.     {
  1203.         file->SetComments(foo);
  1204.         DisposeIText(foo);
  1205.     }
  1206.  
  1207.     // custom icon
  1208.     icons = ODGetPOIconFamily(ev, rootPart);
  1209.     file->SetCustomIconFamily(icons);
  1210.     if (icons)
  1211.         THROW_IF_ERROR( DisposeIconSuite(icons, kODTrue) );
  1212. }
  1213.  
  1214.  
  1215. //------------------------------------------------------------------------------
  1216. // SyncPropertiesToFile
  1217. //------------------------------------------------------------------------------
  1218.  
  1219. void SyncPropertiesToFile(Environment* ev, ODSession* session, ODDocument* document)
  1220. {
  1221.     TempODWindow        odWindow    = session->GetWindowState(ev)->AcquireFrontRootWindow(ev);
  1222.     ODFrame*            frame        = odWindow->GetRootFrame(ev);
  1223.     ODDraft*            tempDraft    = ODGetTempDraftFromOpenDocument(ev, session, document);
  1224.     TempODPart            rootPart    = ODAcquireRootPartOfDraft(ev, tempDraft);
  1225.     ODStorageUnit*        su            = ODGetSUFromPstObj(ev, (ODPart*)rootPart);
  1226.     ODIText*            foo            = kODNULL;
  1227.     ODIconFamily        icons        = kODNULL;
  1228.     TempPlatformFile    file        = GetPlatformFileFromContainer(ev, document->GetContainer(ev));
  1229.     
  1230.     // filename
  1231.     foo = file->GetName();
  1232.     if (foo)
  1233.     {
  1234.         ODSetPOName(ev, rootPart, foo);
  1235.         DisposeIText(foo);
  1236.     }
  1237.     
  1238.     // stationery
  1239. //    ODSetSUIsStationery(ev, su, file->IsStationery());
  1240.  
  1241.     // comments
  1242.     //
  1243.     // this gets comments and makes sure that the file matches the property
  1244.     // we just need to make sure that the property matches the file
  1245.     foo = ODGetComments(ev, frame, kODNULL);
  1246.     if (foo != kODNULL)
  1247.     {
  1248.         ODSetPOComments(ev, rootPart, foo);
  1249.         DisposeIText(foo);
  1250.     }
  1251.  
  1252.     // custom icon
  1253.     icons = file->GetCustomIconFamily();
  1254.     ODSetPOIconFamily(ev, rootPart, icons, kODFalse);
  1255.     if (icons)
  1256.         THROW_IF_ERROR( DisposeIconSuite(icons, kODTrue) );
  1257. }
  1258.  
  1259.