/**************************************************************/
/**  Midas 1.0 for the Macintosh            October 18 1994  **/
/**                                                          **/
/**  C++ code Copyright (C) Nick V. King <nking@eworld.com>  **/
/**************************************************************/

/*****************************************************************************
***********************************************/
/*  Include Headers                                           ****************
***********************************************/
/*****************************************************************************
***********************************************/

#include <sm_mac_mode.h>

/*****************************************************************************
***********************************************/
/*  Declare Globals                                           ****************
***********************************************/
/*****************************************************************************
***********************************************/

double				versionNumber;

ThreadID			theThread;

GWorldPtr			offscreenGWorld;
GDHandle			currentDevice;
WindowPtr			mainWindow, kernelWindow;

ControlHandle		hScroll, vScroll;
Point				offset;
Point				defaultPosition = { -1, -1 };

Cursor				editCursor, waitCursor, rangeCursor;

Rect				mainWindowContents, lastWindowRect;
Rect				headerRect, statusRect;

short				toolbarFieldCount;
toolbarFieldRec		toolbarField[32];

short				dialogFieldCount;
dialogFieldRec		dialogField[32];

short				editField;
TEHandle			editFieldRecord;

int					localFile_type, localFile_record_length;
int					localTplotmode, localCurrent_sc_mode, localCurrent_pra_mode;
int					localYear, localDay, localHour, localMinute;
int					localStart_channel, localEnd_channel, localDuration;
int					localStart_tomplot_channel, localN_tomplot_channels;
int					localTomPlotChannel, localTomPlotLower, localTomPlotUpper;
int					localHigh_res_line, localHigh_res_datum;
int					localHigh_res_channel, localGs2_n_data, localGs2_n_strips;

int					localBrightness, localSaturation;
Boolean				localValid_data[256];
Str255				localComment;
	
Boolean				localStart_channelChanged = false, localEnd_channelChanged = false,
 localDurationChanged = false;
Boolean				localStart_tomplot_channelChanged = false, localN_tomplot_channelsC
hanged = false;

int					localDataColor = blackAndWhiteItem,	dataColor = blackAndWhiteItem;
int					localBackgroundColor = whiteItem,	backgroundColor = whiteItem;
short				localFont = times;
Boolean				localFixedTextSize = true,			fixedTextSize = true; 

Str255				kernelMessage[N_KERNEL_MESSAGES];
RGBColor			kernelMessageColor[N_KERNEL_MESSAGES];

int					lastIgnoreValue = -1, toolbarMode = 1;
int					plotmodesIndex[N_PLOT_MODES], scmodesIndex[N_SC_MODES], pramodesIndex[
N_PRA_MODES];
int					backgrounding = 0;
short				currentProgress = -1;

Boolean				done = false, suspended = false, fileOpen = false, fileUnknown = tr
ue;
Boolean				allFiles = true, printFileWhenOpened = false;
Boolean				appendFileTypeToTitle = true, showKernelMessages = false;
Boolean				soundEffects = true, alertSoundWhenDone = false, beepOnNextUpdate =
 false;
Boolean				threadsCapable = false, backgroundingEnabled = false;
Boolean				memoryAlreadyLow = false;
short				plotSize = matchWindowItem, currentResolution = 72;

long				processorType, fpuType;

StandardFileReply	reply;	

THPrint				printRecord;
TPPrPort			printPort;

Str255				positionString, statusString, localFilename, localTimeRangeString, l
ocalFileTypeString;
Str255				spacecraftMode, praMode, plotMode;

RGBColor			blackRGB    = {     0,     0,     0 };
RGBColor			whiteRGB    = { 65535, 65535, 65535 };
RGBColor			redRGB      = { 65535,     0,     0 };
RGBColor			greenRGB    = {     0, 65535,     0 };
RGBColor			blueRGB     = {     0,     0, 65535 };

RGBColor			validRGB    = { 65535, 65535, 65535 };	// color for valid data
RGBColor			ignoredRGB  = { 65535,     0,     0 };	// color for ignored data
RGBColor			dkgreenRGB  = {     0, 49344,     0 };	// dark green
RGBColor			bkgrayRGB   = { 52428, 52428, 52428 };	// standard 
RGBColor			lngrayRGB   = { 30583, 30583, 30583 };	// standard, control drop-sh
adow
RGBColor			offwhiteRGB = { 61166, 61166, 61166 };	// standard, non-active cont
rols
RGBColor			grayRGB     = { 16448, 16448, 16448 };	// standard, progress bar

RGBColor			tingeArrayRGB[16];

mac_mode*			mmode;

/*****************************************************************************
***********************************************/
/*****************************************************************************
***********************************************/
/**  Kernel Interface                                         ****************
***********************************************/
/*****************************************************************************
***********************************************/
/*****************************************************************************
***********************************************/

/**************************************************************/
/*  Constructor and Destructor                                */
/**************************************************************/

mac_mode::mac_mode(const double rev_nr)
{ 
	InitGraf((Ptr)&qd.thePort);
	InitFonts();
	InitWindows();
	InitMenus();
	TEInit();
	InitDialogs((ResumeProcPtr)0);
	InitCursor();
	MaxApplZone();
	versionNumber = rev_nr;
}

mac_mode::~mac_mode(void)
{
	ExitToShell();
}

/**************************************************************/
/*  Override Member Functions                                 */
/**************************************************************/

void mac_mode::verbose(DREstring message)
{
	Str255 theMessage;
	BlockMove(message, theMessage, maxStringLength);
	c2pstr((char*)theMessage);
	DisplayKernelMessage(theMessage, blueRGB);
}

void mac_mode::error(DREstring message)
{
	GDHandle saveDevice;
	CGrafPtr savePort;
	GetGWorld(&savePort, &saveDevice);
	SetGWorld((CGrafPtr)mainWindow, currentDevice);
	Str255 theMessage;
	BlockMove(message, theMessage, maxStringLength);
	c2pstr((char*)theMessage);
	ParamText(theMessage, "\p", "\p", "\p.");
	Alert(genericStopAlertID, 0L);
	SetGWorld(savePort, saveDevice);
}

void mac_mode::display_status(DREstring& msg)
{
	GDHandle saveDevice;
	CGrafPtr savePort;
	GetGWorld(&savePort, &saveDevice);
	SetGWorld((CGrafPtr)mainWindow, currentDevice);
	if ((msg < 1) || (msg >= 5))
	{
		Str255 theMessage;
		BlockMove(msg, theMessage, maxStringLength);
		c2pstr((char*)theMessage);
		DisplayKernelMessage(theMessage, dkgreenRGB);
	}
	else
	{
		BlockMove(msg, positionString, maxStringLength);
		c2pstr((char*)positionString);
		DrawToolbar();
	}
	SetGWorld(savePort, saveDevice);
}

void mac_mode::clear_status(void)
{
	DrawProgressBar(100);
}

void mac_mode::busy(DREstring& message)
{
	Str255 theMessage;
	BlockMove(message, theMessage, maxStringLength);
	c2pstr((char*)theMessage);
	DisplayKernelMessage(theMessage, redRGB);
}

void mac_mode::unbusy(void)
{
	DrawProgressBar(100);
}

void mac_mode::display_progress(const int percentageDone)
{
	DrawProgressBar(percentageDone);
}

void mac_mode::undisplay_progress(void)
{
	DrawProgressBar(100);
}

void mac_mode::execute(void)
{
	if (SetUpInterface() && Personalize())
		while(!done)
			HandleEvent();
}

/*****************************************************************************
***********************************************/
/*****************************************************************************
***********************************************/
/**  Macintosh User Interface                                 ****************
***********************************************/
/*****************************************************************************
***********************************************/
/*****************************************************************************
***********************************************/

/*****************************************************************************
***********************************************/
/*  Routines to synchronize local and global variables        ****************
***********************************************/
/*****************************************************************************
***********************************************/

void mac_mode::InitializeLocals(void)
{
	FileTypeSubmenu(File_type+1, false);
	localFile_record_length		= File_record_length;
	PlotModeSubmenu(Tplotmode, false);
	SpacecraftModeSubmenu(Current_sc_mode, false);
	PRAModeSubmenu(Current_pra_mode, false);

	GetIndString(localFilename, miscStringsID, filenameStringIndex);
	GetIndString(localTimeRangeString, miscStringsID, notAvailableStringIndex);
	GetIndString(positionString, miscStringsID, notApplicableStringIndex);
	localComment[0] = 0;
	
	localYear					= 0;
	localDay					= 0;
	localHour					= 0;
	localMinute					= 0;
	localStart_channel			= Start_channel;
	localEnd_channel			= End_channel;
	localDuration				= Duration;
	localBrightness				= Brightness;
	localSaturation				= Saturation;

	localStart_tomplot_channel	= Start_tomplot_channel;
	localN_tomplot_channels		= N_tomplot_channels;
	localTomPlotChannel			= 0;
	localTomPlotLower			= 0;
	localTomPlotUpper			= 255;

	localHigh_res_line			= 0;
	localHigh_res_datum			= 0;
	localHigh_res_channel		= High_res_channel;
	localGs2_n_data				= Gs2_n_data;
	localGs2_n_strips			= Gs2_n_strips;

	for (int index = 0; index < 256; index++)
		localValid_data[index]	= Valid_data[index];
}

void mac_mode::UpdateLocals(Boolean onlyUnchanged)
{
	if (onlyUnchanged)
	{
		if (!localStart_channelChanged && !localEnd_channelChanged && !localDuration
Changed)
		{
			localStart_channel = Start_channel;
			localEnd_channel = End_channel;
			localDuration = Duration;
		}
		if (!localStart_tomplot_channelChanged && !localN_tomplot_channelsChanged)
		{
			localStart_tomplot_channel = Start_tomplot_channel;
			localN_tomplot_channels = N_tomplot_channels;
		}
	}
	else if (fileOpen)
	{
		BlockMove((char*)(const char*)_time_range_string(), localTimeRangeString, ma
xStringLength);
		c2pstr((char*)localTimeRangeString);
		GetIndString(positionString, miscStringsID, notApplicableStringIndex);
		Str255 testString;
		GetIndString(testString, miscStringsID, filenameStringIndex);
		if (EqualString(localComment, testString, true, true))
			BlockMove(localFilename, localComment, maxStringLength);
		else
			localComment[0] = 0;
		localYear 				= Minimum_time.year();
		localDay 				= Minimum_time.day()+1;
		localHour 				= Minimum_time.hour();
		localMinute 			= Minimum_time.minute();
		Start_time				= Minimum_time;
		Start_time				-= timeclass(0, 0, 0, 0, Start_time.second());
		localHigh_res_line 		= 0;
		localHigh_res_datum 	= 0;
    	Current_phiex_position	= phiex_position(localHigh_res_line, localHigh_res
_datum);
	}
	else if (!fileOpen)
	{
		GetIndString(localFilename, miscStringsID, filenameStringIndex);
		GetIndString(localTimeRangeString, miscStringsID, notAvailableStringIndex);
		GetIndString(positionString, miscStringsID, notApplicableStringIndex);
		localComment[0] = 0;
	}
}

void mac_mode::SetGlobals(void)
{
	File_type		 		= localFile_type;
	File_record_length		= localFile_record_length;
	Tplotmode        		= localTplotmode;
	if (localTplotmode < Spectral_modes)
		_plot_function = &operating_mode::display_spectral;
	else if (localTplotmode == RAWPLOT)
		_plot_function = &operating_mode::_rawplot;
	else if ((localTplotmode == UNBINNED_TOMPLOT) || (localTplotmode == BINNED_TO
MPLOT))
		_plot_function = &operating_mode::_tomplot;
	Current_sc_mode  		= localCurrent_sc_mode;
	Current_pra_mode 		= localCurrent_pra_mode;

	Start_channel    		= localStart_channel;
	End_channel      		= localEnd_channel;
	Duration         		= localDuration;
	Brightness       		= localBrightness;
	Saturation       		= localSaturation;
	
	Start_tomplot_channel	= localStart_tomplot_channel;
	N_tomplot_channels		= localN_tomplot_channels;

	High_res_channel		= localHigh_res_channel;
	Gs2_n_data				= localGs2_n_data;
	Gs2_n_strips			= localGs2_n_strips;

	for (int index = 0; index <= 255; index++)
		Valid_data[index] = localValid_data[index];

	p2cstr(localComment);
	Comment 				= (char*)localComment;
	c2pstr((char*)localComment);

	fixedTextSize			= localFixedTextSize;
	dataColor        		= localDataColor;
	backgroundColor  		= localBackgroundColor;		

	localStart_channelChanged = localEnd_channelChanged = localDurationChanged = 
false;
	localStart_tomplot_channelChanged = localN_tomplot_channelsChanged = false;
}

/*****************************************************************************
***********************************************/
/*  Routines to draw toolbar and status bar in main window    ****************
***********************************************/
/*****************************************************************************
***********************************************/

void mac_mode::SetUpFieldRecord(toolbarFieldRec* theField)
{
	Handle theVariableRecord = GetResource('VARI', theField->reference);		
	HLock(theVariableRecord);
	Ptr offset = (*theVariableRecord);
	theField->initial = *(long*)offset; offset += 4;
	theField->minimum = *(long*)offset; offset += 4;
	theField->maximum = *(long*)offset;	
	HUnlock(theVariableRecord);
	ReleaseResource(theVariableRecord);

	Boolean doingGS2LowRes = (localTplotmode == GS2_LOW_RES);

	theField->isString = false;
	theField->contents = (Ptr)0;
	theField->contentsChanged = 0;

	if (theField->reference == 1)
		theField->contents = (Ptr)localTimeRangeString;
	else if (theField->reference == 2)
		theField->contents = (Ptr)localFileTypeString;
	else if (theField->reference == 3)
		theField->contents = (Ptr)plotMode;
	else if (theField->reference == 4)
		theField->contents = (Ptr)spacecraftMode;
	else if (theField->reference == 5)
		theField->contents = (Ptr)praMode;
	else if (theField->reference == 6)
		theField->contents = (Ptr)&localStart_channel;
	else if (theField->reference == 7)
		theField->contents = (Ptr)&localEnd_channel;
	else if (theField->reference == 8)
		theField->contents = (Ptr)&localDuration;
	else if (theField->reference == 9)
		theField->contents = (Ptr)&localBrightness;
	else if (theField->reference == 10)
		theField->contents = (Ptr)&localSaturation;
	else if (theField->reference == 11)
		theField->contents = (Ptr)localComment;
	else if (theField->reference == 12)
		theField->contents = (Ptr)&localStart_tomplot_channel;
	else if (theField->reference == 13)
		theField->contents = (Ptr)&localN_tomplot_channels;
	else if (theField->reference == 14)
		theField->contents = (Ptr)&localTomPlotChannel;
	else if (theField->reference == 15)
		theField->contents = (Ptr)&localTomPlotLower;
	else if (theField->reference == 16)
		theField->contents = (Ptr)&localTomPlotUpper;
	else if (theField->reference == 17)
		theField->contents = (Ptr)&localHigh_res_channel;
	else if (theField->reference == 18)
		theField->contents = (Ptr)&localGs2_n_data;
	else if (theField->reference == 19)
		theField->contents = (Ptr)&localGs2_n_strips;
	else if (theField->reference == 20)
		theField->contents = (Ptr)positionString;
	else if (theField->reference == 21)
		theField->contents = (Ptr)&localYear;
	else if (theField->reference == 22)
		theField->contents = (Ptr)&localDay;
	else if (theField->reference == 23)
		theField->contents = (Ptr)&localHour;
	else if (theField->reference == 24)
		theField->contents = (Ptr)&localMinute;
	else if (theField->reference == 25)
		theField->contents = (Ptr)&localHigh_res_line;
	else if (theField->reference == 26)
		theField->contents = (Ptr)&localHigh_res_datum;
	else if (theField->reference == 27)
		theField->contents = (Ptr)&localFile_record_length;
	else if (theField->reference == firstButtonID)
		theField->contents = doingGS2LowRes || backgrounding ? (Ptr)-1 : (Ptr)0;
	else if (theField->reference == priorButtonID)
		theField->contents = doingGS2LowRes || backgrounding ? (Ptr)-1 : (Ptr)0;
	else if (theField->reference == replotButtonID)
		theField->contents = backgrounding ? (Ptr)-1 : (Ptr)0;
	else if (theField->reference == nextButtonID)
		theField->contents = doingGS2LowRes || backgrounding ? (Ptr)-1 : (Ptr)0;
	else if (theField->reference == lastButtonID) 
		theField->contents = doingGS2LowRes || backgrounding ? (Ptr)-1 : (Ptr)0;
	else if (theField->reference == setButtonID)
		theField->contents = backgrounding == plotting ? (Ptr)-1 : (Ptr)0;

	if (theField->reference == 6)
		theField->contentsChanged = &localStart_channelChanged;
	else if (theField->reference == 7)
		theField->contentsChanged = &localEnd_channelChanged;
	else if (theField->reference == 8)
		theField->contentsChanged = &localDurationChanged;
	else if (theField->reference == 12)
		theField->contentsChanged = &localStart_tomplot_channelChanged;
	else if (theField->reference == 13)
		theField->contentsChanged = &localN_tomplot_channelsChanged;
}

