unit IdleUtils;

interface
	uses
		Palettes, Globals, GlobalUtils;

	var
		ozmaFlags: array[0..3] of Boolean;

	procedure CloseHiScores;
	procedure NewMode (randomIt: Boolean);
	procedure DisplayAHelpScreen;
	procedure CloseHelpScreens;
	procedure NextPageHelpScreens;
	procedure OpenHelpScreens;
	procedure InitIdle;
	procedure DoIdle;
	procedure DropIdle;
	procedure DoAbout;
	procedure DoSoundSettings;
	procedure DoCustomizeKeys;

{=================================}

implementation

	var
		idleR1, idleR2, frameR, loadR: Rect;
		maskRgn: RgnHandle;
		colorPoint, loopDelay, screenNum, helpScreenNum: Integer;
		timeWas, tickStamp: LongInt;
		demoAnimate: animateRec;

{=================================}

	procedure CloseHiScores;
	begin
		if (inColor) then
			CopyBits(BitMapPtr(virginCPtr^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, wholeArea, wholeArea, srcCopy, wholeRgn)
		else
			CopyBits(offVirginMap, mainWndo^.portBits, wholeArea, wholeArea, srcCopy, wholeRgn);
		NewMode(TRUE);
	end;

{=================================}

	procedure NewMode;
		var
			tempR, smallR: Rect;

{----------------}

		procedure GetTheStrings (starting: Integer);
			var
				tempStr: Str255;
		begin
			if (inColor) then
				RGBForeColor(rgbBlue)
			else
				TextMode(srcXOr);
			MoveTo(300, 57);
			GetIndString(tempStr, rDemoStrIDs, starting);
			DrawString(tempStr);
			MoveTo(300, 70);
			GetIndString(tempStr, rDemoStrIDs, starting + 1);
			DrawString(tempStr);
			MoveTo(300, 83);
			GetIndString(tempStr, rDemoStrIDs, starting + 2);
			DrawString(tempStr);
			MoveTo(300, 96);
			GetIndString(tempStr, rDemoStrIDs, starting + 3);
			DrawString(tempStr);
			if (inColor) then
				RGBForeColor(rgbBlack)
			else
				PenNormal;
		end;

{----------------}

	begin
		if (randomIt) then
			demoMode := Randomize(lastDemo) + 1;

		UseResFile(gliderResNum);

		if (inColor) then
			SetPort(GrafPtr(virginCPtr))
		else
			SetPort(offVirginPort);
		PenNormal;

		SetRect(tempR, 298, 20, 508, 100);
		FillRect(tempR, black);

		TextFont(16);
		TextSize(12);

		case demoMode of
			balloonMode: 
			begin
				with demoAnimate do
				begin
					phase := 0;
					kind := 2;
					vertOff := 4;
					destRect := animateRct[kind, phase];
					OffsetRect(destRect, -destRect.left, -destRect.top);
					OffsetRect(destRect, 460, 45);
					oldRect := destRect;
					wholeRect := destRect;
				end;
				GetTheStrings(1);
			end;

			copterMode: 
			begin
				with demoAnimate do
				begin
					phase := 0;
					kind := 1;
					vertOff := 3;
					destRect := animateRct[kind, phase];
					OffsetRect(destRect, -destRect.left, -destRect.top);
					OffsetRect(destRect, 460, 45);
					oldRect := destRect;
					wholeRect := destRect;
				end;
				GetTheStrings(5);
			end;

			dartMode: 
			begin
				with demoAnimate do
				begin
					phase := 0;
					kind := 0;
					vertOff := 4;
					destRect := animateRct[kind, phase];
					OffsetRect(destRect, -destRect.left, -destRect.top);
					OffsetRect(destRect, 435, 45);
					oldRect := destRect;
					wholeRect := destRect;
				end;
				GetTheStrings(9);
			end;

			controlMode: 
				GetTheStrings(13);

			tabMode: 
				GetTheStrings(17);

			adMode: 
				GetTheStrings(21);

			editorMode: 
				GetTheStrings(25);

			colorMusicMode: 
				GetTheStrings(29);

			ventCandleMode: 
			begin
				GetTheStrings(33);
				smallR := SrcRect[flrVnt];
				OffsetRect(smallR, -smallR.left, -smallR.top);
				OffsetRect(smallR, 456, 51);
				if (inColor) then
					CopyMask(BitMapPtr(objectCPtr^.portPixMap^)^, offMaskMap, BitMapPtr(virginCPtr^.portPixMap^)^, SrcRect[flrVnt], SrcRect[flrVnt], smallR)
				else
					CopyMask(offPlayerMap, offMaskMap, offVirginMap, SrcRect[flrVnt], SrcRect[flrVnt], smallR);
				smallR := SrcRect[candle];
				OffsetRect(smallR, -smallR.left, -smallR.top);
				OffsetRect(smallR, 466, 75);
				if (inColor) then
					CopyMask(BitMapPtr(objectCPtr^.portPixMap^)^, offMaskMap, BitMapPtr(virginCPtr^.portPixMap^)^, SrcRect[candle], SrcRect[candle], smallR)
				else
					CopyMask(offPlayerMap, offMaskMap, offVirginMap, SrcRect[candle], SrcRect[candle], smallR);
			end;

			bandBatteryMode: 
			begin
				GetTheStrings(37);
				smallR := SrcRect[rbrBnd];
				OffsetRect(smallR, -smallR.left, -smallR.top);
				OffsetRect(smallR, 470, 45);
				if (inColor) then
					CopyMask(BitMapPtr(objectCPtr^.portPixMap^)^, offMaskMap, BitMapPtr(virginCPtr^.portPixMap^)^, SrcRect[rbrBnd], SrcRect[rbrBnd], smallR)
				else
					CopyMask(offPlayerMap, offMaskMap, offVirginMap, SrcRect[rbrBnd], SrcRect[rbrBnd], smallR);
				smallR := SrcRect[battry];
				OffsetRect(smallR, -smallR.left, -smallR.top);
				OffsetRect(smallR, 476, 75);
				if (inColor) then
					CopyMask(BitMapPtr(objectCPtr^.portPixMap^)^, offMaskMap, BitMapPtr(virginCPtr^.portPixMap^)^, SrcRect[battry], SrcRect[battry], smallR)
				else
					CopyMask(offPlayerMap, offMaskMap, offVirginMap, SrcRect[battry], SrcRect[battry], smallR);
			end;

			paperClockMode: 
			begin
				GetTheStrings(41);
				smallR := SrcRect[paper];
				OffsetRect(smallR, -smallR.left, -smallR.top);
				OffsetRect(smallR, 460, 45);
				if (inColor) then
					CopyMask(BitMapPtr(objectCPtr^.portPixMap^)^, offMaskMap, BitMapPtr(virginCPtr^.portPixMap^)^, SrcRect[paper], SrcRect[paper], smallR)
				else
					CopyMask(offPlayerMap, offMaskMap, offVirginMap, SrcRect[paper], SrcRect[paper], smallR);
				smallR := SrcRect[clock];
				OffsetRect(smallR, -smallR.left, -smallR.top);
				OffsetRect(smallR, 468, 69);
				if (inColor) then
					CopyMask(BitMapPtr(objectCPtr^.portPixMap^)^, offMaskMap, BitMapPtr(virginCPtr^.portPixMap^)^, SrcRect[clock], SrcRect[clock], smallR)
				else
					CopyMask(offPlayerMap, offMaskMap, offVirginMap, SrcRect[clock], SrcRect[clock], smallR);
			end;

			otherwise
		end;

		SetPort(GrafPtr(mainWndo));

		if (inColor) then
			CopyBits(BitMapPtr(virginCPtr^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, tempR, tempR, srcCopy, GrafPtr(mainWndo)^.visRgn)
		else
			CopyBits(offVirginMap, mainWndo^.portBits, tempR, tempR, srcCopy, mainWndo^.visRgn);
	end;

{=================================}

	procedure DisplayAHelpScreen;
		var
			destRect: Rect;
			thePict: PicHandle;
			tempByte: SignedByte;

	begin
		SetRect(destRect, 4, 4, 507, 130);

		if (inColor) then
			SetPort(GrafPtr(loadCPtr))
		else
			SetPort(offLoadPort);

		thePict := GetPicture(helpScreenNum + rHelpBasePictID);
		if (thePict <> nil) then
		begin
			tempByte := HGetState(Handle(thePict));
			MoveHHi(Handle(thePict));
			HLock(Handle(thePict));
			DrawPicture(thePict, destRect);
			HSetState(Handle(thePict), tempByte);
		end
		else
		begin
			GenericAlert(kErrNotEnoughMem);
			ExitToShell;		{CHANGE ME}
		end;
		ReleaseResource(Handle(thePict));

		if (inColor) then
		begin
			BackColor(cyanColor);
			CopyBits(BitMapPtr(loadCPtr^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, destRect, destRect, srcCopy, mainWndo^.visRgn);
			BackColor(whiteColor);
		end
		else
		begin
			CopyBits(offLoadMap, mainWndo^.portBits, destRect, destRect, srcCopy, mainWndo^.visRgn);
		end;

	end;

{=================================}

	procedure CloseHelpScreens;
	begin
		if (inColor) then
		begin
			CopyBits(BitMapPtr(virginCPtr^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, wholeArea, wholeArea, srcCopy, mainWndo^.visRgn);
			CopyBits(BitMapPtr(virginCPtr^.portPixMap^)^, BitMapPtr(loadCPtr^.portPixMap^)^, wholeArea, wholeArea, srcCopy, mainWndo^.visRgn);
		end
		else
		begin
			CopyBits(offVirginMap, mainWndo^.portBits, wholeArea, wholeArea, srcCopy, mainWndo^.visRgn);
			CopyBits(offVirginMap, offLoadMap, wholeArea, wholeArea, srcCopy, mainWndo^.visRgn);
		end;

		if (screenBits.bounds.bottom <= 342) then
			ShowMenuBar;

		if (playing) then
			demoMode := Randomize(lastDemo) + 1
		else
			NewMode(TRUE);
	end;

{=================================}

	procedure NextPageHelpScreens;
	begin
		if (helpScreenNum < kLastHelpScreen) then
		begin
			helpScreenNum := helpScreenNum + 1;
			DisplayAHelpScreen;
			FlushEvents(everyEvent, 0);
		end
		else
			CloseHelpScreens;
	end;

{=================================}

	procedure OpenHelpScreens;
	begin
		helpScreenNum := 1;
		demoMode := helpScreensMode;

		if (screenBits.bounds.bottom <= 342) then
			HideMenuBar;

		DisplayAHelpScreen;

		repeat
		until (not Button);
	end;

{=================================}

	procedure InitIdle;
		var
			i: Integer;
	begin
		for i := 0 to 3 do
			ozmaFlags[i] := FALSE;

		SetRect(idleR1, 0, 0, 48, 20);
		OffsetRect(idleR1, -512 + Randomize(450), 130 + Randomize(70));
		SetRect(idleR2, 0, 0, 35, 15);
		OffsetRect(idleR2, -512 + Randomize(450), 130 + Randomize(70));
		tickStamp := TickCount;
		MoveTo(3, 222);
		maskRgn := NewRgn;
		OpenRgn;
		LineTo(29, 222);
		LineTo(16, 183);
		LineTo(82, 183);
		LineTo(93, 161);
		LineTo(204, 161);
		LineTo(214, 200);
		LineTo(329, 200);
		LineTo(335, 206);
		LineTo(352, 206);
		LineTo(368, 221);
		LineTo(396, 221);
		LineTo(509, 278);
		LineTo(509, 130);
		LineTo(3, 130);
		LineTo(3, 222);
		CloseRgn(maskRgn);

		loopDelay := 0;
		colorPoint := 0;
		demoCount := 0;

		NewMode(TRUE);
	end;

{=================================}

	procedure DoAnimate;
	begin

		with demoAnimate do
		begin
			phase := phase + 1;
			if (phase > 7) then
			begin
				phase := 0;
				vertOff := -vertOff;
			end;
			OffsetRect(destRect, 0, vertOff);

			if (inColor) then
			begin
				SetPort(GrafPtr(loadCPtr));
				UnionRect(destRect, oldRect, wholeRect);
				FillRect(wholeRect, black);
				SetPort(GrafPtr(mainWndo));
				CopyMask(BitMapPtr(objectCPtr^.portPixMap^)^, offMaskMap, BitMapPtr(loadCPtr^.portPixMap^)^, animateRct[kind, phase], animateRct[kind, phase], destRect);
				CopyBits(BitMapPtr(loadCPtr^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, wholeRect, wholeRect, srcCopy, GrafPtr(mainWndo)^.visRgn);
			end
			else
			begin
				SetPort(offLoadPort);
				UnionRect(destRect, oldRect, wholeRect);
				FillRect(wholeRect, black);
				SetPort(GrafPtr(mainWndo));
				CopyMask(offPlayerMap, offMaskMap, offLoadMap, animateRct[kind, phase], animateRct[kind, phase], destRect);
				CopyBits(offLoadMap, mainWndo^.portBits, wholeRect, wholeRect, srcCopy, mainWndo^.visRgn);
			end;
			oldRect := destRect;
		end;

	end;

{=================================}

	procedure DoIdle;
		var
			combinedRgn: RgnHandle;
			dummyLong: longInt;
			tempR1, tempR2, srcR: Rect;

	begin
		if (demoMode = highScoreMode) then
			Exit(DoIdle);

		if (demoMode <> helpScreensMode) then
		begin
			demoCount := demoCount + 1;
			if (demoCount >= 159) then
			begin
				demoCount := 0;
				NewMode(TRUE);
			end;

			if ((demoMode >= balloonMode) and (demoMode <= dartMode)) then
				DoAnimate;
		end;

		OffsetRect(idleR1, 4, 0);
		OffsetRect(idleR2, 3, 0);
		if (inColor) then
			SetPort(GrafPtr(loadCPtr))
		else
			SetPort(offLoadPort);
		tempR1 := idleR1;
		tempR1.left := tempR1.left - 4;
		FillRect(tempR1, black);
		tempR2 := idleR2;
		tempR2.left := tempR2.left - 3;
		FillRect(tempR2, black);
		SetRect(srcR, 0, 318, 35, 333);

		SetPort(GrafPtr(mainWndo));
		combinedRgn := NewRgn;
		if (inColor) then
		begin
			SectRgn(maskRgn, GrafPtr(mainWndo)^.visRgn, combinedRgn);
			CopyMask(BitMapPtr(objectCPtr^.portPixMap^)^, offMaskMap, BitMapPtr(loadCPtr^.portPixMap^)^, srcR, srcR, idleR2);
			CopyMask(BitMapPtr(objectCPtr^.portPixMap^)^, offMaskMap, BitMapPtr(loadCPtr^.portPixMap^)^, glideRct[0], glideRct[0], idleR1);
			CopyBits(BitMapPtr(loadCPtr^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, tempR1, tempR1, srcCopy, combinedRgn);
			CopyBits(BitMapPtr(loadCPtr^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, tempR2, tempR2, srcCopy, combinedRgn);
		end
		else
		begin
			SectRgn(maskRgn, mainWndo^.visRgn, combinedRgn);
			CopyMask(offPlayerMap, offMaskMap, offLoadMap, srcR, srcR, idleR2);
			CopyMask(offPlayerMap, offMaskMap, offLoadMap, glideRct[0], glideRct[0], idleR1);
			CopyBits(offLoadMap, mainWndo^.portBits, tempR1, tempR1, srcCopy, combinedRgn);
			CopyBits(offLoadMap, mainWndo^.portBits, tempR2, tempR2, srcCopy, combinedRgn);
		end;
		DisposeRgn(combinedRgn);

		if (idleR1.left > 512) then
		begin
			SetRect(idleR1, 0, 0, 48, 20);
			OffsetRect(idleR1, -512 + Randomize(450), 130 + Randomize(70));
		end;
		if (idleR2.left > 512) then
		begin
			SetRect(idleR2, 0, 0, 35, 15);
			OffsetRect(idleR2, -512 + Randomize(450), 130 + Randomize(70));
		end;

		PenNormal;
		if (inColor) then
			case colorPoint of
				0: 
				begin
					frameR := wholeArea;
					RGBForeColor(rgbBlue);
					FrameRect(frameR);
					InsetRect(frameR, 1, 1);
					RGBForeColor(rgbViolet);
					FrameRect(frameR);
					InsetRect(frameR, 1, 1);
					RGBForeColor(rgbLtBlue);
					FrameRect(frameR);
					RGBForeColor(rgbBlack);
				end;
				1: 
				begin
					frameR := wholeArea;
					RGBForeColor(rgbLtBlue);
					FrameRect(frameR);
					InsetRect(frameR, 1, 1);
					RGBForeColor(rgbBlue);
					FrameRect(frameR);
					InsetRect(frameR, 1, 1);
					RGBForeColor(rgbViolet);
					FrameRect(frameR);
					RGBForeColor(rgbBlack);
				end;
				2: 
				begin
					frameR := wholeArea;
					RGBForeColor(rgbViolet);
					FrameRect(frameR);
					InsetRect(frameR, 1, 1);
					RGBForeColor(rgbLtBlue);
					FrameRect(frameR);
					InsetRect(frameR, 1, 1);
					RGBForeColor(rgbBlue);
					FrameRect(frameR);
					RGBForeColor(rgbBlack);
				end;
			end;

		loopDelay := loopDelay + 1;
		if (loopDelay > 5) then
		begin
			loopDelay := 0;
			colorPoint := colorPoint + 1;
			if (colorPoint > 2) then
				colorPoint := 0;
		end;

		repeat
		until (TickCount >= tickStamp + 2);
		tickStamp := TickCount;
	end;

{=================================}

	procedure DropIdle;
	begin
		DisposeRgn(maskRgn);
	end;

{=================================}

	function idleFilter (theDialog: DialogPtr; var theEvent: EventRecord; var itemHit: integer): boolean;
		var
			iconNum, iType: Integer;
			timeIs: LongInt;
			tempRect: Rect;
			iHand, icnHand: Handle;
			cicnHand: CIconHandle;
	begin
		idleFilter := FALSE;
		if ((theEvent.what = KeyDown) and (BitAnd(theEvent.message, CharCodeMask) = kReturnKey)) then
		begin
			itemHit := 1;
			idleFilter := TRUE;
		end;
		timeIs := TickCount;
		if (timeIs > timeWas + 90) then
		begin
			timeWas := TickCount;
			screenNum := screenNum + 1;
			if (screenNum > 3) then
				screenNum := 0;
			for iconNum := 2 to 10 do
			begin
				SpinBall;
				Delay(1, timeIs);
				SpinBall;
				Delay(1, timeIs);
				GetDItem(theDialog, iconNum, iType, iHand, tempRect);

				if (inColor) then
				begin
					cicnHand := GetCIcon(1226 + iconNum + (screenNum * 9));
					if (cicnHand <> nil) then
					begin
						PlotCIcon(tempRect, cicnHand);
						DisposCIcon(cicnHand);
					end;
				end
				else
				begin
					icnHand := GetIcon(1226 + iconNum + (screenNum * 9));
					if (icnHand <> nil) then
						PlotIcon(tempRect, icnHand);
				end;
				InitCursor;
			end;		{end - for iconnum}
		end;			{end - if (timeIs }
	end;

{=================================}

	procedure DoAbout;

		const
			okayButton = 1;

		var
			savePort: GrafPtr;
			DType, itemHit: Integer;
			DItem: Handle;
			GetSelection: DialogPtr;
			tempRect: Rect;

{----------------------------------}

		procedure RefreshIt;  			{Refresh the dialogs non-controls}
		begin
			SetPort(GetSelection);			{Point to our dialog window}
			GetDItem(GetSelection, okayButton, DType, DItem, tempRect);{Get the item handle}
			PenSize(3, 3);  				{Change pen to draw thick default outline}
			InsetRect(tempRect, -4, -4);		{Draw outside the button by 1 pixel}
			FrameRoundRect(tempRect, 16, 16); {Draw the outline}
			PenSize(1, 1);
		end;

{----------------------------------}

	begin
		GetPort(savePort);

		GetSelection := GetNewDialog(228, nil, Pointer(-1));{Bring in the dialog resource}
		tempRect := GetSelection^.portRect;	{Get window size, we will now center it}
		tempRect.Top := ((screenBits.Bounds.Bottom - screenBits.Bounds.Top) - (tempRect.Bottom - tempRect.Top)) div 2;
		tempRect.Left := ((screenBits.Bounds.Right - screenBits.Bounds.Left) - (tempRect.Right - tempRect.Left)) div 2;
		MoveWindow(GetSelection, tempRect.Left, tempRect.Top, TRUE);{Now move the window to the proper position}
		ShowWindow(GetSelection);  		{Open a dialog box}
		SelectWindow(GetSelection); 		{Lets see it}
		SetPort(GetSelection);     		{Prepare to add conditional text}

		RefreshIt;     					{Draw any Lists, lines, or rectangles}
		timeWas := TickCount;			{Initialize the tick counter}
		screenNum := 0;					{Initialize the set of icons displaying}

		repeat						{Start of dialog handle loop}
			ModalDialog(@idleFilter, itemHit);{Wait until an item is hit}
				{End for this item selected}
		until (ItemHit = okayButton);				{Handle dialog items until exit selected}
		SetPort(GrafPtr(savePort));   		{Restore the previous grafport}
		DisposDialog(GetSelection);   		{Flush the dialog out of memory}
	end;							{End of procedure}

{=================================}

	procedure DoSoundSettings;
		const
			okayItem = 1;
			cancelItem = 2;
			soundOnItem = 3;
			musicOnItem = 4;
			incVolItem = 5;
			decVolItem = 6;
			iconItem = 7;
			volEqualsItem = 12;
			lineItem = 13;
			channel4Radio = 14;
			channel2Radio = 15;

		var
			wasPort: GrafPtr;
			itemT, itemHit, tempVolume, holdVolume: Integer;
			tempStr: Str255;
			itemH: Handle;
			theDlgPtr: DialogPtr;
			tempRect: Rect;
			leaveDlg, holdSound, holdMusic, thisSound, thisMusic, holdChannel: boolean;

{----------------------------------}

		function FixedVolume (theVolume: Integer): Integer;
		begin
			case theVolume of
				0: 
				begin
					SetSoundVol(0);
					theVolume := 800;
				end;
				1, 2: 
				begin
					SetSoundVol(1);
					theVolume := 801;
				end;
				3, 4: 
				begin
					SetSoundVol(3);
					theVolume := 802;
				end;
				5, 6: 
				begin
					SetSoundVol(5);
					theVolume := 803;
				end;
				otherwise
				begin
					SetSoundVol(7);
					theVolume := 804;
				end;
			end;
			FixedVolume := theVolume;
		end;

{----------------------------------}

		procedure RefreshIt;
			var
				offset, isVolume: Integer;
				cicnH: CIconHandle;
				iconH: Handle;
		begin
			SetPort(theDlgPtr);

			GetDItem(theDlgPtr, lineItem, itemT, itemH, tempRect);
			FillRect(tempRect, black);

			GetDItem(theDlgPtr, okayItem, itemT, itemH, tempRect);
			PenSize(3, 3);
			InsetRect(tempRect, -4, -4);
			FrameRoundRect(tempRect, 16, 16);
			PenSize(1, 1);

			GetSoundVol(isVolume);
			GetDItem(theDlgPtr, volEqualsItem, itemT, itemH, tempRect);
			NumToString(isVolume, tempStr);
			SetIText(itemH, tempStr);
			offset := FixedVolume(isVolume);
			GetDItem(theDlgPtr, iconItem, itemT, itemH, tempRect);

			if (inColor) then
			begin
				cicnH := GetCIcon(offset);
				if (cicnH <> nil) then
				begin
					PlotCIcon(tempRect, cicnH);
					ReleaseResource(Handle(iconH));
					DisposCIcon(cicnH);
				end;
			end
			else
			begin
				iconH := GetIcon(offset);
				if (iconH <> nil) then
				begin
					PlotIcon(tempRect, iconH);
					ReleaseResource(iconH);
				end;
			end;
		end;

{----------------------------------}

	begin
		FlushEvents(EveryEvent, 0);

		GetPort(wasPort);
		UseResFile(gliderResNum);
		GetSoundVol(holdVolume);
		holdSound := soundOn;
		holdMusic := musicOn;
		thisSound := soundOn;
		thisMusic := musicOn;
		holdChannel := is4Channel;

		theDlgPtr := GetNewDialog(rSoundDlgID, nil, Pointer(-1));
		tempRect := theDlgPtr^.portRect;
		tempRect.Top := ((screenBits.Bounds.Bottom - screenBits.Bounds.Top) - (tempRect.Bottom - tempRect.Top)) div 2;
		tempRect.Left := ((screenBits.Bounds.Right - screenBits.Bounds.Left) - (tempRect.Right - tempRect.Left)) div 2;
		MoveWindow(theDlgPtr, tempRect.Left, tempRect.Top, TRUE);{Now move the window to the proper position}
		ShowWindow(theDlgPtr);
		SelectWindow(theDlgPtr);
		SetPort(theDlgPtr);

		GetDItem(theDlgPtr, soundOnItem, itemT, itemH, tempRect);
		if (soundOn) then
			SetCtlValue(ControlHandle(itemH), 1)
		else
			SetCtlValue(ControlHandle(itemH), 0);
		GetDItem(theDlgPtr, musicOnItem, itemT, itemH, tempRect);

		if (musicOn) then			{set or hide Music On checkbox}
			SetCtlValue(ControlHandle(itemH), 1)
		else
			SetCtlValue(ControlHandle(itemH), 0);
		if (cantMusic) then
			HideDItem(theDlgPtr, musicOnItem);

		if (is4Channel) then		{set radio buttons for 4/2 channel sound}
			GetDItem(theDlgPtr, channel4Radio, itemT, itemH, tempRect)
		else
			GetDItem(theDlgPtr, channel2Radio, itemT, itemH, tempRect);
		SetCtlValue(ControlHandle(itemH), 1);

		RefreshIt;
		leaveDlg := FALSE;

		repeat
			ModalDialog(nil, itemHit);
			GetDItem(theDlgPtr, itemHit, itemT, itemH, tempRect);

			if (ItemHit = okayItem) then	{clicked on Okay button}
			begin
				leaveDlg := TRUE;
				GetSoundVol(tempVolume);
				soundOn := ((thisSound) and (tempVolume <> 0));
			end;

			if (ItemHit = cancelItem) then	{clicked on Cancle button}
			begin
				leaveDlg := TRUE;
				SetSoundVol(holdVolume);
				soundOn := holdSound;
				musicOn := holdMusic;
				is4Channel := holdChannel;
			end;

			if (ItemHit = soundOnItem) then
			begin
				soundOn := not soundOn;
				thisSound := not thisSound;

				GetDItem(theDlgPtr, soundOnItem, itemT, itemH, tempRect);
				if (soundOn) then
					SetCtlValue(ControlHandle(itemH), 1)
				else
					SetCtlValue(ControlHandle(itemH), 0);
			end;

			if (ItemHit = musicOnItem) then
			begin
				thisMusic := not thisMusic;
				musicOn := not musicOn;

				GetDItem(theDlgPtr, musicOnItem, itemT, itemH, tempRect);
				if (musicOn) then
					SetCtlValue(ControlHandle(itemH), 1)
				else
					SetCtlValue(ControlHandle(itemH), 0);
			end;

			if (ItemHit = incVolItem) then
			begin
				GetSoundVol(tempVolume);
				case tempVolume of
					0: 
						tempVolume := 1;
					1, 2: 
						tempVolume := 3;
					3, 4: 
						tempVolume := 5;
					otherwise
						tempVolume := 7;
				end;
				SetSoundVol(tempVolume);

				soundOn := ((thisSound) and (tempVolume <> 0));
				GetDItem(theDlgPtr, soundOnItem, itemT, itemH, tempRect);
				if (soundOn) then
					SetCtlValue(ControlHandle(itemH), 1)
				else
					SetCtlValue(ControlHandle(itemH), 0);

				musicOn := ((thisMusic) and (tempVolume <> 0));
				GetDItem(theDlgPtr, musicOnItem, itemT, itemH, tempRect);
				if (musicOn) then
					SetCtlValue(ControlHandle(itemH), 1)
				else
					SetCtlValue(ControlHandle(itemH), 0);

				RefreshIt;
			end;

			if (ItemHit = decVolItem) then
			begin
				GetSoundVol(tempVolume);
				case tempVolume of
					1, 2: 
						tempVolume := 0;
					3, 4: 
						tempVolume := 1;
					5, 6: 
						tempVolume := 3;
					7: 
						tempVolume := 5;
					otherwise
						tempVolume := 0;
				end;
				SetSoundVol(tempVolume);

				soundOn := ((thisSound) and (tempVolume <> 0));
				GetDItem(theDlgPtr, soundOnItem, itemT, itemH, tempRect);
				if (soundOn) then
					SetCtlValue(ControlHandle(itemH), 1)
				else
					SetCtlValue(ControlHandle(itemH), 0);

				musicOn := ((thisMusic) and (tempVolume <> 0));
				GetDItem(theDlgPtr, musicOnItem, itemT, itemH, tempRect);
				if (musicOn) then
					SetCtlValue(ControlHandle(itemH), 1)
				else
					SetCtlValue(ControlHandle(itemH), 0);

				RefreshIt;
			end;

			if (ItemHit = channel4Radio) then
			begin
				GetDItem(theDlgPtr, channel4Radio, itemT, itemH, tempRect);
				SetCtlValue(ControlHandle(itemH), 1);
				GetDItem(theDlgPtr, channel2Radio, itemT, itemH, tempRect);
				SetCtlValue(ControlHandle(itemH), 0);
				is4Channel := TRUE;
			end;

			if (ItemHit = channel2Radio) then
			begin
				GetDItem(theDlgPtr, channel2Radio, itemT, itemH, tempRect);
				SetCtlValue(ControlHandle(itemH), 1);
				GetDItem(theDlgPtr, channel4Radio, itemT, itemH, tempRect);
				SetCtlValue(ControlHandle(itemH), 0);
				is4Channel := FALSE;
			end;

		until leaveDlg;

		SetPort(GrafPtr(wasPort));
		DisposDialog(theDlgPtr);
	end;

{=================================}

	procedure DoCustomizeKeys;
		const
			okayItem = 1;
			cancelItem = 2;

			leftIcon = 3;
			rightIcon = 4;
			energyIcon = 5;
			bandIcon = 6;
			leftStat = 7;
			rightStat = 8;
			energyStat = 9;
			bandStat = 10;
			modeStat = 11;
			energyRadio = 12;
			bandRadio = 13;

		type
			string12 = string[12];

		var
			wasPort: GrafPtr;
			itemT, itemHit, i, rawKey, rawChar: Integer;
			newLeftKey, newRightKey, newEnergyKey, newBandKey: Integer;
			theState, tempLong: LongInt;
			tempStr: Str255;
			itemH, keyHandle: Handle;
			theDlgPtr: DialogPtr;
			tempRect: Rect;
			newLeftName, newRightName, newEnergyName, newBandName: string[12];
			leaveDlg, newButtonFires: Boolean;

{------------------}

		procedure RefreshIt;
		begin
			SetPort(theDlgPtr);
			GetDItem(theDlgPtr, okayItem, itemT, itemH, tempRect);{Get the item handle}
			PenSize(3, 3);  				{Change pen to draw thick default outline}
			InsetRect(tempRect, -4, -4);     	{Draw outside the button by 1 pixel}
			FrameRoundRect(tempRect, 16, 16); {Draw the outline}
			PenNormal;
		end;

{------------------}

		function ShowKeyName (rawKeyCode, rawCharCode: Integer): string12;
		begin

			if ((rawCharCode >= $21) and (rawCharCode <= $7A)) then
			begin
				if ((rawKeyCode >= $41) and (rawKeyCode <= $5C)) then
					tempStr := CONCAT(CHR(rawCharCode), ' keypad')
				else
					tempStr := CONCAT(CHR(rawCharCode), ' key');
			end
			else
				case rawCharCode of
					$01: 
						tempStr := 'home';
					$03: 
						tempStr := 'enter';
					$04: 
						tempStr := 'end';
					$05: 
						tempStr := 'help';
					$08: 
						tempStr := 'delete';
					$09: 
						tempStr := 'tab';
					$0B: 
						tempStr := 'page up';
					$0C: 
						tempStr := 'page down';
					$0D: 
						tempStr := 'return';
					$10: 
						case rawKeyCode of
							$60: 
								tempStr := 'F5 key';
							$61: 
								tempStr := 'F6 key';
							$62: 
								tempStr := 'F7 key';
							$63: 
								tempStr := 'F3 key';
							$64: 
								tempStr := 'F8 key';
							$65: 
								tempStr := 'F9 key';
							$67: 
								tempStr := 'F11 key';
							$69: 
								tempStr := 'F13 key';
							$6B: 
								tempStr := 'F14 key';
							$6D: 
								tempStr := 'F10 key';
							$6F: 
								tempStr := 'F12 key';
							$71: 
								tempStr := 'F15 key';
							$76: 
								tempStr := 'F4 key';
							$78: 
								tempStr := 'F2 key';
							$7A: 
								tempStr := 'F1 key';
							otherwise
								NumToString(rawKeyCode, tempStr);
						end;
					$1A: 
						tempStr := 'clear';
					$1B: 
						if (rawKeyCode = $47) then
							tempStr := 'clear'
						else
							tempStr := 'escape';
					$1C: 
						tempStr := 'left arrow';
					$1D: 
						tempStr := 'right arrow';
					$1E: 
						tempStr := 'up arrow';
					$1F: 
						tempStr := 'down arrow';
					$20: 
						tempStr := 'space';
					$7F: 
						tempStr := 'del key';
					otherwise
						tempStr := 'unknown';
				end;

			ShowKeyName := tempStr;
		end;

{------------------}

	begin
		FlushEvents(EveryEvent, 0);

		GetPort(wasPort);
		UseResFile(gliderResNum);

		theDlgPtr := GetNewDialog(rCustomKeysID, nil, Pointer(-1));
		tempRect := theDlgPtr^.portRect;
		tempRect.Top := ((screenBits.Bounds.Bottom - screenBits.Bounds.Top) - (tempRect.Bottom - tempRect.Top)) div 2;
		tempRect.Left := ((screenBits.Bounds.Right - screenBits.Bounds.Left) - (tempRect.Right - tempRect.Left)) div 2;
		MoveWindow(theDlgPtr, tempRect.Left, tempRect.Top, TRUE);{Now move the window to the proper position}
		ShowWindow(theDlgPtr);
		SelectWindow(theDlgPtr);
		SetPort(theDlgPtr);

		newLeftKey := leftKey;
		newRightKey := rightKey;
		newEnergyKey := energyKey;
		newBandKey := bandKey;
		newButtonFires := buttonFires;

		newLeftName := leftName;
		newRightName := rightName;
		newEnergyName := energyName;
		newBandName := bandName;

		GetDItem(theDlgPtr, leftStat, itemT, itemH, tempRect);
		SetIText(itemH, newLeftName);
		GetDItem(theDlgPtr, rightStat, itemT, itemH, tempRect);
		SetIText(itemH, newRightName);
		GetDItem(theDlgPtr, energyStat, itemT, itemH, tempRect);
		SetIText(itemH, newEnergyName);
		GetDItem(theDlgPtr, bandStat, itemT, itemH, tempRect);
		SetIText(itemH, newBandName);

		if (newButtonFires) then
			GetDItem(theDlgPtr, bandRadio, itemT, itemH, tempRect)
		else
			GetDItem(theDlgPtr, energyRadio, itemT, itemH, tempRect);
		SetCtlValue(ControlHandle(itemH), 1);

		RefreshIt;
		leaveDlg := FALSE;

		repeat
			ModalDialog(nil, itemHit);
			GetDItem(theDlgPtr, itemHit, itemT, itemH, tempRect);

			if ((itemHit >= leftIcon) and (itemHit <= bandIcon)) then
			begin

				GetDItem(theDlgPtr, itemHit, itemT, itemH, tempRect);
				InvertRect(tempRect);

				GetDItem(theDlgPtr, modeStat, itemT, itemH, tempRect);
				SetIText(itemH, 'The next key you strike will control this function.');
				InvertRect(tempRect);
				repeat
				until not Button;
				FlushEvents(everyEvent, 0);
				repeat
				until GetNextEvent(keyDownMask, theEvent);
				rawKey := LoWord(BitAnd(KeyCodeMask, theEvent.message) div $FF);
				rawChar := LoWord(BitAnd(CharCodeMask, theEvent.message));
				FlushEvents(everyEvent, 0);

				InvertRect(tempRect);
				GetDItem(theDlgPtr, itemHit, itemT, itemH, tempRect);
				InvertRect(tempRect);

				tempStr := ShowKeyName(rawKey, rawChar);
				GetDItem(theDlgPtr, itemHit + 4, itemT, itemH, tempRect);
				SetIText(itemH, tempStr);

				if (tempStr = 'tab') then
				begin
					SysBeep(3);
					GetDItem(theDlgPtr, modeStat, itemT, itemH, tempRect);
					SetIText(itemH, 'The TAB key is reserved for pausing Glider.');
					Delay(180, tempLong);
					case itemHit of
						leftIcon: 
							tempStr := newLeftName;
						rightIcon: 
							tempStr := newRightName;
						energyIcon: 
							tempStr := newEnergyName;
						otherwise
							tempStr := newBandName;
					end;
					GetDItem(theDlgPtr, itemHit + 4, itemT, itemH, tempRect);
					SetIText(itemH, tempStr);
				end
				else
					case itemHit of
						leftIcon: 
						begin
							newLeftKey := rawKey;
							newLeftName := COPY(tempStr, 1, 12);
						end;
						rightIcon: 
						begin
							newRightKey := rawKey;
							newRightName := COPY(tempStr, 1, 12);
						end;
						energyIcon: 
						begin
							newEnergyKey := rawKey;
							newEnergyName := COPY(tempStr, 1, 12);
						end;
						otherwise
						begin
							newBandKey := rawKey;
							newBandName := COPY(tempStr, 1, 12);
						end;
					end;

				GetDItem(theDlgPtr, modeStat, itemT, itemH, tempRect);
				SetIText(itemH, 'Click on an icon to change its controlling key.');
			end;

			if (itemHit = energyRadio) then
			begin
				newButtonFires := FALSE;
				GetDItem(theDlgPtr, energyRadio, itemT, itemH, tempRect);
				SetCtlValue(ControlHandle(itemH), 1);
				GetDItem(theDlgPtr, bandRadio, itemT, itemH, tempRect);
				SetCtlValue(ControlHandle(itemH), 0);
			end;

			if (itemHit = bandRadio) then
			begin
				newButtonFires := TRUE;
				GetDItem(theDlgPtr, bandRadio, itemT, itemH, tempRect);
				SetCtlValue(ControlHandle(itemH), 1);
				GetDItem(theDlgPtr, energyRadio, itemT, itemH, tempRect);
				SetCtlValue(ControlHandle(itemH), 0);
			end;

			if (itemHit = okayItem) then
			begin
				leaveDlg := TRUE;

				if ((newLeftKey = newRightKey) or (newLeftKey = newEnergyKey) or (newLeftKey = newBandKey)) then
				begin
					SysBeep(3);
					newLeftKey := leftKey;
					newLeftName := leftName;
					GetDItem(theDlgPtr, leftStat, itemT, itemH, tempRect);
					SetIText(itemH, newLeftName);
					GetDItem(theDlgPtr, modeStat, itemT, itemH, tempRect);
					SetIText(itemH, 'Your Left Key has been assigned to another function.');
					Delay(180, tempLong);
					GetDItem(theDlgPtr, modeStat, itemT, itemH, tempRect);
					SetIText(itemH, 'Click on an icon to change its controlling key.');
					leaveDlg := FALSE;
				end;

				if ((newRightKey = newEnergyKey) or (newRightKey = newBandKey)) then
				begin
					SysBeep(3);
					newRightKey := rightKey;
					newRightName := rightName;
					GetDItem(theDlgPtr, rightStat, itemT, itemH, tempRect);
					SetIText(itemH, newRightName);
					GetDItem(theDlgPtr, modeStat, itemT, itemH, tempRect);
					SetIText(itemH, 'Your Right Key has been assigned to another function.');
					Delay(180, tempLong);
					GetDItem(theDlgPtr, modeStat, itemT, itemH, tempRect);
					SetIText(itemH, 'Click on an icon to change its controlling key.');
					leaveDlg := FALSE;
				end;

				if (newEnergyKey = newBandKey) then
				begin
					SysBeep(3);
					newEnergyKey := energyKey;
					newEnergyName := energyName;
					GetDItem(theDlgPtr, energyStat, itemT, itemH, tempRect);
					SetIText(itemH, newEnergyName);
					GetDItem(theDlgPtr, modeStat, itemT, itemH, tempRect);
					SetIText(itemH, 'Your Energize Key has been assigned to another function.');
					Delay(180, tempLong);
					GetDItem(theDlgPtr, modeStat, itemT, itemH, tempRect);
					SetIText(itemH, 'Click on an icon to change its controlling key.');
					leaveDlg := FALSE;
				end;

				if (leaveDlg) then
				begin
					leftKey := newLeftKey;
					rightKey := newRightKey;
					energyKey := newEnergyKey;
					bandKey := newBandKey;
					buttonFires := newButtonFires;

					leftName := newLeftName;
					rightName := newRightName;
					energyName := newEnergyName;
					bandName := newBandName;
				end;
			end;

			if (ItemHit = cancelItem) then
				leaveDlg := TRUE;

		until leaveDlg;

		SetPort(GrafPtr(wasPort));
		DisposDialog(theDlgPtr);
	end;

{=================================}

end.