/*********************************************************/
/* This source code copyright (c) 1991-2001, Aaron Giles */
/* See the Read Me file for licensing information.       */
/* Contact email: mac@aarongiles.com                     */
/*********************************************************/

#if THINK_C
#include "THINK.Header"
#elif applec
#pragma load ":Headers:MPW.Header"
#elif __MWERKS__
//#include "MW.Header"
#else
#include "JPEGView.h"
#endif

/* 
 * Global variables:
 *
 * lDeskFolderSpec	= FSSpec record for the current desktop folder
 *
 */
 
static FSSpec gDeskFolderSpec;
static Boolean gReallyCancelled = true;
static DlgHookYDUPP gStdFolderHook = nil;

/*
 * StandardGetFolder(theSpec)
 *
 *     Purpose: Uses the DTS code to allow the user to select a folder
 *      Inputs: theSpec = the destination FSSpec to stuff the dirID and vRefNum
 *     Returns: true if it wasn't cancelled
 *
 */

Boolean StandardGetFolder(FSSpec *theSpec)
{
	short activeList[2] = { 1, sfItemFileListUser };
	Point where = CenterDialogWhere(rFolderDialog);
	Boolean isFolder, wasAliased;
	StandardFileReply sfReply;
	Str255 dummyString = "\p";
	SFData sfUserData;
	OSErr theErr;
	
	sfUserData.replyPtr = &sfReply;
	sfUserData.origSelection = *theSpec;
	sfUserData.oldSelection.vRefNum = -9999;
	gReallyCancelled = true;
	MySetPort(nil);
	StopSpinning(&qd.arrow);
	GetDeskFolderSpec(&gDeskFolderSpec, sfUserData.origSelection.vRefNum);	
	if (!gStdFolderHook)
		gStdFolderHook = NewDlgHookYDProc((ProcPtr)StdFolderHook);
	CustomPutFile(gNullString, dummyString, &sfReply, rFolderDialog, where, 
				gStdFolderHook, gOpenSaveModalFilter, activeList, nil, &sfUserData);
	sfReply.sfGood = !gReallyCancelled;
	if (sfReply.sfGood) {
		if (MakeCanonFSSpec(&sfReply.sfFile) != noErr) return false;
		if (ResolveAliasFile(&sfReply.sfFile, true, &isFolder, &wasAliased) != noErr)
			return false;
	}
	theErr = FSMakeFSSpec(sfReply.sfFile.vRefNum, sfReply.sfFile.parID, sfReply.sfFile.name,
					 theSpec);
	if (theErr != noErr) return false;
	return sfReply.sfGood;
}

/*
 * StdFolderHook(item, theDialog, userData)
 *
 *     Purpose: Called by CustomGetFile to handle our special button
 *      Inputs: item = the item number hit
 *				theDialog = pointer to the dialog record
 *				userData = pointer to our data
 *     Returns: the item number hit
 *
 */
 
pascal short StdFolderHook(short item, DialogPtr theDialog, Ptr userData)
{
	static short gLastItem = 0, gLastVRefNum = 555;
	SFDataPtr sfUserData = (SFDataPtr)userData;
	SysEnvRec theEnvirons;
	FSSpec curSpec;
	long theID;
	
	if (gLastItem == sfItemEjectButton) {
		SysEnvirons(1, &theEnvirons);
		if (theEnvirons.sysVRefNum != gLastVRefNum) UnmountVol(0, gLastVRefNum);
	}
	if (GetWRefCon(theDialog) != sfMainDialogRefCon) return item;
	if (item == sfHookFirstCall) {
		curSpec = sfUserData->origSelection;
		GetDirectoryID(&curSpec, &theID);
		curSpec.parID = theID;
		curSpec.name[0] = 0;
		sfUserData->replyPtr->sfFile = curSpec;
		FWDeactivate();
		StopSpinning(&qd.arrow);
		return sfHookChangeSelection;
	} else if (item == sfHookLastCall) {
		FWActivate();
		return item;
	}
	curSpec = sfUserData->replyPtr->sfFile;
	if (!SameFile(&curSpec, &sfUserData->oldSelection)) {
		MakeCanonFSSpec(&curSpec);
		if (curSpec.vRefNum != sfUserData->oldSelection.vRefNum)
			GetDeskFolderSpec(&gDeskFolderSpec, curSpec.vRefNum);	
		SetSelectButtonName(curSpec.name, ShouldHiliteSelect(&curSpec), theDialog);
		sfUserData->oldSelection = sfUserData->replyPtr->sfFile;
	}
	if (item == folderSelectButton) {
		item = sfItemCancelButton;
		gReallyCancelled = false;
	}
	gLastVRefNum = sfUserData->replyPtr->sfFile.vRefNum;
	return gLastItem = item;
}

