/*********************************************************/
/* 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

/*
 * Local variables:
 *   lPrefsDialog = preferences dialog pointer
 *
 */

static DialogPtr gPrefsDialog = nil;

/*
 * OpenPrefs()
 *
 *     Purpose: Opens the preferences dialog window
 *      Inputs: initialSection = the starting menu item
 *     Returns: nothing
 *
 */
 
OSErr OpenPrefs(void) 
{
	OSErr theErr = noErr;
	short i;
	
	if (gPrefsDialog) {
		if (!WindowVisible(gPrefsDialog)) FWShowWindow(gPrefsDialog);
		return noErr;
	}
	gOldPrefs = gThePrefs;
	if (!(gPrefsDialog = AllocateDialog())) return gIntError = errNoMemory, memFullErr;
	StartSpinning();
	PushPort();
	MySetPort(nil);
	if (gPrefsDialog = FWGetNewDialog(rPrefsDialog, (Ptr)gPrefsDialog, (WindowPtr)-1)) {
		for (i = prefsWindows; i <= prefsStartup; i++) {
			if (i != gThePrefs.prefsSection) HidePrefsItems(i);
			UpdatePrefsButtons(i);
			KeepSpinning();
		}
		SetItemHandle(gPrefsDialog, prefsBoxUser, (Handle)gPopUpMenuBox);
		SetDCtlValue(gPrefsDialog, prefsPopUpMenu, gThePrefs.prefsSection);
		PlaceWindow(gPrefsDialog, &gThePrefs.prefsBounds, CenterWindow(gPrefsDialog));
	} else gIntError = errNoMemory, theErr = memFullErr, DeallocateDialog(gPrefsDialog);
	StopSpinning(&qd.arrow);
	PopPort();
	return theErr;
}

/*
 * ClosePrefs()
 *
 *     Purpose: Closes the preferences dialog window
 *      Inputs: initialSection = the starting menu item
 *     Returns: nothing
 *
 */
 
void ClosePrefs(void)
{
	PushPort();
	MySetPort(nil);
	if (gPrefsDialog) {
		SaveWindowPosition(gPrefsDialog, &gThePrefs.prefsBounds);
		FWCloseDialog(gPrefsDialog);
		DisposeHandle(((DialogPeek)gPrefsDialog)->items);
		DeallocateDialog(gPrefsDialog);
	}
	gPrefsDialog = nil;
	PopPort();
	ChangeActive(FWFrontWindow());
}

/*
 * GetPrefsWindow()
 *
 *     Purpose: Returns a pointer to the preferences dialog
 *      Inputs: none
 *     Returns: nothing
 *
 */
 
WindowPtr GetPrefsWindow(void)
{
	return (WindowPtr)gPrefsDialog;
}

/*
 * HandlePrefsEvent(theDialog, theItem)
 *
 *     Purpose: Makes changes to the preferences settings as indicated by theItem
 *      Inputs: theDialog = pointer to the preferences dialog
 *				theItem = the dialog item which was hit
 *     Returns: true if the OK or Cancel buttons were hit; false otherwise
 *
 */
 
