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 / DocShell / ODPrcs.cpp < prev    next >
Encoding:
Text File  |  1996-04-22  |  52.4 KB  |  1,880 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        ODPrcs.cpp
  3.  
  4.     Contains:    OpenDoc Process runtime functions
  5.  
  6.     Owned by:    Nick Pilch
  7.  
  8.     Copyright:    © 1994 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <7>    .03.1996    NP        Added comment about lack of error handling
  13.                                     in one routine.
  14.          <6>      3/4/96    TJ        Removed WASSERT.
  15.          <5>      3/1/96    JP        1314798: Made new documents run from temp
  16.                                     file
  17.          <4>      2/6/96    eeh        1318481: change 0 to smCurrentScript
  18.          <3>     1/15/96    TJ        Cleaned Up
  19.          <2>     1/15/96    JA        1269485: Made GetPrefsFileSpec nonstatic.
  20.                                     1303072: Changed criteria for which logo to
  21.                                     show in splash screen.
  22.         <52>    10/31/95    TJ        Made the Splash Screen Non-Modal.#1297413
  23.         <51>    10/26/95    TÇ        1296574 GM:Cannot set default memory
  24.                                     partition size.
  25.         <50>    10/25/95    TÇ        1281409 GM: OpenDoc needs an AboutBox.
  26.         <49>    10/12/95    eeh        1287143: check for open resource forks
  27.         <48>     9/29/95    eeh        1287262: use ShellDef.h
  28.         <47>     9/27/95    TÇ        1287770 GM:Crash when an application is
  29.                                     dragged over the launcher
  30.         <46>     9/27/95    eeh        1284464: use ClipStringToBytes
  31.         <45>      9/8/95    eeh        1268998: get prefs file name from resource
  32.         <44>      9/8/95    CG        #1282518 FB1:Shell moves "bad" aliases from
  33.                                     OD Libs fldr if found.
  34.         <43>      9/8/95    TÇ        1271995 FB1:Get error -35 or -44 opening
  35.                                     stationery off write-protected volume
  36.         <42>      9/5/95    TÇ        1281030 FB1:OpenDoc(tm) corrupts ODF Shared
  37.                                     libraries
  38.         <41>     8/29/95    jpa        Rename Toolbox calls for Univ Hdrs 2.1.
  39.                                     [1279173]
  40.         <40>     8/26/95    TÇ        1269688 FB1:  There is an unnecessary
  41.                                     variable
  42.         <39>     8/22/95    eeh        1278280: include RlShlDef.h
  43.         <38>     8/22/95    eeh        1276821:
  44.                                     kOpenDocShellSignature->kODShellSignature
  45.         <37>     8/16/95    CG        #1274825: Fixed creating stationery for
  46.                                     libs containing multiple editors.
  47.         <36>      8/3/95    TÇ        Remove dependency on obsolete SysPrDef.h
  48.         <35>     6/30/95    TÇ        1251872 BB: Can't open stationery if file
  49.                                     name becomes too long. 1264094 BB:Custom
  50.                                     document size cannot be attached to a
  51.                                     stationery.
  52.         <34>     6/25/95    TÇ        1242642 BB: Turn on ODDebug warning if
  53.                                     refcount is wrong in
  54.                                     ODRefCntObjectsomUninit.
  55.         <33>      6/2/95    TÇ        Need to copy resources into newly created
  56.                                     documents.  Completes fix to 4
  57.                                     BB:1233106,1242232, 1254312, 1242283
  58.         <32>     5/25/95    jpa        Removed CODE 7 -- CFM68K b1 doesn't
  59.                                     generate one. [1241078]
  60.         <31>     5/19/95    TÇ        1155852 BB: String constants need to be
  61.                                     moved to resource for Localization, 1235942
  62.                                     Launching the OpenDoc pref file causes a
  63.                                     1000 exception to be thrown, 1249396 (was
  64.                                     BB) OpenDoc shell should serialize
  65.                                     stationery creation.
  66.         <30>     5/10/95    CG        #1243610    BB: Shell should not rely on the
  67.                                     constant kNMAPid.
  68.         <29>      5/7/95    TÇ        1155852 BB: String constants need to be
  69.                                     moved to resource for Localization (mostly
  70.                                     done)
  71.         <28>     4/29/95    TÇ        1216130 BB: Shell should open top draft
  72.                                     upon receipt of open document Apple event
  73.         <27>     4/24/95    eeh        1216915: remove unnecessary param
  74.         <26>     4/24/95    eeh        1240662: send keyODActivateEventCause param
  75.                                     in activate event
  76.         <25>     4/15/95    TÇ        #1216915 DR/BB:Trying to open a document
  77.                                     that is already open causes an error.
  78.         <24>     4/14/95    TÇ        #1186294    DR/BB: Binding for editor also
  79.                                     affect making stationary.
  80.         <23>      4/7/95    eeh        1221297: eventID param to
  81.                                     VerifyAndLaunchDocumentStub
  82.         <22>     3/31/95    TÇ        1223465 BB: Opening and creating documents
  83.                                     under low disk space.  (Creating documents
  84.                                     under low disk space part fixed).
  85.                                     1211032 BB: Invalid Permissions error
  86.                                     opening locked document
  87.         <21>     3/28/95    TÇ        #1151710 BB: Toolbox running out of app
  88.                                     heap.  Document Size dialog implemented.
  89.                                     TestAndVerify now uses SIZE -1 resource in
  90.                                     OpenDoc Preferences if it exists.
  91.         <20>     3/24/95    CG        #1226064: ODTestmain can create stationary.
  92.         <19>     2/24/95    EL        1220392: fix access check bug in last
  93.                                     checkin.
  94.         <18>     2/23/95    EL        1220392: checking read only fails on file
  95.                                     share volumes.
  96.         <17>     2/20/95    TÇ        #1210979 BB: 5-$ Bugs need to be evaluated
  97.                                     and removed from Shell
  98.                                     #1221861 BB: Incomplete AOCE support needs
  99.                                     to be removed from OpenDoc
  100.         <16>     2/13/95    TÇ        1193359: BB: Opening stationery on other
  101.                                     volume causes bus error in Messaging code
  102.                                     1211032: BB: Invalid Permissions Error
  103.                                     opening locked document
  104.         <15>      2/2/95    CG        #1205177:  "Editors" and "OpenDoc
  105.                                     Libraries" folders are being registered
  106.                                     with cfm (PPC only).
  107.         <14>     1/12/95    jpa        Removed HandToHand workaround for bug in
  108.                                     Dagon a1 [1210936]
  109.         <13>      1/6/95    jpa        Added new docstub rsrcs to tables [1196515]
  110.         <12>     12/5/94    jpa        Added GetLaunchFailedParams. [1198075,
  111.                                     1158966]
  112.         <11>    10/24/94    jpa        Took out WASSERTM call & Use BlockMove, not
  113.                                     BlockMoveData [68k].
  114.         <10>    10/12/94    TÇ        68K: use local static version of HandToHand
  115.          <9>    10/10/94    TÇ        #1191470 Need both 68K and PPC document
  116.                                     stub application
  117.          <8>     10/7/94    TÇ        #1191470 Need both 68K and PPC document
  118.                                     stub application
  119.          <7>     9/29/94    RA        1189812: Mods for 68K build.
  120.          <6>      9/8/94    eeh        #1185443: forgot to eliminate strcat and
  121.                                     strcpy.
  122.          <5>      9/8/94    eeh        #1185443.  Lotso changes to separate
  123.                                     document with content from what gets
  124.                                     launched.
  125.          <4>     8/29/94    TÇ        #1158280 OpenDoc™ should not overwrite old
  126.                                     stationery files when creating new ones
  127.          <3>     8/25/94    TÇ        #1183223 Enabled launching of documents in
  128.                                     folders other than that of the OpenDoc
  129.                                     libraries.  Added new call:
  130.                                     VerifyAndLaunchDocument
  131.          <2>     8/22/94    TÇ        #1182448 System Process quits when no
  132.                                     OpenDoc documents are running
  133.          <1>     8/22/94    TÇ        first checked in
  134.          
  135.     To Do:
  136.         Change all uses of ODFileSpec and FSSpecPtr to PlatformFile objects
  137.     In Progress:
  138.         
  139. */
  140.  
  141. #ifndef _EXCEPT_
  142. #include <Except.h>
  143. #endif
  144.  
  145. #ifndef _ODDEBUG_
  146. #include "ODDebug.h"
  147. #endif
  148.  
  149. #ifndef _ODPRCS_
  150. #include "ODPrcs.h"
  151. #endif
  152.  
  153. #ifndef _SHELLDEF_
  154. #include "ShellDef.h"
  155. #endif
  156.  
  157. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  158. #include <StdDefs.xh>
  159. #endif
  160.  
  161. #ifndef SOM_Module_OpenDoc_ODRegistry_defined
  162. #include "ODRgstry.xh"
  163. #endif
  164.  
  165. #ifndef _PLFMFILE_
  166. #include "PlfmFile.h"
  167. #endif
  168.  
  169. #ifndef _PASCLSTR_
  170. #include "PasclStr.h"
  171. #endif
  172.  
  173. #ifndef __ERRORS__
  174. #include <Errors.h>
  175. #endif
  176.  
  177. #ifndef __FOLDERS__
  178. #include <Folders.h>
  179. #endif
  180.  
  181. #ifndef __OSEVENTS__
  182. #include <OSEvents.h>
  183. #endif
  184.  
  185. #ifndef __ALIASES__
  186. #include <Aliases.h>
  187. #endif
  188.  
  189. #ifndef __FILES__
  190. #include <Files.h>
  191. #endif
  192.  
  193. #ifndef __RESOURCES__
  194. #include <Resources.h>
  195. #endif
  196.  
  197. #ifndef __DIALOGS__
  198. #include <Dialogs.h>
  199. #endif
  200.  
  201. #ifndef __EVENTS__
  202. #include <Events.h>
  203. #endif
  204.  
  205. #ifndef __APPLEEVENTS__
  206. #include <AppleEvents.h>
  207. #endif
  208.  
  209. #ifndef __PROCESSES__
  210. #include <Processes.h>
  211. #endif
  212.  
  213. #ifndef __STRING__
  214. #include <String.h>
  215. #endif
  216.  
  217. #ifndef __TEXTUTILS__
  218. #include <TextUtils.h>
  219. #endif
  220.  
  221. #ifndef __SCRIPT__
  222. #include <script.h>
  223. #endif
  224.  
  225. #ifndef __FINDER__
  226. #include <Finder.h>
  227. #endif
  228.  
  229. #ifndef _ODMEMORY_
  230. #include <ODMemory.h>
  231. #endif
  232.  
  233. #ifndef _REGISTER_
  234. #include <RegisterFileLibs.h>
  235. #endif
  236.  
  237. //==============================================================================
  238. // Constants
  239. //==============================================================================
  240.  
  241. #define kMaxFileNameLen        31
  242.  
  243. #define kNumDocStubRsrcs    11    /* was 12 before CFM68K a3 */
  244.  
  245. const ODULong docStubRsrcType[kNumDocStubRsrcs] = 
  246.     {     kDocStubRsrcType,
  247.         kDocStubRsrcType,
  248.         kDocStubRsrcType,
  249.         kDocStubRsrcType,
  250.         kDocStubRsrcType,
  251.         kDocStubRsrcType,
  252.         kDocStubRsrcType,
  253.         kDocStubRsrcType,
  254. //        kDocStubRsrcType,
  255.         kDocStubRsrcType,
  256.         kDocStubRsrcType,
  257.         kSIZERsrcType 
  258.     };
  259.  
  260. const ODULong docStubRsrcID[kNumDocStubRsrcs] = 
  261.     {    kDocStubRsrcID0,
  262.         kDocStubRsrcID1,
  263.         kDocStubRsrcID2,
  264.         kDocStubRsrcID3,
  265.         kDocStubRsrcID4,
  266.         kDocStubRsrcID5,
  267.         kDocStubRsrcID6,
  268.         kDocStubRsrcID7,
  269.         kDocStubRsrcID8,
  270.         kDocStubRsrcID9,
  271. //        kDocStubRsrcID10,
  272.         kDocStubSIZEID
  273.     };
  274.  
  275. const ODULong copiedRsrcType[kNumDocStubRsrcs] = 
  276.     {     kcfrgRsrcType,
  277.         kMainCFMType,
  278.         kscszRsrcType,
  279.         kMainCFMType,
  280.         kMainCFMType,
  281.         kCODERsrcType,
  282.         kCODERsrcType,
  283.         kCODERsrcType,
  284. //        kCODERsrcType,
  285.         kMainCFMType,
  286.         kMainCFMType,
  287.         kSIZERsrcType 
  288.     };
  289.  
  290. const ODULong copiedRsrcID[kNumDocStubRsrcs] = 
  291.     {    kcfrgID,
  292.         kMainCFMPPCID,
  293.         kscszID,
  294.         kMainCFM68KID,
  295.         kMainCFM68KID1,
  296.         kCODEID0,
  297.         kCODEID1,
  298.         kCODEID6,
  299. //        kCODEID7,
  300.         kSOMMemCFM68KID,
  301.         kSOMMemCFMPPCID,
  302.         kSIZEID
  303.     };
  304.  
  305.  
  306. enum
  307. {
  308.     kIsNotSameAsStub        = 0,
  309.     kIsSameAsStub            = 1,
  310.     kIsAlreadyLaunched        = 2
  311. };
  312. typedef ODSShort DocStubType;
  313.  
  314. struct ITextData {
  315.     ScriptCode      theScriptCode;
  316.     LangCode     theLangCode;
  317.     Str255         theText;
  318. };
  319. typedef struct ITextData ITextData;
  320.  
  321. struct EditorUserStringList {
  322.     Str255                     editor;
  323.     ITextData                name;
  324.     EditorUserStringList*     next;
  325. };
  326. typedef struct EditorUserStringList EditorUserStringList;
  327.  
  328. //==============================================================================
  329. // Macros
  330. //==============================================================================
  331.  
  332. #define CHECK(EXPR)    if ((err=(EXPR)) == noErr) ; else return err
  333. #define CHECKR(EXPR,RET)    if ((err=(EXPR)) == noErr) ; else return (RET)
  334.  
  335. //==============================================================================
  336. // Function Prototype
  337. //==============================================================================
  338.  
  339. static ODBoolean    IsAProcessRunning(OSType procType, OSType procSignature);
  340.  
  341. static void    CreateTempName(short seed, Str255 name, ODBoolean isFile);
  342. static OSErr CreateUniqueTmpFolderForFile(ODFileSpec* result,
  343.         Str63 fileName);
  344. static OSErr MakeDocumentStub(AEDesc *document, FSSpec* documentStub,
  345.         FSSpec* documentSpec,
  346.         DocStubType* isDuplicate, DescType eventID, ODBoolean unsavedDoc);
  347.  
  348. // Document Launching
  349. static OSErr     TestAndUpdate(Handle origRsrc,ResType rtype,short rid);
  350. static OSErr    CreateStationerySeed(FSSpecPtr theDocument, FSSpec* seedFSSPtr);
  351. static size_t    ODXstrlen(const char *s);
  352. static char*     ODXstrncpy(char* destStr, char* srcStr, size_t n);
  353. static char*     ODXstrncat(char* destStr, char* srcStr, size_t n);
  354. static char        ODXmemcmp(char* buffer1,char* buffer2,unsigned int len);
  355. ODBoolean myEqualPascalStrings(ConstStr255Param str1, ConstStr255Param str2);
  356. static ODSLong GetFldrDirID(ODFileSpec theFolderSpec);
  357. ODFileSpec    FindODBinary(ODSShort fldrVRefNum, 
  358.                                         ODSLong fldrDirID, Str255 pbinaryName);
  359. OSErr GetEditorUserStringPairs(ODSShort resRefNum, EditorUserStringList** pairs, ODUShort* editorCount);
  360. OSErr GetEditorSetFromNMAP( ODHandle nmap, EditorUserStringList** pairs, ODUShort* editorCount );
  361. static void MoveToTrash( short vRefnum, long dirID, Str255 name );
  362.  
  363.  
  364. //==============================================================================
  365. // GetOpenDocBinaryFileSpec
  366. //==============================================================================
  367.  
  368. ODFileSpec    GetOpenDocBinaryFileSpec(char* binaryName)
  369. {
  370.  
  371.     ODFileSpec filespec;
  372.     Str255    pbinaryName;
  373.     ODUShort pbinaryLen = 0;
  374.     
  375.     if (binaryName)
  376.     {
  377.         pbinaryLen = ODXstrlen(binaryName);
  378.         
  379.         if (pbinaryLen>255)
  380.         {
  381.             pbinaryLen = 255;
  382.         }
  383.         
  384.         ODXstrncpy((char*)&(pbinaryName[1]),binaryName,pbinaryLen);
  385.     }
  386.     
  387.     ClipStringToBytes( pbinaryName, pbinaryLen, smCurrentScript );
  388.     
  389.     ODFileSpec odLibsFldrSpec = GetOpenDocLibsFldrSpec();
  390.     ODSLong dirID = GetFldrDirID(odLibsFldrSpec);
  391.     filespec = FindODBinary(odLibsFldrSpec.vRefNum, dirID, pbinaryName);
  392.  
  393.     return filespec;
  394. }
  395.  
  396. //==============================================================================
  397. // FindODBinary
  398. //==============================================================================
  399.  
  400. ODFileSpec    FindODBinary(ODSShort fldrVRefNum, 
  401.                                          ODSLong fldrDirID, Str255 pbinaryName)
  402. {
  403.     CInfoPBRec        CinfoPB;
  404.     Str255            fileName;
  405.     ODFileSpec        fileSpec;
  406.     FSMakeFSSpec(    fldrVRefNum, 
  407.                      fldrDirID, 
  408.                      pbinaryName, &fileSpec);
  409.  
  410.         //check that this is not a bogus folder
  411.     if (fldrDirID != -1)
  412.     {
  413.         memset (&CinfoPB,0,sizeof(CinfoPB));
  414.         CinfoPB.dirInfo.ioNamePtr = (StringPtr)&fileName;
  415.         CinfoPB.dirInfo.ioFDirIndex = 1;
  416.         CinfoPB.dirInfo.ioVRefNum = fldrVRefNum;
  417.         CinfoPB.dirInfo.ioDrDirID = fldrDirID;
  418.         
  419.             // Loop through all the files in Library folder
  420.         for(ODSShort i = PBGetCatInfoSync(&CinfoPB); 
  421.                         i == noErr; 
  422.                        i = PBGetCatInfoSync(&CinfoPB))
  423.         {
  424.                 // if this is a folder
  425.             if ((CinfoPB.dirInfo.ioFlAttrib & (1<<4))) 
  426.             {
  427.                 FSSpec fldrSpec;
  428.                 FSMakeFSSpec(CinfoPB.hFileInfo.ioVRefNum, 
  429.                              CinfoPB.hFileInfo.ioFlParID, 
  430.                              fileName, &fldrSpec);
  431.                 OSErr err = RegisterFileLibs(&fldrSpec);
  432.                 fileSpec = FindODBinary(fldrVRefNum, 
  433.                                         CinfoPB.dirInfo.ioDrDirID, 
  434.                                         pbinaryName);
  435.             }
  436.             else
  437.             {
  438.                     // if this is an alias, resolve and do the right thing
  439.                 if ((CinfoPB.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) /* kIsAlias */)
  440.                 {
  441.                     FSSpec    aliasSpec;
  442.                     Boolean    targetIsFolder = kODFalse;
  443.                     Boolean    wasAliased = kODFalse;
  444.                     
  445.                     ODError result = FSMakeFSSpec(CinfoPB.hFileInfo.ioVRefNum, 
  446.                                           CinfoPB.hFileInfo.ioFlParID, 
  447.                                           fileName, &aliasSpec);
  448.                     if (result == noErr)
  449.                     {
  450.                             //resolve alias
  451.                         result = ResolveAliasFile(&aliasSpec, kODTrue, 
  452.                                               &targetIsFolder, &wasAliased);
  453.                         if (result == noErr)
  454.                         {
  455.                             if (aliasSpec.vRefNum != fldrVRefNum)
  456.                                 MoveToTrash( CinfoPB.hFileInfo.ioVRefNum, 
  457.                                              CinfoPB.hFileInfo.ioFlParID, fileName );
  458.                             else
  459.                             {
  460.                                 if (targetIsFolder)
  461.                                 {
  462.                                     OSErr err = RegisterFileLibs(&aliasSpec);
  463.                                     ODSLong dirID = GetFldrDirID(aliasSpec);
  464.                                     FindODBinary(aliasSpec.vRefNum, 
  465.                                                   dirID, pbinaryName);
  466.                                 }
  467.                                 else
  468.                                 {
  469.                                     // if this file's name == pbinaryName, make an FSSpec and return it
  470.                                     if (myEqualPascalStrings(pbinaryName, 
  471.                                                               fileName))
  472.                                         FSMakeFSSpec(aliasSpec.vRefNum, 
  473.                                                       aliasSpec.parID, fileName, 
  474.                                                       &fileSpec);                                    
  475.                                 }
  476.                             }
  477.                         }
  478.                     }
  479.                 }
  480.                 else
  481.                 {
  482.                     // if this file's name == pbinaryName, make an FSSpec and return it
  483.                     if (myEqualPascalStrings(pbinaryName, fileName))
  484.                     {
  485.                         FSMakeFSSpec(CinfoPB.hFileInfo.ioVRefNum, 
  486.                                       CinfoPB.hFileInfo.ioFlParID, 
  487.                                       fileName, &fileSpec);
  488.                     }                            
  489.                 }
  490.             }
  491.  
  492.             CinfoPB.hFileInfo.ioFDirIndex++;
  493.                 //need to do this each time since PBGetCatInfo call returns val here
  494.             CinfoPB.hFileInfo.ioNamePtr = (StringPtr)&fileName;
  495.             CinfoPB.hFileInfo.ioVRefNum = fldrVRefNum;
  496.             CinfoPB.hFileInfo.ioDirID = fldrDirID;  
  497.         }
  498.     }
  499.     return fileSpec;
  500. }
  501.  
  502. //==============================================================================
  503. // GetOpenDocLibsFldrSpec
  504. //==============================================================================
  505.  
  506. ODFileSpec    GetOpenDocLibsFldrSpec()
  507. {
  508.     ODSLong        odDirID, libsFldrDirID;
  509.     ODSShort    odVRef, libsFldrVRefNum;
  510.     ODFileSpec    odFldrSpec;
  511.     Str255        folderName;
  512.  
  513.     GetIndString(folderName, kODXLibsFldrStrID, kODXLibsFldrStrIndex);
  514. #if ODDebug
  515.     if (folderName[0] == 0)
  516.         DebugStr("\pResource Error: OpenDoc Libraries string not found!");
  517. #endif
  518.         
  519.     ODError result = FindFolder(kOnSystemDisk, kExtensionFolderType, 
  520.                                 kDontCreateFolder, &libsFldrVRefNum, 
  521.                                 &libsFldrDirID);
  522.     if (result == noErr)
  523.     {
  524.         CInfoPBRec        CinfoPB;
  525.         memset (&CinfoPB,0,sizeof(CinfoPB));
  526.         CinfoPB.dirInfo.ioNamePtr = (StringPtr)&folderName;
  527.         CinfoPB.dirInfo.ioFDirIndex = 0;
  528.         CinfoPB.dirInfo.ioVRefNum = libsFldrVRefNum;
  529.         CinfoPB.dirInfo.ioDrDirID = libsFldrDirID;
  530.         
  531.         ODSShort result = PBGetCatInfoSync(&CinfoPB);
  532.         if (result == noErr)
  533.         {
  534.             odVRef  = CinfoPB.dirInfo.ioVRefNum;
  535.             odDirID = CinfoPB.dirInfo.ioDrParID;
  536.             result = FSMakeFSSpec(odVRef, odDirID, folderName, &odFldrSpec);
  537.         }
  538.     }
  539.     
  540.     return odFldrSpec;
  541. }
  542.  
  543. //------------------------------------------------------------------------------
  544. // GetFldrDirID
  545. //------------------------------------------------------------------------------
  546. static ODSLong
  547. GetFldrDirID(ODFileSpec theFolderSpec)
  548. {
  549.     ODSLong dirID=-1;
  550.     CInfoPBRec    theParamBlock;
  551.     memset (&theParamBlock,0,sizeof(theParamBlock));
  552.     theParamBlock.dirInfo.ioFDirIndex = 0;
  553.     theParamBlock.dirInfo.ioNamePtr = theFolderSpec.name;
  554.     theParamBlock.dirInfo.ioVRefNum = (ODSShort)theFolderSpec.vRefNum;
  555.     theParamBlock.dirInfo.ioDrDirID = (ODSLong)theFolderSpec.parID;
  556.     ODError result = PBGetCatInfoSync((CInfoPBPtr)&theParamBlock);
  557.     if (result == noErr && (theParamBlock.hFileInfo.ioFlAttrib & (1<<4))) 
  558.         dirID = theParamBlock.dirInfo.ioDrDirID;
  559.  
  560.     return dirID;
  561. }
  562.  
  563. #ifdef NEEDSYSTEMPROCESS
  564. #define    kODSysProcessType            0x4150504C    // 'APPL' ?should be 'appe' eventually
  565. #define kODSysProcessSignature        0x6F647370    // 'odsp'
  566.  
  567. //==============================================================================
  568. // IsODSysProcessRunning
  569. //==============================================================================
  570.  
  571. ODBoolean    IsODSysProcessRunning()
  572. {
  573.     return IsAProcessRunning(kODSysProcessType,kODSysProcessSignature);
  574.  
  575.     ProcessSerialNumber psn = {0,kNoProcess};
  576.     ProcessInfoRec aProcess;
  577.     aProcess.processInfoLength = sizeof(ProcessInfoRec);
  578.     aProcess.processName = NULL;
  579.     aProcess.processAppSpec = NULL;
  580.     
  581.     while (GetNextProcess(&psn) == noErr)
  582.         if (GetProcessInformation(&psn,&aProcess) == noErr)
  583.             if (aProcess.processType == kODSysProcessType &&
  584.                 aProcess.processSignature == kODSysProcessSignature)
  585.                     return true;
  586.     return false;
  587. }
  588. #endif
  589.  
  590. //==============================================================================
  591. // AreODDocumentsRunning
  592. //==============================================================================
  593.  
  594. ODBoolean    AreODDocumentsRunning()
  595. {
  596.     ProcessSerialNumber psn = {0,kNoProcess};
  597.     ProcessInfoRec aProcess;
  598.     aProcess.processInfoLength = sizeof(ProcessInfoRec);
  599.     aProcess.processName = NULL;
  600.     aProcess.processAppSpec = NULL;
  601.     
  602.     while (GetNextProcess(&psn) == noErr)
  603.         if (GetProcessInformation(&psn,&aProcess) == noErr)
  604.             if (aProcess.processType != 'APPL' &&
  605.                 aProcess.processSignature == kODShellSignature)
  606.                     return true;
  607.     return false;
  608. }
  609.  
  610. //==============================================================================
  611. // FileIsReadOnly
  612. //==============================================================================
  613.  
  614. OSErr FileIsReadOnly(ODFileSpec* fs, ODBoolean* result)
  615. {
  616. // Note: copied from PlatformFile::IsLocked.  OpenDoc™ DOES NOT link in Util.lib. -TÇ
  617.  
  618.     CInfoPBRec    pbBlock;
  619.     *result = kODFalse;
  620.     OSErr err = noErr;
  621.  
  622.     // Check to see whether the volume is locked
  623.  
  624.     // Eric's original code with slight modifications.
  625.     // Appears to be needed in the case of a locked floppy. -TÇ
  626.     HParamBlockRec pb;
  627.     pb.volumeParam.ioCompletion = kODNULL;
  628.     pb.volumeParam.ioNamePtr = kODNULL;
  629.     pb.volumeParam.ioVRefNum = fs->vRefNum;
  630.     pb.volumeParam.ioVolIndex = 0;
  631.  
  632.     err = PBHGetVInfoSync(&pb);
  633.     if (err) return err;
  634.  
  635.     *result = (pb.volumeParam.ioVAtrb & 0x80) ? kODTrue : kODFalse;
  636.     
  637.     // Check to see whether the directory is locked
  638.     if (*result == kODFalse) {
  639.         // first assume it is a file share volume
  640.         HParamBlockRec    paramBlk;
  641.         paramBlk.accessParam.ioCompletion = kODNULL;
  642.         paramBlk.accessParam.ioNamePtr = kODNULL;
  643.         paramBlk.accessParam.ioVRefNum = fs->vRefNum;
  644.         paramBlk.accessParam.ioDirID = fs->parID;
  645.         paramBlk.accessParam.ioACAccess = 0;
  646.         err = PBHGetDirAccessSync(¶mBlk);
  647.         
  648.         if (err == noErr) {        /* it is a file share volume, look at the access right */
  649.             if ((paramBlk.accessParam.ioACAccess & 0x04000000) == 0) /* no write access */
  650.                 *result = kODTrue;
  651.         }
  652.         else if (err == paramErr) { /* it is not file share, look at directory */
  653.             pbBlock.dirInfo.ioCompletion = kODNULL;
  654.             pbBlock.dirInfo.ioNamePtr = kODNULL;
  655.             pbBlock.dirInfo.ioVRefNum = fs->vRefNum;
  656.             pbBlock.dirInfo.ioFDirIndex = -1;
  657.             pbBlock.dirInfo.ioDrDirID = fs->parID;
  658.             pbBlock.dirInfo.ioFlAttrib = 0;
  659.             err = PBGetCatInfoSync(&pbBlock);
  660.             if (err) return err;
  661.             if (pbBlock.dirInfo.ioFlAttrib & 1)
  662.                 *result = kODTrue;            
  663.         }
  664.         else
  665.             return err;
  666.     }
  667.  
  668.     // Check to see whether the file is locked
  669.     if (*result == kODFalse) {    
  670.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  671.         pbBlock.hFileInfo.ioFDirIndex = 0;
  672.         pbBlock.hFileInfo.ioNamePtr = fs->name;
  673.         pbBlock.hFileInfo.ioVRefNum = fs->vRefNum;
  674.         pbBlock.hFileInfo.ioDirID = fs->parID;
  675.         
  676.         err =  PBGetCatInfoSync(&pbBlock);
  677.         if (err) return err;
  678.  
  679.         if (pbBlock.hFileInfo.ioFlAttrib & 1)
  680.             *result = kODTrue;
  681.     }
  682.             
  683.     return noErr;
  684. }
  685.  
  686. //==============================================================================
  687. // GetVolumeWritableSpace
  688. //==============================================================================
  689.  
  690. ODULong    GetVolumeWritableSpace(ODFileSpec* fs, ODULong* error)
  691. {    
  692.     ODULong err = noErr;
  693.     HParamBlockRec    paramBlk;
  694.     ODBoolean        writable = kODFalse;
  695.     
  696.     if (error == kODNULL)
  697.         error = &err;
  698.         
  699.     paramBlk.accessParam.ioCompletion = kODNULL;
  700.     paramBlk.accessParam.ioNamePtr = kODNULL;
  701.     paramBlk.accessParam.ioVRefNum = fs->vRefNum;
  702.     paramBlk.accessParam.ioDirID = fs->parID;
  703.     paramBlk.accessParam.ioACAccess = 0;
  704.     *error = PBHGetDirAccessSync(¶mBlk);
  705.     
  706.     if (*error == noErr) {        /* it is a file share volume, look at the access right */
  707.         if (paramBlk.accessParam.ioACAccess & 0x04000000)
  708.             writable = kODTrue;
  709.     }
  710.     else if (*error == paramErr) { /* it is not file share, look at directory */
  711.         CInfoPBRec    pbBlock;
  712.         pbBlock.dirInfo.ioCompletion = kODNULL;
  713.         pbBlock.dirInfo.ioNamePtr = kODNULL;
  714.         pbBlock.dirInfo.ioVRefNum = fs->vRefNum;
  715.         pbBlock.dirInfo.ioFDirIndex = -1;
  716.         pbBlock.dirInfo.ioDrDirID = fs->parID;
  717.         pbBlock.dirInfo.ioFlAttrib = 0;
  718.         *error = PBGetCatInfoSync(&pbBlock);
  719.         if (*error) return 0;
  720.         
  721.         if (!(pbBlock.dirInfo.ioFlAttrib & 1))
  722.             writable = kODTrue;
  723.     }
  724.     else
  725.          return 0;
  726.  
  727.     if (writable != kODFalse) {
  728.         // how much space on this writable volume?
  729.         HParamBlockRec hpb;
  730.         hpb.volumeParam.ioVolIndex = 0;
  731.         hpb.volumeParam.ioNamePtr = kODNULL;
  732.         hpb.volumeParam.ioVRefNum = fs->vRefNum;
  733.         
  734.         *error = PBHGetVInfoSync(&hpb);
  735.         if (*error) return 0;
  736.         
  737.         if (!(hpb.volumeParam.ioVAtrb & 0x80))
  738.             return ((hpb.volumeParam.ioVFrBlk * hpb.volumeParam.ioVAlBlkSiz) / 1024);
  739.         // Appears to be needed in the case of a locked floppy. -TÇ
  740.     }    
  741.  
  742.     *error = kODErrDirectoryNotHaveWriteAccess;
  743.     return 0;
  744. }
  745.  
  746. //==============================================================================
  747. // GetDescFSSpec
  748. //==============================================================================
  749.  
  750. OSErr
  751. GetDescFSSpec(AEDesc *desc, FSSpec &spec)
  752. {
  753.     AEDesc resultDesc;
  754.     OSErr err = AECoerceDesc(desc, typeFSS, &resultDesc);
  755.     if (err) return err;
  756.     spec = **(FSSpec**)(resultDesc.dataHandle);
  757.     AEDisposeDesc(&resultDesc);
  758.     return noErr;
  759. }
  760.  
  761.  
  762. //==============================================================================
  763. // MakeDocumentStub
  764. //==============================================================================
  765.  
  766. static void    CreateTempName(short seed, Str255 name, ODBoolean isFile)
  767. {
  768.     // Don't modify this one!
  769.     char* nmSeed = isFile? "ODShellTempFile" : "ODShellTempFolder";
  770.     ODXstrncpy((char*)name, nmSeed, ODXstrlen(nmSeed)+1);
  771.  
  772.     char theNum[10];
  773.     NumToString(seed, (StringPtr)theNum); 
  774. //    WASSERT(theNum[0] <= 5);
  775.     p2cstr((StringPtr)theNum);
  776.  
  777.     ODXstrncat((char*)name, theNum, ODXstrlen(theNum)+1);
  778.     c2pstr((char *)name);
  779. }
  780.  
  781. OSErr CreateUniqueTmpFolderForFile(ODFileSpec* result,
  782.         Str63 fileName)
  783. {
  784.     Str255        myName;
  785.     ODSLong    myDirID;
  786.     ODSShort    myVRef;
  787.  
  788.     FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder, &myVRef, &myDirID);
  789.  
  790.     OSErr err;
  791.     short limit = 100;
  792.     short seed = 1;
  793.     while (--limit)
  794.     {
  795.         CreateTempName(seed++, myName, kODFalse);
  796.         long createdDirID;
  797.         err = DirCreate(myVRef, myDirID, myName,
  798.                 &createdDirID);
  799.         if (err == noErr)
  800.         {
  801.             FSMakeFSSpec(myVRef, createdDirID, fileName, result);
  802.             return noErr;
  803.         }
  804.     }
  805.     return err;
  806. }
  807.  
  808. static OSErr MakeDocumentStub(AEDesc *document, FSSpec* documentStub,
  809.                                 FSSpec* documentSpec,
  810.                                 DocStubType* isDuplicate,
  811.                                 DescType eventID,
  812.                                 ODBoolean unsavedDoc)
  813. {
  814.     OSErr err;
  815.     
  816.     FSSpec documentFSSpec;
  817.     CHECK(GetDescFSSpec(document, documentFSSpec));
  818.     *documentSpec = documentFSSpec;
  819.  
  820.     if (WasLaunchedThenActivate(documentSpec, eventID, err ))
  821.     {
  822.         *isDuplicate = kIsAlreadyLaunched;
  823.         return err;
  824.     }
  825.  
  826.     FInfo documentFInfo;
  827.     err= FSpGetFInfo(&documentFSSpec, &documentFInfo);
  828.     if (err) return err;
  829.  
  830.     // if it's a read-only file OR if it's on a server OR if it's stationery,
  831.     // OR it's unsaved (i.e. a New document)
  832.     // make a new one.
  833.     
  834.     ODBoolean makeNewOne;
  835.     err = FileIsReadOnly(&documentFSSpec, &makeNewOne);
  836.     if (err) return err;
  837.     makeNewOne = makeNewOne || (((documentFInfo.fdFlags)&kIsStationary)!=0) ||
  838.         (documentFInfo.fdCreator != kODShellSignature) || unsavedDoc;
  839.     if (!makeNewOne || 
  840.         documentFInfo.fdType == kEditorFileType)
  841.     {
  842.         *documentStub = documentFSSpec;
  843.         *isDuplicate = kIsSameAsStub;
  844.         return noErr;
  845.     }
  846.     
  847.     // if we get here we need a new file....
  848.     *isDuplicate = kIsNotSameAsStub;
  849.  
  850.     FSSpec newFileSpec;
  851.     err = CreateUniqueTmpFolderForFile(&newFileSpec, documentFSSpec.name);    
  852.     if (err) return err;
  853.  
  854.     err = FSpCreate( &newFileSpec, kODShellSignature, documentFInfo.fdType,
  855.             smSystemScript );
  856.     FSpCreateResFile( &newFileSpec, kODShellSignature, documentFInfo.fdType,
  857.             smSystemScript );
  858.     if (!err)
  859.         *documentStub = newFileSpec;
  860.  
  861.     // Need to copy over custom SIZE 0 & 1 resource for proper custom heapsize behaviour
  862.     // for readonly documents and documents newly created from stationery.
  863.     
  864.     short theCurResFile = CurResFile();
  865.     short docResFile = FSpOpenResFile((const FSSpec *)&documentFSSpec,fsRdPerm);
  866.     
  867.     if (docResFile != -1)
  868.     {
  869.         ODHandle size0 = kODNULL;
  870.         size0 = Get1Resource(kSIZERsrcType, 0);
  871.         if (size0)
  872.             DetachResource(size0);
  873.         ODHandle size1 = kODNULL;
  874.         size1 = Get1Resource(kSIZERsrcType, 1);
  875.         if (size1)
  876.             DetachResource(size1);
  877.         CloseResFile( docResFile );
  878.         
  879.         short stubResFile = FSpOpenResFile((const FSSpec *)&newFileSpec,fsRdWrPerm);
  880.         if (size0)
  881.             err = TestAndUpdate(size0,kSIZERsrcType,0);
  882.         if (!err && size1)
  883.             err = TestAndUpdate(size1,kSIZERsrcType,1);
  884.         CloseResFile( stubResFile );
  885.         
  886.         if (size0)
  887.             DisposeHandle(size0);
  888.         if (size1)
  889.             DisposeHandle(size1);
  890.  
  891.         UseResFile(theCurResFile);
  892.     }
  893.  
  894.     return err;
  895. }
  896.  
  897. //==============================================================================
  898. // WasLaunchedThenActivate
  899. //==============================================================================
  900.  
  901.  
  902. ODBoolean    WasLaunchedThenActivate(
  903.                         FSSpec* fileSpec,
  904.                         DescType eventID,
  905.                         OSErr & err)
  906. {
  907.     // check if the file we want to open is already open by someone on this machine
  908.     ODULong        refNumCount = 0;
  909.     RefNumPtr    refNums = kODNULL;
  910.  
  911.     CHECKR(GetLocalPaths(fileSpec, kDataFork, &refNumCount, &refNums), kODFalse);
  912.     DisposePtr((Ptr) refNums);
  913.     refNums = kODNULL;
  914.     ODBoolean refnumForResFork = refNumCount == 0;    // don't count on
  915.                                                     // refnumForResFork in the
  916.                                                     // case where
  917.                                                     // we're returning false
  918.     if ( refnumForResFork )        // try again with the resource fork
  919.     {
  920.         CHECKR(GetLocalPaths(fileSpec, kResourceFork, &refNumCount, &refNums),
  921.                 kODFalse);
  922.         DisposePtr((Ptr) refNums);
  923.         if (refNumCount == 0)
  924.             return kODFalse;
  925.     }
  926.         
  927.     AppleEvent    activateEvent, reply;
  928.     AEDesc        addressDesc = {typeNull, kODNULL};
  929.     ProcessSerialNumber psn = {0,kNoProcess};
  930.     ProcessInfoRec aProcess;
  931.     
  932. //    DisposePtr((Ptr) refNums);        // <eeh> why doesn't this come before the return above?
  933.     // create the activate event
  934.     CHECKR(AECreateAppleEvent(kAEOpenDocSuite, kODActivateEvent, &addressDesc, 
  935.                 kAutoGenerateReturnID, kAnyTransactionID, &activateEvent)
  936.             , kODTrue);
  937.  
  938.     err = AEPutParamPtr(&activateEvent, keyDirectObject, typeFSS, 
  939.                                         (Ptr) fileSpec, sizeof(*fileSpec));
  940.     if (err != noErr)
  941.     {
  942.         AEDisposeDesc(&activateEvent);
  943.         return kODTrue;
  944.     }
  945.  
  946.     err = AEPutParamPtr(&activateEvent, keyODActivateEventCause, typeType, 
  947.                                         (Ptr)&eventID, sizeof(eventID));
  948.     if (err != noErr)
  949.     {
  950.         AEDisposeDesc(&activateEvent);
  951.         return kODTrue;
  952.     }
  953.     
  954.     if ( refnumForResFork )
  955.     {
  956.         err = AEPutParamPtr( &activateEvent, keyODRefnumFromResource,
  957.                 typeBoolean, (Ptr)&refnumForResFork,
  958.                 sizeof(refnumForResFork) );
  959.         if (err != noErr)
  960.         {
  961.             AEDisposeDesc(&activateEvent);
  962.             return kODTrue;
  963.         }
  964.     }
  965.  
  966.     // send the activate event to all OpenDoc processes
  967.     aProcess.processInfoLength = sizeof(ProcessInfoRec);
  968.     aProcess.processName = kODNULL;
  969.     aProcess.processAppSpec = kODNULL;
  970.     
  971.     while (GetNextProcess(&psn) == noErr)
  972.         if (GetProcessInformation(&psn, &aProcess) == noErr)
  973.             if (aProcess.processType != 'APPL' &&
  974.                 aProcess.processSignature == kODShellSignature)
  975.             {
  976.                 CHECKR(
  977.                     AECreateDesc(typeProcessSerialNumber, (Ptr) &psn, sizeof(psn),
  978.                                  &addressDesc)
  979.                     , kODTrue);
  980.  
  981.                 CHECKR(AEPutAttributeDesc(&activateEvent, keyAddressAttr, &addressDesc)
  982.                         , kODTrue);
  983.                 CHECKR(AESend(&activateEvent, &reply, kAENoReply, kAENormalPriority,
  984.                                 kAEDefaultTimeout, kODNULL, kODNULL)
  985.                         , kODTrue);
  986.                 // this shouldn't error since the handler always returns noErr
  987.                 // ASSERT that reply == {typeNull, 0}
  988.  
  989.                 CHECKR(AEDisposeDesc(&addressDesc), kODTrue);
  990.             }
  991.     err = AEDisposeDesc(&activateEvent);
  992.     return kODTrue;
  993. }
  994.  
  995. //------------------------------------------------------------------------------
  996. // VerifyAndLaunchDocumentStub
  997. //------------------------------------------------------------------------------
  998.  
  999. OSErr VerifyAndLaunchDocumentStub(AEDesc *theDocument, AEDescList* otherParams,
  1000.         ProcessSerialNumber *psn, DescType eventID, FSSpec* seedFSSPtr, 
  1001.         ODBoolean unsavedDoc)
  1002. {
  1003.     // if the document isn't local or can't be written to, make a local stub
  1004.     // in temp items folder.
  1005.     
  1006.     FSSpec documentStub;
  1007.     FSSpec documentSpec;
  1008.     DocStubType isDuplicate;
  1009.     OSErr err;
  1010.  
  1011.     err = MakeDocumentStub(theDocument, &documentStub, &documentSpec,
  1012.                             &isDuplicate, eventID, unsavedDoc);
  1013.     if (isDuplicate == kIsAlreadyLaunched)
  1014.         return err;
  1015.         
  1016.     if (!err)
  1017.     {
  1018.         if (unsavedDoc) {
  1019.             // If this doesn't work, will be tried again the next time doc is
  1020.             //    launched.
  1021.             err = VerifyDocumentStub(&documentSpec, kODNULL);
  1022.         }
  1023.         err = VerifyDocumentStub(&documentStub, seedFSSPtr);
  1024.         if (!err && documentStub.name[0]!=0) {
  1025.             // need to get the alias here rather than coerce in LaunchDocument,
  1026.             // as the AEM can't coerce FSS->Alias, at least when AOCE docs are
  1027.             // involved.
  1028.             // $Opt: Remove alias stuff if unnecessary for non AOCE docs.
  1029.             AEDesc theAlias;
  1030.             OSErr aliasErr = 1;            // so won't pass test below unless set
  1031.             if (isDuplicate == kIsSameAsStub)
  1032.                 aliasErr = NewAliasMinimal(&documentStub,
  1033.                         (AliasHandle *)&theAlias.dataHandle);
  1034.     
  1035.             if (seedFSSPtr == kODNULL ||
  1036.                 seedFSSPtr->vRefNum != documentStub.vRefNum ||
  1037.                 seedFSSPtr->parID != documentStub.parID ||
  1038.                 seedFSSPtr->name[0] != documentStub.name[0])
  1039.             {
  1040.                 if (!aliasErr) {
  1041.                     theAlias.descriptorType = typeAlias;
  1042.                     err= LaunchDocumentStub(theDocument, &documentStub, &theAlias,
  1043.                         otherParams, psn, eventID);
  1044.                     AEDisposeDesc(&theAlias);
  1045.                 } else
  1046.                     err= LaunchDocumentStub(theDocument, &documentStub, kODNULL,
  1047.                         otherParams, psn, eventID);
  1048.             }
  1049.         }
  1050.     }
  1051.     return err;
  1052. }
  1053.  
  1054. //------------------------------------------------------------------------------
  1055. // GetPrefsFileSpec
  1056. //------------------------------------------------------------------------------
  1057.  
  1058. OSErr GetPrefsFileSpec(ODFileSpec* prefFileSpec)
  1059. {
  1060.     CInfoPBRec        pb;
  1061.     memset (&pb,0,sizeof(pb));
  1062.  
  1063.     FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder, 
  1064.                             &pb.dirInfo.ioVRefNum, &pb.dirInfo.ioDrDirID);
  1065.     StringHandle prefsFileName = GetString( kSHLPrefsFileNameResID );
  1066. #if ODDebug
  1067.     if ( !prefsFileName )
  1068.         DebugStr( "\pcouldn't find kSHLPrefsFileNameResID str resource" );
  1069. #endif
  1070.     StringHandle prefsFolderName = GetString( kSHLPrefsFolderNameResID );
  1071.     //ODGetString(prefFolderName,kODPrefsFolderNameStrID);
  1072.  
  1073.     Str63 name; //must be an array because sizeof depends on it below
  1074.     //CopyPascalString(name,*prefsFolderName);
  1075.     BlockMove(*prefsFolderName,name,sizeof(name));    
  1076.     
  1077.     pb.dirInfo.ioNamePtr = name;
  1078.     pb.dirInfo.ioFDirIndex = 0;
  1079.     OSErr result = PBGetCatInfoSync( &pb );
  1080.     if (result == noErr)
  1081.     {
  1082.         if( pb.hFileInfo.ioFlFndrInfo.fdFlags & kIsAlias ) {
  1083.             FSSpec spec;
  1084.             ODBoolean targetIsFolder, wasAliased;
  1085.             FSMakeFSSpec(pb.dirInfo.ioVRefNum,pb.dirInfo.ioDrParID,name, &spec);
  1086.             result =  ResolveAliasFile(&spec, kODTrue, &targetIsFolder, &wasAliased);
  1087.             if (result == noErr)
  1088.             {
  1089.                 if( !targetIsFolder )
  1090.                     result = dirNFErr;
  1091.                 // Now get dir ID of target folder:
  1092.                 pb.dirInfo.ioNamePtr = spec.name;
  1093.                 pb.dirInfo.ioFDirIndex = 0;
  1094.                 pb.dirInfo.ioVRefNum = spec.vRefNum;
  1095.                 pb.dirInfo.ioDrDirID = spec.parID;
  1096.                 result = PBGetCatInfoSync( &pb );
  1097.             }
  1098.         }
  1099.     
  1100.         if (result == noErr)
  1101.         {
  1102.             FSMakeFSSpec(pb.dirInfo.ioVRefNum, pb.dirInfo.ioDrDirID, *prefsFileName, prefFileSpec);
  1103.             ReleaseResource( (Handle)prefsFileName );
  1104.             ReleaseResource( (Handle)prefsFolderName );
  1105.         }
  1106.     }
  1107.     return result;
  1108. }
  1109.  
  1110. //------------------------------------------------------------------------------
  1111. // GetPrefSizeResource
  1112. //------------------------------------------------------------------------------
  1113.  
  1114. static ODHandle GetPrefSizeResource()
  1115. {
  1116.     ODHandle prefSize = kODNULL;
  1117.     short theCurResFile = CurResFile();
  1118.     // Code partially copied from Prefs.cpp, should probably call a common util function
  1119.     ODFileSpec        prefFileSpec;
  1120.     OSErr result = GetPrefsFileSpec(&prefFileSpec);
  1121.     if (result == noErr)
  1122.     {
  1123.         ODSShort         prefResFile;
  1124.         prefResFile = FSpOpenResFile((const FSSpec *)&prefFileSpec,fsRdPerm);
  1125.         
  1126.         if (prefResFile != -1)
  1127.         {
  1128.             prefSize = Get1Resource(kSIZERsrcType, kSIZEID);
  1129.             if (prefSize)
  1130.                 DetachResource(prefSize);
  1131.             CloseResFile( prefResFile );
  1132.             UseResFile(theCurResFile);
  1133.         }
  1134.     }
  1135.     return prefSize;
  1136. }
  1137.  
  1138. //------------------------------------------------------------------------------
  1139. // TestAndUpdate
  1140. //------------------------------------------------------------------------------
  1141.  
  1142. // Check the doc's resource against the original copy.
  1143. static OSErr TestAndUpdate(Handle origRsrc,ResType rtype,short rid)
  1144. {
  1145.     // For SIZE-1, we need to check to see if there is an override in OpenDoc Prefs
  1146.     ODHandle prefSize = kODNULL;
  1147.     if (rtype == kSIZERsrcType && rid == kSIZEID)
  1148.     {
  1149.         prefSize = GetPrefSizeResource();
  1150.         if (prefSize != kODNULL)
  1151.             origRsrc = prefSize;
  1152.     }
  1153.     
  1154.     Handle docRsrc = Get1Resource(rtype, rid);
  1155.     
  1156.     if (docRsrc) 
  1157.     {
  1158.         // Doc has resource. Compare data and possibly update:
  1159.         Size origSize = GetHandleSize(origRsrc);
  1160.         if (GetHandleSize(docRsrc)!=origSize
  1161.                             || ODXmemcmp(*origRsrc,*docRsrc,origSize)!=0) 
  1162.         {
  1163.             SetHandleSize(docRsrc, origSize);            // Rsrc contents are different
  1164.             if (MemError()) return MemError();
  1165.             BlockMove(*origRsrc,*docRsrc,origSize);        // so copy over the original data
  1166.             ChangedResource(docRsrc);
  1167.             return ResError();
  1168.         }
  1169.         else
  1170.         {
  1171.             return noErr;
  1172.         }
  1173.             
  1174.     } 
  1175.     else 
  1176.     {
  1177.         OSErr err= ResError();
  1178.         if (err!=noErr && err!=resNotFound)
  1179.             return err;                                    // Something bad happened...
  1180.             
  1181.         // No such rsrc in document, so add one:
  1182.         docRsrc = origRsrc;
  1183.         err= HandToHand(&docRsrc);
  1184.         if (err) return err;
  1185.         AddResource(docRsrc,rtype,rid,nil);
  1186.         return ResError();
  1187.     }
  1188.     if (prefSize != kODNULL)
  1189.         DisposeHandle(prefSize);
  1190. }
  1191.  
  1192.  
  1193. //==============================================================================
  1194. // VerifyDocument
  1195. //==============================================================================
  1196.  
  1197. OSErr VerifyDocumentStub(FSSpec *theStub, FSSpec* seedFSSPtr)
  1198. {
  1199. // VerifyDocumentStub precondition: theStub is writable or it is an OpenDoc Editor
  1200. // All resources are verified on both 68K & PPC.
  1201. // if the FSSpec passed in is an OpenDoc Editor
  1202. // then we create a stationery pad seed file and
  1203. //  munge the FSSpec to point to it instead
  1204.  
  1205.     // First, grab my original copies of the rsrcs to be stuffed into the document:
  1206.     Handle origRsrc[kNumDocStubRsrcs] = { kODNULL, kODNULL, kODNULL, kODNULL };
  1207.         
  1208.     OSErr err = noErr;
  1209.     ODUShort i = 0;
  1210.     do {
  1211.         origRsrc[i] = GetResource(docStubRsrcType[i],docStubRsrcID[i]);
  1212.     } while (origRsrc[i] != kODNULL && ++i<kNumDocStubRsrcs);
  1213.         
  1214.     if (i != kNumDocStubRsrcs)
  1215.         return ResError() ? ResError() :resNotFound;        // Some resource is missing
  1216.  
  1217.     // If we are opening a shared library, create a stationery seed file:
  1218.     FInfo finderInfo;
  1219.     FSpGetFInfo(theStub,&finderInfo);
  1220.     if (finderInfo.fdType == kEditorFileType) 
  1221.     {
  1222.         CHECK(CreateStationerySeed(theStub, seedFSSPtr));
  1223.     } 
  1224.     else if (finderInfo.fdType == kPrefFileType) 
  1225.     {
  1226.         theStub->name[0] = 0;
  1227.         Str255 s;
  1228.         GetIndString(s, kODXLibsFldrStrID, 2);
  1229.         if (s[0])
  1230.         {
  1231.             ParamText(s,"\p","\p","\p");
  1232.             NoteAlert(2001,NULL);
  1233.         }
  1234.         return noErr;
  1235.     }
  1236.     else if (finderInfo.fdType == 'APPL')
  1237.     {
  1238.         theStub->name[0] = 0;
  1239.     }
  1240.     
  1241.  
  1242.     if (theStub->name[0] == 0)  // File was non-Editor shared library, or unable to create stub
  1243.         return noErr;
  1244.         
  1245.     // Now open (or create) the document's resource fork:
  1246.     short theCurResFile = CurResFile();
  1247.     short docRefNum = FSpOpenResFile(theStub,fsRdWrPerm);
  1248.     if ((err = ResError()) != noErr)
  1249.     {
  1250.         // Need to create resource fork if there is none:
  1251.         if (err == eofErr)
  1252.         {
  1253.             // If other than eofErr, something's wrong
  1254.             // would have expected fnfErr. 
  1255.             // if the create fails, we might try settting the eof to 0.
  1256.             // and trying the create again
  1257.             FSpCreateResFile(theStub,finderInfo.fdCreator,finderInfo.fdType,smSystemScript);
  1258.             if ((err = ResError()) == noErr)
  1259.             {
  1260.                 docRefNum = FSpOpenResFile(theStub,fsRdWrPerm);
  1261.                 err = ResError();
  1262.             }
  1263.         }
  1264.         if (err != noErr)
  1265.             return err;
  1266.     }
  1267.  
  1268.     // Finally, verify, add, and/or update the document resources:
  1269.     for (i = 0; i<kNumDocStubRsrcs && err==noErr; ++i)
  1270.     {
  1271.         err = TestAndUpdate(origRsrc[i],copiedRsrcType[i],copiedRsrcID[i]);
  1272.     }
  1273.     
  1274.     // Clean up our toys and go home:
  1275.     CloseResFile(docRefNum);
  1276.     if (!err)
  1277.         err= ResError();
  1278.         
  1279.     UseResFile(theCurResFile);
  1280.     
  1281.     return err;
  1282. }
  1283.  
  1284.  
  1285. //==============================================================================
  1286. // CreateStationerySeed
  1287. //==============================================================================
  1288.  
  1289. static OSErr CreateStationerySeed(FSSpec *theDocument, FSSpec* seedFSSPtr)
  1290. {
  1291.     // note that coming in, theDocument is actually the Editor library;
  1292.     // going out, theDocument is the newly created Stationery Seed
  1293.     // seedFSSPtr is used if already set (name[0]≠0), else it is filled in.
  1294.     // IF seedFSSPtr is NOT filled in, then theDocument name is set to null.
  1295.  
  1296.     OSErr err = noErr;
  1297.     ODEditor   editorID = kODNULL;
  1298.     EditorUserStringList*    editorUsrStrgPairs = kODNULL;
  1299.     ODUShort editorCount = 0;
  1300.     EditorUserStringList* pair = kODNULL;
  1301.     
  1302. // First, read in the editorUserString NMAP from the Editor library
  1303.     short saveResFile = CurResFile();
  1304.     short resRefNum = FSpOpenResFile(theDocument,fsRdPerm);
  1305.     if ((err = ResError()) != noErr)
  1306.         return err;
  1307.     
  1308.     err = GetEditorUserStringPairs(resRefNum, &editorUsrStrgPairs, &editorCount);
  1309.     CloseResFile(resRefNum);
  1310.     UseResFile(saveResFile);
  1311.     if (err != noErr)
  1312.         return err;
  1313.  
  1314.     if (editorCount == 0)
  1315.     {
  1316.         theDocument->name[0] = 0;
  1317.         return noErr;
  1318.     }
  1319.     
  1320. // Loop through the list of editor/editorUserString pairs 
  1321. //    (libraries may contain more than one editor)
  1322.  
  1323.     for (pair = editorUsrStrgPairs;
  1324.             pair;
  1325.             pair = pair->next)
  1326.     {
  1327.         long length = pair->editor[0];
  1328.         Handle editor = NewHandleClear(1+length);
  1329.         if (MemError())
  1330.             return MemError();
  1331.         HLock(editor);
  1332.         BlockMove((Ptr)&pair->editor[1], (Ptr)*editor, length);
  1333.         HUnlock(editor);
  1334.         Str255 editorName;
  1335.         editorName[0] = pair->name.theText[0];
  1336.         BlockMove((Ptr)&pair->name.theText[1], (Ptr)&editorName[1], editorName[0]);
  1337.  
  1338.         if (seedFSSPtr != kODNULL && seedFSSPtr->name[0] != 0)
  1339.         {
  1340.             *theDocument = *seedFSSPtr;
  1341.         }
  1342.         else
  1343.         {
  1344.             // Create the stationery seed.  Note: this file is NOT user visible!
  1345.             // I.e. Don't have a cow about the hard coded string.
  1346.             CreateUniqueTmpFolderForFile(theDocument, "\pStationery Seed");
  1347.             FSpCreateResFile(theDocument,kODShellSignature,kODShellSignature,smSystemScript);
  1348.             CHECK(ResError());
  1349.             if (seedFSSPtr != kODNULL)
  1350.                 *seedFSSPtr = *theDocument;
  1351.         }
  1352.         
  1353.     // Plant the 'seed' resource
  1354.         saveResFile = CurResFile();
  1355.         ODSShort    seedRefNum;
  1356.         seedRefNum = FSpOpenResFile(theDocument,fsRdWrPerm);
  1357.         CHECK(ResError());
  1358.         
  1359.         AddResource(editor, kDocSeedResType, Unique1ID(kDocSeedResType), editorName);
  1360.         err= ResError();
  1361.         CloseResFile(resRefNum);
  1362.         UseResFile(saveResFile);
  1363.     }
  1364.  
  1365.     for (pair = editorUsrStrgPairs;
  1366.         pair;)
  1367.     {
  1368.         EditorUserStringList* nextPair = pair->next;
  1369.         DisposePtr( (Ptr)pair );
  1370.         pair = nextPair;
  1371.     }
  1372.     return err;
  1373. }
  1374.  
  1375. //==============================================================================
  1376. // string stuff
  1377. //==============================================================================
  1378.  
  1379. static char ODXmemcmp(char* buffer1,char* buffer2,unsigned int len)
  1380. {
  1381.   while (len-- > 0)
  1382.       if (*buffer1++ != *buffer2++)
  1383.           return (*--buffer1)-(*--buffer2);
  1384.   return 0;
  1385. }
  1386.  
  1387. static size_t    ODXstrlen(const char *s)
  1388. {
  1389.     size_t len = 0;
  1390.     while (*s++) ++len;
  1391.     return len;
  1392. }
  1393.  
  1394. static char*     ODXstrncpy(char* destStr, char* srcStr, size_t n)
  1395. {
  1396.     char* ret = destStr;
  1397.     while (n-- > 0)
  1398.         if ((*destStr++ = *srcStr++) == 0)
  1399.         {
  1400.             while (n-- > 0)
  1401.                 *destStr++ = '\0';
  1402.                 
  1403.             break;
  1404.         }
  1405.         
  1406.     return ret;    
  1407. }
  1408.  
  1409. static char*     ODXstrncat(char* destStr, char* srcStr, size_t n)
  1410. {
  1411.     size_t len = ODXstrlen(destStr);
  1412.     destStr += len;
  1413.     return ODXstrncpy(destStr, srcStr, n);
  1414. }
  1415.  
  1416.  
  1417. //==============================================================================
  1418. // Launching the document process
  1419. //==============================================================================
  1420.  
  1421. //==============================================================================
  1422. // LaunchDocumentStub
  1423. //==============================================================================
  1424.  
  1425. OSErr LaunchDocumentStub(AEDesc* theDocument, FSSpec *documentStub,
  1426.         AEDesc* theAlias, AEDescList* otherParams, ProcessSerialNumber *psn,
  1427.         DescType eventID)
  1428. {
  1429.     
  1430.     ODUnused(otherParams);
  1431.     
  1432.     LaunchParamBlockRec    launchPB;
  1433.     OSErr                err;
  1434.  
  1435.     launchPB.launchBlockID = extendedBlock;
  1436.     launchPB.launchEPBLength = extendedBlockLen;
  1437.     launchPB.launchControlFlags = launchContinue | launchNoFileFlags;
  1438.     launchPB.launchAppSpec = documentStub;
  1439.  
  1440.     AEDesc launchDesc;
  1441.     AEDescList theList;
  1442.     AppleEvent theEvent;
  1443.     AEDesc myAddress;
  1444.     myAddress.descriptorType = nil;
  1445.     myAddress.dataHandle = nil;
  1446.     
  1447.     CHECK(AECreateAppleEvent(kCoreEventClass, eventID, &myAddress,
  1448.                         kAutoGenerateReturnID, kAnyTransactionID, &theEvent));
  1449. //    if (otherParams)
  1450. //        CHECK(AEPutParamDesc(&theEvent, kKeySpecialParams, otherParams));
  1451.  
  1452.     CHECK(AECreateList(nil,0,false,&theList));
  1453.     if (theAlias)
  1454.         CHECK(AEPutDesc(&theList, 0, theAlias));
  1455.     else
  1456.         CHECK(AEPutDesc(&theList, 0, theDocument));
  1457.     CHECK(AEPutParamDesc(&theEvent, keyDirectObject, &theList));
  1458.  
  1459.     CHECK(AECoerceDesc(&theEvent, typeAppParameters, &launchDesc));
  1460. /*
  1461.     This may look a little weird, since we're actually moving the event out of the
  1462.     AppParameters descriptor.  But it's necessary, the coercison to typeAppParameters
  1463.     takes the 'aevt' and puts it all in one handle, instead of
  1464.     leaving it as a AEDesc.  So, only one handle is being added to
  1465.     the launch parameter block instead of an AEDesc.
  1466. */
  1467.     HLock(launchDesc.dataHandle);
  1468.     launchPB.launchAppParameters = (AppParametersPtr)*(launchDesc.dataHandle);
  1469.  
  1470. #if defined(powerc) || defined(__powerc)
  1471. #else
  1472.     FlushInstructionCache();
  1473.     FlushDataCache();
  1474. #endif
  1475.  
  1476.     err= LaunchApplication(&launchPB);
  1477.     
  1478.     if (psn)
  1479.         *psn = launchPB.launchProcessSN;
  1480.     
  1481.     return err;
  1482. }
  1483.  
  1484.  
  1485. void
  1486. GetLaunchFailedParams(AppleEvent *ae, long &launchError, ProcessSerialNumber *psn,
  1487.                                         Str255 appName, Str255 libName)
  1488. {
  1489.     OSErr err;
  1490.     DescType type;
  1491.     Size size;
  1492.     
  1493.     err= AEGetParamPtr(ae,keyErrorNumber,typeLongInteger,&type,
  1494.                             &launchError,sizeof(launchError), &size);
  1495.     if (err)
  1496.         launchError = err;
  1497.         
  1498.     if (psn!=NULL) {
  1499.         psn->lowLongOfPSN = 0;
  1500.         psn->highLongOfPSN = 0;
  1501.         (void) AEGetParamPtr(ae,keyProcessSerialNumber,typeProcessSerialNumber,&type,
  1502.                             psn,sizeof(*psn), &size);
  1503.     }
  1504.     
  1505.     err= AEGetParamPtr(ae,'APPL',typeChar,&type, &appName[1],255, &size);
  1506.     appName[0] = err ?0 :size;
  1507.     
  1508.     err= AEGetParamPtr(ae,'LIBN',typeChar,&type, &libName[1],255, &size);
  1509.     libName[0] = err ?0 :size;
  1510. }
  1511.  
  1512. ODBoolean myEqualPascalStrings(ConstStr255Param str1, ConstStr255Param str2)
  1513. {
  1514.     if (str1[0] != str2[0])
  1515.         return kODFalse;
  1516.     for (int i = 1; i <= str1[0]; i++)
  1517.     {
  1518.         if (str1[i] != str2[i])
  1519.             return kODFalse;
  1520.     }
  1521.     return kODTrue;
  1522. }
  1523.  
  1524.  
  1525. /*
  1526. **    Apple Macintosh Developer Technical Support
  1527. **
  1528. **    File:    GetLocalPaths.c
  1529. **
  1530. **    by Jim Luther, Apple Developer Technical Support
  1531. **
  1532. **    Copyright © 1995 Apple Computer, Inc.
  1533. **    All rights reserved.
  1534. */
  1535.  
  1536.  
  1537. pascal    OSErr    GetLocalPaths(FSSpec *spec,
  1538.                               ForkType fork,
  1539.                               unsigned long *refNumCount,
  1540.                               RefNumPtr *refNums)
  1541. {
  1542.     enum
  1543.     {
  1544.         kMaxFCBs = 348    /* The maximum number of local access paths under System 7 */
  1545.     };
  1546.     
  1547.     OSErr        result;
  1548.     FCBPBRec    pb;
  1549.     short        index;
  1550.     Str31        tempName;
  1551.     RefNumPtr    tempRefNums;
  1552.     
  1553.     /* initialize returned values */
  1554.     *refNumCount = 0;
  1555.     *refNums = NULL;
  1556.     
  1557.     /* Allocate temp storage for refNum matches */
  1558.     tempRefNums = (RefNumPtr)NewPtr(kMaxFCBs * sizeof(short));
  1559.     
  1560.     if ( tempRefNums != NULL )
  1561.     {
  1562.         /* Get FCB name in tempName */
  1563.         pb.ioNamePtr = tempName;
  1564.         
  1565.         /* Index through the open paths on the volume specified by spec->vRefNum */
  1566.         pb.ioVRefNum = spec->vRefNum;
  1567.         index = 1;
  1568.         do
  1569.         {
  1570.             pb.ioRefNum = 0;
  1571.             pb.ioFCBIndx = index;
  1572.             result = PBGetFCBInfoSync(&pb);
  1573.             if ( result == noErr )
  1574.             {
  1575.                 /*
  1576.                 **    See if parent directory ID matches and
  1577.                 **    file name matches and
  1578.                 **    the file fork (resource or data) matches
  1579.                 */
  1580.                 if ( (pb.ioFCBParID == spec->parID) &&
  1581.                      EqualString(spec->name, tempName, false, true) &&
  1582.                      ((fork == kResourceFork) == ((pb.ioFCBFlags & (1 << 9)) != 0)) )
  1583.                 {
  1584.                     /* It's a match - add it to the array of matches */
  1585.                     tempRefNums[*refNumCount] = pb.ioRefNum;
  1586.                     ++(*refNumCount);
  1587.                 }
  1588.                 ++index;    /* next FCB index */
  1589.             }
  1590.         } while ( result == noErr );
  1591.         
  1592.         /* These errors are OK - they mean we hit the end of the FCB list */
  1593.         if ( (result == rfNumErr) || (result == fnOpnErr) )
  1594.         {
  1595.             result = noErr;
  1596.         }
  1597.         
  1598.         if ( (result == noErr) && (*refNumCount != 0) )
  1599.         {
  1600.             /* Allocate memory to return refNum matches in */
  1601.             *refNums = (RefNumPtr)NewPtr(*refNumCount * sizeof(short));
  1602.             if ( *refNums != NULL )
  1603.             {
  1604.                 /* Move refNums from tempRefNums to *refNums */
  1605.                 BlockMoveData((Ptr)tempRefNums, (Ptr)*refNums, (*refNumCount * sizeof(short)));
  1606.             }
  1607.             else
  1608.             {
  1609.                 /* Couldn't allocate memory for refNum array */
  1610.                 result = memFullErr;
  1611.             }
  1612.         }
  1613.         
  1614.         /* Free up tempRefNums storage */ 
  1615.         DisposePtr((Ptr)tempRefNums);
  1616.     }
  1617.     else
  1618.     {
  1619.         /* Couldn't allocate temp memory */
  1620.         result = memFullErr;
  1621.     }
  1622.     
  1623.     return ( result );
  1624. }
  1625.  
  1626. //------------------------------------------------------------------------------
  1627. // GetEditorUserStringPairs
  1628. //------------------------------------------------------------------------------
  1629.  
  1630. OSErr GetEditorUserStringPairs(ODSShort resRefNum, 
  1631.                             EditorUserStringList** pairs, ODUShort* editorCount)
  1632. {
  1633.     Handle         theEdtrUSnmap = kODNULL;
  1634.     *editorCount = 0;
  1635.     ODError result = noErr;
  1636.     
  1637.     if( resRefNum != -1 ) {
  1638.         ODSShort nmapCount = Count1Resources( kODNameMappings );
  1639.         if ((result = ResError()) != noErr)
  1640.             return result;
  1641.             
  1642.         for (short i=1; i<=nmapCount; i++) 
  1643.         {
  1644.                 // Get the Resource
  1645.             ODHandle nmap = (ODHandle)Get1IndResource(kODNameMappings, i);
  1646.             if ((result = ResError()) != noErr)
  1647.                 return result;
  1648.             
  1649.             if ( nmap != nil && !result  )
  1650.             {
  1651.                 HLock((ODHandle) nmap);
  1652.  
  1653.                 result = GetEditorSetFromNMAP(nmap, pairs, editorCount);
  1654.                                          
  1655.                 ReleaseResource( nmap );
  1656.             }
  1657.             
  1658.             if ((*editorCount > 0) || (result != 0))
  1659.                 break;
  1660.         }
  1661.     }
  1662.     return result;
  1663. }
  1664.  
  1665. //------------------------------------------------------------------------------
  1666. // GetEditorSetFromNMAP
  1667. //------------------------------------------------------------------------------
  1668.  
  1669. OSErr GetEditorSetFromNMAP( ODHandle nmap, EditorUserStringList** pairs, 
  1670.                                                          ODUShort* editorCount )
  1671. {
  1672.     ODISOStr        nameSpaceName = kODNULL; ODVolatile(nameSpaceName);
  1673.     ODUShort        nameLen;
  1674.     ODUShort        editorLen;
  1675.     ODSize            bufferPos=(ODSize)*nmap;
  1676.     ODSize            sizeShort = sizeof(ODUShort);
  1677.     OSErr            result = noErr;
  1678.     
  1679.     BlockMove((ODPtr)bufferPos, (ODPtr)&nameLen, sizeShort);
  1680.     bufferPos += sizeShort;
  1681.  
  1682.     nameSpaceName = (ODISOStr)NewPtrClear((ODSize)nameLen+1);
  1683.     if (!nameSpaceName)
  1684.         result = memFullErr;
  1685.     else
  1686.     {
  1687.         BlockMove((ODPtr)bufferPos, (ODPtr)nameSpaceName, (ODSize)nameLen);
  1688.         bufferPos += (ODSize)nameLen;
  1689.         
  1690.         if (!ODXmemcmp(nameSpaceName,kODEditorUserString,ODXstrlen(kODEditorUserString)))
  1691.         {
  1692.             BlockMove((ODPtr)bufferPos,(ODPtr)editorCount, sizeShort);
  1693.             bufferPos += sizeShort;
  1694.             
  1695.             if ( *editorCount > 0 )
  1696.             {
  1697.     
  1698.                 *pairs = (EditorUserStringList*)NewPtrClear(
  1699.                                               sizeof(EditorUserStringList));
  1700.                 if (!*pairs)
  1701.                     result = memFullErr;
  1702.                 else
  1703.                 {
  1704.                     EditorUserStringList* thisPair = *pairs;
  1705.                     
  1706.                     for(ODUShort i=0; i < *editorCount && thisPair; i++)
  1707.                     {
  1708.                         BlockMove((ODPtr)bufferPos,(ODPtr)&editorLen,sizeShort);
  1709.                         bufferPos += sizeShort;
  1710.                         
  1711.                         thisPair->editor[0] = editorLen;
  1712.                         BlockMove((ODPtr)bufferPos,(ODPtr)&thisPair->editor[1],
  1713.                                                          (ODSize)editorLen);
  1714.                         bufferPos += (ODSize)editorLen;
  1715.                         bufferPos += sizeShort;
  1716.                                         
  1717.                             // read UserString from the nmap
  1718.                         BlockMove((ODPtr)bufferPos, 
  1719.                             (ODPtr)&thisPair->name.theScriptCode,sizeof(ScriptCode));
  1720.                         bufferPos += sizeof(ScriptCode);
  1721.                         BlockMove((ODPtr)bufferPos, 
  1722.                             (ODPtr)&thisPair->name.theLangCode,sizeof(LangCode));
  1723.                         bufferPos += sizeof(LangCode);
  1724.                         BlockMove((ODPtr)bufferPos,(ODPtr)&nameLen,sizeShort);
  1725.                         bufferPos += sizeShort;
  1726.                         thisPair->name.theText[0] = nameLen;
  1727.                         BlockMove((ODPtr)bufferPos,(ODPtr)&thisPair->name.theText[1], nameLen);
  1728.                         bufferPos += nameLen;
  1729.                         
  1730.                         if (i+1 < *editorCount )
  1731.                         {
  1732.                             thisPair->next = (EditorUserStringList*)NewPtrClear(
  1733.                                               sizeof(EditorUserStringList));
  1734.                             thisPair = thisPair->next;
  1735.                             if (!thisPair)
  1736.                                 result = memFullErr;
  1737.  
  1738.                         }
  1739.                     }
  1740.                 }
  1741.             }
  1742.         }
  1743.     }
  1744.  
  1745.     DisposePtr(nameSpaceName);
  1746.     return result;
  1747. }
  1748.  
  1749. //------------------------------------------------------------------------------
  1750. // MoveToTrash -- $$$$$ duplicated from Prefs.cpp
  1751. //------------------------------------------------------------------------------
  1752. static void
  1753. MoveToTrash( short vRefnum, long dirID, Str255 name )
  1754. {
  1755.     short foundVRefNum;
  1756.     long  foundDirID;
  1757.     
  1758.     if(!FindFolder(vRefnum, kTrashFolderType, kDontCreateFolder, 
  1759.                                 &foundVRefNum, &foundDirID))
  1760.     {
  1761.  
  1762.         CMovePBRec paramBlock ;
  1763.         memset( ¶mBlock, 0, sizeof(paramBlock) );
  1764.         
  1765.         paramBlock.ioNamePtr = name ;
  1766.         paramBlock.ioVRefNum = foundVRefNum ;
  1767.         paramBlock.ioNewDirID = foundDirID ;
  1768.         paramBlock.ioDirID = dirID ;
  1769.         
  1770.         (void) HDelete(foundVRefNum,foundDirID,name);     // ignore error (may not exist)
  1771.         OSErr result = PBCatMoveSync( ¶mBlock );
  1772.         if (result)
  1773.             (void) HDelete(vRefnum,dirID,name); 
  1774.     }
  1775.     else
  1776.         (void) HDelete(vRefnum,dirID,name); 
  1777. }
  1778.  
  1779.  
  1780. //------------------------------------------------------------------------------
  1781. // ShowAboutScreen
  1782. //------------------------------------------------------------------------------
  1783.  
  1784. static short    GetMainDeviceDepth( ODBoolean *isColor )
  1785. {
  1786.     GDHandle        device;
  1787.     short            depth;
  1788.     PixMapHandle    pmap;
  1789.     
  1790.     depth  = 1;
  1791.     *isColor = kODTrue;
  1792.     device = GetMainDevice();
  1793.     if (
  1794.         (TestDeviceAttribute(device, screenDevice)) &&
  1795.         (TestDeviceAttribute(device, screenActive))
  1796.     ) {
  1797.         pmap  = (*device)->gdPMap;
  1798.         depth = (*pmap)->pixelSize;
  1799.         *isColor = TestDeviceAttribute(device,gdDevType);
  1800.     }
  1801.     
  1802.     return(depth);
  1803. }
  1804.  
  1805. const short kSplashDlogID            = kODSplashDlogID;
  1806. const short kSplashDefaultPICTID    = 131;
  1807. const short kSplashBWPICTID            = 132;
  1808. const short kSplash16GrayPICTID        = 133;
  1809. const short kSplashBestPICTID        = 134;
  1810.  
  1811.  
  1812. DialogPtr ShowAboutScreen( )
  1813. {
  1814.     DialogPtr aboutScreen = NULL;
  1815.     Boolean color;
  1816.     short depth = GetMainDeviceDepth(&color);
  1817.     
  1818.     short pictID = kSplashDefaultPICTID;
  1819.  
  1820.     Str255 s255; s255[0]=0;
  1821.     WindowPtr ww = FrontWindow();
  1822.     if (ww)
  1823.         GetWTitle(ww, s255);
  1824.     else
  1825.         BlockMove(LMGetCurApName(), s255, 32);
  1826.         
  1827.     if (!EqualString(s255, "\pAbout OpenDoc...", TRUE, FALSE))
  1828.                     // Note, the above string is NEVER user visible, so there is no need
  1829.                     // to worry about localizing it.
  1830.         if( !color && depth>=4 )
  1831.             pictID = kSplash16GrayPICTID;    // Use grayscale
  1832.         else if( depth>=8 )
  1833.             pictID = kSplashBestPICTID;        // Use 8-bit color
  1834.         else
  1835.             pictID = kSplashBWPICTID;        // Use black-and-white
  1836.     
  1837.     if( Get1Resource('DLOG',kSplashDlogID) )
  1838.         aboutScreen = GetNewDialog(kSplashDlogID,NULL,(WindowPtr)-1L);
  1839.     if( aboutScreen ) {
  1840.         short        itemHit;
  1841.         Handle        scratchHandle = kODNULL;
  1842.         Rect        itemRect;
  1843.     
  1844.         GetDialogItem(aboutScreen, 1, &itemHit, &scratchHandle, &itemRect);
  1845.         
  1846.         PicHandle pictHandle = (PicHandle)Get1Resource('PICT', pictID);
  1847.         
  1848.         TEHandle te = ((DialogPeek)aboutScreen)->textH;
  1849.         (**te).just = teJustCenter;
  1850.         
  1851.         struct VersRsrc {
  1852.             long    versJunk;
  1853.             short    region;
  1854.             Str255    versionStr;
  1855.         };
  1856.         VersRsrc **vers = (VersRsrc**) Get1Resource('vers',2);
  1857.         if( vers ) {
  1858.             HLock((Handle)vers);
  1859.             ParamText((**vers).versionStr,NULL,NULL,NULL);
  1860.             ReleaseResource((Handle)vers);
  1861.         } else
  1862.             ParamText("\p????",NULL,NULL,NULL);
  1863.         
  1864.         ShowWindow(aboutScreen);
  1865.         SelectWindow(aboutScreen);
  1866.         DrawDialog(aboutScreen);
  1867.         SetPort(aboutScreen);
  1868.         if (pictHandle)
  1869.         {
  1870.             HLock((Handle)pictHandle);
  1871.             DrawPicture(pictHandle, &itemRect);
  1872.             HUnlock((Handle)pictHandle);
  1873.             ReleaseResource((Handle)pictHandle);
  1874.         }
  1875.  
  1876.         ValidRect(&aboutScreen->portRect);
  1877.     }
  1878.     return aboutScreen;
  1879. }
  1880.