void mac_mode::DrawToolbar(void)
{
	short toolbarID;
	if (toolbarMode == timeRangeBar)
		toolbarID = localTplotmode < High_rate_modes ? timeRangeGS2BarID : timeRange
NormalBarID;
	else if (toolbarMode == modesBar)
		toolbarID = localTplotmode < High_rate_modes ? modesGS2BarID : modesNormalBa
rID;
	else if (toolbarMode == plotRangeBar)
	{
		if (localTplotmode < Spectral_modes)
			toolbarID = plotRangeNormalBarID;
		else if (localTplotmode == UNBINNED_TOMPLOT || localTplotmode == BINNED_TOMP
LOT)
			toolbarID = plotRangeTomPlotBarID;
		else if (localTplotmode == GS2_HIGH_RES)
			toolbarID = plotRangeGS2HighResBarID;
		else
			toolbarID = plotRangeEmptyBarID;
	}
	else if (toolbarMode == levelsBar)
		toolbarID = localTplotmode < Spectral_modes ? levelsNormalBarID : levelsEmpt
yBarID;
	else if (toolbarMode == dataRangeBar)
	{
		if (localTplotmode < Spectral_modes)
			toolbarID = dataRangeNormalBarID;
		else if (localTplotmode == UNBINNED_TOMPLOT || localTplotmode == BINNED_TOMP
LOT)
			toolbarID = dataRangeTomPlotBarID;
		else
			toolbarID = dataRangeEmptyBarID;
	}
	else if (toolbarMode == commentBar)
		toolbarID = commentBarID;

	SetPort(mainWindow);
	if (((WindowPeek)mainWindow)->hilited)
	{
		Handle theToolbarRecord = GetResource('TBAR', toolbarStubID);
		Handle theToolbarFields = GetResource('TBAR', toolbarID);
		
		HLock(theToolbarFields);
		short fieldCount = *(*theToolbarFields+1);
		HandAndHand(theToolbarFields, theToolbarRecord);
		HUnlock(theToolbarFields);
		ReleaseResource(theToolbarFields);
		
		HLock(theToolbarRecord);
		short toolbarStubCount = *(*theToolbarRecord+1);
		Ptr offset = (*theToolbarRecord);

		toolbarFieldCount = toolbarStubCount+fieldCount;

		short positionH = -1;
		for(short index = 0; index < toolbarFieldCount; index++)
		{
			if ((index == 0) || (index == toolbarStubCount))
				offset += 2;

			Byte titleLength  = (*(Byte*)offset)+1;
			BlockMove(offset, toolbarField[index].titleString, titleLength); offset += 
titleLength;
			Byte unitsLength  = (*(Byte*)offset)+1;
			BlockMove(offset, toolbarField[index].unitsString, unitsLength); offset += 
unitsLength;
			toolbarField[index].length       	= *(short*)offset; offset += 2;
			toolbarField[index].flags       	= *(Byte*) offset; offset += 1;
			toolbarField[index].popupID			= *(short*)offset; offset += 2;
			toolbarField[index].reference		= *(short*)offset; offset += 2;
			toolbarField[index].step			= *(long*) offset; offset += 4;
			toolbarField[index].delay			= *(long*) offset; offset += 4;

			SetUpFieldRecord(&toolbarField[index]);
			DrawEditField(positionH, &toolbarField[index], editField == index);

			if (toolbarField[index].flags & isRangeMask)
				DrawRangeField(toolbarField[index].editBounds, 0, 255);
				
			positionH = toolbarField[index].bounds.right-1;
		}
		HUnlock(theToolbarRecord);
		ReleaseResource(theToolbarRecord);

		UpdateEditField();
	
		Rect fillRemainderRect;
		SetRect(&fillRemainderRect, toolbarField[index-1].bounds.right-1, -1, mainWi
ndow->portRect.right+2, 16);
		ErasePanelOffwhite(fillRemainderRect);
	}
	else
		ErasePanel(headerRect);
}

void mac_mode::DrawStatusbar(void)
{
	SetPort(mainWindow);
	DrawPanel(statusRect, statusString, !((WindowPeek)mainWindow)->hilited);
	DrawProgressBar(currentProgress);
}

/*****************************************************************************
***********************************************/
/*  Routine to display message in Kernel Messages window      ****************
***********************************************/
/*****************************************************************************
***********************************************/

void mac_mode::DisplayKernelMessage(Str255 theMessage, RGBColor theColor)
{
	for(short index = (N_KERNEL_MESSAGES-1); index >= 1; index--)
	{
		BlockMove(kernelMessage[index-1], kernelMessage[index], maxStringLength);
		kernelMessageColor[index] = kernelMessageColor[index-1];
	}
	BlockMove(theMessage, kernelMessage[0], maxStringLength);
	kernelMessageColor[0] = theColor;
	if (showKernelMessages)
	{
		GDHandle saveDevice;
		CGrafPtr savePort;
		GetGWorld(&savePort, &saveDevice);
		SetGWorld((CGrafPtr)kernelWindow, currentDevice);
		RgnHandle updateRgn = NewRgn();
		ScrollRect(&kernelWindow->portRect, 0, -10, updateRgn);
		DisposeRgn(updateRgn);
		MoveTo(kernelWindow->portRect.left+3, kernelWindow->portRect.bottom-2);
		RGBForeColor(&theColor);
		TextFont(geneva);
		TextSize(9);
		DrawString(theMessage);
		SetGWorld(savePort, saveDevice);
	}
}

/*****************************************************************************
***********************************************/
/*  Routine to resize the GWorld if necessary                 ****************
***********************************************/
/*****************************************************************************
***********************************************/

void mac_mode::ResizeOffscreen(void)
{
	if (plotSize == 1)
		return;
	int width, height;
	if (plotSize == 2)
	{
		width = mainWindow->portRect.right-scrollbarWidth; 
		height = mainWindow->portRect.bottom-scrollbarWidth-toolbarHeight;
	}
	else if (plotSize == 3)
	{
		width = (**printRecord).prInfo.rPage.right;
		height = (**printRecord).prInfo.rPage.bottom;
	}
	if ((width != Offscreen->usable_right()) || (height != Offscreen->usable_bott
om()))
	{
		Offscreen->resize_usable(0, 0, width, height, 0, 0);
		UpdateScrollBars();
	}
}

/*****************************************************************************
***********************************************/
/*  Routines to handle TextEdit toolbar fields                ****************
***********************************************/
/*****************************************************************************
***********************************************/

void mac_mode::NewEditField(short theField, Point thePt, Boolean preSelected)
{
	if (!(toolbarField[theField].flags & editableMask))
		return;
	if (editField)
		DisposeEditField(true);
	editField = theField;
	SetPort(mainWindow);
	RGBColor foregroundRGB, backgroundRGB;
	SaveColors(foregroundRGB, backgroundRGB);
	RGBForeColor(&tingeArrayRGB[0]);
	RGBBackColor(&bkgrayRGB);
	Rect theRect = toolbarField[theField].editBounds;
	InsetRect(&theRect, 0, 2);
	editFieldRecord = TENew(&theRect, &theRect);
	TEAutoView(true, editFieldRecord);
	Str255 theString;
	if (toolbarField[theField].flags & numericOnlyMask)
	{
		if ((toolbarField[theField].flags & zeroIsAllMask) && (*(long*)toolbarField[
theField].contents == 0))
		{
			theString[0] = 0;
			DrawToolbar();
		}
		else
			NumToString(*(long*)toolbarField[theField].contents, theString);
	}
	else
	{
		if ((toolbarField[theField].flags & zeroIsAllMask) && (*(char*)toolbarField[
theField].contents == 0))
		{
			theString[0] = 0;
			DrawToolbar();
		}
		else
			BlockMove(toolbarField[theField].contents, theString, maxStringLength);
	}
	TESetText((Ptr)&theString[1], (long)theString[0], editFieldRecord);
	if (preSelected)
		TESetSelect(0, 32767, editFieldRecord);
	TEUpdate(&theRect, editFieldRecord);
	TEActivate(editFieldRecord);
	if (!preSelected)
		TEClick(thePt, false, editFieldRecord);
	RestoreColors(foregroundRGB, backgroundRGB);
	UpdateMenuItems(0);
}

void mac_mode::DisposeEditField(Boolean storeResult)
{
	if (!editField)
		return;
	SetPort(mainWindow);
	RGBColor foregroundRGB, backgroundRGB;
	SaveColors(foregroundRGB, backgroundRGB);
	RGBForeColor(&tingeArrayRGB[0]);
	RGBBackColor(&bkgrayRGB);
	TEDeactivate(editFieldRecord);
	if (storeResult)
	{
		Str255 theString;
		GetIText((**editFieldRecord).hText, theString);
		if (toolbarField[editField].flags & numericOnlyMask)
		{
			long theResult;
			StringToNum(theString, &theResult);
			if ((toolbarField[editField].flags & zeroIsAllMask) && (theResult <= 0))
			{
				*(long*)toolbarField[editField].contents = 0;
				InvalRect(&toolbarField[editField].editBounds);
			}
			else if (theResult < toolbarField[editField].minimum)
			{
				*(long*)toolbarField[editField].contents = toolbarField[editField].minimum
;
				IndexedVariableError(toolbarField[editField].reference, smallStringIndex);

			}
			else if (theResult > toolbarField[editField].maximum)
			{
				*(long*)toolbarField[editField].contents = toolbarField[editField].maximum
;
				IndexedVariableError(toolbarField[editField].reference, largeStringIndex);

			}
			else
				*(long*)toolbarField[editField].contents = theResult;
		}
		else
		{
			BlockMove(theString, toolbarField[editField].contents, maxStringLength);
			if ((toolbarField[editField].flags & zeroIsAllMask) && (theString[0] == 0))

				InvalRect(&toolbarField[editField].editBounds);
		}
		if (toolbarField[editField].contentsChanged != 0)
			*toolbarField[editField].contentsChanged = true;
		if (toolbarField[editField].flags & hasButtonsMask)
		{
			Rect upDownRect;
			SetRect(&upDownRect, toolbarField[editField].bounds.right-12, -1, toolbarFi
eld[editField].bounds.right, 15);
			InvalRect(&upDownRect);
		}
	}
	TEDispose(editFieldRecord);
	RestoreColors(foregroundRGB, backgroundRGB);
	editField = 0;
	UpdateMenuItems(0);
}

void mac_mode::UpdateEditField(void)
{
	if (!editField)
		return;
	SetPort(mainWindow);
	RGBColor foregroundRGB, backgroundRGB;
	SaveColors(foregroundRGB, backgroundRGB);
	RGBForeColor(&tingeArrayRGB[0]);
	RGBBackColor(&bkgrayRGB);
	TEUpdate(&(**editFieldRecord).destRect, editFieldRecord);
	RestoreColors(foregroundRGB, backgroundRGB);
}

void mac_mode::ActivateEditField(Boolean activating)
{
	if (!editField)
		return;
	SetPort(mainWindow);
	RGBColor foregroundRGB, backgroundRGB;
	SaveColors(foregroundRGB, backgroundRGB);
	RGBForeColor(&tingeArrayRGB[0]);
	RGBBackColor(&bkgrayRGB);
	if (activating)
		TEActivate(editFieldRecord);
	else
		TEDeactivate(editFieldRecord);
	RestoreColors(foregroundRGB, backgroundRGB);
}

void mac_mode::HandleEditFieldIdle(void)
{
	if (!editField || suspended)
		return;
	RGBColor foregroundRGB, backgroundRGB;
	SaveColors(foregroundRGB, backgroundRGB);
	RGBForeColor(&tingeArrayRGB[0]);
	RGBBackColor(&bkgrayRGB);
	TEIdle(editFieldRecord);
	RestoreColors(foregroundRGB, backgroundRGB);
}

void mac_mode::HandleEditFieldEditCommands(short theItem)
{
	RGBColor foregroundRGB, backgroundRGB;
	SaveColors(foregroundRGB, backgroundRGB);
	RGBForeColor(&tingeArrayRGB[0]);
	RGBBackColor(&bkgrayRGB);
	if (theItem == cutItem)
		TECut(editFieldRecord);
	else if (theItem == copyItem)
		TECopy(editFieldRecord);
	else if (theItem == pasteItem)
		TEPaste(editFieldRecord);
	else if (theItem == clearItem)
		TEDelete(editFieldRecord);
	else if (theItem == selectAllItem)
		TESetSelect(0, 32767, editFieldRecord);
	RestoreColors(foregroundRGB, backgroundRGB);
}

void mac_mode::HandleEditFieldMouseDown(short theField, Point thePt, short mod
ifiers)
{
	if (theField != editField)
		NewEditField(theField, thePt, false);
	else
	{
		RGBColor foregroundRGB, backgroundRGB;
		SaveColors(foregroundRGB, backgroundRGB);
		RGBForeColor(&tingeArrayRGB[0]);
		RGBBackColor(&bkgrayRGB);
		TEActivate(editFieldRecord);
		TEUpdate(&(**editFieldRecord).destRect, editFieldRecord);
		if (modifiers & shiftKey)
			TEClick(thePt, true, editFieldRecord);
		else
			TEClick(thePt, false, editFieldRecord);
		RestoreColors(foregroundRGB, backgroundRGB);
	}
}