/*
 * SetSelectButtonName(selName, hilited, theDialog)
 *
 *     Purpose: Set the name of the Select button in our folder dialog
 *      Inputs: selName = the new name
 *				hilited = whether we should enable the button or not
 *				theDialog = pointer to our dialog
 *     Returns: nothing
 *
 */
 
void SetSelectButtonName(StringPtr selName, Boolean hilited, DialogPtr theDialog)
{
	Str255 storeName, tempLenStr, tempSelName;
	short itemType, width;
	Handle itemHandle;
	Rect itemRect;
	
	BlockMove(selName, tempSelName, selName[0] + 1);
	GetDItem(theDialog, folderSelectButton, &itemType, &itemHandle, &itemRect);
	width = itemRect.right - itemRect.left;
	BlockMove(gString[strSelect], tempLenStr, *gString[strSelect] + 1);
	AddCString(tempLenStr, " ÒÓ  ", 5);
	width -= StringWidth(tempLenStr);
	TruncString(width, tempSelName, smTruncMiddle);
	BlockMove(gString[strSelect], storeName, *gString[strSelect] + 1);
	AddCString(storeName, " Ò", 2);
	AddString(storeName, tempSelName);
	AddChar(storeName, 'Ó');
	SetCTitle((ControlHandle)itemHandle, storeName);
	SetDItem(theDialog, folderSelectButton, itemType, itemHandle, &itemRect);
	HiliteControl((ControlHandle)itemHandle, hilited ? 0 : 255);
}

/*
 * MakeCanonFSSpec(theSpec)
 *
 *     Purpose: Checks and creates a FSSpec record for the given directory
 *      Inputs: theSpec = the spec to check
 *     Returns: OSErr if there's a problem
 *
 */
 
OSErr MakeCanonFSSpec(FSSpec *theSpec)
{
	DirInfo infoPB;
	OSErr err;

	if (theSpec->name[0] != '\0') return fnfErr;
	infoPB.ioNamePtr = theSpec->name;
	infoPB.ioVRefNum = theSpec->vRefNum;
	infoPB.ioDrDirID = theSpec->parID;
	infoPB.ioFDirIndex = -1;
	err = PBGetCatInfo((CInfoPBPtr)&infoPB, false);
	theSpec->parID = infoPB.ioDrParID;
	return err;
}

/*
 * GetDeskFolderSpec(theSpec, vRefNum)
 *
 *     Purpose: Get the desktop folder's FSSpec for the given vRefNum
 *      Inputs: theSpec = the spec we want
 *				vRefNum = the volume reference number for the folder we desire
 *     Returns: OSErr if there's a problem
 *
 */
 
extern OSErr GetDeskFolderSpec(FSSpec *theSpec, short vRefNum)
{
	OSErr err;
	
	theSpec->name[0] = '\0';
	if ((err = FindFolder(vRefNum, kDesktopFolderType, kDontCreateFolder, 
					 	  &theSpec->vRefNum, &theSpec->parID)) != noErr) return err;
	return MakeCanonFSSpec(theSpec);
}

/*
 * ShouldHiliteSelect(theSpec)
 *
 *     Purpose: Checks the validity of the given folder and says if we should enable it
 *      Inputs: theSpec = the spec we want
 *     Returns: true to enable, false to disable
 *
 */
 
Boolean ShouldHiliteSelect(FSSpec *theSpec)
{
	if (SameFile(theSpec, &gDeskFolderSpec)) 
		BlockMove(gString[strDesktop], theSpec->name, *gString[strDesktop] + 1);
	return true;
}

extern Boolean SameFile(FSSpec *file1, FSSpec *file2)
{
	return (file1->vRefNum == file2->vRefNum &&
				file1->parID == file2->parID &&
				EqualString(file1->name, file2->name, false, true));
}
