#ifndef __GNUC__
	#include "Files.h"
#endif

#include "Utils.h"
#include "Network.h"
#include "AliasUtils.h"

#ifdef __ADFS__
	#include "IC_Errors.h"
	#include "ADFS_LogFile.h"
	#include "Utils.h"
	#include "MemUtils.h"
#else
	#include "Standard.h"
	#define	ADFS_Log(foo)
	#define	TrackNewHandle(foo, bar)		NewHandle(bar)
	#define	TrackDisposeHandle(foo)			DisposeHandle(foo)
#endif

#include "FSUtils.h"

#ifndef __68k__
	#ifndef __GNUC__
		#include "LaunchServices.h"
	#endif
#endif

#ifdef __68k__

#if 0
//ndef __ADFS__

OSErr	FSpMakeFSRef(
	const FSSpec *  source,
	FSRef *         newRef)
{
	*newRef = *source;
	return noErr;
}  

OSErr	FSOpenIterator(
	const FSRef *     container,
	FSIteratorFlags   iteratorFlags,
	FSIterator *      iterator)
{
	*iterator = (FSIterator)container;
	return noErr;
}

OSErr	FSGetCatalogInfoBulk(
	FSIterator            folderSpecP,
	ItemCount             maximumObjects,
	ItemCount *           actualObjects,
	Boolean *             containerChanged,       /* can be NULL */
	FSCatalogInfoBitmap   whichInfo,
	void *                catalogInfos,           /* can be NULL */
	FSRef *               refs,                   /* can be NULL */
	FSSpec *              specs,                  /* can be NULL */
	void *                names)                 /* can be NULL */
{
	OSErr		err = noErr;
	ulong		maxItemsL, itemIndexL, specIndexL;
	
	err = FSpCountFilesInFolder(folderSpecP, &maxItemsL);
	
	if (!err) {
		if (maxItemsL > maximumObjects) {
			maxItemsL = maximumObjects;
		}
		
		for (itemIndexL = 0, specIndexL = 0; !err && itemIndexL < maxItemsL; itemIndexL++) {
			err = FSpGetIndFileInFolder(folderSpecP, itemIndexL, &specs[specIndexL]);
			
			if (!err) {
				specIndexL++;
			} else if (err == IC_Err_INVISIBLE_FILE) {
				err = noErr;
			}
		}
	}
	
	if (!err) {
		*actualObjects = specIndexL;
		err = errFSNoMoreItems;
	}
	
	return err;	
}

OSErr	FSCloseIterator(FSIterator iterator)
{
	return noErr;
}

#endif //	#ifndef __ADFS__
#endif //	powerpc

/*
	The Drag Manager defines a special data flavor for promising file system
	objects. The Promise HFS flavor is used when you wish to create a new 
	file when dragging to the Finder. The flavor consists of an array of the
	following PromiseHFSFlavor structures, with the first entry being the 
	preferred file type you would like to create, and subsequent array 
	entries being file types in descending preference. This structure allows
	you to create the file in your DragSendDataProc, and provide the FSSpec 
	for the new file at that time.

	typedef struct PromiseHFSFlavor {
		OSType			fileType;		// file type
		OSType			fileCreator;	// file creator
		unsigned short	fdFlags;		// Finder flags
		FlavorType 		promisedFlavor;	// FSSpec flavor
	} HFSFlavor;

	"PromiseHFSFlavor.promisedFlavor"
	is the FlavorType of a separate promised flavor to contain the FSSpec 
	for the new file. Call AddDragItemFlavor and promise this separate
	flavor if you wish to create the file in your DragSendDataProc. After
	providing an FSSpec in this flavor, the Finder will move the new file to
	the drop location. If you wish to create the file before the drag and
	provide the FSSpec data up front, create the new file in the Temporary
	Items folder so it does not prematurely appear in an open Finder window.
*/

OSErr		FSSpecFromDragRef(DragRef dragRef, Str32 fName, FSSpec *fsSpecP)
{
	OSErr		err = noErr;
	OSErr		err2;
	AEDesc		dropLocDesc, targetDirDesc;
	
	//	get target folder
	if (!err) err = GetDropLocation(dragRef, &dropLocDesc);
	if (!err) {
		if (dropLocDesc.descriptorType != typeAlias) {
			err = paramErr;
		}
		
		if (!err) err = AECoerceDesc(&dropLocDesc, typeFSS, &targetDirDesc);
		if (!err) {
			err = AEGetDescData(&targetDirDesc, fsSpecP, sizeof(FSSpec));
		
			err2 = AEDisposeDesc(&targetDirDesc);
			if (!err) err = err2;
		}
		
		err2 = AEDisposeDesc(&dropLocDesc);
		if (!err) err = err2;
	}
	
	//	descend into folder
	if (!err) err = FSpGetFolderID(fsSpecP, &fsSpecP->parID);
	
	// construct the target FSSpec, verify the name is free...
	if (!err) {
		err = FSMakeFSSpec(
			fsSpecP->vRefNum, fsSpecP->parID, fName, fsSpecP);
		
		if (err == noErr) err = dupFNErr;
		else if (err == fnfErr) err = noErr;
	}
	
	return err;
}

OSErr		DragWentToTrash(DragRef theDrag, Boolean *inTrashB)
{
	OSErr		err;
	AEDesc		descLocation;
	
	*inTrashB = FALSE;
	
	err	= GetDropLocation(theDrag, &descLocation);
	
	if (!err) {
		FSSpec		spec, specTrash;
		AEDesc		resultDesc;
		CInfoPBRec	cpb;
		
		err = AECoerceDesc( &descLocation, typeFSS, &resultDesc );
		if (!err) err = AEGetDescData( &resultDesc, &spec, sizeof(FSSpec) );
		
		if (!err) {
			
			cpb.hFileInfo.ioFDirIndex	= 0;
			cpb.hFileInfo.ioNamePtr		= spec.name;
			cpb.hFileInfo.ioVRefNum		= spec.vRefNum;
			cpb.hFileInfo.ioDirID		= spec.parID;
			err	= PBGetCatInfoSync( &cpb );
		}
		
		if (!err) {
			err = FindFolder(kOnUserDisk, kTrashFolderType, true, &specTrash.vRefNum, &specTrash.parID);

			if (
				!err 
				&& (specTrash.vRefNum == cpb.hFileInfo.ioVRefNum)
				&& (specTrash.parID == cpb.hFileInfo.ioDirID)
			) {
				*inTrashB = TRUE;
			}
		}
	}
	
	return err;
}