void HandlePrefsEvent(short theItem)
{
	short i;
	
	switch (theItem) {
		case kDialogClose:
			SaveGeneralPrefs();
			ClosePrefs();
			return;
		case kDialogOK:
		case kDialogCancel:
			SaveGeneralPrefs();
			SendCloseWindow(gPrefsDialog);
			return;
		case prefsPopUpMenu:
			gThePrefs.prefsSection = GetDCtlValue(gPrefsDialog, prefsPopUpMenu);
			for (i = prefsWindows; i <= prefsStartup; i++)
				if (i != gThePrefs.prefsSection) HidePrefsItems(i);
			ShowPrefsItems(gThePrefs.prefsSection);
			break;

		case prefsImageDeepestButton:	gThePrefs.openScreen = osDeepest;			break;
		case prefsImageLargestButton:	gThePrefs.openScreen = osLargest;			break;
		case prefsImageMainButton:		gThePrefs.openScreen = osMain;				break;
		case prefsUseColorBox:			gThePrefs.pickColor = !gThePrefs.pickColor; break;
		case prefsAlwaysFullButton: 	gThePrefs.openFull = ofNoMatterWhat; 		break;
		case prefsAlwaysLargeButton: 	gThePrefs.openFull = ofAlways; 				break;
		case prefsAskLargeButton: 		gThePrefs.openFull = ofAsk;					break;
		case prefsNeverFullButton:		gThePrefs.openFull = ofNever;				break;
		case prefsExpandSmallBox:		gThePrefs.expandSmall = !gThePrefs.expandSmall;break;
		case prefsOnlyOneBox:			gThePrefs.onlyOne = !gThePrefs.onlyOne;		break;

		case prefsVHighQualityButton:	gThePrefs.imageQuality = iqVHigh;			break;
		case prefsHighQualityButton:	gThePrefs.imageQuality = iqHigh;			break;
		case prefsMedQualityButton:		gThePrefs.imageQuality = iqMedium;			break;
		case prefsBackgroundBox:		gThePrefs.updateBack = !gThePrefs.updateBack;break;
		case prefsQuantizeAlwaysButton:	gThePrefs.autoQuant = aqAlways;				break;
		case prefsQuantizeOnlyButton:	gThePrefs.autoQuant = aqOnly;				break;
		case prefsQuantizeNeverButton:	gThePrefs.autoQuant = aqNever;				break;
		case prefsDitherQuantizedBox:	gThePrefs.ditherQuant = !gThePrefs.ditherQuant; break;
		case prefsUsePaletteBox:		gThePrefs.imagePalette = !gThePrefs.imagePalette;	break;
		case prefsRestoreColorsBox:		gThePrefs.restoreColors = !gThePrefs.restoreColors; break;

		case prefsBitmapsAlwaysButton:	gThePrefs.useBitmaps = ubAlways;			break;
		case prefsBitmapsOptionalButton:gThePrefs.useBitmaps = ubOptional;			break;
		case prefsBitmapsNeverButton:	gThePrefs.useBitmaps = ubNever;				break;
		case prefsOriginalSizeBox:		gThePrefs.origSize = !gThePrefs.origSize;	break;
		case prefsNoUncompressedBox:	gThePrefs.noUncomp = !gThePrefs.noUncomp;	break;

		case prefsFixFilesBox:			gThePrefs.autoFix = !gThePrefs.autoFix;		break;
		case prefsFixCreatorsBox:		gThePrefs.changeCreator = !gThePrefs.changeCreator;break;
		case prefsSaveQAlwaysButton:	gThePrefs.saveQuant = sqAlways;				break;
		case prefsSaveQOnlyButton:		gThePrefs.saveQuant = sqOnly;				break;
		case prefsSaveQNeverButton:		gThePrefs.saveQuant = sqNever;				break;
		case prefsDefaultPICTBox:		gThePrefs.savePICT = !gThePrefs.savePICT;	break;
		case prefsSavePreviewsBox:		gThePrefs.savePrev = !gThePrefs.savePrev;	break;
		case prefsCompressPreviewsBox:	gThePrefs.compressPrev = !gThePrefs.compressPrev; break;
		case prefsAddIconsBox:			gThePrefs.makeIcons = !gThePrefs.makeIcons; break;
		case prefsIconStyleMenu:		gThePrefs.iconStyle = GetDCtlValue(gPrefsDialog, prefsIconStyleMenu); break;

		case prefsBeginSlidesButton:	gThePrefs.startWith = swAutoSlide;			break;
		case prefsSlideDialogButton:	gThePrefs.startWith = swSlide;				break;
		case prefsOpenDialogButton:		gThePrefs.startWith = swOpen;				break;
		case prefsNothingButton:		gThePrefs.startWith = swNone;				break;
		case prefsAutoCommentsBox:		gThePrefs.autoComments = !gThePrefs.autoComments;break;
		case prefsMaximalBox:			gThePrefs.backgroundTime = bgMaximal;		break;
		case prefsReasonableBox:		gThePrefs.backgroundTime = bgReasonable;	break;
		case prefsMinimalBox:			gThePrefs.backgroundTime = bgMinimal;		break;
		case prefsUseQuickTimeBox:		gThePrefs.useQuickTime = !gThePrefs.useQuickTime;break;
	}
	UpdatePrefsButtons(gThePrefs.prefsSection);
}

/*
 * HandlePrefsKey(theChar)
 *
 *     Purpose: Handles key down events in the preferences dialog
 *      Inputs: theChar = the ASCII representation of the character
 *     Returns: nothing
 *
 */

Boolean HandlePrefsKey(char theChar)
{
	if (theChar == kDownArrowChar && gThePrefs.prefsSection < prefsStartup) {
		SetDCtlValue(gPrefsDialog, prefsPopUpMenu, GetDCtlValue(gPrefsDialog, prefsPopUpMenu) + 1);
		HandlePrefsEvent(prefsPopUpMenu);
	} else if (theChar == kUpArrowChar && gThePrefs.prefsSection > prefsWindows) {
		SetDCtlValue(gPrefsDialog, prefsPopUpMenu, GetDCtlValue(gPrefsDialog, prefsPopUpMenu) - 1);
		HandlePrefsEvent(prefsPopUpMenu);
	}
	return true;
}

