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 / Utilities / PlfmFile.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-22  |  48.2 KB  |  1,649 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        PlfmFile.cpp
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Owned by:    Jon Pugh
  7.  
  8.     Copyright:    © 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <3>     3/15/96    DH        1329039 - OpenDoc's routine
  13.                                     PlatformFile::HasCustomIcon() does not
  14.                                     work.
  15.          <2>      3/1/96    JP        1314798: Made CreateResFile get type &
  16.                                     creator first
  17.  
  18.     To Do:
  19. */
  20.  
  21. /*
  22.     File:        PlfmFile.cpp
  23.  
  24.     Contains:    Implmentation for PlatformFile class
  25.  
  26.     Owned by:    Vincent Lo
  27.  
  28.     Copyright:    © 1993-95 by Apple Computer, Inc., all rights reserved.
  29.  
  30. */
  31.  
  32. #ifndef _ODTYPES_
  33. #include "ODTypes.h"
  34. #endif
  35.  
  36. #ifndef _PLFMFILE_
  37. #include "PlfmFile.h"
  38. #endif
  39.  
  40. #ifndef _ODMEMORY_
  41. #include "ODMemory.h"
  42. #endif
  43.  
  44. #ifndef _EXCEPT_
  45. #include "Except.h"
  46. #endif
  47.  
  48. #ifndef _ODDEBUG_
  49. #include "ODDebug.h"
  50. #endif
  51.  
  52. #ifndef _PASCLSTR_
  53. #include "PasclStr.h"
  54. #endif
  55.  
  56. #ifndef _ITEXT_
  57. #include "IText.h"
  58. #endif
  59.  
  60. #ifndef _DOCUTILS_
  61. #include "DocUtils.h"
  62. #endif
  63.  
  64. #ifndef _DLOGUTIL_
  65. #include <DlogUtil.h>
  66. #endif
  67.  
  68. #ifndef _UTILDEFS_
  69. #include "UtilDefs.h"
  70. #endif
  71.  
  72. #ifndef _TEMPOBJ_
  73. #include "TempObj.h"
  74. #endif
  75.  
  76. #ifndef _UTILERRS_
  77. #include "UtilErrs.h"
  78. #endif
  79.  
  80. #ifndef __FILES__
  81. #include <Files.h>
  82. #endif
  83.  
  84. #ifndef __FOLDERS__
  85. #include <Folders.h>
  86. #endif
  87.  
  88. #ifndef __FINDER__
  89. #include <Finder.h>
  90. #endif
  91.  
  92. #ifndef __ICONS__
  93. #include <Icons.h>
  94. #endif
  95.  
  96. #ifndef __STRING__
  97. #include <string.h>
  98. #endif
  99.  
  100. #ifndef __ERRORS__
  101. #include <Errors.h>
  102. #endif
  103.  
  104. #ifndef __TEXTUTILS__
  105. #include "TextUtils.h"
  106. #endif
  107.  
  108. #ifndef _USERSRCM_
  109. #include <UseRsrcM.h>
  110. #endif
  111.  
  112. #ifndef __TEXTUTILS__
  113. #include "TextUtils.h"
  114. #endif
  115.  
  116. #pragma segment PlatformFile
  117.  
  118. //==============================================================================
  119. // Constants
  120. //==============================================================================
  121.  
  122. const    ODSShort    kMaxFileNameSize        = 64;
  123.  
  124. #define    kFileContainerType                    'ctyp'
  125. #define    kFileContainerTypeResID                1
  126.  
  127. const ODULong    kMaxCopyBufferSize            = 32 * 1024L;
  128. const ODULong    kMinCopyBufferSize            = 512;
  129.  
  130. static const ResType            kIconType[6] = {'ICN#','icl4','icl8','ics#','ics4','ics8'};
  131. static const short                kIconSize[6] = {256,   512,   1024,  64,    128,   256   };
  132.  
  133. //==============================================================================
  134. // Scalar Types
  135. //==============================================================================
  136.  
  137. //==============================================================================
  138. // Local Classes
  139. //==============================================================================
  140.  
  141. //==============================================================================
  142. // Global Variables
  143. //==============================================================================
  144.  
  145. //==============================================================================
  146. // Function Prototype
  147. //==============================================================================
  148.  
  149. //==============================================================================
  150. // PlatformFile
  151. //==============================================================================
  152.  
  153. const ODOSType kBogusOSType = 0;    // Default type/creator value until it's read
  154.  
  155. //------------------------------------------------------------------------------
  156. // PlatformFile::PlatformFile
  157. //------------------------------------------------------------------------------
  158. PlatformFile::PlatformFile()
  159. {
  160.     fContainerType = kODNULL;
  161.     fCreator = kBogusOSType;
  162.     fFileType = kBogusOSType;
  163.     fScriptTag = smSystemScript;
  164.     
  165.     fFileSpec.vRefNum = 0;
  166.     fFileSpec.parID = 0;
  167.     fFileSpec.name[0] = 0;
  168.     fDataRefNum = 0;
  169.     fFileID = kODNoFileID;
  170.     fPermission = fsCurPerm;
  171.     fResRefNum = kODNoFileRefNum;
  172.     fResOpenStack = 0;
  173.     fNeedToClose = kODFalse;
  174.     
  175.     fVolModDate = fTimeLastChecked = 0;
  176. }
  177.  
  178. //------------------------------------------------------------------------------
  179. // PlatformFile::~PlatformFile
  180. //------------------------------------------------------------------------------
  181. PlatformFile::~PlatformFile()
  182. {
  183.     ODDisposePtr(fContainerType);
  184. }
  185.  
  186. //------------------------------------------------------------------------------
  187. // PlatformFile::Specify
  188. //------------------------------------------------------------------------------
  189. void PlatformFile::Specify(const ODFileSpec* fileSpec)
  190. {
  191.     fFileSpec = *fileSpec;
  192.     fCreator = kBogusOSType;
  193.     fFileType = kBogusOSType;
  194.     fFileID = kODNoFileID;
  195. }
  196.  
  197. void PlatformFile::SpecifyFromFile(PlatformFile* file)
  198. {
  199.     const ODFileSpec &fileSpec = file->GetFileSpec();
  200.     this->Specify(&fileSpec);
  201. }
  202.  
  203. //------------------------------------------------------------------------------
  204. // PlatformFile::SetAsciiname
  205. //------------------------------------------------------------------------------
  206. void PlatformFile::SetAsciiName(const char* asciiName)
  207. {
  208.     ODSByte pname[kMaxFileNameSize+1];
  209.     strncpy(pname,asciiName,kMaxFileNameSize);
  210.     pname[kMaxFileNameSize] = 0;
  211.     
  212.     CToPascalString(pname);
  213.     if (fFileSpec.vRefNum == 0 &&
  214.         fFileSpec.parID == 0 &&
  215.         fFileSpec.name[0] == 0)
  216.     {
  217.         FSMakeFSSpec(0, 0, (StringPtr)pname, &fFileSpec);
  218.     }
  219.     else
  220.     {
  221.         CopyPascalString(fFileSpec.name,(StringPtr)pname);
  222.     }    
  223.     this->Specify(&fFileSpec);
  224. }
  225.  
  226. //------------------------------------------------------------------------------
  227. // PlatformFile::IsLocked
  228. //------------------------------------------------------------------------------
  229. ODBoolean PlatformFile::IsLocked()
  230. {
  231.     CInfoPBRec    pbBlock;
  232.     ODBoolean    result = kODFalse;
  233.  
  234.     // Check to see whether the volume is locked
  235.  
  236.     // Eric's original code with slight modifications.
  237.     // Appears to be needed in the case of a locked floppy. -TÇ
  238.     HParamBlockRec pb;
  239.     pb.volumeParam.ioCompletion = kODNULL;
  240.     pb.volumeParam.ioNamePtr = kODNULL;
  241.     pb.volumeParam.ioVRefNum = fFileSpec.vRefNum;
  242.     pb.volumeParam.ioVolIndex = 0;
  243.  
  244.     THROW_IF_ERROR(PBHGetVInfoSync(&pb));
  245.  
  246.     // <eeh> I have no clue if this "0x80"is right!!!  Find out what
  247.     // the constant is for write-access possible....
  248.  
  249.     result = (pb.volumeParam.ioVAtrb & 0x80) ? kODTrue : kODFalse;
  250.  
  251.     // Check to see whether the directory is locked
  252.     if (result == kODFalse) {
  253.         // first assume it is a file share volume
  254.         HParamBlockRec    paramBlk;
  255.         paramBlk.accessParam.ioCompletion = kODNULL;
  256.         paramBlk.accessParam.ioNamePtr = kODNULL;
  257.         paramBlk.accessParam.ioVRefNum = fFileSpec.vRefNum;
  258.         paramBlk.accessParam.ioDirID = fFileSpec.parID;
  259.         paramBlk.accessParam.ioACAccess = 0;
  260.         OSErr err = PBHGetDirAccessSync(¶mBlk);
  261.         
  262.         if (err == noErr) {        /* it is a file share volume, look at the access right */
  263.             if ((paramBlk.accessParam.ioACAccess & 0x04000000) == 0) /* no write access */
  264.                 result = kODTrue;
  265.         }
  266.         else if (err == paramErr) { /* it is not file share, look at directory */
  267.             pbBlock.dirInfo.ioCompletion = kODNULL;
  268.             pbBlock.dirInfo.ioNamePtr = kODNULL;
  269.             pbBlock.dirInfo.ioVRefNum = fFileSpec.vRefNum;
  270.             pbBlock.dirInfo.ioFDirIndex = -1;
  271.             pbBlock.dirInfo.ioDrDirID = fFileSpec.parID;
  272.             pbBlock.dirInfo.ioFlAttrib = 0;
  273.             THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  274.             if (pbBlock.dirInfo.ioFlAttrib & 1)
  275.                 result = kODTrue;
  276.         }
  277.         else
  278.             THROW(err);
  279.     }
  280.  
  281.     // Check to see whether the file is locked
  282.     if (result == kODFalse) {    
  283.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  284.         pbBlock.hFileInfo.ioFDirIndex = 0;
  285.         pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  286.         pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  287.         pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  288.         
  289.         THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  290.  
  291.         if (pbBlock.hFileInfo.ioFlAttrib & 1)
  292.             result = kODTrue;
  293.     }
  294.     
  295.     return result;
  296. }
  297.  
  298. //------------------------------------------------------------------------------
  299. // PlatformFile::Lock
  300. //------------------------------------------------------------------------------
  301. void PlatformFile::Lock()
  302. {
  303.     THROW_IF_ERROR( FSpSetFLock(&fFileSpec) );
  304. }
  305.  
  306. //------------------------------------------------------------------------------
  307. // PlatformFile::Unlock
  308. //------------------------------------------------------------------------------
  309. void PlatformFile::Unlock()
  310. {
  311.     THROW_IF_ERROR( FSpRstFLock(&fFileSpec) );
  312. }
  313.  
  314.  
  315. //------------------------------------------------------------------------------
  316. // PlatformFile::IsStationery
  317. //------------------------------------------------------------------------------
  318. ODBoolean PlatformFile::IsStationery()
  319. {
  320.     FInfo fileInfo;
  321.     THROW_IF_ERROR( FSpGetFInfo(&fFileSpec,&fileInfo) );
  322.     return (((fileInfo.fdFlags)&kIsStationary)!=0);
  323. }
  324.  
  325. //------------------------------------------------------------------------------
  326. // PlatformFile::SetStationery
  327. //------------------------------------------------------------------------------
  328. void PlatformFile::SetStationery(ODBoolean isStationery)
  329. {
  330.     FInfo fileInfo;
  331.     THROW_IF_ERROR( FSpGetFInfo(&fFileSpec,&fileInfo) );
  332.     if (isStationery)
  333.         (fileInfo.fdFlags) |= kIsStationary;
  334.     else
  335.         (fileInfo.fdFlags) &= ~kIsStationary;
  336.     THROW_IF_ERROR( FSpSetFInfo(&fFileSpec,&fileInfo) );
  337.     BumpFolderModDate();
  338. }
  339.  
  340.  
  341. //------------------------------------------------------------------------------
  342. // PlatformFile::SetCustomIcon
  343. //------------------------------------------------------------------------------
  344. void PlatformFile::SetCustomIcon(ODBoolean hasCustomIcon)
  345. {
  346.     FInfo fileInfo;
  347.  
  348.     THROW_IF_ERROR( FSpGetFInfo(&fFileSpec, &fileInfo) );
  349.     if (hasCustomIcon)
  350.         (fileInfo.fdFlags) |= kHasCustomIcon;
  351.     else
  352.         (fileInfo.fdFlags) &= ~kHasCustomIcon;
  353.     THROW_IF_ERROR( FSpSetFInfo(&fFileSpec, &fileInfo) );
  354.     BumpFolderModDate();
  355. }
  356.  
  357. //------------------------------------------------------------------------------
  358. // PlatformFile::HasCustomIcon
  359. //------------------------------------------------------------------------------
  360. ODBoolean PlatformFile::HasCustomIcon()
  361. {
  362.     FInfo fileInfo;
  363.  
  364.     THROW_IF_ERROR( FSpGetFInfo(&fFileSpec, &fileInfo) );
  365.     return ( (fileInfo.fdFlags & kHasCustomIcon) ? kODTrue : kODFalse);
  366. }
  367.  
  368. //------------------------------------------------------------------------------
  369. // PlatformFile::IsDirectory
  370. //------------------------------------------------------------------------------
  371. ODBoolean PlatformFile::IsDirectory()
  372. {    
  373.     ODBoolean isDirectory = kODFalse;
  374.     
  375.     if( fFileID == kODNoFileID ) {
  376.         CInfoPBRec    pbBlock;
  377.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  378.         pbBlock.hFileInfo.ioFDirIndex = 0;
  379.         pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  380.         pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  381.         pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  382.         THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  383.         isDirectory = pbBlock.dirInfo.ioFlAttrib & 0x10 ? kODTrue : kODFalse;
  384.     }
  385.     return isDirectory;
  386. }
  387.  
  388. //------------------------------------------------------------------------------
  389. // PlatformFile::IsEqualTo
  390. //------------------------------------------------------------------------------
  391. ODBoolean PlatformFile::IsEqualTo(PlatformFile* file)
  392. {
  393.     return (fFileSpec.parID == file->fFileSpec.parID &&
  394.             fFileSpec.vRefNum == file->fFileSpec.vRefNum &&
  395.             EqualPascalStrings(fFileSpec.name, file->fFileSpec.name));
  396. }
  397.  
  398. //------------------------------------------------------------------------------
  399. // PlatformFile::GetFInfoFlags
  400. //------------------------------------------------------------------------------
  401. ODUShort    PlatformFile::GetFInfoFlags()
  402. {
  403.     FInfo fileInfo;
  404.  
  405.     THROW_IF_ERROR( FSpGetFInfo(&fFileSpec, &fileInfo) );
  406.     return fileInfo.fdFlags;
  407. }
  408.  
  409. //------------------------------------------------------------------------------
  410. // PlatformFile::Create
  411. //------------------------------------------------------------------------------
  412. void PlatformFile::Create(ODOSType creator, ODOSType fileType, ODScriptCode scriptCode)
  413. {    
  414.     
  415.     if (fDataRefNum == kODNoFileRefNum) {
  416.         THROW_IF_ERROR( FSpCreate(&fFileSpec, creator, fileType, scriptCode) );
  417.     }
  418.     fCreator = creator;
  419.     fFileType = fileType;
  420.     fScriptTag = scriptCode;
  421.     
  422.     this->GetFileID();
  423. }
  424.  
  425. //------------------------------------------------------------------------------
  426. // PlatformFile::CreateResFile
  427. //------------------------------------------------------------------------------
  428. void PlatformFile::CreateResFile()
  429. {
  430.     if (fResRefNum == kODNoFileRefNum)
  431.     {
  432.         this->GetPlatformType();    // make sure the type and creator are known
  433.         FSpCreateResFile(&fFileSpec, fCreator, fFileType, fScriptTag);
  434.         THROW_IF_ERROR(ResError());
  435.     }
  436.     this->GetFileID();
  437. }
  438.  
  439. //------------------------------------------------------------------------------
  440. // PlatformFile::OpenResFile
  441. //------------------------------------------------------------------------------
  442. void PlatformFile::OpenResFile()
  443. {
  444.     ASSERT(fResOpenStack >= 0, kODErrAssertionFailed);
  445.     if (fResRefNum == kODNoFileRefNum)
  446.     {
  447.         ASSERT(fResOpenStack == 0, fResOpenStack);
  448.         fResRefNum = GetFirstLocalPath(PlatformFile::kODResourceFork);
  449.         if (fResRefNum != kODNoFileRefNum)
  450.         {
  451.             // Resource fork is already open
  452.             UseResFile(fResRefNum);
  453.             fNeedToClose = kODFalse;
  454.         }
  455.         else
  456.         {
  457.             // Resource fork is closed
  458.             fResRefNum = FSpOpenResFile(&fFileSpec, fPermission);
  459.             if (fResRefNum == -1 && fPermission != fsRdPerm)
  460.             {
  461.                 fResRefNum = kODNoFileRefNum;
  462.                 CreateResFile();
  463.                 fResRefNum = FSpOpenResFile(&fFileSpec, fPermission);
  464.             }
  465.             OSErr err = ResError();
  466.             if (err != eofErr)
  467.             {
  468.                 if (fResRefNum == -1)
  469.                     fResRefNum = kODNoFileRefNum;
  470.                 THROW_IF_ERROR(ResError());
  471.             }
  472.             if (fResRefNum == -1)
  473.             {
  474.                 fResRefNum = kODNoFileRefNum;
  475.                 THROW(resFNotFound);
  476.             }
  477.             fNeedToClose = kODTrue;
  478.         }
  479.     }
  480.     else
  481.         UseResFile(fResRefNum);
  482.     ++fResOpenStack;
  483. }
  484.  
  485. //------------------------------------------------------------------------------
  486. // PlatformFile::CloseResFile
  487. //------------------------------------------------------------------------------
  488. void PlatformFile::CloseResFile()
  489. {
  490.     ASSERT(fResOpenStack > 0, fResOpenStack);
  491.     if (--fResOpenStack == 0 && fNeedToClose)
  492.     {
  493.         ::CloseResFile(fResRefNum);
  494.         THROW_IF_ERROR(ResError());
  495.         fResRefNum = kODNoFileRefNum;
  496.     }
  497. }
  498.  
  499. //------------------------------------------------------------------------------
  500. // PlatformFile::GetFileID
  501. //------------------------------------------------------------------------------
  502. void PlatformFile::GetFileID()
  503. {
  504.     if( fFileID == kODNoFileID ) {
  505.         CInfoPBRec    pbBlock;
  506.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  507.         pbBlock.hFileInfo.ioFDirIndex = 0;
  508.         pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  509.         pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  510.         pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  511.         THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  512.         fFileID = pbBlock.hFileInfo.ioDirID;    /* for tracking the file later */
  513.     }
  514. }
  515.  
  516. //------------------------------------------------------------------------------
  517. // PlatformFile::UpdateSpecFromID
  518. //------------------------------------------------------------------------------
  519. void PlatformFile::UpdateSpecFromID()
  520. {
  521.     if (fFileID != kODNoFileID) {    /* make sure got the latest name in file spec */
  522.         HParamBlockRec hPB;
  523.         hPB.fidParam.ioCompletion = kODNULL;
  524.         hPB.fidParam.ioNamePtr = fFileSpec.name;
  525.         hPB.fidParam.ioVRefNum = fFileSpec.vRefNum;
  526.         hPB.fidParam.ioFileID = fFileID;
  527.         if (PBResolveFileIDRefSync(&hPB) == noErr)    /* ignore any error */
  528.             fFileSpec.parID = hPB.fidParam.ioSrcDirID;
  529.     }
  530. }
  531.  
  532.  
  533. //------------------------------------------------------------------------------
  534. // PlatformFile::Exists
  535. //------------------------------------------------------------------------------
  536. ODBoolean PlatformFile::Exists()
  537. {
  538.     const ODFileSpec &filespec = this->GetFileSpec();
  539.     FInfo ignore ;
  540.     OSErr err = FSpGetFInfo( &filespec, &ignore );
  541.     if ( err == noErr )
  542.         return kODTrue ;
  543.     else {
  544.         if ( err != fnfErr )
  545.             THROW( err );
  546.         return kODFalse ;
  547.     }
  548. }
  549.  
  550. //------------------------------------------------------------------------------
  551. // PlatformFile::Open
  552. //------------------------------------------------------------------------------
  553. void PlatformFile::Open()
  554. {    
  555.     if (fDataRefNum == kODNoFileRefNum) {
  556.         this->GetFileID();
  557.         THROW_IF_ERROR(FSpOpenDF(&fFileSpec, fPermission, &fDataRefNum));
  558.     }
  559.     else
  560.         THROW(kODErrFileOpened);
  561. }
  562.  
  563. //------------------------------------------------------------------------------
  564. // PlatformFile::Close
  565. //------------------------------------------------------------------------------
  566. void PlatformFile::Close()
  567. {    
  568.     if (fDataRefNum != kODNoFileRefNum) {
  569.         THROW_IF_ERROR(FSClose(fDataRefNum));
  570.         fDataRefNum = kODNoFileRefNum;
  571.     }
  572.     else
  573.         THROW(kODErrFileClosed);
  574. }
  575.  
  576. //------------------------------------------------------------------------------
  577. // PlatformFile::Delete
  578. //------------------------------------------------------------------------------
  579. void PlatformFile::Delete()
  580. {    
  581.     THROW_IF_ERROR(FSpDelete(&fFileSpec));
  582.     fFileID = kODNoFileID;
  583. }
  584.  
  585.  
  586. //------------------------------------------------------------------------------
  587. // PlatformFile::FlushVolume
  588. //------------------------------------------------------------------------------
  589. void PlatformFile::FlushVolume()
  590. {    
  591.     if (fDataRefNum != kODNoFileRefNum) {
  592.         ParamBlockRec    pb;
  593.     
  594.         pb.ioParam.ioCompletion = kODNULL;
  595.         pb.ioParam.ioRefNum = fDataRefNum;
  596.         (void) PBFlushFileSync(&pb);
  597.     }
  598.  
  599.     (void) FlushVol(kODNULL, fFileSpec.vRefNum);
  600. }
  601.  
  602. //------------------------------------------------------------------------------
  603. // PlatformFile::SetFilePos
  604. //------------------------------------------------------------------------------
  605. void PlatformFile::SetFilePos(ODSShort posMode, ODSLong posOff)
  606. {    
  607.     THROW_IF_ERROR(SetFPos(fDataRefNum, posMode, posOff));
  608. }
  609.  
  610. //------------------------------------------------------------------------------
  611. // PlatformFile::GetFilePos
  612. //------------------------------------------------------------------------------
  613. ODSLong PlatformFile::GetFilePos()
  614. {
  615.     ODSLong    posOff;
  616.     
  617.     THROW_IF_ERROR(GetFPos(fDataRefNum, &posOff));
  618.     return posOff;
  619. }
  620.  
  621. //------------------------------------------------------------------------------
  622. // PlatformFile::Read
  623. //------------------------------------------------------------------------------
  624. void PlatformFile::Read(void* buffer, ODSLong* count)
  625. {    
  626.     THROW_IF_ERROR(FSRead(fDataRefNum, count, buffer));
  627. }
  628.  
  629. //------------------------------------------------------------------------------
  630. // PlatformFile::Write
  631. //------------------------------------------------------------------------------
  632. void PlatformFile::Write(const void* buffer, ODSLong* count)
  633. {    
  634.     THROW_IF_ERROR(FSWrite(fDataRefNum, count, buffer));
  635. }
  636.  
  637. //------------------------------------------------------------------------------
  638. // PlatformFile::GetEndOfFile
  639. //------------------------------------------------------------------------------
  640. ODSLong PlatformFile::GetEndOfFile()
  641. {    
  642.     ODSLong    length;
  643.     
  644.     THROW_IF_ERROR(GetEOF(fDataRefNum, &length));
  645.     return length;
  646. }
  647.  
  648. //------------------------------------------------------------------------------
  649. // PlatformFile::SetEndOfFile
  650. //------------------------------------------------------------------------------
  651. void  PlatformFile::SetEndOfFile(ODSLong length)
  652. {    
  653.     THROW_IF_ERROR(SetEOF(fDataRefNum, length));
  654. }
  655.  
  656. //------------------------------------------------------------------------------
  657. // PlatformFile::GetName
  658. //------------------------------------------------------------------------------
  659. ODName* PlatformFile::GetName()
  660. {
  661.     this->UpdateSpecFromID();
  662.  
  663.     return CreateIText(fScriptTag, 0, fFileSpec.name);
  664. }
  665.  
  666. //------------------------------------------------------------------------------
  667. // PlatformFile::GetAsciiName
  668. //------------------------------------------------------------------------------
  669. void PlatformFile::GetAsciiName(char* asciiName, ODULong maxLength)
  670. {
  671.     this->UpdateSpecFromID();
  672.  
  673.     ODULong n = fFileSpec.name[0];
  674.     if( n > maxLength )
  675.         n = maxLength;
  676.     ODBlockMove(&(fFileSpec.name[1]), asciiName, n);
  677.     asciiName[n] = '\0';
  678. }
  679.  
  680. //------------------------------------------------------------------------------
  681. // PlatformFile::GetPlatformCreator
  682. //------------------------------------------------------------------------------
  683. ODOSType PlatformFile::GetPlatformCreator()
  684. {
  685.     if (fCreator == kBogusOSType) {
  686.         FInfo    fileInfo;
  687.         THROW_IF_ERROR(FSpGetFInfo(&fFileSpec, &fileInfo));
  688.         fCreator = fileInfo.fdCreator;
  689.         fFileType = fileInfo.fdType;
  690.     }
  691.     return fCreator;
  692. }    
  693.  
  694. //------------------------------------------------------------------------------
  695. // PlatformFile::GetPlatformType
  696. //------------------------------------------------------------------------------
  697. ODOSType PlatformFile::GetPlatformType()
  698. {
  699.     if (fFileType == kBogusOSType) {
  700.         FInfo    fileInfo;
  701.         THROW_IF_ERROR(FSpGetFInfo(&fFileSpec, &fileInfo));
  702.         fCreator = fileInfo.fdCreator;
  703.         fFileType = fileInfo.fdType;
  704.     }
  705.     return fFileType;
  706. }    
  707.  
  708. //------------------------------------------------------------------------------
  709. // PlatformFile::SetPlatformType
  710. //------------------------------------------------------------------------------
  711. void PlatformFile::SetPlatformType(ODOSType fileType)
  712. {
  713.     FInfo    fileInfo;
  714.     THROW_IF_ERROR(FSpGetFInfo(&fFileSpec, &fileInfo));
  715.     if( fileInfo.fdType != fileType ) {
  716.         fileInfo.fdType = fileType;
  717.         THROW_IF_ERROR(FSpSetFInfo(&fFileSpec, &fileInfo));
  718.         fFileType = fileType;
  719.         this->BumpFolderModDate();
  720.     }
  721. }    
  722.  
  723.  
  724. //------------------------------------------------------------------------------
  725. // PlatformFile::GetContainerType
  726. //------------------------------------------------------------------------------
  727.  
  728. ODContainerType PlatformFile::GetContainerType()
  729. {
  730.     if (fContainerType == kODNULL)
  731.         fContainerType =
  732.             (ODContainerType)
  733.             (this->ReadResourcePtr(kFileContainerType, kFileContainerTypeResID, kODNULL));
  734.  
  735.     return fContainerType;
  736. }
  737.  
  738. //------------------------------------------------------------------------------
  739. // PlatformFile::SetContainerType
  740. //------------------------------------------------------------------------------
  741.  
  742. void PlatformFile::SetContainerType(ODContainerType containerType)
  743. {
  744.     ODDisposePtr(fContainerType);
  745.     fContainerType = containerType;
  746.  
  747.     this->WriteResourcePtr(kFileContainerType, kFileContainerTypeResID, 
  748.                         (ODPtr)containerType, strlen(containerType)+1);
  749. }
  750.  
  751.  
  752. //------------------------------------------------------------------------------
  753. // CWithActiveResources class
  754. //------------------------------------------------------------------------------
  755.  
  756. class CWithActiveResources :Destructo {
  757.     public:
  758.     CWithActiveResources( PlatformFile* );
  759.    ~CWithActiveResources( );
  760.     private:
  761.     PlatformFile    *fFile;
  762.     ODFileRefNum    fCurResFile;
  763.     ODBoolean        fSuccessfullyOpened;
  764. };
  765.  
  766. CWithActiveResources::CWithActiveResources( PlatformFile *pf )
  767. {
  768.     fSuccessfullyOpened = kODFalse;
  769.     fFile = pf;
  770.     fCurResFile = CurResFile();
  771.     fFile->OpenResFile();
  772.     fSuccessfullyOpened = kODTrue;
  773. }
  774.  
  775. CWithActiveResources::~CWithActiveResources( )
  776. {
  777.     if (fSuccessfullyOpened)
  778.         fFile->CloseResFile();
  779.     UseResFile(fCurResFile);
  780. }
  781.         
  782.  
  783. //------------------------------------------------------------------------------
  784. // PlatformFile::ReadResourcePtr
  785. //------------------------------------------------------------------------------
  786. ODPtr PlatformFile::ReadResourcePtr(ODPlatformType resType, ODSShort resID, ODULong* size)
  787. {
  788.     ODPtr resPtr = kODNULL;     ODVolatile(resPtr);    // Method Specific
  789.     
  790.     TRY
  791.         CWithActiveResources w(this); // this throws if no resfile
  792.         
  793.         Handle resHandle = Get1Resource(resType, resID);
  794.         if (resHandle != kODNULL)
  795.         {
  796.             HNoPurge(resHandle);
  797.             ODULong hsize = GetHandleSize(resHandle);
  798.             if (size != kODNULL)
  799.                 *size = hsize;
  800.             resPtr = ODNewPtrClear(hsize,0);
  801.             ODBlockMove(*resHandle,resPtr, hsize);
  802.             ReleaseResource(resHandle);
  803.         } else if( ResError() != resNotFound )
  804.             THROW_IF_ERROR(ResError());
  805.  
  806.     CATCH_ALL
  807.     ENDTRY
  808.     
  809.     return resPtr;  // Method Specific
  810. }
  811.  
  812. //------------------------------------------------------------------------------
  813. // PlatformFile::WriteResourcePtr
  814. //------------------------------------------------------------------------------
  815. void PlatformFile::WriteResourcePtr(ODPlatformType resType, ODSShort resID, 
  816.                                     const void *resPtr, ODULong size)
  817. {
  818.     ASSERT(resPtr!=kODNULL,kODErrIllegalNullInput);
  819.     
  820.     SetPermission(fsRdWrPerm);
  821.     CWithActiveResources w(this);
  822.     
  823.     Handle resHandle = Get1Resource(resType,resID);
  824.     if( ResError() != resNotFound )
  825.         THROW_IF_ERROR(ResError());
  826.         
  827.     ODBoolean needsAdding = (resHandle == kODNULL);
  828.     if (needsAdding)
  829.         resHandle = ODNewHandle(size);
  830.     else {
  831.         HNoPurge(resHandle);
  832.         ODSetHandleSize(resHandle, size);
  833.     }
  834.     
  835.     ODBlockMove(resPtr,*resHandle, size);
  836.     
  837.     if (needsAdding)
  838.         AddResource(resHandle,resType,resID,"\p");
  839.     else
  840.         ChangedResource(resHandle);
  841.     THROW_IF_ERROR(ResError());
  842. }
  843.  
  844.  
  845. //------------------------------------------------------------------------------
  846. // PlatformFile::DeleteResource
  847. //------------------------------------------------------------------------------
  848. void PlatformFile::DeleteResource(ODPlatformType resType, ODSShort resID)
  849. {
  850.     SetPermission(fsRdWrPerm);
  851.     CWithActiveResources w(this);
  852.     
  853.     Handle resHandle = Get1Resource(resType, resID);
  854.     OSErr err= ResError();
  855.     if( resHandle ) {
  856.         RemoveResource(resHandle);
  857.         err= ResError();
  858.         if( !err )
  859.             DisposeHandle(resHandle);    // After RemoveResource it's not a rsrc
  860.     } else {
  861.         if( err == resNotFound )
  862.             err = noErr;
  863.     }
  864.     THROW_IF_ERROR(err);
  865. }
  866.  
  867. //------------------------------------------------------------------------------
  868. // PlatformFile::GetAllocationBlockSize
  869. //------------------------------------------------------------------------------
  870. ODULong PlatformFile::GetAllocationBlockSize()
  871. {
  872.     HParamBlockRec pb;
  873.     
  874.     pb.volumeParam.ioCompletion = kODNULL;
  875.     pb.volumeParam.ioNamePtr = kODNULL;
  876.     pb.volumeParam.ioVRefNum = fFileSpec.vRefNum;
  877.     pb.volumeParam.ioVolIndex = 0;
  878.  
  879.     THROW_IF_ERROR(PBHGetVInfoSync(&pb));
  880.  
  881.     return pb.volumeParam.ioVAlBlkSiz;
  882. }
  883.  
  884. //------------------------------------------------------------------------------
  885. // PlatformFile::CopyFrom
  886. //------------------------------------------------------------------------------
  887. void PlatformFile::CopyFrom( PlatformFile* src )
  888. {
  889.     ODBoolean srcIsOpen = (src->GetFileRefNum() != kODNoFileRefNum);
  890.     if ( !srcIsOpen )
  891.         src->Open();
  892.     this->SetPermission( fsRdWrPerm );        // currently this is the default value
  893.     if (!this->Exists())
  894.         this->Create(src->GetPlatformCreator(), src->GetPlatformType(), 0 /*$$$$$ scriptcode?*/);
  895.  
  896.     this->Open();
  897.             
  898.     src->SetFilePos( fsFromStart, 0 );
  899.     this->SetFilePos( fsFromStart, 0 );
  900.     
  901.     ODSLong bytesLeft = src->GetEndOfFile();
  902.  
  903.     TempODHandle hbuffer = kODNULL;
  904.     ODSLong bufferSize = kMaxCopyBufferSize;
  905.     if( bufferSize > bytesLeft )
  906.         bufferSize = bytesLeft;
  907.     for( ; bufferSize>=kMinCopyBufferSize; bufferSize /= 2 ) {
  908.         OSErr err;
  909.         hbuffer= TempNewHandle(bufferSize,&err);
  910.         if( hbuffer ) break;
  911.     }
  912.     WASSERT(bufferSize > 0);
  913.     THROW_IF_NULL(hbuffer);
  914.     void *buffer = *hbuffer;
  915.     
  916.     ODSLong count;
  917.  
  918.     while( bytesLeft > 0 )
  919.     {
  920.         count = bytesLeft < bufferSize? bytesLeft: bufferSize ;
  921.         WASSERT(count > 0);
  922.         src->Read( buffer, &count );
  923.         this->Write( buffer, &count );
  924.         bytesLeft -= count ;
  925.     }
  926.     
  927.     if ( !srcIsOpen )
  928.         src->Close();
  929.     this->Close();
  930. }
  931.  
  932. //------------------------------------------------------------------------------
  933. // PlatformFile::MoveRename
  934. //------------------------------------------------------------------------------
  935. void PlatformFile::MoveRename( ODFileSpec* newSpec, ODBoolean isDuplicate )
  936. {
  937.     // This will fail if a file with the old name already exists in the
  938.     // target directory. MoreFiles (DTS) has a more robust version of this.
  939.     
  940.     ASSERT(newSpec->vRefNum == fFileSpec.vRefNum, kODErrAssertionFailed);
  941.  
  942.     if ( isDuplicate )
  943.     {
  944.         THROW_IF_ERROR( FSpDelete( newSpec ) ); 
  945.     }
  946.  
  947.     this->Move( newSpec->parID );
  948.     this->Rename( newSpec->name );
  949. }    // MoveRename()
  950.  
  951.  
  952. //------------------------------------------------------------------------------
  953. // PlatformFile::Move
  954. //------------------------------------------------------------------------------
  955.  
  956. void PlatformFile::Move( ODSLong targetParID )
  957. {
  958.     CMovePBRec paramBlock ;
  959.     memset( ¶mBlock, 0, sizeof(paramBlock) );
  960.     
  961.     paramBlock.ioNamePtr = fFileSpec.name ;
  962.     paramBlock.ioVRefNum = fFileSpec.vRefNum ;
  963.     paramBlock.ioNewDirID = targetParID ;
  964.     paramBlock.ioDirID = fFileSpec.parID ;
  965.     
  966.     (void) HDelete(fFileSpec.vRefNum,targetParID,fFileSpec.name);     // ignore error (may not exist)
  967.     OSErr err = PBCatMoveSync( ¶mBlock );
  968.     THROW_IF_ERROR( err );
  969.  
  970.     fFileSpec.parID = targetParID ;
  971. }
  972.  
  973. //------------------------------------------------------------------------------
  974. // PlatformFile::UniquifyName
  975. // Given in this a platformfile (whose filespec only is used) that may conflict
  976. // with an existing file, deal with this conflict in one of two ways depending
  977. // on the value of action.  The two values are:
  978. // 1. kSpecifyNewNameOnly: just change the name field of the filespec so that the
  979. // platform file represents a file that would be unique if created
  980. // 2. kRenameInPlace: this file already exists, but we want it to have a different
  981. // name so we can reuse this one.  Find that name, and rename the actual file.
  982. // 
  983. // Two string templates are expected, and the caller can either pass in their
  984. // resource IDs or StringHandles to the strings themselves, signifying the latter
  985. // with a resource ID of kODNoResourceID.  The first of these strings is used
  986. // the first time through the renaming loop (which typically sticks something
  987. // like " copy" on the end of the file name, and the second is used thereafter
  988. // (when increasingly large numbers are put into the string in an attempt to
  989. // make it unique.
  990. //------------------------------------------------------------------------------
  991.  
  992. void PlatformFile::UniquifyName( ODSShort uniquifyingStringID,
  993.             StringHandle uniquifyingString, 
  994.             ODSShort uniquifyingNumberID,
  995.             StringHandle uniquifyingNumberString, 
  996.             short copyCount,
  997.             PFUniquifyAction action, 
  998.             ODBoolean forceNewName)
  999. {
  1000.     if ((forceNewName!=kODTryCurrentName) || this->Exists() )
  1001.     {
  1002.         PlatformFile* possibleOther = new PlatformFile;
  1003.         TempPlatformFile t = possibleOther;        // save so will get deconstructed
  1004. //        possibleOther->SpecifyFromFile( this );
  1005.     
  1006.         // Get the strings to be used in substitution if they weren't passed in.
  1007.         // Assign them to tempobjs so we don't have to dispose later.  Don't assign
  1008.         // if they're passed in (of course....)
  1009.         TempODHandle registerNoNumHandleIfLocal = kODNULL;
  1010.         TempODHandle registerNumHandleIfLocal = kODNULL;
  1011.         CUsingLibraryResources r;
  1012.         if ( uniquifyingStringID != kODNoResourceID )
  1013.         {
  1014.             WASSERT( !uniquifyingString );
  1015.             uniquifyingString = GetString( uniquifyingStringID );
  1016.             DetachResource( (Handle)uniquifyingString );
  1017.             registerNoNumHandleIfLocal = (Handle)uniquifyingString;
  1018.             WASSERT( uniquifyingString );
  1019.         }
  1020.         if ( uniquifyingNumberID != kODNoResourceID )
  1021.         {
  1022.             WASSERT(!uniquifyingNumberString);
  1023.             uniquifyingNumberString = GetString( uniquifyingNumberID );
  1024.             DetachResource( (Handle)uniquifyingNumberString );
  1025.             registerNumHandleIfLocal = (Handle)uniquifyingNumberString;
  1026.         }
  1027.         WASSERT(uniquifyingNumberString);
  1028.     
  1029.         ODFileSpec localCopy = this->GetFileSpec();
  1030.         // save the name (as we'll be munging localCopy)
  1031.         Str63 originalName;
  1032.         ODBlockMove( localCopy.name, originalName, localCopy.name[0]+1 );
  1033.     
  1034.         TempODHandle baseText = ODNewHandle(kMaxFileNameSize+1);
  1035.         THROW_IF_NULL(baseText);
  1036.         TempODHandle substitutionText = ODNewHandle(kMaxFileNameSize+1);
  1037.         THROW_IF_NULL(substitutionText);
  1038.     
  1039.         ODBoolean nameNeedsNumber = (uniquifyingString == kODNULL);
  1040.             // if there is no uniquifyingString, we immediately need to start using
  1041.             // the uniquifyingNumberString, or in other words nameNeedsNumber==true.
  1042.             
  1043.         for ( ; ; nameNeedsNumber = kODTrue)
  1044.         {
  1045.             // nameNeedsNumber = copyCount > 1;
  1046.             StringHandle templateToUse = nameNeedsNumber ?
  1047.                     uniquifyingNumberString : uniquifyingString;
  1048.     
  1049.             short thisTemplateLen = **templateToUse;
  1050.             // <eeh> NOTE that this forces callers to have two ^number tuples in the
  1051.             // second template.
  1052.             thisTemplateLen -= nameNeedsNumber? 4 : 2;
  1053.     
  1054.             short numberLen;
  1055.             Str32 numberString;
  1056.             if ( nameNeedsNumber )
  1057.             {
  1058.                 NumToString( copyCount, numberString );
  1059.                 numberLen = numberString[0];
  1060.             }
  1061.             else
  1062.                 numberLen = 0;
  1063.     
  1064.             // truncate the name if after appending it will be too long
  1065.             Str63 localName;
  1066.             ODBlockMove( originalName, localName, originalName[0] + 1 );
  1067.             short postAppendLen = localName[0] + thisTemplateLen + numberLen;
  1068.             if ( postAppendLen > kODMaxFileNameSize )
  1069.                 ClipStringToBytes( localName,
  1070.                         kODMaxFileNameSize - thisTemplateLen - numberLen, fScriptTag );
  1071.     
  1072.             // copy the template into the base handle, then pass in the possible file
  1073.             // name
  1074.             short len;
  1075.             SetHandleSize( baseText, len = **templateToUse );
  1076.             ODBlockMove( (*templateToUse)+1, *baseText, len );
  1077.             SetHandleSize( substitutionText, len = localName[0] );
  1078.             ODBlockMove( &localName[1], *substitutionText, len );
  1079.             short err = ReplaceText( baseText, substitutionText, "\p^0" );
  1080.             WASSERT( err >= 0 );
  1081.             
  1082.             if ( nameNeedsNumber )        // do same for number
  1083.             {
  1084.                 SetHandleSize( substitutionText, len = numberString[0] );
  1085.                 ODBlockMove( &numberString[1], *substitutionText, len );
  1086.                 err = ReplaceText( baseText, substitutionText, "\p^1" );
  1087.                 WASSERT( err >= 0 );
  1088.             }
  1089.     
  1090.             ODBlockMove( *baseText, &localCopy.name[1], len = GetHandleSize(baseText) );
  1091.             localCopy.name[0] = len;
  1092.     
  1093.             possibleOther->Specify( &localCopy );
  1094.             if ( !possibleOther->Exists() )
  1095.             {
  1096.                 WASSERT( localCopy.name[0] <= kODMaxFileNameSize );
  1097.                 if ( action == kSpecifyNewNameOnly )
  1098.                 {
  1099.                     // set up this so that when created it will represent a unique file
  1100.                     PascalToCString( localCopy.name );
  1101.                     this->SetAsciiName( (char*)localCopy.name );
  1102.                 }
  1103.                 else if ( action == kRenameInPlace )
  1104.                 {
  1105.                     // put the original file spec back in the target, then call
  1106.                     // Rename passing in the new name
  1107.                     WASSERT(this->Exists());
  1108.                     this->Rename( localCopy.name );
  1109.                 }
  1110.                 else
  1111.                     WARN( "unknown PFUniquifyAction" );
  1112.                 break;
  1113.             }
  1114.             if (nameNeedsNumber)
  1115.                 ++copyCount;        
  1116.                 // Gets executed after 2nd time through loop if there was a valid
  1117.                 // uniquifyString.  
  1118.                 // Otherwise gets executed after 1st time through loop.
  1119.         }
  1120.     }
  1121. }    // UniquifyName
  1122.  
  1123. //------------------------------------------------------------------------------
  1124. // PlatformFile::MoveToTrash
  1125. //------------------------------------------------------------------------------
  1126.  
  1127. void PlatformFile::MoveToTrash()
  1128. {
  1129.     ODSLong parID = fFileSpec.parID;
  1130.     ODSLong            trashDirID;
  1131.     THROW_IF_ERROR(FindFolder(fFileSpec.vRefNum, kTrashFolderType, kCreateFolder,
  1132.                             &(fFileSpec.vRefNum), &trashDirID));
  1133.                             
  1134.     // Move deletes any file that may conflict with the file once moved, but
  1135.     // in this case that isn't what we want.  So check if such a file exists,
  1136.     // and if so rename the conflicting file first (following the Finder's
  1137.     // model.)
  1138.     ODFileSpec possibleOtherFS = this->GetFileSpec();
  1139.     possibleOtherFS.parID = trashDirID;
  1140.     PlatformFile target;        // represents a file that *may* be in the trash
  1141.     target.Specify( &possibleOtherFS );
  1142.     
  1143. #if 1
  1144. //    if ( target.Exists() )
  1145.     {
  1146.         CUsingLibraryResources r;
  1147.         target.UniquifyName( kCopyDefaultNameNoNumStrID, kODNULL,
  1148.                 kCopyDefaultNameWithNumStrID, kODNULL, 2, kRenameInPlace,
  1149.                 kODTryCurrentName ) ;
  1150.     }
  1151. #else
  1152.     Str32 uniqueName;
  1153.     if ( MakeUniqueFileName( &target, kCopyDefaultNameNoNumStrID,
  1154.             kCopyDefaultNameWithNumStrID, 31, uniqueName ) )
  1155.         target.Rename( uniqueName );
  1156. #endif
  1157.     this->Move(trashDirID);
  1158.  
  1159.     CInfoPBRec pbRec;
  1160.     pbRec.hFileInfo.ioCompletion = NULL;
  1161.     pbRec.hFileInfo.ioNamePtr = fFileSpec.name;
  1162.     pbRec.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  1163.     pbRec.hFileInfo.ioFDirIndex = 0;
  1164.     pbRec.hFileInfo.ioDirID = fFileSpec.parID;
  1165.     
  1166.     
  1167.     if ( PBGetCatInfoSync( &pbRec ) == noErr )
  1168.     {
  1169.         // <eeh> stuffing this field *may* not work under Copland
  1170.         pbRec.hFileInfo.ioFlXFndrInfo.fdPutAway = parID;
  1171.         // this was changed by PBGetCatInfoSync...
  1172.         pbRec.hFileInfo.ioDirID = fFileSpec.parID;
  1173.         (void)PBSetCatInfoSync( &pbRec );    // ignore the error
  1174.     }
  1175. }
  1176.  
  1177. //------------------------------------------------------------------------------
  1178. // PlatformFile::Rename
  1179. //        This routine will not yet delete a file that will prevent the
  1180. //            renaming (as Move() does above.)
  1181. //------------------------------------------------------------------------------
  1182. void PlatformFile::Rename( Str63 newName )
  1183. {
  1184.     this->UpdateSpecFromID();
  1185.     
  1186.     THROW_IF_ERROR( FSpRename( &fFileSpec, newName ) );
  1187.      CopyPascalString(fFileSpec.name, newName);
  1188.     BumpFolderModDate();
  1189. }
  1190.  
  1191.  
  1192. //------------------------------------------------------------------------------
  1193. // PlatformFile::GetFileModDate
  1194. //        This routine will set the file modification date to the input parameter
  1195. //------------------------------------------------------------------------------
  1196. ODTime PlatformFile::GetFileModDate()
  1197. {
  1198.     this->UpdateSpecFromID();
  1199.     
  1200.     CInfoPBRec    pbBlock;
  1201.     pbBlock.hFileInfo.ioCompletion = kODNULL;
  1202.     pbBlock.hFileInfo.ioFDirIndex = 0;
  1203.     pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  1204.     pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  1205.     pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1206.     THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  1207.     return pbBlock.hFileInfo.ioFlMdDat;
  1208. }
  1209.  
  1210.  
  1211. //------------------------------------------------------------------------------
  1212. // PlatformFile::SetFileModDate
  1213. //        This routine will set the file modification date to the input parameter
  1214. //------------------------------------------------------------------------------
  1215. void PlatformFile::SetFileModDate(ODTime date)
  1216. {
  1217.     this->UpdateSpecFromID();
  1218.     
  1219.     if (!this->IsLocked()) {
  1220.         CInfoPBRec    pbBlock;
  1221.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  1222.         pbBlock.hFileInfo.ioFDirIndex = 0;
  1223.         pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  1224.         pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  1225.         pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1226.         if (PBGetCatInfoSync(&pbBlock) == noErr) {
  1227.             pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1228.             pbBlock.hFileInfo.ioFlMdDat = date;
  1229.             (void) PBSetCatInfoSync(&pbBlock); /* who cares if it fails */
  1230.         }
  1231.     }
  1232. }
  1233.  
  1234. //------------------------------------------------------------------------------
  1235. // PlatformFile::SetFileCreationDate
  1236. //        This routine will set the file creation date to the input parameter
  1237. //------------------------------------------------------------------------------
  1238. void PlatformFile::SetFileCreationDate(ODTime date)
  1239. {
  1240.     this->UpdateSpecFromID();
  1241.  
  1242.     CInfoPBRec    pbBlock;
  1243.  
  1244.     if (!this->IsLocked()) {
  1245.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  1246.         pbBlock.hFileInfo.ioFDirIndex = 0;
  1247.         pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  1248.         pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  1249.         pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1250.         if (PBGetCatInfoSync(&pbBlock) == noErr) {
  1251.             pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1252.             pbBlock.hFileInfo.ioFlCrDat = date;
  1253.             (void) PBSetCatInfoSync(&pbBlock); /* who cares if it fails */
  1254.         }
  1255.     }
  1256. }
  1257.                 
  1258. //------------------------------------------------------------------------------
  1259. // PlatformFile::GetFileCreationDate
  1260. //        This routine will get the file creation date and return it.
  1261. //------------------------------------------------------------------------------
  1262. ODTime PlatformFile::GetFileCreationDate()
  1263. {
  1264.     this->UpdateSpecFromID();
  1265.     
  1266.     CInfoPBRec    pbBlock;
  1267.     pbBlock.hFileInfo.ioCompletion = kODNULL;
  1268.     pbBlock.hFileInfo.ioFDirIndex = 0;
  1269.     pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  1270.     pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  1271.     pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1272.     THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  1273.     return pbBlock.hFileInfo.ioFlCrDat;
  1274. }
  1275.             
  1276. //------------------------------------------------------------------------------
  1277. // PlatformFile::BumpFolderModDate
  1278. //        This routine will set the file modification date of the parent folder
  1279. //        to the current time so as to cause the Finder to refresh the folder if
  1280. //        it is open.  It only has WARNs if it errors.
  1281. //------------------------------------------------------------------------------
  1282. void PlatformFile::BumpFolderModDate()
  1283. {
  1284.     CInfoPBRec    theParamBlock;
  1285.  
  1286.     memset (&theParamBlock, 0, sizeof(theParamBlock));
  1287.     // ioNamePtr = 0
  1288.     theParamBlock.dirInfo.ioFDirIndex = -1;
  1289.     theParamBlock.dirInfo.ioVRefNum = fFileSpec.vRefNum;
  1290.     theParamBlock.dirInfo.ioDrDirID = fFileSpec.parID;
  1291.     OSErr err = PBGetCatInfoSync(&theParamBlock);
  1292.     if( err )
  1293.         WARN("Couldn't get dir mod date, err %hd",err);
  1294.     else
  1295.     {
  1296.         ODULong newTime;
  1297.  
  1298.         GetDateTime(&newTime);
  1299.         // set to the future if it is now
  1300.         if (theParamBlock.dirInfo.ioDrMdDat >= newTime)
  1301.             ++newTime;
  1302.         theParamBlock.dirInfo.ioDrMdDat = newTime;
  1303.         err = PBSetCatInfoSync(&theParamBlock);
  1304.         if( err )
  1305.             WARN("Couldn't bump dir mod date, err %hd",err);
  1306.     }
  1307. }
  1308.                 
  1309. //------------------------------------------------------------------------------
  1310. // PlatformFile::GetFirstLocalPath
  1311. //------------------------------------------------------------------------------
  1312.  
  1313. ODFileRefNum PlatformFile::GetFirstLocalPath( ODForkType fork )
  1314. {
  1315.     ODFileSpec* spec = &fFileSpec;
  1316.     
  1317.     OSErr        result;
  1318.     FCBPBRec    pb;
  1319.     short        index;
  1320.     Str31        tempName;
  1321.     
  1322.     /* Get FCB name in tempName */
  1323.     pb.ioNamePtr = tempName;
  1324.     
  1325.     /* Index through the open paths on the volume specified by fFileSpec.vRefNum */
  1326.     pb.ioVRefNum = fFileSpec.vRefNum;
  1327.     index = 1;
  1328.     do
  1329.     {
  1330.         pb.ioRefNum = 0;
  1331.         pb.ioFCBIndx = index;
  1332.         result = PBGetFCBInfoSync(&pb);
  1333.         if ( result == noErr )
  1334.         {
  1335.             /*
  1336.             **    See if parent directory ID matches and
  1337.             **    file name matches and
  1338.             **    the file fork (resource or data) matches
  1339.             */
  1340.             if ( (pb.ioFCBParID == fFileSpec.parID) &&
  1341.                  EqualString(fFileSpec.name, tempName, false, true) &&
  1342.                  ((fork == kODResourceFork) == ((pb.ioFCBFlags & (1 << 9)) != 0)) )
  1343.             {
  1344.                 return pb.ioRefNum;            // Found it!
  1345.             }
  1346.             ++index;    /* next FCB index */
  1347.         }
  1348.     } while ( result == noErr );
  1349.     
  1350.     return kODNoFileRefNum;
  1351. }
  1352.  
  1353.  
  1354. //------------------------------------------------------------------------------
  1355. // PlatformFile::GetLocalPaths
  1356. //------------------------------------------------------------------------------
  1357.  
  1358. ODError        PlatformFile::GetLocalPaths(
  1359.                               ODForkType fork,
  1360.                               ODULong *refNumCount,
  1361.                               ODFileRefNumPtr *refNums)
  1362. {
  1363.     const ODULong kMaxFCBs = 348;    /* The maximum number of local access paths under System 7 */
  1364.     
  1365.     OSErr        result;
  1366.     FCBPBRec    pb;
  1367.     short        index;
  1368.     Str31        tempName;
  1369.     ODFileRefNumPtr    tempRefNums;
  1370.     
  1371.     /* initialize returned values */
  1372.     *refNumCount = 0;
  1373.     *refNums = NULL;
  1374.     
  1375.     /* Allocate temp storage for refNum matches */
  1376.     tempRefNums = (ODFileRefNumPtr)ODNewPtr(kMaxFCBs * sizeof(short));
  1377.     
  1378.     if ( tempRefNums != NULL )
  1379.     {
  1380.         /* Get FCB name in tempName */
  1381.         pb.ioNamePtr = tempName;
  1382.         
  1383.         /* Index through the open paths on the volume specified by fFileSpec.vRefNum */
  1384.         pb.ioVRefNum = fFileSpec.vRefNum;
  1385.         index = 1;
  1386.         do
  1387.         {
  1388.             pb.ioRefNum = 0;
  1389.             pb.ioFCBIndx = index;
  1390.             result = PBGetFCBInfoSync(&pb);
  1391.             if ( result == noErr )
  1392.             {
  1393.                 /*
  1394.                 **    See if parent directory ID matches and
  1395.                 **    file name matches and
  1396.                 **    the file fork (resource or data) matches
  1397.                 */
  1398.                 if ( (pb.ioFCBParID == fFileSpec.parID) &&
  1399.                      EqualString(fFileSpec.name, tempName, false, true) &&
  1400.                      ((fork == kODResourceFork) == ((pb.ioFCBFlags & (1 << 9)) != 0)) )
  1401.                 {
  1402.                     /* It's a match - add it to the array of matches */
  1403.                     tempRefNums[*refNumCount] = pb.ioRefNum;
  1404.                     ++(*refNumCount);
  1405.                 }
  1406.                 ++index;    /* next FCB index */
  1407.             }
  1408.         } while ( result == noErr );
  1409.         
  1410.         /* These errors are OK - they mean we hit the end of the FCB list */
  1411.         if ( (result == rfNumErr) || (result == fnOpnErr) )
  1412.         {
  1413.             result = noErr;
  1414.         }
  1415.         
  1416.         if ( (result == noErr) && (*refNumCount != 0) )
  1417.         {
  1418.             // Note: the below two lines were a gratuitous change from the tested code
  1419.             // given to me by Jim Luther.  Therefore I have commented them out and returned
  1420.             // the original code. -Tantek
  1421.             //*refNums = (ODFileRefNumPtr) ODReallocate( tempRefNums, *refNumCount * sizeof(short) );
  1422.             //*tempRefNums = kODNULL;
  1423.             /* Allocate memory to return refNum matches in */
  1424.             *refNums = (ODFileRefNumPtr)ODNewPtr(*refNumCount * sizeof(short));
  1425.             if ( *refNums != NULL )
  1426.             {
  1427.                 /* Move refNums from tempRefNums to *refNums */
  1428.                 ODBlockMove((Ptr)tempRefNums, (Ptr)*refNums, (*refNumCount * sizeof(short)));
  1429.             }
  1430.             else
  1431.             {
  1432.                 /* Couldn't allocate memory for refNum array */
  1433.                 result = memFullErr;
  1434.             }
  1435.  
  1436.         }
  1437.         
  1438.         /* Free up tempRefNums storage */ 
  1439.         ODDisposePtr((Ptr)tempRefNums);
  1440.     }
  1441.     else
  1442.     {
  1443.         /* Couldn't allocate temp memory */
  1444.         result = memFullErr;
  1445.     }
  1446.     
  1447.     return ( result );
  1448. }
  1449.  
  1450. //------------------------------------------------------------------------------
  1451. // PlatformFile::GetComments
  1452. //
  1453. //    If a pointer is passed in, the text is placed there and a pointer to it is
  1454. //    returned.  If the comments pointer is null, then a new pointer is allocated
  1455. //    and returned.
  1456. //------------------------------------------------------------------------------
  1457.  
  1458. enum {
  1459.     uppPBDTInfo = kRegisterBased
  1460.          | RESULT_SIZE(sizeof(OSErr))
  1461.          | REGISTER_RESULT_LOCATION(kRegisterD0)
  1462.          
  1463.          | REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(kTwoByteCode))    // trap word
  1464.          | REGISTER_ROUTINE_PARAMETER(2, kRegisterD0, SIZE_CODE(kTwoByteCode))    // selector
  1465.          
  1466.          | REGISTER_ROUTINE_PARAMETER(3, kRegisterA0, SIZE_CODE(sizeof(DTPBRec*)))
  1467.          | REGISTER_ROUTINE_PARAMETER(4, kRegisterA3, SIZE_CODE(sizeof(void*)))
  1468. };
  1469.  
  1470. #if GENERATING68K && GENERATINGCFM
  1471. OSErr PBDTGetCommentSyncGlue(DTPBRec *pb);
  1472. OSErr PBDTGetCommentSyncGlue(DTPBRec *pb)
  1473. {
  1474.     void* hfsdispatch = GetOSTrapAddress(0xA260);
  1475.     return CallOSTrapUniversalProc((UniversalProcPtr) hfsdispatch,
  1476.                                     uppPBDTInfo,
  1477.                                     (short) 0xA260,    // trap word
  1478.                                     (short) 0x002A,    // selector
  1479.                                     pb,                // a1, the param block ptr
  1480.                                     pb                // a3 should be ignored
  1481.                                   );
  1482. }
  1483. #endif
  1484.  
  1485. #if GENERATING68K && GENERATINGCFM
  1486. OSErr PBDTSetCommentSyncGlue(DTPBRec *pb);
  1487. OSErr PBDTSetCommentSyncGlue(DTPBRec *pb)
  1488. {
  1489.     void* hfsdispatch = GetOSTrapAddress(0xA260);
  1490.     return CallOSTrapUniversalProc((UniversalProcPtr) hfsdispatch,
  1491.                                     uppPBDTInfo,
  1492.                                     (short) 0xA260,    // trap word
  1493.                                     (short) 0x0028,    // selector
  1494.                                     pb,                // a1, the param block ptr
  1495.                                     pb                // a3 should be ignored
  1496.                                   );
  1497. }
  1498. #endif
  1499.  
  1500. ODIText*    PlatformFile::GetComments(ODIText* comments)
  1501. {
  1502.     DTPBRec            pb;    
  1503.     memset( &pb, 0, sizeof(pb) );
  1504.     
  1505.     pb.ioVRefNum = fFileSpec.vRefNum;
  1506.     OSErr err = PBDTGetPath(&pb);
  1507.     if (err == noErr)
  1508.     {
  1509.         pb.ioNamePtr = fFileSpec.name;
  1510.         pb.ioDirID = fFileSpec.parID;
  1511.         char buffer[256];
  1512.         pb.ioDTBuffer = buffer;
  1513.  
  1514.         // avoid the crash on 68K if the PlatformFile is remote
  1515. #if GENERATING68K && GENERATINGCFM
  1516.         err = PBDTGetCommentSyncGlue(&pb);
  1517. #else
  1518.         err = PBDTGetCommentSync(&pb);
  1519. #endif
  1520.         if (err == noErr) {
  1521.             buffer[pb.ioDTActCount] = 0; // make it a c string
  1522.             if (comments == kODNULL)
  1523.             {
  1524.                 ODScriptCode script = FontToScript( GetSysFont() );
  1525.                 comments = CreateITextCString(script, 
  1526.                         GetScriptVariable( script, smScriptLang ), buffer);
  1527.             }
  1528.             else
  1529.                 SetITextCString(comments, buffer);
  1530.         }
  1531.     }
  1532.     
  1533.     return comments;
  1534. }
  1535.  
  1536. //------------------------------------------------------------------------------
  1537. // PlatformFile::SetComments
  1538. //------------------------------------------------------------------------------
  1539.  
  1540. void
  1541. PlatformFile::SetComments(ODIText* comments)
  1542. {
  1543.     DTPBRec        pb;
  1544.     OSErr        err = noErr;    // PBDTGetPath seems not to return anything,
  1545.                                 // so must init
  1546.     
  1547.     if (comments) // <eeh> --> prevents removing 'em: && GetITextStringLength(comments) > 0)
  1548.     {
  1549.         pb.ioNamePtr = kODNULL;
  1550.         pb.ioVRefNum = fFileSpec.vRefNum;
  1551.         err = PBDTGetPath(&pb);
  1552.         if (err == noErr)
  1553.         {
  1554.             pb.ioNamePtr = fFileSpec.name;
  1555.             pb.ioDirID = fFileSpec.parID;
  1556.             pb.ioDTBuffer = GetITextPtr(comments);
  1557.             pb.ioDTReqCount = GetITextStringLength(comments);
  1558.             // avoid the crash on 68K if the PlatformFile is remote
  1559. #if GENERATING68K && GENERATINGCFM
  1560.             err = PBDTSetCommentSyncGlue(&pb);
  1561. #else
  1562.             err = PBDTSetCommentSync(&pb);
  1563. #endif
  1564.         }
  1565.     }
  1566. }
  1567.  
  1568. //------------------------------------------------------------------------------
  1569. // PlatformFile::GetCustomIconFamily
  1570. //------------------------------------------------------------------------------
  1571.  
  1572. ODIconFamily
  1573. PlatformFile::GetCustomIconFamily()
  1574. {
  1575.     ODIconFamily icons = kODNULL;
  1576.     
  1577.     if (HasCustomIcon())
  1578.     {
  1579.         // read icons from the file
  1580.         SetPermission(fsRdPerm);
  1581.         OpenResFile();
  1582.         TRY
  1583.             for( long i=5; i>=0; i-- )
  1584.             {
  1585.                 ODPtr    ptr;
  1586.                 Handle    icon;
  1587.                 ODULong    size;
  1588.                 
  1589.                 ptr = ReadResourcePtr(kIconType[i], kCustomIconResource, &size);
  1590.                 if (ptr != kODNULL)
  1591.                 {
  1592.                     if (icons == kODNULL)
  1593.                         THROW_IF_ERROR( NewIconSuite(&icons) );
  1594.                     PtrToHand(ptr, &icon, size);
  1595.                     THROW_IF_ERROR( AddIconToSuite(icon, icons, kIconType[i]) );
  1596.                 }
  1597.             }
  1598.         CATCH_ALL
  1599.         ENDTRY
  1600.         CloseResFile();
  1601.     }
  1602.     return icons;
  1603. }
  1604.  
  1605. //------------------------------------------------------------------------------
  1606. // PlatformFile::SetCustomIconFamily
  1607. //------------------------------------------------------------------------------
  1608.  
  1609. void
  1610. PlatformFile::SetCustomIconFamily(ODIconFamily icons)
  1611. {
  1612.     // set with kODNULL as the icons to delete the custom icons
  1613.     TRY
  1614.         if (!icons)
  1615.         {
  1616.             // check to see if there's a resFile so that we don't
  1617.             // create one while trying to delete nonexistant icons
  1618.             SetPermission(fsRdPerm);
  1619.             OpenResFile();        // THROW if no resFile
  1620.             CloseResFile();
  1621.         }
  1622.         // write icons to the file
  1623.         SetPermission(fsRdWrPerm);
  1624.         OpenResFile();
  1625.         for( long i=5; i>=0; i-- )
  1626.         {
  1627.             Handle    icon;
  1628.             char    state;
  1629.             
  1630.             if( icons )
  1631.                 THROW_IF_ERROR( GetIconFromSuite(&icon, icons, kIconType[i]) );
  1632.             else
  1633.                 icon = kODNULL;
  1634.             if (icon)
  1635.             {
  1636.                 state = HGetState(icon);
  1637.                 HLock(icon);
  1638.                 WASSERT(GetHandleSize(icon) == kIconSize[i]);
  1639.                 WriteResourcePtr(kIconType[i], kCustomIconResource, *icon, kIconSize[i]);
  1640.                 HSetState(icon, state);
  1641.             } else
  1642.                 DeleteResource(kIconType[i], kCustomIconResource);
  1643.         }
  1644.         CloseResFile();
  1645.     CATCH_ALL
  1646.     ENDTRY
  1647.     SetCustomIcon(icons != kODNULL);
  1648. }
  1649.