static pascal Size MinimumBytesForFSSpec(const FSSpec *fss)
{
	// callers can and do assume this does not move memory
	return (Size)(sizeof(*fss) - sizeof(fss->name) + fss->name[0] + 1);
}

OSErr	HFSFlavorDataFromDrag(
	DragReference	theDrag, 
	ItemReference	itemRef, 
	HFSFlavor		*hfsFlavor)
{
	OSErr	err = noErr;
	long	size = sizeof(*hfsFlavor);
	
	err = GetFlavorData(
		theDrag, itemRef, 
		flavorTypeHFS,
		hfsFlavor, &size, 0);
	
	//	see tech note 1085 for explaination of below code
	if (!err) {
		Size	minSize = sizeof(*hfsFlavor) - sizeof(hfsFlavor->fileSpec);
		
		minSize += MinimumBytesForFSSpec(&(hfsFlavor->fileSpec));
		
		if (size < minSize) {
			err = cantGetFlavorErr;
		}
	}
	
	if (!err) err = FSpResolveAlias(&(hfsFlavor->fileSpec));
	
	return err;
}

OSErr		FSpResolveAlias(
	FSSpec		*fileSpecP)
{
	OSErr			err = noErr;
	Boolean			wasFolderB, wasAliasB;
	
	err = ResolveAliasFile(fileSpecP, TRUE, &wasFolderB, &wasAliasB);
	
	return err;
}

OSErr		FSpFindFolder(
	short		vRefNum, 
	OSType		folderType, 
	FSSpec		*fileSpec)
{
	OSErr		err = noErr;
	
	err = FindFolder(
		vRefNum, folderType, kCreateFolder, 
		&fileSpec->vRefNum, &fileSpec->parID);

	if (!err) err = FSMakeFSSpec(
		fileSpec->vRefNum, fileSpec->parID, 
		"\p:", fileSpec);
	
	return err;
}

void	memclr(void *mem, unsigned long size);

OSErr			FSpGetFolderID(FSSpec *folderSpecP, long *dirID)
{
	OSErr		err			= noErr;
	CInfoPBRec	paramBlock;
	
	memclr(&paramBlock, sizeof(CInfoPBRec));
	
	paramBlock.dirInfo.ioNamePtr		= folderSpecP->name;
	paramBlock.dirInfo.ioVRefNum		= folderSpecP->vRefNum;
	paramBlock.dirInfo.ioDrDirID		= folderSpecP->parID;
	
	err = PBGetCatInfo(&paramBlock, FALSE);
	
	if (!err) {
		if (paramBlock.dirInfo.ioFlAttrib & kioFlAttribDirMask == 0) {
			err = errFSNotAFolder;
		} else {
			*dirID = paramBlock.dirInfo.ioDrDirID;
		}
	}
	
	return err;
}

OSErr		FSpCreateFileOrFolder(
	FSSpec		*fileSpecP, 
	OSType		fileType, 
	OSType		fileCreator, 
	Boolean		isFolderB)
{
	OSErr	err;
	
	if (isFolderB) {
		long	newDirID;
		
		err = FSpDirCreate(fileSpecP, smSystemScript, &newDirID);
	} else {
		err = FSpCreate(fileSpecP, fileCreator, fileType, smSystemScript);
	}
	
	return err;
}

OSErr		FSpGetFileDates(
	FSSpec		*fileSpec, 
	DateTimeRec	*creDate, 
	DateTimeRec	*modDate)
{
	OSErr			err;
	CInfoPBRec		paramBlock;
	
	memclr(&paramBlock, sizeof(CInfoPBRec));

	paramBlock.hFileInfo.ioVRefNum		= fileSpec->vRefNum;
	paramBlock.hFileInfo.ioNamePtr		= fileSpec->name;
	paramBlock.hFileInfo.ioDirID		= fileSpec->parID;
	
	err = PBGetCatInfo(&paramBlock, FALSE);
	
	if (!err) {
		SecondsToDate(paramBlock.hFileInfo.ioFlCrDat, creDate);
		SecondsToDate(paramBlock.hFileInfo.ioFlMdDat, modDate);
	}
	
	return err;
}

OSErr		FSpSetFileDates(
	FSSpec		*fileSpec, 
	DateTimeRec	*creDate, 
	DateTimeRec	*modDate)
{
	OSErr			err;
	CInfoPBRec		paramBlock;
	
	memclr(&paramBlock, sizeof(CInfoPBRec));
	
	paramBlock.hFileInfo.ioNamePtr		= fileSpec->name;
	paramBlock.hFileInfo.ioVRefNum		= fileSpec->vRefNum;
	paramBlock.hFileInfo.ioDirID		= fileSpec->parID;
	
	err = PBGetCatInfo(&paramBlock, FALSE);
	
	if (!err) {
		paramBlock.hFileInfo.ioFVersNum		= 0;
		paramBlock.hFileInfo.ioFDirIndex	= 0;
		paramBlock.hFileInfo.ioDirID		= fileSpec->parID;

		DateToSeconds(creDate, &paramBlock.hFileInfo.ioFlCrDat);
		DateToSeconds(modDate, &paramBlock.hFileInfo.ioFlMdDat);
		err = PBSetCatInfo(&paramBlock, FALSE);
	}
	
	return err;
}

OSErr		FSpSetMagicBusyDate(FSSpec *fileSpec)
{
	OSErr			err;
	CInfoPBRec		paramBlock;
	
	memclr(&paramBlock, sizeof(CInfoPBRec));
	
	paramBlock.hFileInfo.ioNamePtr		= fileSpec->name;
	paramBlock.hFileInfo.ioVRefNum		= fileSpec->vRefNum;
	paramBlock.hFileInfo.ioDirID		= fileSpec->parID;
	
	err = PBGetCatInfo(&paramBlock, FALSE);
	
	if (!err) {
		paramBlock.hFileInfo.ioFVersNum		= 0;
		paramBlock.hFileInfo.ioFDirIndex	= 0;
		paramBlock.hFileInfo.ioDirID		= fileSpec->parID;
		paramBlock.hFileInfo.ioFlCrDat		= kMagicBusyCreationDate;
		paramBlock.hFileInfo.ioFlMdDat		= kMagicBusyCreationDate;

		err = PBSetCatInfo(&paramBlock, FALSE);
	}
	
	return err;
}