void mac_mode::HandleEditFieldTab(short modifiers)
{
	short nextField = editField;
	do
	{
		if (modifiers & shiftKey)
			nextField = (nextField == 0) ? toolbarFieldCount-1 : nextField-1;
		else
			nextField = (nextField == toolbarFieldCount-1) ? 0 : nextField+1;
		if (toolbarField[nextField].flags & editableMask)
		{
			Point dummyPt = { 0, 0 };
			NewEditField(nextField, dummyPt, true);
			return;
		}
	}
	while (nextField != editField);
}

void mac_mode::HandleEditFieldKeyDown(short theKey, short modifiers)
{
	if (theKey == 9)
		HandleEditFieldTab(modifiers);
	else if (editField)
	{
		RGBColor foregroundRGB, backgroundRGB;
		SaveColors(foregroundRGB, backgroundRGB);
		RGBForeColor(&tingeArrayRGB[0]);
		RGBBackColor(&bkgrayRGB);
		if ((theKey == 13) || (theKey == 3))
			DisposeEditField(true);
		else if (theKey == 27)
		{
			DisposeEditField(false);
			DrawToolbar();
		}
		else if (theKey < 32)
			TEKey(theKey, editFieldRecord);
		else if ((toolbarField[editField].flags & numericOnlyMask) && ((theKey < 48)
 || (theKey > 57)))
			IndexedStringError(infoAlertID, numericOnlyStringIndex);
		else
			TEKey(theKey, editFieldRecord);
		RestoreColors(foregroundRGB, backgroundRGB);
	}
}

void mac_mode::HandleEditFieldButtons(toolbarFieldRec* theField, Point thePt, 
Rect upRect, Rect downRect)
{
	DisposeEditField(true);
	RGBColor foregroundRGB, backgroundRGB;
	SaveColors(foregroundRGB, backgroundRGB);
	RGBForeColor(&tingeArrayRGB[0]);
	RGBBackColor(&bkgrayRGB);
	long* value = (long*)theField->contents;
	long min    = theField->minimum;
	long max    = theField->maximum;
	long step   = theField->step;
	long delay  = theField->delay;
	if (((*value+step) <= max) && TrackButton(thePt, upRect, upButtonID, oneSecon
dDelay, false))
	{
		if (theField->contentsChanged != 0)
			*theField->contentsChanged = true;
		if (*value == min)
			InvalRect(&downRect);
		DrawFieldContents(theField, (*value += step, true));
		while (((*value+step) <= max) && StillDown() && (TrackButton(thePt, upRect, 
upButtonID, delay, true) == 2))
			DrawFieldContents(theField, (*value += step, true));
		if (((*value+step) > max) && StillDown())
			PlaySoundEffect(mouseUpSoundID);
	}
	else if (((*value-step) >= min) && TrackButton(thePt, downRect, downButtonID,
 oneSecondDelay, false))
	{
		if (theField->contentsChanged != 0)
			*theField->contentsChanged = true;
		if (*value == max)
			InvalRect(&upRect);
		DrawFieldContents(theField, (*value -= step, true));
		while (((*value-step) >= min) && StillDown() && (TrackButton(thePt, downRect
, downButtonID, delay, true) == 2))
			DrawFieldContents(theField, (*value -= step, true));
		if (((*value-step) < min) && StillDown())
			PlaySoundEffect(mouseUpSoundID);
	}
	RestoreColors(foregroundRGB, backgroundRGB);
}

void mac_mode::HandleEditFieldPopup(toolbarFieldRec* theField, Point thePt)
{
	DisposeEditField(true);
	if (CountMItems(GetMHandle(theField->popupID)) != 1)
	{
		UpdateMenuItems(0);
		Point where;
		Boolean isPopupBelow = (theField->flags & popupBelowMask);
		if (isPopupBelow)
			SetPt(&where, theField->bounds.left+1, theField->bounds.bottom+1);
		else
		{
			SetPt(&where, theField->editBounds.left+1, theField->bounds.top+1);
			Str255 theString;
			if (theField->flags & numericOnlyMask)
				NumToString(*(long*)theField->contents, theString);
			else
				BlockMove(theField->contents, theString, maxStringLength);
			InsMenuItem(GetMHandle(theField->popupID), "\p-", 0);
			InsMenuItem(GetMHandle(theField->popupID), theString, 0);
		}
		PlaySoundEffect(mouseDownSoundID);
		LocalToGlobal(&where);
		long result = PopUpMenuSelect(GetMHandle(theField->popupID), where.v, where.
h, 1);
		if (!isPopupBelow)
		{
			DelMenuItem(GetMHandle(theField->popupID), 1);
			DelMenuItem(GetMHandle(theField->popupID), 1);
		}
		DoCommand(result, 0, !isPopupBelow);
	}
}

void mac_mode::HandleButtonMouseDown(toolbarFieldRec* theField, Point thePt)
{
	DisposeEditField(true);
	if (theField->contents == (Ptr)-1)
		return;
	if (TrackButton(thePt, theField->bounds, theField->reference, 0, false))
	{
		if (theField->reference == firstButtonID)
			PlotMenu(firstItem);
		else if (theField->reference == priorButtonID)
			PlotMenu(previousItem);
		else if (theField->reference == replotButtonID)
			PlotMenu(replotItem);
		else if (theField->reference == nextButtonID)
			PlotMenu(nextItem);
		else if (theField->reference == lastButtonID)
			PlotMenu(lastItem);
		else if (theField->reference == setButtonID)
			TomPlotRange();
	}
}
			
/**************************************************************/
/*  Routines to draw and handle ignored data toolbar          */
/**************************************************************/

void mac_mode::DrawRangeField(Rect theRect, int startValue, int endValue)
{
	if ((startValue > 255) || (endValue < 0))
		return;
	if (startValue < 0)
		startValue = 0;
	if (endValue > 255)
		endValue = 255;
	Rect borderRect = theRect;
	InsetRect(&borderRect, -1, 4);
	RGBForeColor(&blackRGB);
	FrameRect(&borderRect);
	for (int i = startValue; i <= endValue; i++)
	{
		RGBForeColor(localValid_data[i] ? &validRGB : &ignoredRGB);
		MoveTo(theRect.left+i, theRect.top+5);
		Line(0, 5);
	}
	RGBForeColor(&blackRGB);
}

void mac_mode::CursorInIgnore(int theField)
{
	SetPort(mainWindow);
	Point mousePt;
	GetMouse(&mousePt);
	if (PtInRect(mousePt, &toolbarField[theField].editBounds))
	{
		int currentIgnoreValue =
		LoWord(PinRect(&toolbarField[theField].editBounds, mousePt))-toolbarField[th
eField].editBounds.left;
		if (currentIgnoreValue != lastIgnoreValue)
		{
			lastIgnoreValue = currentIgnoreValue;
			toolbarField[theField+1].contents = (Ptr)&lastIgnoreValue;
			DrawFieldContents(&toolbarField[theField+1], true);
		}
	}
	else if (lastIgnoreValue != -1)
	{
		toolbarField[theField+1].contents = (Ptr)0;
		DrawFieldContents(&toolbarField[theField+1], true);
		lastIgnoreValue = -1;
	}
}

void mac_mode::HandleIgnore(Rect theRect, int theField, DialogPtr theDialog)
{
	Boolean hilited = false, validating;
	Point mousePt, lastPt = { 0, 0 };
	Rect hilitedRect;
	int initialValue, finalValue, origin = theRect.left;
	PlaySoundEffect(mouseDownSoundID);
	do
	{
		GetMouse(&mousePt);
		if (theField == 0)
			IgnoredDataIdleProcedure(theDialog, mousePt);
		else	
			CursorInIgnore(theField);
		if (!hilited && PtInRect(mousePt, &theRect))
		{
			initialValue = mousePt.h-origin;
			if (initialValue > 255) initialValue = 255;
			else if (initialValue < 0) initialValue = 0;
			validating = !localValid_data[initialValue];
			hilited = true;
		}
		if (hilited && PtInRect(mousePt, &theRect))
		{
			if (!EqualPt(mousePt, lastPt))
			{
				finalValue = mousePt.h-origin;
				if (finalValue > 255) finalValue = 255;
				else if (finalValue < 0) finalValue = 0;
				if (initialValue <= finalValue)
				{
					SetRect(&hilitedRect, origin+initialValue, theRect.top+5, origin+finalVal
ue+1, theRect.bottom-5);
					DrawRangeField(theRect, 0, initialValue-1);
					DrawRangeField(theRect, finalValue+1, 255);
				}
				else
				{
					SetRect(&hilitedRect, origin+finalValue, theRect.top+5, origin+initialVal
ue+1, theRect.bottom-5);
					DrawRangeField(theRect, 0, finalValue-1);
					DrawRangeField(theRect, initialValue+1, 255);
				}
				RGBForeColor(validating ? &validRGB : &ignoredRGB);
				PaintRect(&hilitedRect);
				RGBForeColor(&blackRGB);
				lastPt = mousePt;
			}
		}
		else if (hilited && !PtInRect(mousePt, &theRect))
			DrawRangeField(theRect, 0, 255);
	}
	while (Button());
	if (PtInRect(mousePt, &theRect))
	{
		if (initialValue <= finalValue)
			for (int setValid = initialValue; setValid <= finalValue; setValid++)
				localValid_data[setValid] = validating;
		else
			for (setValid = finalValue; setValid <= initialValue; setValid++)
				localValid_data[setValid] = validating;
	}
	PlaySoundEffect(mouseUpSoundID);
	DrawRangeField(theRect, 0, 255);
}

/*****************************************************************************
***********************************************/
/*  Routines to handle clicks in toolbar and statusbar        ****************
***********************************************/
/*****************************************************************************
***********************************************/

void mac_mode::HandleToolbarMouseDown(Point thePt, short modifiers)
{
	for (short index = 0; index < toolbarFieldCount; index++)
	{
		if (PtInRect(thePt, &toolbarField[index].bounds))
		{
			Boolean isButton = (toolbarField[index].flags & isButtonMask);
			if (isButton)
			{
				HandleButtonMouseDown(&toolbarField[index], thePt);
				return;
			}
			Boolean editable = (toolbarField[index].flags & editableMask);
			Boolean isRange = (toolbarField[index].flags & isRangeMask);
			if (editable && PtInRect(thePt, &toolbarField[index].editBounds))
			{
				HandleEditFieldMouseDown(index, thePt, modifiers);
				return;
			}
			DisposeEditField(true);
			if (isRange && PtInRect(thePt, &toolbarField[index].editBounds))
			{
				HandleIgnore(toolbarField[index].editBounds, index, 0);
				return;
			}
			Boolean hasButtons = (toolbarField[index].flags & hasButtonsMask);
			Rect upRect, downRect;
			SetRect(&upRect, toolbarField[index].bounds.right-12, -1, toolbarField[inde
x].bounds.right, 8);
			SetRect(&downRect, toolbarField[index].bounds.right-12, 6, toolbarField[ind
ex].bounds.right, 15);
			if (hasButtons && (PtInRect(thePt, &upRect) || PtInRect(thePt, &downRect)))

			{
				HandleEditFieldButtons(&toolbarField[index], thePt, upRect, downRect);
				return;
			}
			Boolean hasPopup = (toolbarField[index].flags & hasPopupMask);
			if (hasPopup)
			{
				HandleEditFieldPopup(&toolbarField[index], thePt);
				return;
			}
		}
	}
}

void mac_mode::HandleStatusbarMouseDown(Point thePt, short modifiers)
{
	DisposeEditField(true);
	PlaySoundEffect(mouseDownSoundID);
	if (modifiers & cmdKey)
		DisplayOffscreenInfo();
	else
		DisplayMemoryBar();
	TimeDelay(twoSecondDelay, true);
	DrawStatusbar();
}

/*****************************************************************************
***********************************************/
/*  Routines to update and activate windows and scrollbars    ****************
***********************************************/
/*****************************************************************************
***********************************************/

void mac_mode::UpdateWindow(WindowPtr theWindow)
{
	AuxWinHandle auxRecord;
	GetAuxWin(theWindow, &auxRecord);
	RGBColor tingeLightRGB = (**(**auxRecord).awCTable).ctTable[11].rgb;
	RGBColor tingeDarkRGB  = (**(**auxRecord).awCTable).ctTable[12].rgb;
	if ((tingeLightRGB.red == 0) && (tingeLightRGB.green == 0) && (tingeLightRGB.
blue == 0))
	{
		offwhiteRGB.red = offwhiteRGB.green = offwhiteRGB.blue = 65535;
		lngrayRGB.red = lngrayRGB.green = lngrayRGB.blue = 65535;
		bkgrayRGB.red = bkgrayRGB.green = bkgrayRGB.blue = 65535;
		for(short shade = 0; shade < 15; shade++)
			tingeArrayRGB[shade].red = tingeArrayRGB[shade].green = tingeArrayRGB[shade
].blue = 0;
		tingeArrayRGB[15].red = tingeArrayRGB[15].green = tingeArrayRGB[15].blue = 6
5535;
	}
	else
	{
		offwhiteRGB.red = offwhiteRGB.green = offwhiteRGB.blue = 61166;
		lngrayRGB.red = lngrayRGB.green = lngrayRGB.blue = 30583;
		bkgrayRGB.red = bkgrayRGB.green = bkgrayRGB.blue = 52428;
		for(short shade = 0; shade < 16; shade++)
		{
			tingeArrayRGB[shade].red   = (tingeLightRGB.red   - tingeDarkRGB.red)   * s
hade/15 + tingeDarkRGB.red;
			tingeArrayRGB[shade].green = (tingeLightRGB.green - tingeDarkRGB.green) * s
hade/15 + tingeDarkRGB.green;
			tingeArrayRGB[shade].blue  = (tingeLightRGB.blue  - tingeDarkRGB.blue)  * s
hade/15 + tingeDarkRGB.blue;
		}
	}
	if ((theWindow == mainWindow) && (backgrounding == plotting))
	{
		SetPort(mainWindow);
		InvalRect(&mainWindowContents);
	}
	BeginUpdate(theWindow);
	if (theWindow == mainWindow)
	{
		ShowGrowBox(mainWindow, toolbarHeight);
		DrawToolbar();
		DrawStatusbar();
		DrawControls(mainWindow);
		Offscreen->update();
		if (beepOnNextUpdate)
			SysBeep(1);
		beepOnNextUpdate = false;
	}
	else if (theWindow == kernelWindow)
	{
		SetPort(kernelWindow);
		TextFont(geneva);
		TextSize(9);
		for (short index = 0; index < N_KERNEL_MESSAGES; index++)
		{
			MoveTo(kernelWindow->portRect.left+3, kernelWindow->portRect.bottom-2-10*in
dex);
			RGBForeColor(&kernelMessageColor[index]);
			DrawString(kernelMessage[index]);
		}
	}
	EndUpdate(theWindow);
}

void mac_mode::ActivateWindow(WindowPtr theWindow, Boolean activating)
{
	if (theWindow != mainWindow)
		return;
	Rect hScrollRect = (**hScroll).contrlRect;
	Rect vScrollRect = (**vScroll).contrlRect;
	InsetRect(&hScrollRect, 1, 1);
	InsetRect(&vScrollRect, 1, 1);
	Rect growRect = mainWindow->portRect;
	growRect.left = growRect.right - scrollbarWidth + 1;
	growRect.top = growRect.bottom - scrollbarWidth + 1;
	SetPort(theWindow);
	if (activating)
	{
		(**hScroll).contrlVis = (**vScroll).contrlVis = 255;
		InvalRect(&headerRect);
		InvalRect(&hScrollRect);
		InvalRect(&vScrollRect);
		InvalRect(&statusRect);
		InvalRect(&growRect);
		UpdateWindow(theWindow);
		ActivateEditField(true);
	}
	else
	{
		ActivateEditField(false);
		(**hScroll).contrlVis = (**vScroll).contrlVis = 0;
		RGBBackColor(&whiteRGB);
		EraseRect(&hScrollRect);
		EraseRect(&vScrollRect);
		EraseRect(&growRect);
		InvalRect(&headerRect);
		InvalRect(&statusRect);
		UpdateWindow(theWindow);
	}
	UpdateMenuItems(0);
}

