mirror of
https://github.com/microsoft/Microsoft-3D-Movie-Maker.git
synced 2024-11-25 19:52:43 +01:00
843 lines
20 KiB
C++
843 lines
20 KiB
C++
/* Copyright (c) Microsoft Corporation.
|
|
Licensed under the MIT License. */
|
|
|
|
/***************************************************************************
|
|
Author: ShonK
|
|
Project: Kauai
|
|
Reviewed:
|
|
Copyright (c) Microsoft Corporation
|
|
|
|
File name management.
|
|
|
|
***************************************************************************/
|
|
#include "util.h"
|
|
#include <folders.h>
|
|
ASSERTNAME
|
|
|
|
|
|
// This is the FTG to use for temp files - clients may set this to whatever
|
|
// they want.
|
|
FTG vftgTemp = kftgTemp;
|
|
|
|
|
|
/***************************************************************************
|
|
Implementation notes: The _fss is a standard FSSpec record and is
|
|
always filled in via a call to FSMakeFSSpec. If the fni is a directory,
|
|
_ftg will be kftgDir. For files, _lwDir is the same as _fss.parID.
|
|
For directories, _lwDir is the directory id for the directory described
|
|
by the fni (while _fss.parID is the id of its parent).
|
|
***************************************************************************/
|
|
|
|
|
|
typedef StandardFileReply SFR;
|
|
priv bool _FFssDir(FSS *pfss, long *plwDir);
|
|
|
|
RTCLASS(FNI)
|
|
RTCLASS(FNE)
|
|
|
|
|
|
/***************************************************************************
|
|
Sets the fni to nil values.
|
|
***************************************************************************/
|
|
void FNI::SetNil(void)
|
|
{
|
|
_ftg = ftgNil;
|
|
_lwDir = 0;
|
|
ClearPb(&_fss, size(_fss));
|
|
AssertThis(ffniEmpty);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Constructor for fni class.
|
|
***************************************************************************/
|
|
FNI::FNI(void)
|
|
{
|
|
SetNil();
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Get an fni (for opening) from the user.
|
|
***************************************************************************/
|
|
bool FNI::FGetOpen(FTG *prgftg, short cftg)
|
|
{
|
|
AssertThis(0);
|
|
AssertNilOrVarMem(prgftg);
|
|
|
|
SFR sfr;
|
|
|
|
StandardGetFile(pvNil, cftg <= 0 ? -1 : cftg, (ulong *)prgftg, &sfr);
|
|
if (sfr.sfGood)
|
|
{
|
|
_fss = sfr.sfFile;
|
|
_ftg = sfr.sfType;
|
|
_lwDir = _fss.parID;
|
|
AssertThis(ffniFile);
|
|
}
|
|
else
|
|
SetNil();
|
|
|
|
return sfr.sfGood;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Get an fni (for saving) from the user.
|
|
***************************************************************************/
|
|
bool FNI::FGetSave(FTG ftg, PST pstPrompt, PST pstDefault)
|
|
{
|
|
AssertThis(0);
|
|
AssertNilOrSt(pstPrompt);
|
|
AssertNilOrSt(pstDefault);
|
|
|
|
SFR sfr;
|
|
|
|
StandardPutFile((byte *)pstPrompt, (byte *)pstDefault, &sfr);
|
|
if (sfr.sfGood)
|
|
{
|
|
_fss = sfr.sfFile;
|
|
_ftg = ftg;
|
|
_lwDir = _fss.parID;
|
|
AssertThis(ffniFile);
|
|
}
|
|
else
|
|
SetNil();
|
|
|
|
return sfr.sfGood;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Get a unique filename in the given directory.
|
|
***************************************************************************/
|
|
bool FNI::FGetUnique(FTG ftg)
|
|
{
|
|
AssertThis(ffniFile | ffniDir);
|
|
static long _dlw = 0;
|
|
long lw;
|
|
short cact;
|
|
short err;
|
|
STN stn;
|
|
long lwDir = _lwDir;
|
|
short swVol = _fss.vRefNum;
|
|
|
|
Assert(ftg != kftgDir && ftg != ftgNil, "bad ftg");
|
|
lw = TsSystemCurrent() + ++_dlw;
|
|
for (cact = 0; cact < 20; cact++, lw += ++_dlw)
|
|
{
|
|
AssertDo(stn.FFormatSz(PszLit("~TempFile#%08x"), lw), 0);
|
|
err = FSMakeFSSpec(swVol, lwDir, &stn, &_fss);
|
|
if (err == fnfErr)
|
|
{
|
|
_ftg = ftg;
|
|
_lwDir = _fss.parID;
|
|
AssertThis(ffniFile);
|
|
return fTrue;
|
|
}
|
|
}
|
|
SetNil();
|
|
PushErc(ercFniGeneral);
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Get a temporary fni.
|
|
***************************************************************************/
|
|
bool FNI::FGetTemp(void)
|
|
{
|
|
AssertThis(0);
|
|
static short _swVolTemp = 0;
|
|
static long _lwDirTemp = -1;
|
|
|
|
// This is so we only call FindFolder once.
|
|
if (_swVolTemp == 0 && _lwDirTemp == -1 &&
|
|
FindFolder(0, kTemporaryFolderType, kCreateFolder,
|
|
&_swVolTemp, &_lwDirTemp) != noErr)
|
|
{
|
|
_swVolTemp = 0;
|
|
_lwDirTemp = 0;
|
|
}
|
|
|
|
if (FSMakeFSSpec(_swVolTemp, _lwDirTemp, pvNil, &_fss) != noErr)
|
|
{
|
|
SetNil();
|
|
PushErc(ercFniGeneral);
|
|
return fFalse;
|
|
}
|
|
|
|
_ftg = kftgDir;
|
|
_lwDir = _lwDirTemp;
|
|
return FGetUnique(vftgTemp);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Return the file type of the fni.
|
|
***************************************************************************/
|
|
FTG FNI::Ftg(void)
|
|
{
|
|
AssertThis(0);
|
|
return _ftg;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Return the volume kind for the given fni.
|
|
***************************************************************************/
|
|
ulong FNI::Grfvk(void)
|
|
{
|
|
AssertThis(0);
|
|
ulong grfvk = fvkNil;
|
|
|
|
//REVIEW shonk: Mac Grfvk: implement
|
|
RawRtn();
|
|
return grfvk;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Set the leaf for the fni.
|
|
***************************************************************************/
|
|
bool FNI::FSetLeaf(PSTZ pstz, FTG ftg)
|
|
{
|
|
AssertThis(ffniFile | ffniDir);
|
|
return FBuild(_fss.vRefNum, _lwDir, pstz, ftg);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Set the leaf for the fni.
|
|
***************************************************************************/
|
|
bool FNI::FBuild(long lwVol, long lwDir, PSTZ pstz, FTG ftg)
|
|
{
|
|
AssertNilOrStz(pstz);
|
|
short err;
|
|
FSS fss;
|
|
|
|
Assert(FPure(ftg == kftgDir) == FPure(pstz == pvNil || CchStz(pstz) == 0),
|
|
"pstz doesn't match ftg");
|
|
if (ftg == kftgDir)
|
|
pstz = pvNil;
|
|
|
|
err = FSMakeFSSpec((short)lwVol, lwDir, (byte *)pstz, &fss);
|
|
if (ftg == kftgDir)
|
|
{
|
|
//a directory (it had better exist)
|
|
if (noErr != err)
|
|
goto LFail;
|
|
_lwDir = lwDir;
|
|
}
|
|
else
|
|
{
|
|
//not supposed to be a directory - so make sure it isn't
|
|
if (fnfErr != err)
|
|
{
|
|
if (noErr != err)
|
|
goto LFail;
|
|
if (_FFssDir(&fss, pvNil))
|
|
goto LFail;
|
|
}
|
|
_lwDir = fss.parID;
|
|
}
|
|
_fss = fss;
|
|
_ftg = ftg;
|
|
AssertThis(ffniFile | ffniDir);
|
|
return fTrue;
|
|
|
|
LFail:
|
|
SetNil();
|
|
PushErc(ercFniGeneral);
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Set the FTG for the fni.
|
|
***************************************************************************/
|
|
bool FNI::FChangeFtg(FTG ftg)
|
|
{
|
|
AssertThis(ffniFile);
|
|
Assert(ftg != ftgNil && ftg != kftgDir, "Bad FTG");
|
|
|
|
_ftg = ftg;
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Get the leaf name for the fni.
|
|
***************************************************************************/
|
|
void FNI::GetLeaf(PSTZ pstz)
|
|
{
|
|
AssertThis(0);
|
|
AssertMaxStz(pstz);
|
|
|
|
if (_ftg == kftgDir)
|
|
SetStzNil(pstz);
|
|
else
|
|
CopyStStz((achar *)_fss.name, pstz);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Get a string representing the path of the fni.
|
|
***************************************************************************/
|
|
void FNI::GetStzPath(PSTZ pstz)
|
|
{
|
|
AssertThis(0);
|
|
AssertMaxStz(pstz);
|
|
RawRtn(); //REVIEW shonk: Mac GetStzPath: implement for real
|
|
CopyStStz((achar *)_fss.name, pstz);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Determines if the file/directory exists. Returns tMaybe on error or
|
|
if the fni type (file or dir) doesn't match the disk object of the
|
|
same name or if the file/dir is invisible or is an alias. Pushes an
|
|
erc if it returns tMaybe.
|
|
***************************************************************************/
|
|
bool FNI::TExists(void)
|
|
{
|
|
AssertThis(ffniFile | ffniDir);
|
|
CInfoPBRec iob;
|
|
short err;
|
|
achar st[kcbMaxSt];
|
|
|
|
ClearPb(&iob, size(iob));
|
|
CopySt((achar *)_fss.name, st);
|
|
iob.hFileInfo.ioNamePtr = (byte *)st;
|
|
iob.hFileInfo.ioVRefNum = _fss.vRefNum;
|
|
iob.hFileInfo.ioDirID = _fss.parID;
|
|
if ((err = PBGetCatInfo(&iob, fFalse)) != noErr)
|
|
{
|
|
if (err != fnfErr)
|
|
{
|
|
PushErc(ercFniGeneral);
|
|
return tMaybe;
|
|
}
|
|
return tNo;
|
|
}
|
|
if ((_ftg == kftgDir) != FPure(iob.hFileInfo.ioFlAttrib & 0x0010))
|
|
{
|
|
PushErc(ercFniMismatch);
|
|
return tMaybe;
|
|
}
|
|
if (iob.hFileInfo.ioFlFndrInfo.fdFlags & (kIsInvisible | kIsAlias))
|
|
{
|
|
PushErc(ercFniHidden);
|
|
return tMaybe;
|
|
}
|
|
return tYes;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Delete the file.
|
|
***************************************************************************/
|
|
bool FNI::FDelete(void)
|
|
{
|
|
AssertThis(ffniFile);
|
|
if (FSpDelete(&_fss) == noErr)
|
|
return fTrue;
|
|
PushErc(ercFniDelete);
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Rename the file as indicated by *pfni. The directories must match.
|
|
***************************************************************************/
|
|
bool FNI::FRename(FNI *pfni)
|
|
{
|
|
AssertThis(ffniFile);
|
|
AssertPo(pfni, ffniFile);
|
|
Assert(_fss.vRefNum == pfni->_fss.vRefNum &&
|
|
_fss.parID == pfni->_fss.parID, "directory change");
|
|
Assert(_ftg == pfni->_ftg, "ftg's don't match");
|
|
|
|
if (FSpRename(&_fss, pfni->_fss.name) == noErr)
|
|
return fTrue;
|
|
PushErc(ercFniRename);
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Compare two fni's for equality. Doesn't consider the ftg's.
|
|
***************************************************************************/
|
|
bool FNI::FEqual(FNI *pfni)
|
|
{
|
|
//NOTE: see IM:Text, pg 5-17. It's not documented whether the comparison
|
|
//should be case sensitive and/or diacritical sensitive. Experimenting
|
|
//with the US finder indicates that we should use case insensitive,
|
|
//diacritical sensitive comparison.
|
|
AssertThis(ffniFile | ffniDir);
|
|
AssertPo(pfni, ffniFile | ffniDir);
|
|
|
|
return pfni->_fss.vRefNum == _fss.vRefNum && pfni->_fss.parID == _fss.parID &&
|
|
EqualString(pfni->_fss.name, _fss.name, fFalse, fTrue);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Return whether the fni refers to a directory.
|
|
***************************************************************************/
|
|
bool FNI::FDir(void)
|
|
{
|
|
AssertThis(0);
|
|
return _ftg == kftgDir;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Return whether the directory portions of the fni's are the same.
|
|
***************************************************************************/
|
|
bool FNI::FSameDir(FNI *pfni)
|
|
{
|
|
AssertThis(ffniDir | ffniFile);
|
|
AssertPo(pfni, ffniDir | ffniFile);
|
|
|
|
return pfni->_fss.vRefNum == _fss.vRefNum &&
|
|
pfni->_lwDir == _lwDir;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Determine if the directory pstz in fni exists, optionally creating it
|
|
and/or moving into it. Specify ffniCreateDir to create it if it
|
|
doesn't exist. Specify ffniMoveTo to make the fni refer to it.
|
|
If this fails, the fni is untouched.
|
|
***************************************************************************/
|
|
bool FNI::FDownDir(PSTZ pstz, ulong grffni)
|
|
{
|
|
AssertThis(ffniDir);
|
|
AssertStz(pstz);
|
|
FSS fss;
|
|
long lwDir;
|
|
short err;
|
|
|
|
//make the fss
|
|
err = FSMakeFSSpec(_fss.vRefNum, _lwDir, (byte *)pstz, &fss);
|
|
if (noErr == err)
|
|
{
|
|
//exists, make sure it is a directory and get the directory id
|
|
if (!_FFssDir(&fss, &lwDir))
|
|
{
|
|
PushErc(ercFniMismatch);
|
|
return fFalse;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (fnfErr != err)
|
|
{
|
|
PushErc(ercFniGeneral);
|
|
return fFalse;
|
|
}
|
|
|
|
//doesn't exist
|
|
if (!(grffni & ffniCreateDir))
|
|
return fFalse;
|
|
|
|
// create it
|
|
err = FSpDirCreate(&fss, smSystemScript, &lwDir);
|
|
if (err != noErr)
|
|
{
|
|
PushErc(ercFniDirCreate);
|
|
return fFalse;
|
|
}
|
|
}
|
|
|
|
if (grffni & ffniMoveToDir)
|
|
{
|
|
_fss = fss;
|
|
_lwDir = lwDir;
|
|
_ftg = kftgDir;
|
|
}
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Gets the lowest directory name (if pstz is not nil) and optionally
|
|
moves the fni up a level (if ffniMoveToDir is specified). If this
|
|
fails, the fni is untouched.
|
|
***************************************************************************/
|
|
bool FNI::FUpDir(PSTZ pstz, ulong grffni)
|
|
{
|
|
AssertThis(ffniDir);
|
|
AssertNilOrMaxStz(pstz);
|
|
|
|
CInfoPBRec iob;
|
|
short err;
|
|
FSS fss;
|
|
|
|
if (_lwDir == fsRtDirID)
|
|
return fFalse;
|
|
|
|
ClearPb(&iob, size(iob));
|
|
iob.dirInfo.ioFDirIndex = -1; //ignore name, look at vol/dir
|
|
iob.dirInfo.ioNamePtr = (byte *)pstz;
|
|
iob.dirInfo.ioVRefNum = _fss.vRefNum;
|
|
iob.dirInfo.ioDrDirID = _lwDir;
|
|
if (PBGetCatInfo(&iob, fFalse) != noErr)
|
|
{
|
|
PushErc(ercFniGeneral);
|
|
return fFalse;
|
|
}
|
|
if (pstz != pvNil)
|
|
SetStzCch(pstz, CchSt(pstz));
|
|
Assert(iob.dirInfo.ioFlAttrib & 0x0010, "not a directory?!");
|
|
if (grffni & ffniMoveToDir)
|
|
{
|
|
err = FSMakeFSSpec(_fss.vRefNum, iob.dirInfo.ioDrParID, pvNil, &fss);
|
|
if (noErr != err)
|
|
{
|
|
PushErc(ercFniGeneral);
|
|
return fFalse;
|
|
}
|
|
_fss = fss;
|
|
_lwDir = iob.dirInfo.ioDrParID;
|
|
_ftg = kftgDir;
|
|
AssertThis(ffniDir);
|
|
}
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
/***************************************************************************
|
|
Assert validity of the FNI.
|
|
***************************************************************************/
|
|
void FNI::AssertValid(ulong grffni)
|
|
{
|
|
FNI_PAR::AssertValid(0);
|
|
if (grffni == 0)
|
|
grffni = ffniEmpty | ffniFile | ffniDir;
|
|
|
|
if (_ftg == ftgNil)
|
|
{
|
|
Assert(grffni & ffniEmpty, "unexpected nil fni");
|
|
Assert(_fss.vRefNum == 0 && _fss.parID == 0 && _lwDir == 0 &&
|
|
CchSt((achar *)_fss.name) == 0, "bad nil");
|
|
}
|
|
else if (_ftg == kftgDir)
|
|
{
|
|
Assert(grffni & ffniDir, "unexpected dir");
|
|
Assert(_lwDir != _fss.parID, "dir is its own parent?");
|
|
}
|
|
else
|
|
{
|
|
Assert(grffni & ffniFile, "unexpected file");
|
|
Assert(CchSt((achar *)_fss.name) > 0, "no name for file");
|
|
Assert(_lwDir == _fss.parID, "parent not consistent?");
|
|
}
|
|
}
|
|
#endif //DEBUG
|
|
|
|
|
|
/***************************************************************************
|
|
Low level routine to determine if the given fss points to an existing
|
|
directory. If so and plwDir is not nil, sets *plwDir to the id of
|
|
the directory.
|
|
***************************************************************************/
|
|
priv bool _FFssDir(FSS *pfss, long *plwDir)
|
|
{
|
|
CInfoPBRec iob;
|
|
|
|
//find the entry
|
|
ClearPb(&iob, size(iob));
|
|
iob.hFileInfo.ioNamePtr = (StringPtr)pfss->name;
|
|
iob.hFileInfo.ioVRefNum = pfss->vRefNum;
|
|
iob.hFileInfo.ioDirID = pfss->parID;
|
|
if (PBGetCatInfo(&iob, fFalse) != noErr)
|
|
{
|
|
PushErc(ercFniGeneral);
|
|
goto LFail;
|
|
}
|
|
|
|
//entry exists so see if it's a directory
|
|
if (!(iob.hFileInfo.ioFlAttrib & 0x0010))
|
|
{
|
|
LFail:
|
|
TrashVar(plwDir);
|
|
return fFalse;
|
|
}
|
|
|
|
if (plwDir != pvNil)
|
|
*plwDir = iob.dirInfo.ioDrDirID;
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Constructor for a File Name Enumerator.
|
|
***************************************************************************/
|
|
FNE::FNE(void)
|
|
{
|
|
AssertBaseThis(0);
|
|
_prgftg = _rgftg;
|
|
_pglfes = pvNil;
|
|
_fInited = fFalse;
|
|
AssertThis(0);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Destructor for an FNE.
|
|
***************************************************************************/
|
|
FNE::~FNE(void)
|
|
{
|
|
AssertBaseThis(0);
|
|
_Free();
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Free all the memory associated with the FNE.
|
|
***************************************************************************/
|
|
void FNE::_Free(void)
|
|
{
|
|
if (_prgftg != _rgftg)
|
|
{
|
|
FreePpv((void **)&_prgftg);
|
|
_prgftg = _rgftg;
|
|
}
|
|
ReleasePpo(&_pglfes);
|
|
_fInited = fFalse;
|
|
AssertThis(0);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Initialize the fne to do an enumeration.
|
|
***************************************************************************/
|
|
bool FNE::FInit(FNI *pfniDir, FTG *prgftg, long cftg, ulong grffne)
|
|
{
|
|
AssertThis(0);
|
|
AssertNilOrVarMem(pfniDir);
|
|
AssertIn(cftg, 0, kcbMax);
|
|
AssertPvCb(prgftg, LwMul(cftg, size(FTG)));
|
|
|
|
//free the old stuff
|
|
_Free();
|
|
|
|
if (0 >= cftg)
|
|
_cftg = 0;
|
|
else
|
|
{
|
|
long cb = LwMul(cftg, size(FTG));
|
|
|
|
if (cftg > kcftgFneBase &&
|
|
!FAllocPv((void **)&_prgftg, cb, fmemNil, mprNormal))
|
|
{
|
|
_prgftg = _rgftg;
|
|
PushErc(ercFneGeneral);
|
|
AssertThis(0);
|
|
return fFalse;
|
|
}
|
|
CopyPb(prgftg, _prgftg, cb);
|
|
_cftg = cftg;
|
|
}
|
|
|
|
if (pfniDir == pvNil)
|
|
_fesCur.lwVol = 0;
|
|
else
|
|
{
|
|
_fesCur.lwVol = (long)pfniDir->_fss.vRefNum;
|
|
_fesCur.lwDir = pfniDir->_lwDir;
|
|
}
|
|
_fesCur.iv = 0;
|
|
_fRecurse = FPure(grffne & ffneRecurse);
|
|
_fInited = fTrue;
|
|
AssertThis(0);
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Get the next FNI in the enumeration.
|
|
***************************************************************************/
|
|
bool FNE::FNextFni(FNI *pfni, ulong *pgrffneOut, ulong grffneIn)
|
|
{
|
|
AssertThis(0);
|
|
AssertVarMem(pfni);
|
|
AssertNilOrVarMem(pgrffneOut);
|
|
short err;
|
|
|
|
if (!_fInited)
|
|
{
|
|
Bug("must initialize the FNE before using it!");
|
|
return fFalse;
|
|
}
|
|
|
|
if (grffneIn & ffneSkipDir)
|
|
{
|
|
//skip the rest of the stuff in this dir
|
|
if (pvNil == _pglfes || !_pglfes->FPop(&_fesCur))
|
|
goto LDone;
|
|
}
|
|
|
|
if (_fesCur.lwVol == 0)
|
|
{
|
|
//volume
|
|
ParamBlockRec iob;
|
|
|
|
do
|
|
{
|
|
ClearPb(&iob, size(iob));
|
|
iob.volumeParam.ioVolIndex = (short)++_fesCur.iv;
|
|
if ((err = PBGetVInfoSync(&iob)) != noErr)
|
|
{
|
|
if (err != nsvErr)
|
|
PushErc(ercFneGeneral);
|
|
goto LDone;
|
|
}
|
|
}
|
|
while (!pfni->FBuild(iob.volumeParam.ioVRefNum, 0, pvNil, kftgDir));
|
|
|
|
//we've got one
|
|
goto LGotOne;
|
|
}
|
|
|
|
// directory or file
|
|
for (;;)
|
|
{
|
|
int ich;
|
|
bool fT;
|
|
FTG *pftg;
|
|
PSZ pszExt;
|
|
CInfoPBRec iob;
|
|
achar stz[kcbMaxStz];
|
|
|
|
ClearPb(&iob, size(iob));
|
|
iob.hFileInfo.ioNamePtr = (byte *)stz;
|
|
iob.hFileInfo.ioVRefNum = (short)_fesCur.lwVol;
|
|
iob.hFileInfo.ioDirID = _fesCur.lwDir;
|
|
iob.hFileInfo.ioFDirIndex = (short)++_fesCur.iv;
|
|
if ((err = PBGetCatInfoSync(&iob)) != noErr)
|
|
{
|
|
if (err != fnfErr)
|
|
PushErc(ercFneGeneral);
|
|
goto LPop;
|
|
}
|
|
|
|
if (iob.hFileInfo.ioFlFndrInfo.fdFlags &
|
|
(kIsInvisible | kNameLocked | kIsAlias))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (iob.hFileInfo.ioFlAttrib & 0x0010)
|
|
fT = pfni->FBuild(_fesCur.lwVol, iob.hFileInfo.ioDirID, pvNil, kftgDir);
|
|
else
|
|
{
|
|
StToStz(stz);
|
|
fT = pfni->FBuild(_fesCur.lwVol, _fesCur.lwDir, stz,
|
|
iob.hFileInfo.ioFlFndrInfo.fdType);
|
|
}
|
|
if (!fT)
|
|
continue;
|
|
|
|
if (_cftg == 0)
|
|
goto LGotOne;
|
|
for (pftg = _prgftg + _cftg; pftg-- > _prgftg; )
|
|
{
|
|
if (*pftg == pfni->_ftg)
|
|
goto LGotOne;
|
|
|
|
// see if the file has a dos-like extension matching the ftg
|
|
if (pfni->_ftg != kftgDir && (pszExt = (achar *) pftg)[3] == 0 &&
|
|
(ich = CchStz(stz) - CchSz(pszExt)) > 0 &&
|
|
PszStz(stz)[ich - 1] == '.' &&
|
|
fcmpEq == FcmpCompareInsSz(PszStz(stz) + ich, pszExt))
|
|
{
|
|
goto LGotOne;
|
|
}
|
|
}
|
|
}
|
|
Bug("How did we fall through to here?");
|
|
|
|
LPop:
|
|
if (_pglfes == pvNil || _pglfes->IvMac() == 0)
|
|
goto LDone;
|
|
|
|
//we're about to pop a directory, so send the current directory back
|
|
//with ffnePost
|
|
if (pvNil != pgrffneOut)
|
|
*pgrffneOut = ffnePost;
|
|
if (!pfni->FBuild(_fesCur.lwVol, _fesCur.lwDir, pvNil, kftgDir))
|
|
{
|
|
PushErc(ercFneGeneral);
|
|
LDone:
|
|
_Free();
|
|
AssertThis(0);
|
|
return fFalse;
|
|
}
|
|
Assert(_pglfes->FPop(&_fesCur), 0);
|
|
AssertPo(pfni, ffniDir);
|
|
AssertThis(0);
|
|
return fTrue;
|
|
|
|
LGotOne:
|
|
AssertPo(pfni, ffniFile | ffniDir);
|
|
if (pvNil != pgrffneOut)
|
|
*pgrffneOut = ffnePre | ffnePost;
|
|
|
|
if (_fRecurse && pfni->_ftg == kftgDir)
|
|
{
|
|
if ((pvNil != _pglfes || pvNil != (_pglfes = GL::PglNew(size(FES), 5))) &&
|
|
_pglfes->FPush(&_fesCur))
|
|
{
|
|
//set up the new fes
|
|
_fesCur.lwVol = pfni->_fss.vRefNum;
|
|
_fesCur.lwDir = pfni->_lwDir;
|
|
_fesCur.iv = 0;
|
|
if (pvNil != pgrffneOut)
|
|
*pgrffneOut = ffnePre;
|
|
}
|
|
else
|
|
PushErc(ercFneGeneral);
|
|
}
|
|
AssertThis(0);
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
/***************************************************************************
|
|
Assert the validity of a FNE.
|
|
***************************************************************************/
|
|
void FNE::AssertValid(ulong grf)
|
|
{
|
|
FNE_PAR::AssertValid(0);
|
|
if (_fInited)
|
|
{
|
|
AssertNilOrPo(_pglfes, 0);
|
|
AssertIn(_cftg, 0, kcbMax);
|
|
AssertPvCb(_prgftg, LwMul(size(FTG), _cftg));
|
|
Assert((_cftg > kcftgFneBase) == (_prgftg == _rgftg),
|
|
"wrong _prgftg");
|
|
}
|
|
else
|
|
Assert(_pglfes == pvNil, 0);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Mark memory used by the FNE.
|
|
***************************************************************************/
|
|
void FNE::MarkMem(void)
|
|
{
|
|
AssertValid(0);
|
|
FNE_PAR::MarkMem();
|
|
if (_prgftg != _rgftg)
|
|
MarkPv(_prgftg);
|
|
MarkMemObj(_pglfes);
|
|
}
|
|
#endif //DEBUG
|
|
|