/*
 * HidePrefsItems(theSect)
 *
 *     Purpose: Hides all the dialog items in theSect
 *      Inputs: theSect = the section number of items to hide
 *     Returns: nothing
 *
 */
 
void HidePrefsItems(short theSect)
{
	short i;
	
	switch (theSect) {
		case prefsWindows:
			for (i = prefsFirstWindowsItem; i <= prefsLastWindowsItem; i++)
				HideDItem(gPrefsDialog, i);
			break;
		case prefsDisplay:
			for (i = prefsFirstDisplayItem; i <= prefsLastDisplayItem; i++)
				HideDItem(gPrefsDialog, i);
			break;
		case prefsOffscreen:
			for (i = prefsFirstBitmapsItem; i <= prefsLastBitmapsItem; i++)
				HideDItem(gPrefsDialog, i);
			break;
		case prefsFiles:
			for (i = prefsFirstFilesItem; i <= prefsLastFilesItem; i++)
				HideDItem(gPrefsDialog, i);
			break;
		case prefsStartup:
			for (i = prefsFirstMiscItem; i <= prefsLastMiscItem; i++)
				HideDItem(gPrefsDialog, i);
			break;
	}
}

/*
 * ShowPrefsItems(theSect)
 *
 *     Purpose: Shows all the dialog items in theSect
 *      Inputs: theSect = the section number of items to show
 *     Returns: nothing
 *
 */
 
void ShowPrefsItems(short theSect)
{
	short i;
	
	switch (theSect) {
		case prefsWindows:
			for (i = prefsFirstWindowsItem; i <= prefsLastWindowsItem; i++)
				ShowDItem(gPrefsDialog, i);
			break;
		case prefsDisplay:
			for (i = prefsFirstDisplayItem; i <= prefsLastDisplayItem; i++)
				ShowDItem(gPrefsDialog, i);
			break;
		case prefsOffscreen:
			for (i = prefsFirstBitmapsItem; i <= prefsLastBitmapsItem; i++)
				ShowDItem(gPrefsDialog, i);
			break;
		case prefsFiles:
			for (i = prefsFirstFilesItem; i <= prefsLastFilesItem; i++)
				ShowDItem(gPrefsDialog, i);
			break;
		case prefsStartup:
			for (i = prefsFirstMiscItem; i <= prefsLastMiscItem; i++)
				ShowDItem(gPrefsDialog, i);
			break;
	}
}

/*
 * UpdatePrefsButtons(theSect)
 *
 *     Purpose: Updates the values of all the buttons in the given section of the
 *					preferences dialog
 *      Inputs: theSect = the section number we want to update
 *     Returns: nothing
 *
 */
 