void mac_mode::UpdateScrollBars(void)
{
	mainWindowContents = mainWindow->portRect;
	mainWindowContents.top += toolbarHeight;
	mainWindowContents.bottom -= scrollbarWidth;
	mainWindowContents.right -= scrollbarWidth;
	SetRect(&headerRect, -1, -1, mainWindow->portRect.right+2, toolbarHeight);
	SetRect(&statusRect, -1, mainWindow->portRect.bottom-scrollbarWidth, 201, mai
nWindow->portRect.bottom+1);

	Rect hScrollRect = mainWindow->portRect;
	hScrollRect.top = hScrollRect.bottom-scrollbarWidth;
	hScrollRect.right -= 14;
	hScrollRect.left += statusbarWidth;
	hScrollRect.bottom += 1;
	if (!hScroll)
		hScroll = NewControl(mainWindow, &hScrollRect, "\p", false, 0, 0, 0, scrollB
arProc, 0L);
	else
	{
		HideControl(hScroll);
		(**hScroll).contrlRect = hScrollRect;
	}
	short hMax = Offscreen->usable_right() - mainWindowContents.right;
	HiliteControl(hScroll, (hMax <= 0) ? -1 : 0);
	SetCtlMax(hScroll, hMax);
	if (hMax <= 0)
		offset.h = hMax/2;
	else if (offset.h > hMax)
		offset.h = hMax;
	else if (offset.h <= 0)
		SetCtlValue(hScroll, offset.h = 0);
		
	Rect vScrollRect = mainWindow->portRect;
	vScrollRect.top += 15;
	vScrollRect.right += 1;
	vScrollRect.left = vScrollRect.right-16;
	vScrollRect.bottom -= 14;
	if (!vScroll)
		vScroll = NewControl(mainWindow, &vScrollRect, "\p", false, 0, 0, 0, scrollB
arProc, 0L);
	else
	{
		HideControl(vScroll);
		(**vScroll).contrlRect = vScrollRect;
	}
	short vMax = Offscreen->usable_bottom() - (mainWindowContents.bottom-mainWind
owContents.top);
	HiliteControl(vScroll, (vMax <= 0) ? -1 : 0);
	SetCtlMax(vScroll, vMax);
	if (vMax <= 0)
		offset.v = vMax/2;
	else if (offset.v > vMax)
		offset.v = vMax;
	else if (offset.v <= 0)
		SetCtlValue(vScroll, offset.v = 0);

	ShowControl(hScroll);
	ShowControl(vScroll);
}

/*****************************************************************************
***********************************************/
/*  Routines to handle dialogs                                ****************
***********************************************/
/*****************************************************************************
***********************************************/

void mac_mode::SetValues(DialogPtr theDialog, Boolean defaults)
{
	short  itemType;
	Handle itemHandle;
	Rect   itemRect;
	Str255 itemString;

	for (short theItem = 0; theItem < dialogFieldCount; theItem++)
	{
		GetDItem(theDialog, theItem+1, &itemType, &itemHandle, &itemRect);
		if (dialogField[theItem].reference == -1)
			HiliteControl((ControlHandle)itemHandle, 255);
		else if (dialogField[theItem].reference == outlineButtonProcID)
			SetDItem(theDialog, theItem+1, itemType, (Handle)OutlineButton, &itemRect);

		else if (dialogField[theItem].reference == dottedLineProcID)
			SetDItem(theDialog, theItem+1, itemType, (Handle)DottedLine, &itemRect);
		else if (dialogField[theItem].reference == checkBoxID)
			CheckBox(theDialog, theItem+1, false, defaults);
		else if (dialogField[theItem].reference == ignoredDataProcID)
		{
			SetDItem(theDialog, theItem+1, itemType, (Handle)IgnoredDataUserItem, &item
Rect);
			if (defaults)
			{
				localValid_data[0] = false;
				for (int index = 1; index <= 254; index++)
					localValid_data[index] = true;
				localValid_data[255] = false;
				SetPort(theDialog);
				InvalRect(&itemRect);
			}
		}
		else if (defaults && (dialogField[theItem].reference > 20) && (dialogField[t
heItem].reference < 25))
		{
			if (dialogField[theItem].reference == 21)
				NumToString(Minimum_time.year(), itemString);
			if (dialogField[theItem].reference == 22)
				NumToString(Minimum_time.day()+1, itemString);
			if (dialogField[theItem].reference == 23)
				NumToString(Minimum_time.hour(), itemString);
			if (dialogField[theItem].reference == 24)
				NumToString(Minimum_time.minute(), itemString);
			SetIText(itemHandle, itemString);
		}
		else if ((dialogField[theItem].reference > 0) && (dialogField[theItem].refer
ence < 100))
		{
			if (dialogField[theItem].reference == 11)
				BlockMove(defaults ? (Ptr)localFilename : dialogField[theItem].contents, i
temString, maxStringLength);
			else if (dialogField[theItem].reference == 1)
				BlockMove(dialogField[theItem].contents, itemString, maxStringLength);
			else
				NumToString(defaults ? dialogField[theItem].initial : *(long*)dialogField[
theItem].contents, itemString);
			SetIText(itemHandle, itemString);
		}
	}
	if (dialogField[4].reference != ignoredDataProcID)
		SelIText(theDialog, 5, 0, 32767);
}

void mac_mode::GetValues(DialogPtr theDialog)
{
	short  itemType;
	Handle itemHandle;
	Rect   itemRect;
	Str255 itemString;

	for (short theItem = 0; theItem < dialogFieldCount; theItem++)
	{
		if (dialogField[theItem].reference == checkBoxID)
		{
			GetDItem(theDialog, theItem+1, &itemType, &itemHandle, &itemRect);
			if (GetCtlValue((ControlHandle)itemHandle))
			{
				GetDItem(theDialog, theItem+2, &itemType, &itemHandle, &itemRect);
				itemString[0] = 0;
				SetIText(itemHandle, itemString);
			}
		}
 		else if ((dialogField[theItem].reference > 0) && (dialogField[theItem].refe
rence < 100))
		{
			GetDItem(theDialog, theItem+1, &itemType, &itemHandle, &itemRect);
			GetIText(itemHandle, itemString);
			if (dialogField[theItem].reference == 11)
				BlockMove(itemString, dialogField[theItem].contents, maxStringLength);
			else if (dialogField[theItem].reference != 1)
			{
				long tempValue;
				StringToNum(itemString, &tempValue);
				if (tempValue < dialogField[theItem].minimum)
				{
					tempValue = dialogField[theItem].minimum;
					IndexedVariableError(dialogField[theItem].reference, smallStringIndex);
				}
				else if (tempValue > dialogField[theItem].maximum)
				{
					tempValue = dialogField[theItem].maximum;
					IndexedVariableError(dialogField[theItem].reference, largeStringIndex);
				}
				*(long*)dialogField[theItem].contents = tempValue;
			}
		}
	}
}

Boolean mac_mode::HandleDialog(short theDialogID)
{
	Handle theDialogRecord = GetResource('DVAR', theDialogID);
	HLock(theDialogRecord);
	Ptr offset = *theDialogRecord;
	dialogFieldCount = *(short*)offset; offset += sizeof(short);
	for (short index = 0; index < dialogFieldCount; index++)
	{
		dialogField[index].reference = *(short*)offset; offset += sizeof(short);
		SetUpFieldRecord((toolbarFieldRec*)&dialogField[index]);
	}
	HUnlock(theDialogRecord);
	ReleaseResource(theDialogRecord);

	DialogPtr theDialog = GetNewDialog(theDialogID, 0, (WindowPtr)-1); 
	SetValues(theDialog, false);
	ShowWindow(theDialog);
	short itemHit;
	ModalFilterProcPtr whichFilter = theDialogID == ignoredDataDialogID ? Ignored
DataFilter : NormalFilter;
	do
	{
		ModalDialog(whichFilter, &itemHit);
		if (itemHit == dialogDefaultsButtonID)
			SetValues(theDialog, true);
		else if (dialogField[itemHit-1].reference == checkBoxID)
			CheckBox(theDialog, itemHit, true, false);
		else if (dialogField[itemHit-1].reference == setButtonID)
		{
			GetValues(theDialog);
			TomPlotRange();
			SetValues(theDialog, false);
		}
	}
	while (itemHit > dialogCancelButtonID);
	if (itemHit == dialogOkayButtonID)
		GetValues(theDialog);
	DisposeDialog(theDialog);
	return(itemHit == dialogOkayButtonID);
}

/*****************************************************************************
***********************************************/
/*  Routines to perform menu commands                         ****************
***********************************************/
/*****************************************************************************
***********************************************/

/**************************************************************/
/*  Apple menu                                                */
/**************************************************************/

void mac_mode::AppleMenu(short theItem)
{
	Str255 itemString;
	switch (theItem)
	{
	case aboutItem:
		AppleAbout(false);
		break;
		
	default:
		GetItem(GetMHandle(appleMenuID), theItem, itemString);
		OpenDeskAcc(itemString);
		break;
	}
}

OSErr mac_mode::AppleAbout(Boolean startUp)
{
	GrafPtr savePort; 
	Str255 theString;

	GetPort(&savePort);
	WindowPtr aboutWindow = GetNewCWindow(aboutwindowID, 0, (WindowPtr)-1);
	SetPort(aboutWindow);
	ShowWindow(aboutWindow);
	PicHandle aboutPicture = GetPicture(aboutPictureID);
	DrawPicture(aboutPicture, &aboutWindow->portRect);
	RGBForeColor(&whiteRGB);
	RGBBackColor(&blackRGB);
	TextFont(geneva);
	TextSize(9);

	MoveTo(10,100);
	int stringIndex = 1;
	while((stringIndex == 1) || theString[0])
	{
		GetIndString(theString, creditsStringsID, stringIndex++);
		DrawString(theString);
		MoveTo(10, aboutWindow->pnLoc.v+11);
	}

	MoveTo(10, aboutWindow->pnLoc.v-6);
	GetIndString(theString, personalizationStringsID, nameStringIndex);
	DrawString(theString);
	if (theString[0])
		MoveTo(10, aboutWindow->pnLoc.v+11);
	else
		MoveTo(10, aboutWindow->pnLoc.v);
	GetIndString(theString, personalizationStringsID, companyStringIndex);
	DrawString(theString);
	if (theString[0])
		MoveTo(10, aboutWindow->pnLoc.v+11);
	else
		MoveTo(10, aboutWindow->pnLoc.v);
	GetIndString(theString, personalizationStringsID, addressStringIndex);
	DrawString(theString);
	if (theString[0])
		MoveTo(10, aboutWindow->pnLoc.v+11);
	else
		MoveTo(10, aboutWindow->pnLoc.v);
	GetIndString(theString, personalizationStringsID, cityStringIndex);
	DrawString(theString);
	if (theString[0])
		DrawString("\p ");
	GetIndString(theString, personalizationStringsID, stateStringIndex);
	DrawString(theString);
	if (theString[0])
		DrawString("\p ");
	GetIndString(theString, personalizationStringsID, zipStringIndex);
	DrawString(theString);
	if (theString[0])
		DrawString("\p ");
	GetIndString(theString, personalizationStringsID, countryStringIndex);
	DrawString(theString);

	if (startUp)
		TimeDelay(fourSecondDelay, true);
	else
	{
		while(!Button());
		KeyMap theKeys;
		GetKeys(theKeys);
		while(Button());
	
		if (theKeys[1] & 4)
		{
			Rect textRect;
			SetRect(&textRect, 0, 90, 240, 240);
			EraseRect(&textRect);
			MoveTo(10,100);
			
			GetIndString(theString, environmentStringsID, environmentStringIndex);
			DrawString(theString);
			MoveTo(10, aboutWindow->pnLoc.v+17);

			GetIndString(theString, environmentStringsID, cpuStringIndex);
			DrawString(theString);
			DrawString("\p  ");
			GetIndString(theString, cpusStringsID, 1+(short)processorType);
			if (theString[0] == 0)
				GetIndString(theString, cpusStringsID, 1);
			DrawString(theString);
			MoveTo(10, aboutWindow->pnLoc.v+11);
		
			GetIndString(theString, environmentStringsID, fpuStringIndex);
			DrawString(theString);
			DrawString("\p  ");
			GetIndString(theString, fpusStringsID, 2+(short)fpuType);
			if (theString[0] == 0)
				GetIndString(theString, fpusStringsID, 1);
			DrawString(theString);
			MoveTo(10, aboutWindow->pnLoc.v+11);
		
			GetIndString(theString, environmentStringsID, threadsStringIndex);
			DrawString(theString);
			DrawString("\p  ");
			GetIndString(theString, threadsStringsID, 1+threadsCapable);
			DrawString(theString);
			MoveTo(10, aboutWindow->pnLoc.v+11);
		
			while(!Button());
			while(Button());		
		}
		
		HideCursor();
		PicHandle voyagerPicture = GetPicture(voyagerPictureID);
		Rect voyagerRect;
		for (float reduceVoyager = 1; reduceVoyager >= 0; reduceVoyager -= 0.02)
		{
			voyagerRect.top = (short)(120-120*reduceVoyager);
			voyagerRect.bottom = (short)(120+120*reduceVoyager);
			voyagerRect.left = (short)(270-70*reduceVoyager);
			voyagerRect.right = (short)(270+70*reduceVoyager);
			DrawPicture(voyagerPicture, &voyagerRect);
		}
		ShowCursor();
		TimeDelay(oneSecondDelay, false);
	}

	DisposeWindow(aboutWindow);
	SetPort(savePort);
	FlushEvents(mDownMask+mUpMask, 0);

	return(noErr);
}

/**************************************************************/
/*  File menu                                                 */
/**************************************************************/

void mac_mode::FileMenu(short theItem)
{
	switch (theItem)
	{
	case openItem:
		FileOpen();
		break;

	case closeItem:
		FileClose(false);
		break;
	
	case saveFileTypeItem:
		FileSaveFileType();
		break;
	
	case binFileItem:
		FileBin();
		break;
	
	case exportItem:
		FileExport();
		break;

	case pageSetupItem:
		FilePageSetup();
		break;

	case printItem:
		FilePrint(false);
		break;

	case printAllItem:
		FilePrintAllOrRemainder(false, true);
		break;

	case printRemainderItem:
		FilePrintAllOrRemainder(false, false);
		break;

	case quitItem:
		FileQuit(false);
		break;
	}
}

void mac_mode::FileOpen(void)
{
	CustomGetFile(CustomFileFilter, -1, 0, &reply, customOpenDialogID, defaultPos
ition, (DlgHookYDProcPtr)CustomDialogHook, 0, 0, 0, 0);
	if (reply.sfGood)
	{
		if (!backgroundingEnabled)
			FileOpenFSSpec(&reply.sfFile);
		else
		{
			backgrounding = opening;
			UpdateMenuItems(0);
			NewThread(kCooperativeThread, FileOpenThread, (void*)&reply.sfFile, 0, kCre
ateIfNeeded, 0, &theThread);
		}
	}
}