OSErr	FSFlushFile(short fileRefNum)
{
	ParamBlockRec	params;
	
	memclr(&params, sizeof(ParamBlockRec));
	
	params.ioParam.ioRefNum = fileRefNum;
	return PBFlushFile(&params, FALSE);
}

OSErr	FSpGetParentFolder(FSSpec *fileSpec, FSSpec *parentSpec)
{
	OSErr	err = FSMakeFSSpec(
		fileSpec->vRefNum, fileSpec->parID, "\p:", parentSpec);

	if (err == dirNFErr) {
		*parentSpec = *fileSpec;
		err = noErr;
	}

	return err;	
}

OSErr	FSpGetParentVolume(FSSpec *fileSpec, FSSpec *parentSpec)
{
	OSErr		err;

//	err = FSMakeFSSpec(fileSpec->vRefNum, 0, "\p", parentSpec);

	err = FSpGetParentFolder(fileSpec, parentSpec);
	if (!err) {
		if (!FSpEqual(fileSpec, parentSpec)) {
			err = FSpGetParentVolume(parentSpec, parentSpec);
		}
	}

	return err;
}

OSErr	FSGetVolSize(short vRefNum, ulong *freeSpaceL)
{
	OSErr				err;
	HParamBlockRec		paramBlock;
	unsigned char		volName[256];

	memclr(&paramBlock, sizeof(HVolumeParam));

	paramBlock.volumeParam.ioNamePtr	= volName;
	paramBlock.volumeParam.ioVRefNum	= vRefNum;
	
	err = PBHGetVInfo(&paramBlock, FALSE);
	
	if (!err) {
		*freeSpaceL = (ulong)paramBlock.volumeParam.ioVAlBlkSiz 
			* (ulong)paramBlock.volumeParam.ioVFrBlk;
	}
	
	return err;
}

OSErr	FSGetVolDriveNum(short vRefNum, short *driveNumS)
{
	OSErr				err;
	HParamBlockRec		paramBlock;
	unsigned char		volName[256];

	memclr(&paramBlock, sizeof(HVolumeParam));

	paramBlock.volumeParam.ioNamePtr	= volName;
	paramBlock.volumeParam.ioVRefNum	= vRefNum;
	
	err = PBHGetVInfo(&paramBlock, FALSE);
	
	if (!err) {
		*driveNumS = paramBlock.volumeParam.ioVDrvInfo;
	}
	
	return err;
}