void UpdatePrefsButtons(short theSect) 
{
	switch (theSect) {
		case prefsWindows:
			SetDCtlValue(gPrefsDialog, prefsImageDeepestButton, gThePrefs.openScreen == osDeepest);
			SetDCtlValue(gPrefsDialog, prefsImageLargestButton, gThePrefs.openScreen == osLargest);
			SetDCtlValue(gPrefsDialog, prefsImageMainButton, gThePrefs.openScreen == osMain);
			SetDCtlValue(gPrefsDialog, prefsUseColorBox, gThePrefs.pickColor);
			SetDCtlValue(gPrefsDialog, prefsAlwaysFullButton, gThePrefs.openFull == ofNoMatterWhat);
			SetDCtlValue(gPrefsDialog, prefsAlwaysLargeButton, gThePrefs.openFull == ofAlways);
			SetDCtlValue(gPrefsDialog, prefsAskLargeButton, gThePrefs.openFull == ofAsk);
			SetDCtlValue(gPrefsDialog, prefsNeverFullButton, gThePrefs.openFull == ofNever);
			SetDCtlValue(gPrefsDialog, prefsExpandSmallBox, gThePrefs.expandSmall);
			SetDCtlValue(gPrefsDialog, prefsOnlyOneBox, gThePrefs.onlyOne);
			break;
		case prefsDisplay:
			SetDCtlValue(gPrefsDialog, prefsVHighQualityButton, gThePrefs.imageQuality == iqVHigh);
			SetDCtlValue(gPrefsDialog, prefsHighQualityButton, gThePrefs.imageQuality == iqHigh);
			SetDCtlValue(gPrefsDialog, prefsMedQualityButton, gThePrefs.imageQuality == iqMedium);
			SetDCtlValue(gPrefsDialog, prefsBackgroundBox, !gThePrefs.updateBack);
			SetDCtlValue(gPrefsDialog, prefsQuantizeAlwaysButton, gThePrefs.autoQuant == aqAlways);
			SetDCtlValue(gPrefsDialog, prefsQuantizeOnlyButton, gThePrefs.autoQuant == aqOnly);
			SetDCtlValue(gPrefsDialog, prefsQuantizeNeverButton, gThePrefs.autoQuant == aqNever);
			SetDCtlValue(gPrefsDialog, prefsDitherQuantizedBox, gThePrefs.ditherQuant);
			SetDCtlValue(gPrefsDialog, prefsUsePaletteBox, gThePrefs.imagePalette);
			SetDCtlValue(gPrefsDialog, prefsRestoreColorsBox, gThePrefs.restoreColors);
			break;
		case prefsOffscreen:
			SetDCtlValue(gPrefsDialog, prefsBitmapsAlwaysButton, gThePrefs.useBitmaps == ubAlways);
			SetDCtlValue(gPrefsDialog, prefsBitmapsOptionalButton, gThePrefs.useBitmaps == ubOptional);
			SetDCtlValue(gPrefsDialog, prefsBitmapsNeverButton, gThePrefs.useBitmaps == ubNever);
			SetDCtlValue(gPrefsDialog, prefsOriginalSizeBox, gThePrefs.origSize);
			SetDCtlValue(gPrefsDialog, prefsNoUncompressedBox, gThePrefs.noUncomp);
			break;
		case prefsFiles:
			SetDCtlValue(gPrefsDialog, prefsFixFilesBox, gThePrefs.autoFix);
			SetDCtlValue(gPrefsDialog, prefsFixCreatorsBox, gThePrefs.changeCreator);
			SetDCtlValue(gPrefsDialog, prefsSaveQAlwaysButton, gThePrefs.saveQuant == sqAlways);
			SetDCtlValue(gPrefsDialog, prefsSaveQOnlyButton, gThePrefs.saveQuant == sqOnly);
			SetDCtlValue(gPrefsDialog, prefsSaveQNeverButton, gThePrefs.saveQuant == sqNever);
			SetDCtlValue(gPrefsDialog, prefsDefaultPICTBox, gThePrefs.savePICT);
			SetDCtlValue(gPrefsDialog, prefsSavePreviewsBox, gThePrefs.savePrev);
			SetDCtlValue(gPrefsDialog, prefsCompressPreviewsBox, gThePrefs.compressPrev);
			SetDCtlValue(gPrefsDialog, prefsAddIconsBox, gThePrefs.makeIcons);
			SetDCtlValue(gPrefsDialog, prefsIconStyleMenu, gThePrefs.iconStyle);
			break;
		case prefsStartup:
			SetDCtlValue(gPrefsDialog, prefsBeginSlidesButton, gThePrefs.startWith == swAutoSlide);
			SetDCtlValue(gPrefsDialog, prefsSlideDialogButton, gThePrefs.startWith == swSlide);
			SetDCtlValue(gPrefsDialog, prefsOpenDialogButton, gThePrefs.startWith == swOpen);
			SetDCtlValue(gPrefsDialog, prefsNothingButton, gThePrefs.startWith == swNone);
			SetDCtlValue(gPrefsDialog, prefsAutoCommentsBox, gThePrefs.autoComments);
			SetDCtlValue(gPrefsDialog, prefsMaximalBox, gThePrefs.backgroundTime == bgMaximal);
			SetDCtlValue(gPrefsDialog, prefsReasonableBox, gThePrefs.backgroundTime == bgReasonable);
			SetDCtlValue(gPrefsDialog, prefsMinimalBox, gThePrefs.backgroundTime == bgMinimal);
			SetDCtlValue(gPrefsDialog, prefsUseQuickTimeBox, gThePrefs.useQuickTime);
			break;
	}
}

/*
 * GetPrefsSpec(theSpec)
 *
 *     Purpose: Locates the preferences folder and returns an FSSpec pointing to the
 *					JPEGView preferences file
 *      Inputs: theSpec = pointer to a destination file specification
 *     Returns: true if things went okay; false otherwise
 *
 */
 