OSErr mac_mode::FileOpenAE(AppleEvent* theEvent, Boolean printFile)
{
	if (fileOpen || (backgrounding == opening))
	{
		IndexedStringError(infoAlertID, oneDocumentStringIndex);
		return(errAEEventNotHandled);
	}
	
	AEDesc theDesc;
	AEGetParamDesc(theEvent, keyDirectObject, typeAEList, &theDesc);
	long itemsInList;
	AECountItems(&theDesc, &itemsInList);
	if (itemsInList > 1)
		IndexedStringError(infoAlertID, firstDocumentStringIndex);

	printFileWhenOpened = printFile;

	AEKeyword	theAEKeyword;
	DescType	theDescType;
	Size		theSize;
	AEGetNthPtr(&theDesc, 1, typeFSS, &theAEKeyword, &theDescType, (Ptr)&reply.sf
File, sizeof(FSSpec), &theSize);
	if (!backgroundingEnabled)
		FileOpenFSSpec(&reply.sfFile);
	else
	{
		backgrounding = opening;
		UpdateMenuItems(0);
		NewThread(kCooperativeThread, FileOpenThread, (void*)&reply.sfFile, 0, kCrea
teIfNeeded, 0, &theThread);
	}
	AEDisposeDesc(&theDesc);
	return(noErr);
}

pascal void* FileOpenThread(void* theFSSpec)
{
	mmode->FileOpenFSSpec((FSSpec*)theFSSpec);
	backgrounding = idle;
	mmode->UpdateMenuItems(0);
}

void mac_mode::FileOpenFSSpec(FSSpec* theFSSpec)
{
	OSErr theError;
	short refNum;
	if ((theError = FSpOpenDF(theFSSpec, fsRdPerm, &refNum)) != 0)
		IndexedFileError(theFSSpec->name, 15, theError);
	else
	{
		FSClose(refNum);
		AdjustCursor(true);
		DisplayStatus(opening);
		FileTypeSubmenu(GetFileType(theFSSpec)+1, false);
		fileUnknown = (GetFileType(theFSSpec) == -1);
		BlockMove(theFSSpec->name, localFilename, maxStringLength);
		SetWindowTitle(mainWindow, localFilename, localFileTypeString, appendFileTyp
eToTitle);
		ResizeOffscreen();
		Offscreen->lock();
		Offscreen->clear();
		Offscreen->unlock();
		ToolbarMenu(timeRangeBar);
		ShowWindow(mainWindow);
		SelectWindow(mainWindow);
		UpdateWindow(mainWindow);
		HSetVol(0, theFSSpec->vRefNum, theFSSpec->parID);
		SetGlobals();
		fileOpen = _open(p2cstr(theFSSpec->name));
		c2pstr((char*)theFSSpec->name);
		UpdateLocals(false);
		DrawProgressBar(100);
		if (fileOpen)
		{
			UpdateModeMenus(true);
			UpdateMenuItems(0);
			InvalRect(&headerRect);
			DisplayStatus(idle);
		}
		else
		{
			DisplayStatus(closing);
			TimeDelay(oneSecondDelay, false);
			HideWindow(mainWindow);
		}
	}
}

void mac_mode::FileClose(Boolean skipConfirmation)
{
	if (!skipConfirmation)
	{
		if (backgrounding)
		{
			Str255 closeItString, theReason;
			GetIndString(closeItString, miscStringsID, closeItStringIndex);
			if (backgrounding == opening)
				GetIndString(theReason, miscStringsID, openedStringIndex);
			else if (backgrounding == printing)
				GetIndString(theReason, miscStringsID, printedStringIndex);
			else if (backgrounding == plotting)
				GetIndString(theReason, miscStringsID, plottedStringIndex);
			ParamText(localFilename, theReason, closeItString, "\p");
			if (Alert(backgroundingCloseAlertID, 0L) == 1)
				return;
			DisposeThread(theThread, 0, false);
			backgrounding = idle;
			backgroundingEnabled = true;
		}
		else if (fileOpen)
		{
			ParamText(localFilename, "\p", "\p", "\p");
			if (Alert(closeAlertID, 0L) == 1)
				return;
		}
	}
	DrawProgressBar(100);
	HideWindow(mainWindow);
	fileOpen = false;
	UpdateLocals(false);
	UpdateModeMenus(false);
	UpdateMenuItems(0);
}

void mac_mode::FileSaveFileType(void)
{
	Str255 fileTypeString;
	GetItem(GetMHandle(fileTypeMenuID), localFile_type+1, fileTypeString);
	ParamText(localFilename, fileTypeString, "\p", "\p");
	if (Alert(saveFileTypeAlertID, 0L) == 2)
	{
		FInfo theFInfo;
		OSErr theErr = FSpGetFInfo(&reply.sfFile, &theFInfo);
		if (theErr == noErr)
		{
			theFInfo.fdCreator = 'MIDS';
			theFInfo.fdType = GetFileOSType(localFile_type);
			theErr = FSpSetFInfo(&reply.sfFile, &theFInfo);
		}
		if (theErr == noErr)
			fileUnknown = false;
		else
			IndexedFileError(localFilename, convertedStringIndex, theErr);
	}
}

void mac_mode::FileBin(void)
{
	ParamText(localFilename, "\p", "\p", "\p");
	if (Alert(binFileAlertID, 0L) == 1)
		return;
	AdjustCursor(true);
	DisplayStatus(binning);
	UpdateWindow(mainWindow);
	SetGlobals();
	_bin();
	DisplayStatus(idle);
}

void mac_mode::FileExport(void)
{
	AdjustCursor(true);
	PicHandle exportToPICT = Offscreen->PICT();
	HLock((Handle)exportToPICT);
	if (EmptyRect(&(**exportToPICT).picFrame))
		IndexedStringError(stopAlertID, couldntExportStringIndex);
	else
	{
		SFReply dumpReply;
		SFPutFile(defaultPosition, "\pSave picture as:", "\pUntitled", 0L, &dumpRepl
y);
		if (dumpReply.good)
		{
			Create(dumpReply.fName, dumpReply.vRefNum, 'ttxt', 'PICT');
			short refNum;
			FSOpen(dumpReply.fName, dumpReply.vRefNum, &refNum);
			SetFPos(refNum, fsFromStart, 0);
			char zero = 0;
			long byteCount = 1;
			for (short index = 0; index < 512; index++)
				FSWrite(refNum, &byteCount, &zero);
			byteCount = GetHandleSize((Handle)exportToPICT);
			FSWrite(refNum, &byteCount, (Ptr)*exportToPICT);
			GetFPos(refNum, &byteCount);
			SetEOF(refNum, byteCount);
			FSClose(refNum);
		}
	}
	HUnlock((Handle)exportToPICT);
	KillPicture(exportToPICT);
}

void mac_mode::FilePageSetup(void)
{
	PrOpen();
	if (PrStlDialog(printRecord))
	{
		ChangedResource((Handle)printRecord);
		WriteResource((Handle)printRecord);
	}
	PrClose();
}

void mac_mode::FilePrint(Boolean useDefaultPrintRecord)
{
	PrOpen();
	Boolean isValid = useDefaultPrintRecord ? true : PrJobDialog(printRecord);
	UpdateWindow(mainWindow);
	if (isValid)
	{
		AdjustCursor(true);
		DisplayStatus(printingWindow);
		printPort = PrOpenDoc(printRecord, 0L, 0L);
		Offscreen->lock();
		print();
		Offscreen->unlock();
		PrCloseDoc(printPort);
		TPrStatus prStatus;
		PrPicFile(printRecord, 0L, 0L, 0L, &prStatus);
		DisplayStatus(idle);
	}
	PrClose();
}

void mac_mode::FilePrintAllOrRemainder(Boolean useDefaultPrintRecord, Boolean 
doAll)
{
	PrOpen();
	Boolean isValid = useDefaultPrintRecord ? true : PrJobDialog(printRecord);
	UpdateWindow(mainWindow);
	if (isValid)
	{
		AdjustCursor(true);
		DisplayStatus(printing);
		SetGlobals();
		printPort = PrOpenDoc(printRecord, 0L, 0L);
		ResizeOffscreen();
		Offscreen->lock();
		if (doAll)
			plotall();
		else
			plotrmdr();
		Offscreen->unlock();
		PrCloseDoc(printPort);
		TPrStatus prStatus;
		PrPicFile(printRecord, 0L, 0L, 0L, &prStatus);
		DisplayStatus(idle);
		InvalRect(&mainWindowContents);
	}
	PrClose();
}

OSErr mac_mode::FileQuit(Boolean isAppleEvent)
{
	if (isAppleEvent && printFileWhenOpened)
		return(errAEEventNotHandled);
	if (backgrounding)
	{
		Str255 quitString, theReason;
		GetIndString(quitString, miscStringsID, quitStringIndex);
		if (backgrounding == opening)
			GetIndString(theReason, miscStringsID, openedStringIndex);
		else if (backgrounding == printing)
			GetIndString(theReason, miscStringsID, printedStringIndex);
		else if (backgrounding == plotting)
			GetIndString(theReason, miscStringsID, plottedStringIndex);
		ParamText(localFilename, theReason, quitString, "\p");
		if (Alert(backgroundingQuitAlertID, 0L) == 1)
			return(errAEEventNotHandled);
	}
	else if (fileOpen)
	{
		if (Alert(quitAlertID, 0L) == 1)
			return(errAEEventNotHandled);
	}	
	done = true;
	return(noErr);
}

/**************************************************************/
/*  Edit menu                                                 */
/**************************************************************/

void mac_mode::EditMenu(short theItem)
{
	if (SystemEdit(theItem-1) == 0)
	{
		if (editField)
			HandleEditFieldEditCommands(theItem);
		else if (theItem == cutItem)
		{
			if (EditCopy())
				EditClear();
		}
		else if (theItem == copyItem)
			EditCopy();
		else if (theItem == clearItem)
			EditClear();
	}
}

Boolean mac_mode::EditCopy(void)
{
	Boolean theResult = false;	
	AdjustCursor(true);
	PicHandle exportToClipboard = Offscreen->PICT();
	HLock((Handle)exportToClipboard);
	if (EmptyRect(&(**exportToClipboard).picFrame))
		IndexedStringError(stopAlertID, couldntCopyStringIndex);
	else
	{
		ZeroScrap();
		if (PutScrap(GetHandleSize((Handle)exportToClipboard), 'PICT', (Ptr)*exportT
oClipboard) == noErr)
		{
			UnloadScrap();
			theResult = true;
		}
		else
			IndexedStringError(stopAlertID, couldntCopyStringIndex);
	}
	HUnlock((Handle)exportToClipboard);
	KillPicture(exportToClipboard);
	return(theResult);
}

void mac_mode::EditClear(void)
{
	ResizeOffscreen();
	Offscreen->lock();
	Offscreen->clear();
	Offscreen->unlock();
	InvalRect(&mainWindowContents);
}

/**************************************************************/
/*  Plot menu                                                 */
/**************************************************************/

void mac_mode::PlotMenu(short theItem)
{
	if (theItem < cancelPlotItem)
	{
		Boolean doingGS2LowRes = (localTplotmode == GS2_LOW_RES);
		Boolean doingGS2HighRes = (localTplotmode == GS2_HIGH_RES);
		if ((theItem == plotItem) && !doingGS2LowRes)
		{
			if (!HandleDialog(doingGS2HighRes ? startGS2HighResDialogID : startNormalDi
alogID))
				return;
		}
		if (!backgroundingEnabled)
			PlotMenuItems(theItem);
		else
		{
			backgrounding = plotting;
			UpdateMenuItems(0);
			DrawToolbar();
			NewThread(kCooperativeThread, PlotMenuItemsThread, (void*)theItem, 0, kCrea
teIfNeeded, 0, &theThread);
		}
	}
	else if (theItem == cancelPlotItem)
	{
		Offscreen->unlock();
		DisposeThread(theThread, 0, false);
		backgrounding = idle;
		backgroundingEnabled = true;
		DrawProgressBar(100);
		TimeDelay(quarterSecondDelay, false);
		DisplayStatus(cancelling);
		TimeDelay(oneSecondDelay, false);
		DisplayStatus(idle);
		DrawToolbar();
		InvalRect(&mainWindowContents);
		UpdateWindow(mainWindow);
	}
}

pascal void* PlotMenuItemsThread(void* theItem)
{
	mmode->PlotMenuItems((short)(int)theItem);
	backgrounding = idle;
	mmode->UpdateMenuItems(0);
	mmode->DrawToolbar();
}

void mac_mode::PlotMenuItems(short theItem)
{
	DisplayStatus(plotting);
	AdjustCursor(true);
	SetGlobals();	
	ResizeOffscreen();
	Offscreen->lock();
	if (theItem == plotItem)
	{
		if (Tplotmode < GS2_LOW_RES)
		{
			Start_time = timeclass(localYear, localDay-1, localHour, localMinute, 0);
    		_execute_low_rate_plot_command();
		}
		else if (Tplotmode == GS2_LOW_RES)
			_plot_full_frame();
		else if (Tplotmode == GS2_HIGH_RES)
		{
    		Current_phiex_position = phiex_position(localHigh_res_line, localHigh_re
s_datum);
			_plot_gs2_hi_res(Current_phiex_position, Gs2_n_data, Gs2_n_strips);
		}
	}
	else if (theItem == replotItem)
		replot();
	else if (theItem == firstItem)
		first();
	else if (theItem == lastItem)
		last();
	else if (theItem == previousItem)
		prior();
	else if (theItem == nextItem)
		next();
	Offscreen->unlock();
	UpdateLocals(true);
	InvalRect(&mainWindowContents);
	beepOnNextUpdate = alertSoundWhenDone;
	DisplayStatus(idle);
}

/**************************************************************/
/*  Settings menu                                             */
/**************************************************************/

void mac_mode::SettingsMenu(short theItem)
{
	if (theItem == recordLengthItem)
		HandleDialog(recordLengthDialogID);
	else if (theItem == plotRangeItem)
	{
		if (localTplotmode < Spectral_modes)
			HandleDialog(rangeNormalDialogID);
		else if (localTplotmode == UNBINNED_TOMPLOT || localTplotmode == BINNED_TOMP
LOT)
			HandleDialog(rangeTomPlotDialogID);
		else if (localTplotmode == GS2_HIGH_RES)
			HandleDialog(rangeGS2HighResDialogID);
	}
	else if (theItem == levelsItem)
		HandleDialog(levelsDialogID);
	else if (theItem == dataRangeItem)
	{
		if (localTplotmode == UNBINNED_TOMPLOT || localTplotmode == BINNED_TOMPLOT)
			HandleDialog(validDataDialogID);
		else
			HandleDialog(ignoredDataDialogID);
	}
	else if (theItem == commentItem)
		HandleDialog(commentDialogID);
}

/**************************************************************/
/*  Options menu                                              */
/**************************************************************/