OSErr	FSpIsFolder(FSSpec *fileSpec, Boolean *isFolderB)
{
	OSErr			err;
	CInfoPBRec		paramBlock;
	
	memclr(&paramBlock, sizeof(CInfoPBRec));

	paramBlock.hFileInfo.ioNamePtr		= fileSpec->name;
	paramBlock.hFileInfo.ioVRefNum		= fileSpec->vRefNum;
	paramBlock.hFileInfo.ioDirID		= fileSpec->parID;
	
	err = PBGetCatInfo(&paramBlock, FALSE);
	
	if (!err) {
		*isFolderB = (Boolean)((paramBlock.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0);
	}
	
	return err;
}


OSErr		FSpSetFileLock(FSSpec *fileSpecP, Boolean lockedB)
{
	OSErr		err = noErr;
	
	if (lockedB) {
		err = FSpSetFLock(fileSpecP);
	} else {
		err = FSpRstFLock(fileSpecP);
	}
	
	return err;
}

OSErr		FSpGetFileLock(FSSpec *fileSpec, Boolean *isLockedB)
{
	OSErr			err;
	CInfoPBRec		paramBlock;
	
	memclr(&paramBlock, sizeof(CInfoPBRec));

	paramBlock.hFileInfo.ioNamePtr		= fileSpec->name;
	paramBlock.hFileInfo.ioVRefNum		= fileSpec->vRefNum;
	paramBlock.hFileInfo.ioDirID		= fileSpec->parID;
	
	err = PBGetCatInfo(&paramBlock, FALSE);
	
	if (!err) {
		*isLockedB = (Boolean)((paramBlock.hFileInfo.ioFlAttrib & kioFlAttribLockedMask) != 0);
	}
	
	return err;
}

OSErr		FSpGetCatFInfo(FSSpec *fileSpec, FInfo *fInfoP)
{
	OSErr			err;
	CInfoPBRec		paramBlock;
	
	memclr(&paramBlock, sizeof(CInfoPBRec));

	paramBlock.hFileInfo.ioNamePtr		= fileSpec->name;
	paramBlock.hFileInfo.ioVRefNum		= fileSpec->vRefNum;
	paramBlock.hFileInfo.ioDirID		= fileSpec->parID;
	
	err = PBGetCatInfo(&paramBlock, FALSE);
	
	if (!err) {
		if ((paramBlock.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0) {
			fInfoP->fdType		= kDragPseudoFileTypeDirectory;
			fInfoP->fdCreator	= kDragPseudoCreatorVolumeOrDirectory;
			fInfoP->fdFlags		= paramBlock.dirInfo.ioDrUsrWds.frFlags;
			fInfoP->fdLocation	= paramBlock.dirInfo.ioDrUsrWds.frLocation;
			fInfoP->fdFldr		= 0;
		} else {
			*fInfoP = paramBlock.hFileInfo.ioFlFndrInfo;
		}
	}
	
	return err;
}

OSErr		FSpSetCatFInfo(FSSpec *fileSpec, FInfo *fInfoP)
{
	OSErr			err;
	CInfoPBRec		paramBlock;
	
	memclr(&paramBlock, sizeof(CInfoPBRec));

	paramBlock.hFileInfo.ioNamePtr		= fileSpec->name;
	paramBlock.hFileInfo.ioVRefNum		= fileSpec->vRefNum;
	paramBlock.hFileInfo.ioDirID		= fileSpec->parID;
	
	err = PBGetCatInfo(&paramBlock, FALSE);
	
	if (!err) {
		if ((paramBlock.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0) {
			paramBlock.dirInfo.ioDrUsrWds.frFlags		= fInfoP->fdFlags;
			paramBlock.dirInfo.ioDrUsrWds.frLocation	= fInfoP->fdLocation;
		} else {
			paramBlock.hFileInfo.ioFlFndrInfo			= *fInfoP;
		}

		paramBlock.hFileInfo.ioFVersNum		= 0;
		paramBlock.hFileInfo.ioFDirIndex	= 0;
		paramBlock.hFileInfo.ioDirID		= fileSpec->parID;
		
		err = PBSetCatInfo(&paramBlock, FALSE);
	}
	
	return err;
}

OSErr		FSpGetXFInfo(FSSpec *fileSpec, FXInfo *xFInfoP)
{
	OSErr			err;
	CInfoPBRec		paramBlock;
	
	memclr(&paramBlock, sizeof(CInfoPBRec));

	paramBlock.hFileInfo.ioNamePtr		= fileSpec->name;
	paramBlock.hFileInfo.ioVRefNum		= fileSpec->vRefNum;
	paramBlock.hFileInfo.ioDirID		= fileSpec->parID;
	
	err = PBGetCatInfo(&paramBlock, FALSE);
	
	if (!err) {
		if ((paramBlock.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0) {
			err = notAFileErr;
		} else {
			*xFInfoP = paramBlock.hFileInfo.ioFlXFndrInfo;
		}
	}
	
	return err;
}

OSErr		FSpSetXFInfo(FSSpec *fileSpec, FXInfo *xFInfoP)
{
	OSErr			err;
	CInfoPBRec		paramBlock;
	
	memclr(&paramBlock, sizeof(CInfoPBRec));

	paramBlock.hFileInfo.ioNamePtr		= fileSpec->name;
	paramBlock.hFileInfo.ioVRefNum		= fileSpec->vRefNum;
	paramBlock.hFileInfo.ioDirID		= fileSpec->parID;
	
	err = PBGetCatInfo(&paramBlock, FALSE);
	
	if (!err) {
		if ((paramBlock.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0) {
			err = notAFileErr;
		} else {
			paramBlock.hFileInfo.ioFlXFndrInfo	= *xFInfoP;
			paramBlock.hFileInfo.ioFVersNum		= 0;
			paramBlock.hFileInfo.ioFDirIndex	= 0;
			paramBlock.hFileInfo.ioDirID		= fileSpec->parID;
			
			err = PBSetCatInfo(&paramBlock, FALSE);
		}
	}
	
	return err;
}

OSErr		FSpThisApp(FSSpec *appFSSpec)
{
	ProcessSerialNumber		myProcess;
	ProcessInfoRec			myProcInfo;
	OSErr					err;

	ADFS_Log("getting this app's file spec\n");
	err = GetCurrentProcess(&myProcess);
//	if (err) ReportErrorStr(err, "Error getting my process.");

	if (!err) {
		myProcInfo.processInfoLength	= sizeof(ProcessInfoRec);
		myProcInfo.processName			= NULL;
		myProcInfo.processAppSpec		= appFSSpec;

		ADFS_Log("getting this app's process info\n");
		err = GetProcessInformation(&myProcess, &myProcInfo);
//		if (err) ReportErrorStr(err, "Error getting process info.");
	}
	
	return err;
}

/* CODE EXAMPLE #1 */

/*
	Launch application with doc using Apple Events
	This short application demonstrates how to send an Apple event () to the
	Finder requesting it to open a document as if it had been double clicked.
	Everything about this code is System 7 dependent, so don't even bother trying
	to run it under System 6. Just add MacTraps and MacTraps2 to the project.
*/

// Constants for dealing with FinderEvents. See Chapter 8 of the Apple Event
// Registry for more information.
#define kFinderSig			'FNDR'
#define kAEFinderEvents		'FNDR'
#define kSystemType			'MACS'

#define kAEOpenSelection	'sope'
#define keySelection		'fsel'

// Given a FSSpecPtr to either an application or a document, OpenSelection creates a
// finder Open Selection Apple event for the object described by the FSSpec.
OSErr		FSpLaunchInFinder(FSSpec *fileSpecP)
{
	OSErr					err = noErr;
//	Boolean					isFolderB;
	
//	err = FSpIsFolder(fileSpecP, &isFolderB);
//	if (err) goto bailError;

	if (Is_OS_X()) {	//	 && !isFolderB) {
		#ifndef OLD68K
			FSRef		fsRef;
			
			err = FSpMakeFSRef(fileSpecP, &fsRef);
			if (!err) {
				#ifndef __68k__
					if (LSOpenFSRef(&fsRef, NULL) != noErr) {
						err = dsBadLaunch;
					}
				#endif
			}
		#endif
	} else {
		AppleEvent				aeEvent;		// the event to create;
		AEDesc					myAddressDesc, aeDirDesc, listElem, fileList;
		FSSpec					dirSpec;
		AliasHandle				dirAlias, fileAlias;	// alias of the file itself
		ProcessSerialNumber		process;		// the finder's psn

		// Get the psn of the Finder and create the target address for the .
		err = FindAProcess(kFinderSig,kSystemType,&process);
		if (err) goto bailError;
				
		err = AECreateDesc(
			typeProcessSerialNumber, (Ptr)&process, 
			sizeof(process), &myAddressDesc);
		if (err) goto bailError;

		// Create an empty 
		err = AECreateAppleEvent(
			kAEFinderEvents, kAEOpenSelection, &myAddressDesc, 
			kAutoGenerateReturnID, kAnyTransactionID, &aeEvent);
		if (err) goto bailError;

		// Make an FSSpec and alias for the parent folder, and an alias for the file
		err = FSMakeFSSpec(fileSpecP->vRefNum, fileSpecP->parID, NULL, &dirSpec);
		if (err) goto bailError;

		err = NewAlias(NULL, &dirSpec, &dirAlias);
		if (err) goto bailError;

		err = NewAlias(NULL, fileSpecP, &fileAlias);
		if (err) goto bailError;

		/* Create the folder descriptor*/
		HLock((Handle)dirAlias);
		err = AECreateDesc(
			typeAlias, (Ptr)*dirAlias, 
			GetHandleSize((Handle)dirAlias), &aeDirDesc);
		HUnlock((Handle)dirAlias);
		DisposeHandle((Handle)dirAlias);
		if (err) goto bailError;

		err = AEPutParamDesc(&aeEvent,keyDirectObject,&aeDirDesc);
		if (err) goto bailError;

		err = AEDisposeDesc(&aeDirDesc);
		if (err) goto bailError;

		HLock((Handle)fileAlias);
		err = AECreateDesc(
			typeAlias, (Ptr)*fileAlias,
			GetHandleSize((Handle)fileAlias), &listElem);
		HUnlock((Handle)fileAlias);
		DisposeHandle((Handle)fileAlias);
		if (err) goto bailError;

		// Create the file list.
		err = AECreateList(NULL, 0, FALSE, &fileList);
		if (err) goto bailError;

		err = AEPutDesc(&fileList,0,&listElem);
		if (err) goto bailError;

		err = AEDisposeDesc(&listElem);
		if (err) goto bailError;

		err = AEPutParamDesc(&aeEvent,keySelection,&fileList);
		if (err) goto bailError;

		err = AEDisposeDesc(&fileList);
		if (err) goto bailError;

		err = AESend(&aeEvent, NULL,
				kAENoReply+kAEAlwaysInteract+kAECanSwitchLayer,
				kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
		if (err) goto bailError;

		err = AEDisposeDesc(&aeEvent);
		if (err) goto bailError;
	}

	goto done;
	
	bailError:
	AlertID("Some kind of AppleEvent error", err);

	done:
	return err;
}

OSErr		FSpGetResEOF(FSSpec *fileSpec, long *resSize)
{
	OSErr			err;
	CInfoPBRec		paramBlock;
	
	memclr(&paramBlock, sizeof(CInfoPBRec));

	paramBlock.hFileInfo.ioNamePtr		= fileSpec->name;
	paramBlock.hFileInfo.ioVRefNum		= fileSpec->vRefNum;
	paramBlock.hFileInfo.ioDirID		= fileSpec->parID;
	
	err = PBGetCatInfo(&paramBlock, FALSE);
	
	if (!err) {
		*resSize = paramBlock.hFileInfo.ioFlRLgLen;
	}
	
	return err;
}

OSErr	FSpGetEOF(FSSpecPtr fileSpec, long *fileSize)
{
	OSErr		err = noErr;
	short		refNum;
	
	err = FSpOpenDF(fileSpec, fsCurPerm, &refNum);
	
	if (!err) {
		OSErr	err2;
		
		err = GetEOF(refNum, fileSize);
		
		err2 = FSClose(refNum);
		
		if (!err) err = err2;
	}
	
	return err;
}

OSErr	FSpSetEOF(FSSpecPtr fileSpec, long fileSize)
{
	OSErr		err = noErr;
	short		refNum;
	
	err = FSpOpenDF(fileSpec, fsRdWrPerm, &refNum);
	
	if (!err) {
		OSErr	err2;
		
		err = SetEOF(refNum, fileSize);
		
		err2 = FSClose(refNum);
		
		if (!err) err = err2;
	}
	
	return err;
}

OSErr	FSpSetFileTypeAndCreator(
	FSSpec				*fileSpec, 
	OSType				fileCreator, 
	OSType				fileType)
{
	FInfo		fInfo;	
	OSErr		err = FSpGetCatFInfo(fileSpec, &fInfo);
	
	if (!err) {
		fInfo.fdCreator	= fileCreator;
		fInfo.fdType	= fileType;

		err = FSpSetCatFInfo(fileSpec, &fInfo);
	}
	
	return err;
}

OSErr	FSpCreateTempFile(
	short				vRefNum, 
	ConstStr255Param	nameP, 
	OSType				fileCreator, 
	OSType				fileType, 
	FSSpec				*returnSpecP)
{
	OSErr		err = noErr;
	long		folderID;

	ADFS_Log("Finding temp items folder\n");
	if (!err) err = FSpFindFolder(
		vRefNum, kTemporaryFolderType, returnSpecP);
	
	
	if (!err) {
		ADFS_Log("Getting temp folder ID\n");
		err = FSpGetFolderID(returnSpecP, &folderID);
	}

	if (!err) {
		ADFS_Log("Making FSSpec for new temp file\n");
		err = FSMakeFSSpec(
			returnSpecP->vRefNum, folderID, 
			nameP, returnSpecP);

		if (err == fnfErr) {
			err = noErr;
		} else if (err == noErr) {
			ADFS_Log("temp file already exists with that name, so "
				"attempting to unlock it (so I can delete it)\n");
			
			err	= FSpSetFileLock(returnSpecP, FALSE);
			if (!err) {
				ADFS_Log("deleting that file\n");
				err = FSpDelete(returnSpecP);
			}
		}

		if (!err) {
			ADFS_Log("Creating new temp file: \n");
			err = FSpCreate(
				returnSpecP, fileCreator, 
				fileType, smSystemScript);
			
			#ifdef DEBUG
			{
				char		pathAC[kMaxFilePathLen];
				
				if (!err) err = FSpGetFullPath(returnSpecP, kMaxFilePathLen, pathAC);
				if (!err) {
					ADFS_Log(pathAC);
					ADFS_Log("\n");
				}
			}
			#endif
		}
	}
	
	return err;
}

#define		kFileBufSize	(800L * 1024L)

OSErr	FSpSetSOF(FSSpecPtr origFileSpecP, long offset)
{
	OSErr		err = noErr, err2 = noErr;
	FSSpec		tempFileSpec;
	short		tempRefNum, fileRefNum;
	FInfo		fInfo;
	long		fileBufSize = kFileBufSize;
	Handle		bufH = TrackNewHandle("FSpSetSOF buf", fileBufSize);
	Ptr			bufP;
	
	if (bufH == NULL) {
		err = memFullErr;
	} else {
		HLockHi(bufH);
		bufP = *bufH;
	}
	
	if (!err) err = FSpGetFInfo(origFileSpecP, &fInfo);

	if (!err) err = FSpCreateTempFile(
		origFileSpecP->vRefNum, 
		"\pADFS Temp", 
		fInfo.fdCreator, 
		fInfo.fdType, 
		&tempFileSpec);
			
	if (!err) {
		if (!err) err = FSpOpenDF(origFileSpecP, fsCurPerm, &fileRefNum);

		if (!err) {
			if (!err) err = FSpOpenDF(&tempFileSpec, fsRdWrPerm, &tempRefNum);

			if (!err) {
				long		inOutCount;
				Boolean		doneB;
				
				if (offset > 0) {
					err = SetFPos(fileRefNum, fsFromStart, offset);
				} else {
					Byte		zeroByte	= 0;
					
					#ifdef __ADFS__
//						ASSERT(offset < 0);
					#endif
					
					offset = -offset;
					inOutCount	= 1;
					
					do {
						err = FSWrite(tempRefNum, &inOutCount, &zeroByte);
						if (inOutCount != 1) {
							err = paramErr;
						}
					} while (!err && --offset);
				}
				
				if (!err) {
					inOutCount	= kFileBufSize;
					doneB		= FALSE;
					
					do {
						if (inOutCount != kFileBufSize) {
							err = paramErr;
						}

						if (!err) err = FSRead(fileRefNum, &inOutCount, bufP);

						if (err == eofErr) {
							err = noErr;
							doneB = TRUE;
						} else if (!err && inOutCount != kFileBufSize) {
							err = paramErr;
						}
						
						if (!err) err = FSWrite(tempRefNum, &inOutCount, bufP);
					} while (!err && !doneB);
				}
				
				err2 = FSClose(tempRefNum);
				if (!err) err = err2;
				tempRefNum = 0;
			}

			err2 = FSClose(fileRefNum);
			if (!err) err = err2;
			fileRefNum = 0;
		}
		
		if (!err) err = FSpExchangeFiles(origFileSpecP, &tempFileSpec);

		err2 = FSpDelete(&tempFileSpec);
		if (!err) err = err2;
	}
	
	if (fileRefNum) {
		err2 = FSClose(fileRefNum);
		if (!err) err = err2;
	}
	
	if (bufH) {
		HUnlock(bufH);
		TrackDisposeHandle(bufH);
	}
	
	return err;
}

OSErr			FSpCountFilesInFolder(FSSpec *folderSpecP, ulong *numFilesL)
{
	OSErr		err			= noErr;
	CInfoPBRec	pbRec;
	
	memclr(&pbRec, sizeof(CInfoPBRec));
	
	pbRec.dirInfo.ioNamePtr		= folderSpecP->name;
	pbRec.dirInfo.ioVRefNum		= folderSpecP->vRefNum;
	pbRec.dirInfo.ioDrDirID		= folderSpecP->parID;
	
	err = PBGetCatInfo(&pbRec, FALSE);
	
	if (!err) {
		*numFilesL = pbRec.dirInfo.ioDrNmFls;
	}
	
	return err;
}

/*
OSErr	FSpIsFileVisible(const FSRef *ref, Boolean *visible)
{
	OSStatus		err;
	FSCatalogInfo	info;
	HFSUniStr255	name;

	ASSERT(ref != NULL);
	ASSERT(visible != NULL);

	err = FSGetCatalogInfo(ref, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo, &info, &name, NULL, NULL);
	if (err == noErr) {
		*visible =     ((info.nodeFlags & kFSNodeIsDirectoryMask) == 0)      // file
		&& ((((FInfo *) &info.finderInfo[0])->fdFlags & kIsInvisible) == 0)  // visible
		&& (name.unicode[0] != '.');           // doesn't begin with .
	}
	return err;
} 
*/


OSErr			FSpGetIndFileInFolder(
	FSSpec	*folderSpecP, 
	ulong	fileIndex, 
	FSSpec	*indFileSpecP)
{
	OSErr		err			= noErr;
	CInfoPBRec	pbRec;
	
	memclr(&pbRec, sizeof(CInfoPBRec));
	CopyString(folderSpecP->name, indFileSpecP->name);
	
	pbRec.dirInfo.ioNamePtr		= indFileSpecP->name;
	pbRec.dirInfo.ioVRefNum		= folderSpecP->vRefNum;
	pbRec.dirInfo.ioDrDirID		= folderSpecP->parID;
	
	err = PBGetCatInfo(&pbRec, FALSE);
	
	if (!err) {
		pbRec.dirInfo.ioFDirIndex	= (short)(fileIndex + 1);
		err = PBGetCatInfo(&pbRec, FALSE);
	}

	if (!err) {
		indFileSpecP->vRefNum	= pbRec.dirInfo.ioVRefNum;
		indFileSpecP->parID		= pbRec.dirInfo.ioDrParID;

		if (
			(pbRec.hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible) != 0
			|| (indFileSpecP->name[1] == '.')
		) {
			err = IC_Err_INVISIBLE_FILE;
		}
	}
	
	return err;
}

#ifndef __ADFS__
	static	short		ComparePString(unsigned char *strA, unsigned char *strB)
	{
		return CompareText(&strA[1], &strB[1], strA[0], strB[0], NULL);
	}
#endif

Boolean		FSpEqual(
	FSSpec	*spec1, 
	FSSpec	*spec2)
{
	Boolean		sameB = FALSE;
	
	sameB = spec1->vRefNum == spec2->vRefNum
		&& spec1->parID == spec2->parID;
		
	if (sameB) {
		sameB = (Boolean)(ComparePString(spec1->name, spec2->name) == 0);
	}

	return sameB;
}

OSErr		FSpGetFullPath(
	FSSpec	*specP, 
	short	maxPathLen, 
	char	*pathZ)
{
	FSSpec		parentSpec;
	OSErr		err = FSpGetParentVolume(specP, &parentSpec);
	
	if (!err) {
		if (FSpEqual(specP, &parentSpec)) {
			CopyPascalStringToC(specP->name, pathZ);
		} else {
			err = FSpGetParentFolder(specP, &parentSpec);
			
			if (!err) err = FSpGetFullPath(&parentSpec, maxPathLen, pathZ);
			
			if (!err) {
				ulong	strLenS = strlen(pathZ);
				
				if (specP->name[0] + strLenS < maxPathLen) {
					char	nameAC[256];
	
					CopyPascalStringToC(specP->name, nameAC);
					strcat(pathZ, ":");
					strcat(pathZ, nameAC);
				}			
			}
		}
	}
	
	return err;
}


/*
OSErr	LaunchApplication(OSType creator, Boolean inBackgroundB)
{
	ProcessSerialNumber	theAppPSN;
	FSSpec					theAppToLaunch;
	OSErr					err  = noErr;

	// Check for already running app

	err = FindApplicationProcess(creator, &theAppPSN );

	if(err == noErr) {
		err = SetFrontProcess( &theAppPSN );
	} else {
		err = FindApplicationOnDisk (creator, 0, &theAppToLaunch);
		if(err == noErr)
		{
		LaunchParamBlockRec launchPB;

		launchPB.launchBlockID   = extendedBlock;
		launchPB.launchEPBLength  = extendedBlockLen;
		launchPB.launchFileFlags  = 0;
		launchPB.launchControlFlags  = launchContinue | launchNoFileFlags;
		launchPB.launchAppSpec   = &theAppToLaunch;
		launchPB.launchAppParameters = nil;

		LaunchApplication( &launchPB );

		} 
	}

	return err;
}
 
 
 
 
//
// This runs through the process list looking for the requested application.  It searches for
// applications of type 'APPL', 'APPC' (control panel apps), 'APPE' (extension apps), and
// 'APPD' (desk accessory apps).  Once the requested application has been found processSN
// will contain the process serial number of the running application that was just found.
//
static OSErr FindApplicationProcess (OSType creatorToFind, ProcessSerialNumberPtr processSN)
 {
 ProcessInfoRec   procInfo;
 FSSpec     procSpec;
 Str31     processName;
 OSErr     err    = noErr;

 // Clear out the PSN so we're starting at the beginning of the list.
 processSN->lowLongOfPSN = kNoProcess;
 processSN->highLongOfPSN = kNoProcess;

 // Initialize the process information record.
 procInfo.processInfoLength = sizeof (ProcessInfoRec);
 procInfo.processName = &processName[0];
 procInfo.processAppSpec = &procSpec;

 // Loop through all the processes until we find the process we want or
 // error out because of some reason (usually, no more processes).
 do {
  err = GetNextProcess (processSN);
  if (err == noErr) {
   err = GetProcessInformation (processSN, &procInfo);
  }
 } while ((procInfo.processSignature != creatorToFind || !(procInfo.processType == 'APPL' ||
    procInfo.processType == 'APPC' || procInfo.processType == 'appe' ||
    procInfo.processType == 'APPD')) && err == noErr);

 return (err);
}

//
// Finds the requested application on disk searching the desktop database and returns an FSSpec to that app.
// It first searches local disks, then searches remote disks.  Once a possible application has been found
// in the desktop database the application is verified to actually exist because the desktop database is
// often not totally accurate.
//
// If startVRefNum is negative then it will be treated as a VRefNum and the search will start on specified
// volume.  If the value of startVRefNum is 0 or positive then the search starts on the first local disk,
// runs through all local disks, and then searches the first remote volume and runs through all remote
// volumes looking for the requested application.
//
static OSErr FindApplicationOnDisk (OSType creatorToSearchFor, short startVRefNum, FSSpec* foundApp) {
 HVolumeParam   volPB;
 HIOParam    paramPB;
 DTPBRec     desktopPB;
 GetVolParmsInfoBuffer volinfo;
 FInfo     fndrInfo;
 OSErr     err    = fnfErr;   // default return value

 volPB.ioNamePtr = nil;
 paramPB.ioNamePtr = nil;
 paramPB.ioBuffer = (Ptr)&volinfo;
 paramPB.ioReqCount = sizeof (volinfo);

 // Try to find the application on the specified disk, if one was specified, first.
 if (startVRefNum < 0) {
  volPB.ioVolIndex = startVRefNum;
  if (PBHGetVInfoSync ((HParmBlkPtr)&volPB) == noErr) {
   // Call PBDTGetPath to find the desktop file on the volume.
   desktopPB.ioCompletion = nil;
   desktopPB.ioNamePtr = nil;
   desktopPB.ioVRefNum = volPB.ioVRefNum;
   desktopPB.ioIndex = 0;  // Find the most recent application.

   if (PBDTGetPath (&desktopPB) == noErr) {
    desktopPB.ioFileCreator = creatorToSearchFor;
    desktopPB.ioNamePtr = (*foundApp).name;

    if (PBDTGetAPPLSync (&desktopPB) == noErr) {
     // At this point we think we have found the correct application.
     (*foundApp).vRefNum = volPB.ioVRefNum;
     (*foundApp).parID = desktopPB.ioAPPLParID;

     // Verify that this application actually exists.
     if (FSpGetFInfo (foundApp, &fndrInfo) == noErr && fndrInfo.fdCreator == creatorToSearchFor) {
      // This application actually exists, we can use it.
      err = noErr;
     }
    }
   }
  }
 }

 if (err != noErr) {
  // The application wasn't on the starting disk, so loop over every local volume looking for the application.
  for (volPB.ioVolIndex = 1; PBHGetVInfoSync ((HParmBlkPtr)&volPB) == noErr; volPB.ioVolIndex++) {
   // Call PBHGetVolParms call to ensure the volume is a local volume.
   paramPB.ioVRefNum = volPB.ioVRefNum;

   if (PBHGetVolParmsSync ((HParmBlkPtr)&paramPB) == noErr && volinfo.vMServerAdr == 0) {
    // Call PBDTGetPath to find the desktop file on the volume.
    desktopPB.ioCompletion = nil;
    desktopPB.ioNamePtr = nil;
    desktopPB.ioVRefNum = volPB.ioVRefNum;
    desktopPB.ioIndex = 0;  // Find the most recent application.

    if (PBDTGetPath (&desktopPB) == noErr) {
     desktopPB.ioFileCreator = creatorToSearchFor;
     desktopPB.ioNamePtr = (*foundApp).name;

     if (PBDTGetAPPLSync (&desktopPB) == noErr) {
      // At this point we think we have found the correct application.
      (*foundApp).vRefNum = volPB.ioVRefNum;
      (*foundApp).parID = desktopPB.ioAPPLParID;

      // Verify that this application actually exists.
      if (FSpGetFInfo (foundApp, &fndrInfo) == noErr && fndrInfo.fdCreator == creatorToSearchFor) {
       // This application actually exists, we can use it.
       err = noErr;
       break;
      }
     }
    }
   }
  }
 }

 if (err != noErr) {
  // If we didn't find the application locally, check remote volumes.

  // Loop over every local volume looking for the application.
  for (volPB.ioVolIndex = 1; PBHGetVInfoSync ((HParmBlkPtr)&volPB) == noErr; volPB.ioVolIndex++) {
   // Call PBHGetVolParms call to ensure the volume is a remote volume.
   paramPB.ioVRefNum = volPB.ioVRefNum;

   if (PBHGetVolParmsSync ((HParmBlkPtr)&paramPB) == noErr && volinfo.vMServerAdr != 0) {
    // Call PBDTGetPath to find the desktop file on the volume.
    desktopPB.ioCompletion = nil;
    desktopPB.ioNamePtr = nil;
    desktopPB.ioVRefNum = volPB.ioVRefNum;
    desktopPB.ioIndex = 0;  // Find the most recent application.

    if (PBDTGetPath (&desktopPB) == noErr) {
     desktopPB.ioFileCreator = creatorToSearchFor;
     desktopPB.ioNamePtr = (*foundApp).name;

     if (PBDTGetAPPLSync (&desktopPB) == noErr) {
      // At this point we have found the correct application.
      (*foundApp).vRefNum = volPB.ioVRefNum;
      (*foundApp).parID = desktopPB.ioAPPLParID;

      // Verify that this application actually exists.
      if (FSpGetFInfo (foundApp, &fndrInfo) == noErr && fndrInfo.fdCreator == creatorToSearchFor) {
       // This application actually exists, we can use it.
       err = noErr;
       break;
      }
     }
    }
   }
  }
 }

 return err;
}

*/

/*
	If you're starting with an FSRef , just skip to    step 2.
		If you're starting with an FSSpec , convert it    to an FSRef using FSpMakeFSRef .
	Create a CFURL based on the FSRef using CFURLCreateFromFSRef .
	Pass that CFURL to LSOpenCFURLRef .
	Release your reference to the CFURL. 
*/

OSStatus	LaunchURL(char *url_AC)
{
	OSStatus	err = noErr;
	
	#ifndef OLD68K
	CFURLRef	url;

//	url = CFURLCreateWithString(NULL, CFSTR(url_AC), NULL);

	url = CFURLCreateWithBytes(
		kCFAllocatorDefault, 
		(unsigned char *)url_AC, strlen(url_AC), 
		kCFStringEncodingMacRoman , NULL);
	
	err = LSOpenCFURLRef(url, NULL);
	
	CFRelease(url);

	#endif
	
    return (err);
} 


OSErr		FSpMakeWritable(FSSpec *fileSpecP)
{
	OSErr				err = noErr;

	#ifndef OLD68K

	FSRef				fsRef;
	FSCatalogInfo		catalogInfo;
	
	err = FSpMakeFSRef(fileSpecP, &fsRef);

	if (!err) err = FSGetCatalogInfo(
		&fsRef, kFSCatInfoPermissions, 
		&catalogInfo, NULL, NULL, NULL);
		
	if (!err) {
		FSPermissionInfo    *permissions;

		permissions = (FSPermissionInfo*)(catalogInfo.permissions);

		//Octal 222, write access for user, group, world
		//Read : Write : Execute 
		permissions->mode    |= 0222;

		err = FSSetCatalogInfo(&fsRef, kFSCatInfoPermissions, &catalogInfo );
	}
	
	#endif
	
	return err;
}

OSErr		FSpResolveFile(FSSpec *fileSpecP, FSSpec *goodSpecP)
{
	FInfo		fInfo;
	OSErr		err = FSpGetCatFInfo(fileSpecP, &fInfo);
	
	if (err == fnfErr) {
		fileSpecP->parID	= goodSpecP->parID;
		fileSpecP->vRefNum	= goodSpecP->vRefNum;
		err = FSpGetCatFInfo(fileSpecP, &fInfo);
	}
	
	return err;
}

OSErr		FSpMakeFSSpecFromFolderAndPName(
	FSSpec				*folderP, 
	ConstStr63Param		nameUZ, 
	FSSpec				*destSpecP)
{
	Str255		pathStr;

	*destSpecP = *folderP;
	
	pathStr[0] = 0;
	Concat(c2p(":"), folderP->name, pathStr);
	Concat(pathStr, c2p(":"), pathStr);
	Concat(pathStr, (unsigned char *)nameUZ, pathStr);

	return FSMakeFSSpec(
		folderP->vRefNum, folderP->parID, pathStr, destSpecP);
}

OSErr		FSpMakeFSSpecFromFolderAndCName(
	FSSpec		*folderP, 
	char		*nameZ, 
	FSSpec		*destSpecP)
{
	unsigned char	nameUAC[64];
	
	CopyCStringToPascal(nameZ, nameUAC);

	return FSpMakeFSSpecFromFolderAndPName(folderP, nameUAC, destSpecP);
}

OSErr		FSpCreateAliasFile(
	FSSpec	*targetFileP, 
	FSSpec	*destFolderP, 
	FSSpec	*aliasP0)
{
	OSErr		err = noErr;
	
	err = MoreFECreateAliasFile(targetFileP, destFolderP, targetFileP->name, NULL);
	
	if (!err && aliasP0) {
		err = FSpMakeFSSpecFromFolderAndPName(destFolderP, targetFileP->name, aliasP0);
	}
	
	return err;
}

/*
OSErr	FSRefToFSSpec(
	const FSRef	*fsRef, 
	FSSpec		*fsSpec)
{
	return FSGetCatalogInfo(kFSCatInfoNone, NULL, NULL, fsSpec, NULL);
}
*/