Boolean GetPrefsSpec(FSSpec *theSpec) 
{
	short vRefNum;
	long dirID;
	
	if (FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder, &vRefNum, &dirID) == noErr) {
		FSMakeFSSpec(vRefNum, dirID, gString[strJPEGViewPrefs], theSpec);
		return true;
	}
	return false;
}

/*
 * SavePrefs()
 *
 *     Purpose: Saves the current preferences into the preferences file
 *      Inputs: none
 *     Returns: nothing
 *
 */
 
extern void SaveGeneralPrefs(void) 
{
	long theSize = sizeof(gThePrefs);
	FSSpec theSpec;
	short theFile;
	OSErr theErr;
	
	if (GetPrefsSpec(&theSpec)) {
		theErr = FSpOpenDF(&theSpec, fsRdWrPerm, &theFile);
		if (theErr != noErr) {
			if ((theErr = FSpCreate(&theSpec, kCreator, kPrefsType, 0)) == noErr)
				theErr = FSpOpenDF(&theSpec, fsRdWrPerm, &theFile);
		}
		if (theErr == noErr) {
			if (SetEOF(theFile, 0L) == noErr) {
				if (FSWrite(theFile, &theSize, &gThePrefs) == noErr) {
					FSClose(theFile);
					return;
				} else MinorError(errCantWritePrefs);
				FSClose(theFile);
			} else MinorError(errCantWritePrefs);
			FSpDelete(&theSpec);
		} else MinorError(errCantWritePrefs);
	} else MinorError(errCantWritePrefs);
}

/*
 * LoadPrefs()
 *
 *     Purpose: Loads the current preferences from the preferences file; if the file
 *					isn't found, we write a new one with the default preferences;
 *					if the preferences are from an old version, we display the help
 *					beginning at the appropraite place
 *      Inputs: none
 *     Returns: nothing
 *
 */
 
extern void LoadGeneralPrefs(void) 
{
	long theSize = 0, start = 0;
	PrefsData thePrefs = gThePrefs;
	FSSpec theSpec;
	short theFile;
	
	if (GetPrefsSpec(&theSpec)) {
		if (FSpOpenDF(&theSpec, fsRdPerm, &theFile) == noErr) {
			theSize = sizeof(PrefsData);
			if (FSRead(theFile, &theSize, &thePrefs) == noErr) {
				if (thePrefs.versionID == kPrefsVersion && thePrefs.prefsSize == sizeof(PrefsData)) {
					gThePrefs = thePrefs;
					FSClose(theFile);
					return;
				}
			}
			FSClose(theFile);
			FSpDelete(&theSpec);
		}
		if (OpenHelp() == noErr) ChangeActive(GetHelpWindow());
	}
	SaveGeneralPrefs();
}

extern OSErr LoadPrefsHandle(OSType type, short index, Handle *theHandle)
{
	OSErr theErr = noErr;
	FSSpec theSpec;
	short theFile;
	
	if (GetPrefsSpec(&theSpec)) {
		if ((theFile = FSpOpenResFile(&theSpec, fsRdPerm)) != -1) {
			if (*theHandle = Get1Resource(type, index)) {
				DetachResource(*theHandle);
				CloseResFile(theFile);
				return noErr;
			} else theErr = fnfErr;	// need to signal something since ResError() == 0
			CloseResFile(theFile);
		} else theErr = ResError();
	}
	return theErr;
}

extern OSErr SavePrefsHandle(OSType type, short index, Handle theHandle)
{
	OSErr theErr = noErr;
	Handle oldResource;
	FSSpec theSpec;
	short theFile;
	
	if (GetPrefsSpec(&theSpec)) {
		FSpCreateResFile(&theSpec, kCreator, kPrefsType, 0);
		if ((theFile = FSpOpenResFile(&theSpec, fsRdWrPerm)) != -1) {
			if (oldResource = Get1Resource(type, index)) {
				RmveResource(oldResource);
				if ((theErr = ResError()) == noErr) {
					DisposeHandle(oldResource);
					UpdateResFile(theFile);
				} else ReleaseResource(oldResource);
			}
			if (theErr == noErr) {
				AddResource(theHandle, type, index, (StringPtr)"\p");
				if ((theErr = ResError()) == noErr) {
					WriteResource(theHandle);
					if ((theErr = ResError()) == noErr) {
						DetachResource(theHandle);
						UpdateResFile(theFile);
						CloseResFile(theFile);
						return noErr;
					}
					ReleaseResource(theHandle);
				}
			}
			CloseResFile(theFile);
		} else theErr = ResError();
	}
	return theErr;
}