void mac_mode::OptionsMenu(short theItem)
{
	switch (theItem)
	{
	case appendFileTypeToTitleItem:
		appendFileTypeToTitle = !appendFileTypeToTitle;
		SetWindowTitle(mainWindow, localFilename, localFileTypeString, appendFileTyp
eToTitle);
		break;

	case showKernelMessagesItem:
		showKernelMessages = !showKernelMessages;
		if (!showKernelMessages)
			HideWindow(kernelWindow);
		else
		{
			ShowWindow(kernelWindow);
			SelectWindow(kernelWindow);
		}
		SetPort(mainWindow);
		InvalRect(&headerRect);
		break;

	case soundEffectsItem:
		soundEffects = !soundEffects;
		break;

	case alertSoundWhenDoneItem:
		alertSoundWhenDone = !alertSoundWhenDone;
		break;

	case backgroundingItem:
		backgroundingEnabled = !backgroundingEnabled;
		break;

	case fixedTextSizeItem:
		localFixedTextSize = !localFixedTextSize;
		break;
	}
}

/**************************************************************/
/*  File Type submenu                                         */
/**************************************************************/

void mac_mode::FileTypeSubmenu(short theItem, Boolean warningRequired)
{
	if (theItem == 0)
		return;
	GetItem(GetMHandle(fileTypeMenuID), theItem, localFileTypeString);
	localFile_type = --theItem;
	UpdateModeMenus(warningRequired);
}

/**************************************************************/
/*  Mode submenus                                             */
/**************************************************************/

void mac_mode::PlotModeSubmenu(short theItem, Boolean indexed)
{
	localTplotmode = indexed ? plotmodesIndex[theItem-1] : theItem;
	GetIndString(plotMode, plotModesStringsID, localTplotmode+1);
	DrawToolbar();
}

void mac_mode::SpacecraftModeSubmenu(short theItem, Boolean indexed)
{
	localCurrent_sc_mode = indexed ? scmodesIndex[theItem-1] : theItem;
	BlockMove(_sc_mode_name[localCurrent_sc_mode], spacecraftMode, maxStringLengt
h);
	c2pstr((char*)spacecraftMode);
	if (toolbarMode == modesBar)
		DrawToolbar();
}

void mac_mode::PRAModeSubmenu(short theItem, Boolean indexed)
{
	localCurrent_pra_mode = indexed ? pramodesIndex[theItem-1] : theItem;
	BlockMove(_pra_mode_name[localCurrent_pra_mode], praMode, maxStringLength);
	c2pstr((char*)praMode);
	if (toolbarMode == modesBar)
		DrawToolbar();
}

/**************************************************************/
/*  Levels submenus                                           */
/**************************************************************/

void mac_mode::BrightnessLevelSubmenu(short theItem)
{
	localBrightness = --theItem*10;
	if (toolbarMode == levelsBar)
		DrawToolbar();
}

void mac_mode::SaturationLevelSubmenu(short theItem)
{
	localSaturation = --theItem*10;
	if (toolbarMode == levelsBar)
		DrawToolbar();
}

/**************************************************************/
/*  Plot Size submenu                                         */
/**************************************************************/

void mac_mode::PlotSizeSubmenu(short theItem)
{
	plotSize = theItem;
}

/**************************************************************/
/*  Imaging submenus                                          */
/**************************************************************/

void mac_mode::FontSubmenu(short theItem)
{
	Str255 fontName;
	GetItem(GetMHandle(fontsMenuID), theItem, fontName);
	GetFNum(fontName, &localFont);
}

void mac_mode::DataColorSubmenu(short theItem)
{
	localDataColor = theItem;
}

void mac_mode::BackgroundColorSubmenu(short theItem)
{
	localBackgroundColor = theItem;
}

/**************************************************************/
/*  Toolbar popup menu                                        */
/**************************************************************/

void mac_mode::ToolbarMenu(short theItem)
{
	DisposeEditField(true);
	toolbarMode = theItem;
	DrawToolbar();
}

/**************************************************************/
/*  Comment pop up menu                                       */
/**************************************************************/

void mac_mode::CommentSubmenu(short theItem)
{
	if (theItem == noneItem)
		localComment[0] = 0;
	else if (theItem == filenameItem)
		BlockMove(localFilename, localComment, maxStringLength);
	DrawToolbar();
}

/**************************************************************/
/*  TomPlot Range routine                                     */
/**************************************************************/

void mac_mode::TomPlotRange(void)
{
	DisposeEditField(true);
 	if (localTomPlotChannel == 0)
	{
		for (short channelNumber = 1; channelNumber <= 200; channelNumber++)
		{
			Tomplot_dn_range[channelNumber][0] = (byte)localTomPlotLower;
			Tomplot_dn_range[channelNumber][1] = (byte)localTomPlotUpper;
		}
	}
	else if ((localTomPlotChannel >= 1) && (localTomPlotChannel <= 200))
	{
		Tomplot_dn_range[localTomPlotChannel][0] = (byte)localTomPlotLower;
		Tomplot_dn_range[localTomPlotChannel][1] = (byte)localTomPlotUpper;
	}
}

/*****************************************************************************
***********************************************/
/*  Routines to handle menus                                  ****************
***********************************************/
/*****************************************************************************
***********************************************/

void mac_mode::UpdateMenuItems(short modifiers)
{
	Boolean fileIsGS2 = ((localFile_type == jpl_phiex) || (localFile_type == pds_
phiex));
	Boolean fileOpenOrOpening = fileOpen || (backgrounding == opening);

	Boolean doingSpectral	= (localTplotmode < Spectral_modes);
	Boolean doingRawplot	= (localTplotmode == RAWPLOT);
	Boolean doingTomPlot	= ((localTplotmode == UNBINNED_TOMPLOT) || (localTplotmo
de == BINNED_TOMPLOT));
	Boolean doingGS2LowRes	= (localTplotmode == GS2_LOW_RES);
	Boolean doingGS2HighRes	= (localTplotmode == GS2_HIGH_RES);

	Boolean windowFrontmost = fileOpen && (mainWindow == FrontWindow());
	Boolean imageSelected	= windowFrontmost && !editField && !Offscreen->locked()
;
	Boolean textSelected	= windowFrontmost && editField && ((**editFieldRecord).s
elEnd - (**editFieldRecord).selStart);
	Boolean textInScrap		= windowFrontmost && editField && TEGetScrapLen();

	HiliteMenu(0);

	HiliteMenuItem(fileMenuID,		openItem,					!fileOpenOrOpening);
	HiliteMenuItem(fileMenuID,		closeItem,					fileOpenOrOpening);
	HiliteMenuItem(fileMenuID,		saveFileTypeItem,			fileOpen && !backgrounding &&
 fileUnknown);
	HiliteMenuItem(fileMenuID,		binFileItem,				fileOpen && !backgrounding && !fi
leIsGS2);
	HiliteMenuItem(fileMenuID,		exportItem,					windowFrontmost && !Offscreen->lo
cked());
	HiliteMenuItem(fileMenuID,		printItem,					windowFrontmost && !Offscreen->loc
ked());
	HiliteMenuItem(fileMenuID,		printAllItem,				fileOpen && !backgrounding);
	HiliteMenuItem(fileMenuID,		printRemainderItem,			fileOpen && !backgrounding)
;

	HiliteMenuItem(editMenuID,		menuTitle,					windowFrontmost);
	HiliteMenuItem(editMenuID,		cutItem,					textSelected || imageSelected);
	HiliteMenuItem(editMenuID,		copyItem,					textSelected || imageSelected);
	HiliteMenuItem(editMenuID,   	pasteItem,					textInScrap);
	HiliteMenuItem(editMenuID,   	clearItem,					textSelected || imageSelected);
	HiliteMenuItem(editMenuID,   	selectAllItem,				editField);

	HiliteMenuItem(plotMenuID,   	menuTitle,					(fileOpen && !backgrounding) || 
backgrounding == plotting);
	HiliteMenuItem(plotMenuID,   	plotItem,					!backgrounding);
	HiliteMenuItem(plotMenuID,   	replotItem,					!backgrounding);
	HiliteMenuItem(plotMenuID,   	firstItem,					!backgrounding && !doingGS2LowRe
s);
	HiliteMenuItem(plotMenuID,   	lastItem,					!backgrounding && !doingGS2LowRes
);
	HiliteMenuItem(plotMenuID,   	previousItem,				!backgrounding && !doingGS2Low
Res);
	HiliteMenuItem(plotMenuID,   	nextItem,					!backgrounding && !doingGS2LowRes
);
	HiliteMenuItem(plotMenuID,   	cancelPlotItem,				backgrounding == plotting);

	HiliteMenuItem(settingsMenuID,	fileTypeItem,				!fileOpenOrOpening);
	HiliteMenuItem(settingsMenuID,	recordLengthItem,			!fileOpenOrOpening && !loc
alFile_type);
	HiliteMenuItem(settingsMenuID,	spacecraftModeItem,			!fileIsGS2);
	HiliteMenuItem(settingsMenuID,	praModeItem,				!fileIsGS2);
	HiliteMenuItem(settingsMenuID,	plotRangeItem,				!doingRawplot && !doingGS2Lo
wRes);
	HiliteMenuItem(settingsMenuID,	levelsItem,					doingSpectral);
	HiliteMenuItem(settingsMenuID,	dataRangeItem,				doingSpectral || doingTomPlo
t);

	HiliteMenuItem(optionsMenuID,	backgroundingItem,			threadsCapable);

	HiliteMenuItem(toolbarMenuID,	plotRangeBar,				!doingRawplot && !doingGS2LowR
es);
	HiliteMenuItem(toolbarMenuID,	levelsBar,					doingSpectral);
	HiliteMenuItem(toolbarMenuID,	dataRangeBar,				doingSpectral || doingTomPlot)
;

	Str255 tempString;
	GetIndString(tempString, miscStringsID, doingGS2LowRes ? plotFullFrameStringI
ndex : plotEStringIndex);
	SetItem(GetMHandle(plotMenuID), plotItem, tempString);

	GetIndString(tempString, miscStringsID, doingSpectral ? ignoredDataEStringInd
ex : validDataEStringIndex);
	SetItem(GetMHandle(settingsMenuID), dataRangeItem, tempString);

	GetIndString(tempString, miscStringsID, fileIsGS2 ? timeStampStringIndex : ti
meRangeStringIndex);
	SetItem(GetMHandle(toolbarMenuID), timeRangeBar, tempString);
	GetIndString(tempString, miscStringsID, doingSpectral ? ignoredDataStringInde
x : validDataStringIndex);
	SetItem(GetMHandle(toolbarMenuID), dataRangeBar, tempString);

	for (short item = CountMItems(GetMHandle(toolbarMenuID)); item > 0; item--)
		CheckItem(GetMHandle(toolbarMenuID), item, toolbarMode == item);

	for (item = CountMItems(GetMHandle(fileTypeMenuID)); item > 0; item--)
		CheckItem(GetMHandle(fileTypeMenuID), item, localFile_type == (item-1));

	for (item = CountMItems(GetMHandle(plotmodesMenuID)); item > 0; item--)
		CheckItem(GetMHandle(plotmodesMenuID), item, localTplotmode == plotmodesInde
x[item-1]);
	for (item = CountMItems(GetMHandle(scmodesMenuID)); item > 0; item--)
		CheckItem(GetMHandle(scmodesMenuID), item, localCurrent_sc_mode == scmodesIn
dex[item-1]);
	for (item = CountMItems(GetMHandle(pramodesMenuID)); item > 0; item--)
		CheckItem(GetMHandle(pramodesMenuID), item, localCurrent_pra_mode == pramode
sIndex[item-1]);

	for (item = CountMItems(GetMHandle(brightnessLevelMenuID)); item > 0; item--)

		CheckItem(GetMHandle(brightnessLevelMenuID), item, localBrightness == (item-
1)*10);
	for (item = CountMItems(GetMHandle(saturationLevelMenuID)); item > 0; item--)

		CheckItem(GetMHandle(saturationLevelMenuID), item, localSaturation == (item-
1)*10);

	CheckItem(GetMHandle(optionsMenuID),	appendFileTypeToTitleItem,	appendFileTyp
eToTitle);
	CheckItem(GetMHandle(optionsMenuID),	showKernelMessagesItem,		showKernelMessa
ges);
	CheckItem(GetMHandle(optionsMenuID),	soundEffectsItem,			soundEffects);
	CheckItem(GetMHandle(optionsMenuID),	alertSoundWhenDoneItem,		alertSoundWhenD
one);
	CheckItem(GetMHandle(optionsMenuID),	backgroundingItem,			backgroundingEnable
d);
	CheckItem(GetMHandle(optionsMenuID),	fixedTextSizeItem,			localFixedTextSize)
;

	short fontNumber;
	for (item = CountMItems(GetMHandle(fontsMenuID)); item > 0; item--)
	{
		GetItem(GetMHandle(fontsMenuID), item, tempString);
		GetFNum(tempString, &fontNumber);
		CheckItem(GetMHandle(fontsMenuID), item, fontNumber == localFont);
	}

	CheckItem(GetMHandle(dataColorMenuID), 1, localDataColor == 1);
	CheckItem(GetMHandle(dataColorMenuID), 2, localDataColor == 2);
	CheckItem(GetMHandle(dataColorMenuID), 3, localDataColor == 3);

	CheckItem(GetMHandle(backgroundColorMenuID), 1, localBackgroundColor == 1);
	CheckItem(GetMHandle(backgroundColorMenuID), 2, localBackgroundColor == 2);

	CheckItem(GetMHandle(plotSizeMenuID), 1, plotSize == 1);
	CheckItem(GetMHandle(plotSizeMenuID), 2, plotSize == 2);
	CheckItem(GetMHandle(plotSizeMenuID), 3, plotSize == 3);

	InvalMenuBar();
}

void mac_mode::UpdateModeMenus(Boolean warningRequired)
{
	Boolean fileIsGS2 = ((localFile_type == jpl_phiex) || (localFile_type == pds_
phiex));

	for (int item = CountMItems(GetMHandle(plotmodesMenuID)); item > 0; item--)
		DelMenuItem(GetMHandle(plotmodesMenuID), item);
	int itemsAdded = 0;
	Str255 itemText;
	Boolean plotModeValid = false;
	for (item = 0; item < N_PLOT_MODES; item++)
		if ((!fileIsGS2 && ((item+1) <= binnedTomPlotItem))
		|| (fileIsGS2 && ((item+1) >= gs2LowResItem)))
		{
			if (localTplotmode == item)
				plotModeValid = true;
			GetIndString(itemText, plotModesStringsID, item+1);
			InsMenuItem(GetMHandle(plotmodesMenuID), itemText, N_PLOT_MODES);
			plotmodesIndex[itemsAdded++] = item;
		}

	for (item = CountMItems(GetMHandle(scmodesMenuID)); item > 0; item--)
		DelMenuItem(GetMHandle(scmodesMenuID), item);
	itemsAdded = 0;
	Boolean scModeValid = false;
	for (item = 0; item < N_SC_MODES; item++)
		if (Sc_modes_present[item] || !fileOpen)
		{
			if (localCurrent_sc_mode == item)
				scModeValid = true;
			BlockMove(_sc_mode_name[item], itemText, maxStringLength);
			c2pstr((char*)itemText);
			InsMenuItem(GetMHandle(scmodesMenuID), itemText, N_SC_MODES);
			scmodesIndex[itemsAdded++] = item;
		}

	int Pra_modes_present[N_PRA_MODES];
	for (int index = 0; index < N_PRA_MODES; index++)
		Pra_modes_present[index] = 0;
	for (index = 0; index < 16; index++)
		if (Pra_submodes_present[index]) then
			Pra_modes_present[_pra_mode_fm_submode(index)]++;
	for (item = CountMItems(GetMHandle(pramodesMenuID)); item > 0; item--)
		DelMenuItem(GetMHandle(pramodesMenuID), item);
	Boolean praModeValid = false;
	for (itemsAdded = item = 0; item < N_PRA_MODES; item++)
		if (Pra_modes_present[item] || !fileOpen)
		{
			if (localCurrent_pra_mode == item)
				praModeValid = true;
			BlockMove(_pra_mode_name[item], itemText, maxStringLength);
			c2pstr((char*)itemText);
			InsMenuItem(GetMHandle(pramodesMenuID), itemText, N_PRA_MODES);
			pramodesIndex[itemsAdded++] = item;
		}

	if (!plotModeValid)
		PlotModeSubmenu(fileIsGS2 ? GS2_LOW_RES : UNBINNED_SPECTRUM, false);
	if (!scModeValid)
		SpacecraftModeSubmenu(1, true);
	if (!praModeValid)
		PRAModeSubmenu(1, true);

	if (warningRequired && (!plotModeValid || !scModeValid || !praModeValid))
		IndexedStringError(infoAlertID, badSettingsStringIndex);
}

void mac_mode::DoCommand(long mResult, short modifiers, Boolean isPopupOverFie
ld)
{
	short theItem = LoWord(mResult);
	if (isPopupOverField)
	{
		if (theItem == 1)
			return;
		theItem -= 2;
	}
	switch (HiWord(mResult))
	{
	case appleMenuID:
		AppleMenu(theItem);
		break;

	case fileMenuID: 
		FileMenu(theItem);
		break;

	case editMenuID: 
		EditMenu(theItem);
		break;

	case plotMenuID:
		PlotMenu(theItem);
		break;

	case settingsMenuID:
		SettingsMenu(theItem);
		break;

	case optionsMenuID:
		OptionsMenu(theItem);
		break;

	case fileTypeMenuID:
		FileTypeSubmenu(theItem, true);
		break;

	case scmodesMenuID:
		SpacecraftModeSubmenu(theItem, true);
		break;

	case pramodesMenuID:
		PRAModeSubmenu(theItem, true);
		break;

	case plotmodesMenuID:
		PlotModeSubmenu(theItem, true);
		break;

	case brightnessLevelMenuID:
		BrightnessLevelSubmenu(theItem);
		break;

	case saturationLevelMenuID:
		SaturationLevelSubmenu(theItem);
		break;

	case fontsMenuID:
		FontSubmenu(theItem);
		break;
		
	case plotSizeMenuID:
		PlotSizeSubmenu(theItem);
		break;
		
	case dataColorMenuID:
		DataColorSubmenu(theItem);
		break;

	case backgroundColorMenuID:
		BackgroundColorSubmenu(theItem);
		break;

	case toolbarMenuID:
		ToolbarMenu(theItem);
		break;
		
	case commentMenuID:
		CommentSubmenu(theItem);
		break;
	}
	if (theItem > 0)
		UpdateMenuItems(0);
}

/*****************************************************************************
***********************************************/
/*  Routines to handle window clicks                          ****************
***********************************************/
/*****************************************************************************
***********************************************/

/**************************************************************/
/*  Routine to handle clicks in content region                */
/**************************************************************/

void mac_mode::DoContent(WindowPtr theWindow, Point thePt, short modifiers)
{
	if (theWindow != FrontWindow())
		SelectWindow(theWindow);
	else if (theWindow == kernelWindow)
		SysBeep(1);
	else if (theWindow == mainWindow)
	{
		GrafPtr savePort;	
		GetPort(&savePort);
		SetPort(mainWindow);
		GlobalToLocal(&thePt);
		ControlHandle theControl;
		int cntlCode;
		if ((cntlCode = FindControl(thePt, mainWindow, &theControl)) == 0)
		{
			if (PtInRect(thePt, &headerRect))
				HandleToolbarMouseDown(thePt, modifiers);
			else if (PtInRect(thePt, &statusRect))
				HandleStatusbarMouseDown(thePt, modifiers);
			else
				DisposeEditField(true);
		}
		else if (cntlCode == inThumb)
		{
			TrackControl(theControl, thePt, (ProcPtr)0);
			if (theControl == hScroll)
				offset.h = GetCtlValue(hScroll);
			else
				offset.v = GetCtlValue(vScroll);
			InvalRect(&mainWindowContents);
			UpdateWindow(mainWindow);
		}
		else
			TrackControl(theControl, thePt, (ProcPtr)TrackScrollbar);
		SetPort(savePort);
	}
}

/**************************************************************/
/*  Routine to grow window                                    */
/**************************************************************/

void mac_mode::DoGrowWindow(WindowPtr whichWindow, Point thePt)
{
	Rect theLimitRect;
	if (whichWindow == mainWindow)
		SetRect(&theLimitRect, 507, 298, 32767, 32767);
	else
		SetRect(&theLimitRect, 250, 21, 32767, 101);
	long theResult = GrowWindow(whichWindow, thePt, &theLimitRect);
	if (theResult == 0)
		return;
	SizeWindow(whichWindow, LoWord(theResult), HiWord(theResult), true);
	if (whichWindow == mainWindow)
		lastWindowRect = mainWindow->portRect;
	SetPort(whichWindow);
	EraseRect(&whichWindow->portRect);
	InvalRect(&whichWindow->portRect);
	if (whichWindow == mainWindow)
		UpdateScrollBars();
	UpdateWindow(whichWindow);
}

/**************************************************************/
/*  Routine to zoom window                                    */
/**************************************************************/

void mac_mode::DoZoomWindow(WindowPtr whichWindow, Point thePt, short modifier
s, short windowPart)
{
	if (TrackBox(whichWindow, thePt, windowPart))
	{
		if (whichWindow == mainWindow)
		{
			Boolean	alreadyFittedToWindow =
			((Offscreen->usable_right() == mainWindowContents.right) &&
			(Offscreen->usable_bottom() == (mainWindowContents.bottom-mainWindowContent
s.top)));
			if (modifiers & optionKey)
			{
				ZoomWindow(mainWindow, inZoomOut, true);
				lastWindowRect = mainWindow->portRect;
			}
			else if (alreadyFittedToWindow)
				SizeWindow(mainWindow, lastWindowRect.right, lastWindowRect.bottom, false)
;
			else
				SizeWindow(mainWindow, Offscreen->usable_right()+scrollbarWidth,
				Offscreen->usable_bottom()+toolbarHeight+scrollbarWidth, false);
			SetPort(mainWindow);
			EraseRect(&mainWindow->portRect);
			InvalRect(&mainWindow->portRect);
			UpdateScrollBars();
			UpdateWindow(mainWindow);
		}
	}
}

/**************************************************************/
/*  Routine to close window                                   */
/**************************************************************/

void mac_mode::DoCloseWindow(WindowPtr whichWindow, Point thePt)
{
	if (TrackGoAway(whichWindow, thePt))
	{
		if (whichWindow == mainWindow)
			FileClose(false);
		else
		{
			showKernelMessages = false;
			HideWindow(kernelWindow);
		}
	}
}

/*****************************************************************************
***********************************************/
/*  Routines to handle events                                 ****************
***********************************************/
/*****************************************************************************
***********************************************/

/**************************************************************/
/*  Routines to handle null events                            */
/**************************************************************/

void mac_mode::HandleNullEvent(EventRecord *theEvent)
{
	yield();
	AdjustCursor(false);
	HandleEditFieldIdle();
	if ((MaxBlock() < minimumMemoryFree) && !memoryAlreadyLow)
	{
		IndexedStringError(warningAlertID, memoryLowStringIndex);
		memoryAlreadyLow = true;
	}
	if (fileOpen && printFileWhenOpened)
		IndexedStringError(infoAlertID, couldntPrintStringIndex);
}
		
void mac_mode::AdjustCursor(Boolean lengthyTask)
{
	if (lengthyTask && !backgrounding)
	{
		SetCursor(&waitCursor);
		return;
	}
	Point thePoint;
	GetMouse(&thePoint);
	if (backgrounding)
	{
		if ((mainWindow == FrontWindow()) && PtInRect(thePoint, &mainWindowContents)
)
		{
			SetCursor(&waitCursor);
			return;
		}
		else if ((kernelWindow == FrontWindow()) && PtInRect(thePoint, &kernelWindow
->portRect))
		{
			SetCursor(&waitCursor);
			return;
		}
	}
	for (short index = 1; index < toolbarFieldCount; index++)
	{
		if (toolbarField[index].flags & editableMask)
		{
			if (PtInRect(thePoint, &toolbarField[index].editBounds))
			{
				SetCursor(&editCursor);
				return;
			}
		}
		else if (toolbarField[index].flags & isRangeMask)
		{
			CursorInIgnore(index);
			if (PtInRect(thePoint, &toolbarField[index].editBounds))
			{
				SetCursor(&rangeCursor);
				return;
			}
		}
	}
	SetCursor(&qd.arrow);
}

/**************************************************************/
/*  Routine to handle mouse down events                       */
/**************************************************************/

void mac_mode::HandleMouseDownEvent(EventRecord *theEvent)
{
	WindowPtr whichWindow;
	short windowPart = FindWindow(theEvent->where, &whichWindow);
	switch (windowPart)
	{
	case inMenuBar:
		UpdateMenuItems(theEvent->modifiers);
		DoCommand(MenuSelect(theEvent->where), theEvent->modifiers, false);
		break;

	case inSysWindow:
		SystemClick(theEvent, whichWindow);
		break;

	case inContent:
		DoContent(whichWindow, theEvent->where, theEvent->modifiers);
		break;

	case inDrag:
		DragWindow(whichWindow, theEvent->where, &(const Rect)(**GetGrayRgn()).rgnBB
ox);
		break;
	
	case inGrow:
		DoGrowWindow(whichWindow, theEvent->where);
		break;

	case inZoomIn:
	case inZoomOut:
		DoZoomWindow(whichWindow, theEvent->where, theEvent->modifiers, windowPart);

		break;

	case inGoAway:
		DoCloseWindow(whichWindow, theEvent->where);
		break;
	}
}

/**************************************************************/
/*  Routine to handle key down events                         */
/**************************************************************/

void mac_mode::HandleKeyDownEvent(EventRecord *theEvent)
{
	short theChar = theEvent->message & charCodeMask;
	if ((theEvent->modifiers & cmdKey) != 0)
	{
		UpdateMenuItems(theEvent->modifiers);
		DoCommand(MenuKey(theChar), theEvent->modifiers, false);
	}
	else
		HandleEditFieldKeyDown(theChar, theEvent->modifiers);
}

/**************************************************************/
/*  Routine to handle activate/deactivate events              */
/**************************************************************/

void mac_mode::HandleActivateEvent(EventRecord *theEvent)
{
	WindowPtr theWindow = (WindowPtr)theEvent->message;
	Boolean activating = theEvent->modifiers & resumeFlag;
	ActivateWindow(theWindow, activating);
}

/**************************************************************/
/*  Routine to handle update events                           */
/**************************************************************/

void mac_mode::HandleUpdateEvent(EventRecord *theEvent)
{
	WindowPtr theWindow = (WindowPtr)theEvent->message;
	UpdateWindow(theWindow);
}

/**************************************************************/
/*  Routine to handle OS events                               */
/**************************************************************/

void mac_mode::HandleOSEvent(EventRecord *theEvent)
{
	if ((theEvent->message & osEvtMessageMask) == suspendResumeMessage)
	{
		suspended = !(theEvent->message & resumeFlag);
		ActivateWindow(mainWindow, !suspended);
	}
}

/**************************************************************/
/*  Routine to handle disk events                             */
/**************************************************************/

void mac_mode::HandleDiskEvent(EventRecord *theEvent)
{
	if (HiWord(theEvent->message) != noErr)
	{
		DILoad();
		Point thePoint = { -1, -1 };
		DIBadMount(thePoint, theEvent->message);
		DIUnload();
	}
}

/**************************************************************/
/*  Routine to handle an event                                */
/**************************************************************/

void mac_mode::HandleEvent() 
{
	EventRecord theEvent;	
	WaitNextEvent(everyEvent, &theEvent, 0, 0);
	switch (theEvent.what)
	{
	case nullEvent:
		HandleNullEvent(&theEvent);
		break;

	case mouseDown:
		HandleMouseDownEvent(&theEvent);
		break;

	case keyDown:
	case autoKey: 
		HandleKeyDownEvent(&theEvent);
		break;

	case updateEvt:
		HandleUpdateEvent(&theEvent);
		break;
		
	case diskEvt:
		HandleDiskEvent(&theEvent);
		break;
		
	case activateEvt:
		HandleActivateEvent(&theEvent);
		break;
		
	case osEvt:
		HandleOSEvent(&theEvent);
		break;

	case kHighLevelEvent:
		AEProcessAppleEvent(&theEvent);
		break;
	}
}

/*****************************************************************************
***********************************************/
/*  Routine to personalize Midas                              ****************
***********************************************/
/*****************************************************************************
***********************************************/

Boolean mac_mode::Personalize(void)
{
	KeyMap theKeys;
	GetKeys(theKeys);
	if (theKeys[1] & 4)
	{
		Handle personalizationResource = GetResource('STR#', personalizationStringsI
D);
		RmveResource(personalizationResource);
		ReleaseResource(personalizationResource);
		UpdateResFile(CurResFile());
	}
	Handle personalizationResource = GetResource('STR#', personalizationStringsID
);		
	if (personalizationResource == 0)
	{
		short  itemType;
		Handle itemHandle;
		Rect   itemRect;

		DialogPtr personalizationDialog = GetNewDialog(personalizationDialogID, 0, (
WindowPtr)-1); 
		GetDItem(personalizationDialog, 3, &itemType, &itemHandle, &itemRect);
		SetDItem(personalizationDialog, 3, itemType, (Handle)OutlineButton, &itemRec
t);
	
		ShowWindow(personalizationDialog);
		short itemHit;
		do { ModalDialog(PersonalizeFilter, &itemHit); } while (itemHit > dialogCanc
elButtonID);
		GetDItem(personalizationDialog, itemHit, &itemType, &itemHandle, &itemRect);

		HiliteControl((ControlHandle)itemHandle, inButton);
		TimeDelay(hiliteDelay, false);
		if (itemHit == dialogCancelButtonID)
		{
			DisposeDialog(personalizationDialog);
			return(false);
		}
		HideWindow(personalizationDialog);
	
		personalizationResource = NewHandle((Size)0);
		short stringCount = countryStringIndex;
		PtrAndHand(&stringCount, personalizationResource, sizeof(short));
		Str255 stringTemp;
		for(int stringIndex = nameStringIndex; stringIndex <= countryStringIndex; st
ringIndex++)
		{
			GetDItem(personalizationDialog, 3+stringIndex, &itemType, &itemHandle, &ite
mRect);
			GetIText(itemHandle, stringTemp);
			if (stringIndex == stateStringIndex)
				UprString(stringTemp, true);
			PtrAndHand(stringTemp, personalizationResource, 1+stringTemp[0]);
		}
		AddResource(personalizationResource, 'STR#', personalizationStringsID, "\pPe
rsonalization");
		ReleaseResource(personalizationResource);
		UpdateResFile(CurResFile());

		DisposeDialog(personalizationDialog);
	}
	else
		ReleaseResource(personalizationResource);
	return(true);
}

/*****************************************************************************
***********************************************/
/*  Routine to set up user interface                          ****************
***********************************************/
/*****************************************************************************
***********************************************/

Boolean mac_mode::SetUpInterface(void)
{
	long gestaltAnswer;
	OSErr returnErr = Gestalt(gestaltQuickdrawVersion, &gestaltAnswer);
	if (returnErr == noErr)
	{
		if (gestaltAnswer < gestalt32BitQD)
			IndexedStringError(warningAlertID, qdRequiredStringIndex);
	}
	else
		IndexedStringError(warningAlertID, gestaltProblemStringIndex);

	returnErr = Gestalt(gestaltThreadMgrAttr, &gestaltAnswer);
	if (returnErr == noErr)
		threadsCapable = BitTst(&gestaltAnswer, 31-gestaltThreadMgrPresent);
	else
		IndexedStringError(warningAlertID, gestaltProblemStringIndex);
	backgroundingEnabled = threadsCapable;

	Gestalt(gestaltProcessorType, &processorType);
	Gestalt(gestaltFPUType, &fpuType);
	
	printRecord = (THPrint)GetResource('PREC', printerRecordID);
	if (printRecord != 0)
		PrValidate(printRecord);
	else
	{
		printRecord = (THPrint)NewHandle(sizeof(TPrint));
		PrintDefault(printRecord);
		AddResource((Handle)printRecord, 'PREC', printerRecordID, "\p");
		WriteResource((Handle)printRecord);
	}

	GetGWorld(0, &currentDevice);
	kernelWindow = GetNewCWindow(kernelwindowID, 0, (WindowPtr)-1);
	mainWindow = GetNewCWindow(mainwindowID, 0, (WindowPtr)-1);
	lastWindowRect = mainWindow->portRect;
	Pad = Screen_device = Offscreen = new macscreen;
	ResizeOffscreen();	

	CursHandle tempCursorHandle = GetCursor(iBeamCursor);
	editCursor = **tempCursorHandle;
	tempCursorHandle = GetCursor(watchCursor);
	waitCursor = **tempCursorHandle;
	tempCursorHandle = GetCursor(rangeCursorID);
	rangeCursor = **tempCursorHandle;
	DisposHandle((Handle)tempCursorHandle);

	Handle menuBar = GetNewMBar(menuBarID);
	SetMenuBar(menuBar);
	DisposHandle(menuBar);
	short hierMenusIndex = fileTypeMenuID;
	MenuHandle theMenuHandle;
	do
	{
		theMenuHandle = GetMenu(hierMenusIndex++);
		InsertMenu(theMenuHandle, hierMenu);
	}
	while (theMenuHandle != 0);
	AddResMenu(GetMHandle(appleMenuID), 'DRVR');
	AddResMenu(GetMHandle(fontsMenuID), 'FONT');

	AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, (EventHandlerProcP
tr)OpenApplicationHandler, 0, false);
	AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, (EventHandlerProcPtr
)OpenDocumentsHandler, 0, false);
	AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, (EventHandlerProcPt
r)PrintDocumentsHandler, 0, false);
	AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, (EventHandlerProcP
tr)QuitApplicationHandler, 0, false);
								   
	InitializeLocals();
	UpdateModeMenus(false);
	UpdateMenuItems(0);

	return(true);
}

/*****************************************************************************
***********************************************/
/*  Pascal Routines                                           ****************
***********************************************/
/*****************************************************************************
***********************************************/

/**************************************************************/
/*  AppleEvent handlers                                       */
/**************************************************************/

pascal OSErr OpenApplicationHandler(AppleEvent* theEvent, AppleEvent* theReply
, long reference)
{
	return(mmode->AppleAbout(true));
}

pascal OSErr OpenDocumentsHandler(AppleEvent* theEvent, AppleEvent* theReply, 
long reference)
{
	return(mmode->FileOpenAE(theEvent, false));
}

pascal OSErr PrintDocumentsHandler(AppleEvent* theEvent, AppleEvent* theReply,
 long reference)
{
	return(mmode->FileOpenAE(theEvent, true));
}

pascal OSErr QuitApplicationHandler(AppleEvent* theEvent, AppleEvent* theReply
, long reference)
{
	return(mmode->FileQuit(true));
}

/**************************************************************/
/*  Scrollbar handler                                         */
/**************************************************************/

pascal void TrackScrollbar(ControlHandle theControl, short theCode)
{
	int	oldCtl, distanceMoved, scrollAmt;
	RgnHandle updateRgn;
	
	if (theCode == 0)
		return;
	switch (theCode)
	{
		case inUpButton: 
			scrollAmt = -scrollPixels;
			break;
		case inDownButton: 
			scrollAmt = scrollPixels;
			break;
		case inPageUp: 
			if (theControl == hScroll)
				scrollAmt = -mainWindowContents.right;
			else
				scrollAmt = -(mainWindowContents.bottom-mainWindowContents.top);
			break;
		case inPageDown: 
			if (theControl == hScroll)
				scrollAmt = mainWindowContents.right;
			else
				scrollAmt = (mainWindowContents.bottom-mainWindowContents.top);
			break;
	}
	oldCtl = GetCtlValue(theControl);
	SetCtlValue(theControl, oldCtl+scrollAmt);
	distanceMoved = oldCtl-GetCtlValue(theControl);
	if (distanceMoved)
	{
		if (theControl == hScroll)
			offset.h = GetCtlValue(hScroll);
		else
			offset.v = GetCtlValue(vScroll);
		updateRgn = NewRgn();
		RGBBackColor(backgroundColor == 1 ? &whiteRGB : &blackRGB);
		if (theControl == hScroll)
			ScrollRect(&mainWindowContents, distanceMoved, 0, updateRgn);
		else
			ScrollRect(&mainWindowContents, 0, distanceMoved, updateRgn);
		RGBBackColor(&whiteRGB);
		InvalRgn(updateRgn);
		DisposeRgn(updateRgn);
		mmode->UpdateWindow(mainWindow);
	}
}

/**************************************************************/
/*  CustomGetFile routines                                    */
/**************************************************************/

pascal short CustomDialogHook(short theItem, DialogPtr theDialog, Ptr theData)

{
	if (GetWRefCon(theDialog) == sfMainDialogRefCon)
	{
		short itemType;
		Handle itemHandle;
		Rect itemRect;
		if (theItem == sfHookFirstCall)
		{
			GetDItem(theDialog, 10, &itemType, &itemHandle, &itemRect);
			SetCtlValue((ControlHandle)itemHandle, localFile_type+1);
			GetDItem(theDialog, 13, &itemType, &itemHandle, &itemRect);
			SetCtlValue((ControlHandle)itemHandle, allFiles);
			return(sfHookNullEvent);
		}
		else if (theItem == 10)
		{
			GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect);
			mmode->FileTypeSubmenu(GetCtlValue((ControlHandle)itemHandle), false);
			return(sfHookNullEvent);
		}
		else if (theItem == 14)
		{
			mmode->HandleDialog(recordLengthDialogID);
			return(sfHookNullEvent);
		}
		else if (theItem == 13)
		{
			GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect);
			SetCtlValue((ControlHandle)itemHandle, !GetCtlValue((ControlHandle)itemHand
le));
			allFiles = !allFiles;
			return(sfHookRebuildList);
		}
		else
		{
			Str255 currentFileTypeString, newFileTypeString;
			GetDItem(theDialog, 12, &itemType, &itemHandle, &itemRect);
			GetIText(itemHandle, currentFileTypeString);
			int theFileType = GetFileType(&reply.sfFile)+1;
			if (!theFileType && !reply.sfIsFolder && !reply.sfIsVolume && reply.sfFile.
name[0])
			{
				GetDItem(theDialog, 10, &itemType, &itemHandle, &itemRect);
				HiliteControl((ControlHandle)itemHandle, 0);
				GetDItem(theDialog, 11, &itemType, &itemHandle, &itemRect);
				SetDItem(theDialog, 11, itemType &= ~itemDisable, itemHandle, &itemRect);
				GetDItem(theDialog, 12, &itemType, &itemHandle, &itemRect);
				SetDItem(theDialog, 12, itemType &= ~itemDisable, itemHandle, &itemRect);
				GetIndString(newFileTypeString, miscStringsID, unknownStringIndex);
			}
			else
			{
				GetDItem(theDialog, 10, &itemType, &itemHandle, &itemRect);
				HiliteControl((ControlHandle)itemHandle, 255);
				GetDItem(theDialog, 11, &itemType, &itemHandle, &itemRect);
				SetDItem(theDialog, 11, itemType |= itemDisable, itemHandle, &itemRect);
				GetDItem(theDialog, 12, &itemType, &itemHandle, &itemRect);
				SetDItem(theDialog, 12, itemType |= itemDisable, itemHandle, &itemRect);
				GetItem(GetMHandle(fileTypeMenuID), theFileType, newFileTypeString);
			}
			GetDItem(theDialog, 12, &itemType, &itemHandle, &itemRect);
			if (!EqualString(currentFileTypeString, newFileTypeString, true, true))
				SetIText(itemHandle, newFileTypeString);
			GetDItem(theDialog, 14, &itemType, &itemHandle, &itemRect);
			if ((theFileType == 1) || (localFile_type == 0))
				HiliteControl((ControlHandle)itemHandle, 0);
			else
				HiliteControl((ControlHandle)itemHandle, 255);
		}
	}
	return(theItem);
}

pascal Boolean CustomFileFilter(ParmBlkPtr PB, void *theData)
{
	OSType theCreator = PB->fileParam.ioFlFndrInfo.fdCreator;
	OSType theType = PB->fileParam.ioFlFndrInfo.fdType;
	short isFolder = PB->fileParam.ioFlFndrInfo.fdFldr;
	if (theType == 'APPL')
		return(true);
	else if (isFolder)
		return(false);
	else if (allFiles)
		return(false);
	else if (theCreator != 'MIDS')
		return(true);
}

/**************************************************************/
/*  Dialog Filters                                            */
/**************************************************************/

pascal Boolean NormalFilter(DialogPtr theDialog, EventRecord *theEvent, short 
*itemHit)
{
	if (theEvent->what == keyDown)
	{
		switch (theEvent->message & charCodeMask)
		{
		case 0x0D:
		case 0x03:
			HiliteButton(theDialog, *itemHit = 1);
			return(true);
		case 0x1B:
			HiliteButton(theDialog, *itemHit = 2);
			return(true);
		}
	}
	return(false);
}

pascal Boolean PersonalizeFilter(DialogPtr theDialog, EventRecord *theEvent, s
hort *itemHit)
{
	if (theEvent->what == keyDown)
	{
		switch (theEvent->message & charCodeMask)
		{
		case 0x0D:
		case 0x03:
			theEvent->message = 0x3009;
			return(false);
		case 0x1B:
			HiliteButton(theDialog, *itemHit = 2);
			return(true);
		}
	}
	return(false);
}

pascal Boolean IgnoredDataFilter(DialogPtr theDialog, EventRecord *theEvent, s
hort *itemHit)
{
	short itemType;
	Handle itemHandle;
	Rect itemRect;
	SetPort(theDialog);
	Point thePt = theEvent->where;
	GlobalToLocal(&thePt);
	if (theEvent->what == nullEvent)
		IgnoredDataIdleProcedure(theDialog, thePt);
	else if (theEvent->what == mouseDown)
	{
		if (FindDItem(theDialog, thePt) == 4)
		{
			GetDItem(theDialog, 5, &itemType, &itemHandle, &itemRect);
			mmode->HandleIgnore(itemRect, 0, theDialog);
			*itemHit = 5;
			return(true);
		}
	}
	else if (theEvent->what == keyDown)
	{
		switch (theEvent->message & charCodeMask)
		{
		case 0x0D:
		case 0x03:
			HiliteButton(theDialog, *itemHit = 1);
			return(true);
		case 0x1B:
			HiliteButton(theDialog, *itemHit = 2);
			return(true);
		}
	}
	return(false);
}

pascal void IgnoredDataIdleProcedure(DialogPtr theDialog, Point thePt)
{
	short itemType;
	Handle itemHandle;
	Rect itemRect;

	if (FindDItem(theDialog, thePt) == 4)
	{
		SetCursor(&rangeCursor);
		GetDItem(theDialog, 5, &itemType, &itemHandle, &itemRect);
		int currentIgnoreValue = LoWord(PinRect(&itemRect, thePt))-itemRect.left;
		if (currentIgnoreValue != lastIgnoreValue)
		{
			GetDItem(theDialog, 6, &itemType, &itemHandle, &itemRect);
			Str255 currentIgnoreValueString;
			NumToString(currentIgnoreValue, currentIgnoreValueString);
			SetIText(itemHandle, currentIgnoreValueString);
			lastIgnoreValue = currentIgnoreValue;
		}
	}
	else
	{
		SetCursor(&qd.arrow);
		if (lastIgnoreValue != -1)
		{
			GetDItem(theDialog, 6, &itemType, &itemHandle, &itemRect);
			SetIText(itemHandle, "\p");
			lastIgnoreValue = -1;
		}
	}
}

/**************************************************************/
/*  Dialog Item Procedures                                    */
/**************************************************************/

pascal void HiliteButton(DialogPtr theDialog, short theItem)
{
	short itemType;
	Handle itemHandle;
	Rect itemRect;

	GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect);
	HiliteControl((ControlHandle)itemHandle, inButton);
	TimeDelay(hiliteDelay, false);
}

pascal void CheckBox(DialogPtr theDialog, short theItem, Boolean hit, Boolean 
defaults)
{
	short itemType;
	Handle itemHandle;
	Rect itemRect;

	GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect);
	short newState = hit ? !GetCtlValue((ControlHandle)itemHandle)
	: (defaults ? 1 : GetCtlValue((ControlHandle)itemHandle));
	SetCtlValue((ControlHandle)itemHandle, newState);
	HideDItem(theDialog, newState ? theItem+1 : theItem+2);
	ShowDItem(theDialog, newState ? theItem+2 : theItem+1);
	SelIText(theDialog, newState ? theItem-2 : theItem+1, 0, 32767);
}

pascal void OutlineButton(DialogPtr theDialog, short theItem)
{
	short itemType;
	Handle itemHandle;
	Rect itemRect;

	GetDItem(theDialog, 1, &itemType, &itemHandle, &itemRect);
	InsetRect(&itemRect, -4, -4);
	PenSize(3,3);
	FrameRoundRect(&itemRect, 16, 16);
	PenNormal();
}

pascal void DottedLine(DialogPtr theDialog, short theItem)
{
	short itemType;
	Handle itemHandle;
	Rect itemRect;

	GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect);
	PenPat((ConstPatternParam)&qd.gray);
	FrameRect(&itemRect);
	PenNormal();
}

pascal void IgnoredDataUserItem(DialogPtr theDialog, short theItem)
{
	short itemType;
	Handle itemHandle;
	Rect itemRect;

	GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect);
	mmode->DrawRangeField(itemRect, 0, 255);
}

/*****************************************************************************
***********************************************/
/*  End                                                       ****************
***********************************************/
/*****************************************************************************
***********************************************/
