/* WaveTableSizeDialog.c */
/*****************************************************************************/
/*                                                                           */
/*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
/*    Copyright (C) 1994  Thomas R. Lawrence                                 */
/*                                                                           */
/*    This program is free software; you can redistribute it and/or modify   */
/*    it under the terms of the GNU General Public License as published by   */
/*    the Free Software Foundation; either version 2 of the License, or      */
/*    (at your option) any later version.                                    */
/*                                                                           */
/*    This program is distributed in the hope that it will be useful,        */
/*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
/*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
/*    GNU General Public License for more details.                           */
/*                                                                           */
/*    You should have received a copy of the GNU General Public License      */
/*    along with this program; if not, write to the Free Software            */
/*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
/*                                                                           */
/*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
/*                                                                           */
/*****************************************************************************/

#include "MiscInfo.h"
#include "Audit.h"
#include "Debug.h"
#include "Definitions.h"

#include "WaveTableSizeDialog.h"
#include "Screen.h"
#include "EventLoop.h"
#include "RadioButton.h"
#include "SimpleButton.h"
#include "WrapTextBox.h"
#include "Memory.h"
#include "Menus.h"


#define XBORDER (13)
#define YBORDER (13)
#define BUTTONHEIGHT (12)
#define SEPARATOR (5)
#define BUTTONWIDTH (80)

#define MESSAGEX (XBORDER)
#define MESSAGEY (YBORDER)
#define MESSAGEHEIGHT (30)

#define BUTTON2X (MESSAGEX)
#define BUTTON2Y (MESSAGEY + MESSAGEHEIGHT + (4 * SEPARATOR))

#define BUTTON4X (BUTTON2X)
#define BUTTON4Y (BUTTON2Y + BUTTONHEIGHT + SEPARATOR)

#define BUTTON8X (BUTTON4X)
#define BUTTON8Y (BUTTON4Y + BUTTONHEIGHT + SEPARATOR)

#define BUTTON16X (BUTTON8X)
#define BUTTON16Y (BUTTON8Y + BUTTONHEIGHT + SEPARATOR)

#define BUTTON32X (BUTTON2X + BUTTONWIDTH)
#define BUTTON32Y (BUTTON2Y)

#define BUTTON64X (BUTTON32X)
#define BUTTON64Y (BUTTON32Y + BUTTONHEIGHT + SEPARATOR)

#define BUTTON128X (BUTTON64X)
#define BUTTON128Y (BUTTON64Y + BUTTONHEIGHT + SEPARATOR)

#define BUTTON256X (BUTTON128X)
#define BUTTON256Y (BUTTON128Y + BUTTONHEIGHT + SEPARATOR)

#define BUTTON512X (BUTTON32X + BUTTONWIDTH)
#define BUTTON512Y (BUTTON32Y)

#define BUTTON1024X (BUTTON512X)
#define BUTTON1024Y (BUTTON512Y + BUTTONHEIGHT + SEPARATOR)

#define BUTTON2048X (BUTTON1024X)
#define BUTTON2048Y (BUTTON1024Y + BUTTONHEIGHT + SEPARATOR)

#define BUTTON4096X (BUTTON2048X)
#define BUTTON4096Y (BUTTON2048Y + BUTTONHEIGHT + SEPARATOR)

#define BUTTON8192X (BUTTON512X + BUTTONWIDTH)
#define BUTTON8192Y (BUTTON512Y)

#define BUTTON16384X (BUTTON8192X)
#define BUTTON16384Y (BUTTON8192Y + BUTTONHEIGHT + SEPARATOR)

#define BUTTON32768X (BUTTON16384X)
#define BUTTON32768Y (BUTTON16384Y + BUTTONHEIGHT + SEPARATOR)

#define BUTTON65536X (BUTTON32768X)
#define BUTTON65536Y (BUTTON32768Y + BUTTONHEIGHT + SEPARATOR)

#define WINXSIZE (BUTTON65536X + BUTTONWIDTH + XBORDER)

#define MESSAGEWIDTH (WINXSIZE - (2 * XBORDER))

#define CANCELBUTTONX (XBORDER)
#define CANCELBUTTONY (BUTTON65536Y + BUTTONHEIGHT + (5 * SEPARATOR))
#define CANCELBUTTONWIDTH (80)
#define CANCELBUTTONHEIGHT (21)

#define OKBUTTONY (CANCELBUTTONY)
#define OKBUTTONWIDTH (CANCELBUTTONWIDTH)
#define OKBUTTONHEIGHT (CANCELBUTTONHEIGHT)
#define OKBUTTONX (WINXSIZE - XBORDER - OKBUTTONWIDTH)

#define WINYSIZE (OKBUTTONY + OKBUTTONHEIGHT + YBORDER)


typedef struct
	{
		WinType*						ScreenID;
		RadioButtonRec*			Buttons[16];
		SimpleButtonRec*		OKButton;
		SimpleButtonRec*		CancelButton;
	} WindowRec;


/* redrawer for the thing */
static void					RedrawWaveDialog(WindowRec* Window)
	{
		long							Scan;

		CheckPtrExistence(Window);
		for (Scan = 0; Scan < 16; Scan += 1)
			{
				RedrawRadioButton(Window->Buttons[Scan]);
			}
		RedrawSimpleButton(Window->OKButton);
		RedrawSimpleButton(Window->CancelButton);
		SetClipRect(Window->ScreenID,0,0,WINXSIZE,WINYSIZE);
		DrawWrappedTextBox(Window->ScreenID,"Select the number of frames per wave table:",
			GetUglyFont(),12,MESSAGEX,MESSAGEY,MESSAGEWIDTH,MESSAGEHEIGHT);
	}


/* ask for a new wave table size */
long								AskForNewWaveTableSize(long CurrentSize)
	{
		WindowRec*				Window;
		MyBoolean					LoopFlag;
		long							ReturnValue = CurrentSize;
		long							Scan;

		ERROR((CurrentSize != 2) && (CurrentSize != 4)
			&& (CurrentSize != 8) && (CurrentSize != 16) && (CurrentSize != 32)
			&& (CurrentSize != 64) && (CurrentSize != 128) && (CurrentSize != 256)
			&& (CurrentSize != 512) && (CurrentSize != 1024) && (CurrentSize != 2048)
			&& (CurrentSize != 4096) && (CurrentSize != 8192) && (CurrentSize != 16384)
			&& (CurrentSize != 32768) && (CurrentSize != 65536),PRERR(ForceAbort,
			"AskForNewWaveTableSize:  bad input value"));
		Window = (WindowRec*)AllocPtrCanFail(sizeof(WindowRec),"AskForNewWaveTableSize");
		if (Window == NIL)
			{
			 FailurePoint1:
				return CurrentSize;
			}
		Window->ScreenID = MakeNewWindow(eModelessDialogWindow,eWindowNotClosable,
			eWindowNotZoomable,eWindowNotResizable,DialogLeftEdge(WINXSIZE),
			DialogTopEdge(WINYSIZE),WINXSIZE,WINYSIZE,
			(void (*)(void*))&RedrawWaveDialog,Window);
		if (Window->ScreenID == NIL)
			{
			 FailurePoint2:
				ReleasePtr((char*)Window);
				goto FailurePoint1;
			}
		SetWindowName(Window->ScreenID,"Wave Table Frames");
		Window->Buttons[0] = NewRadioButton(Window->ScreenID,"2",BUTTON2X,BUTTON2Y,
			BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[0] == NIL)
			{
			 FailurePoint3:
				KillWindow(Window->ScreenID);
				goto FailurePoint2;
			}
		Window->Buttons[1] = NewRadioButton(Window->ScreenID,"4",BUTTON4X,BUTTON4Y,
			BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[1] == NIL)
			{
			 FailurePoint4:
				DisposeRadioButton(Window->Buttons[0]);
				goto FailurePoint3;
			}
		Window->Buttons[2] = NewRadioButton(Window->ScreenID,"8",BUTTON8X,BUTTON8Y,
			BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[2] == NIL)
			{
			 FailurePoint5:
				DisposeRadioButton(Window->Buttons[1]);
				goto FailurePoint4;
			}
		Window->Buttons[3] = NewRadioButton(Window->ScreenID,"16",BUTTON16X,BUTTON16Y,
			BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[3] == NIL)
			{
			 FailurePoint6:
				DisposeRadioButton(Window->Buttons[2]);
				goto FailurePoint5;
			}
		Window->Buttons[4] = NewRadioButton(Window->ScreenID,"32",BUTTON32X,BUTTON32Y,
			BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[4] == NIL)
			{
			 FailurePoint7:
				DisposeRadioButton(Window->Buttons[3]);
				goto FailurePoint6;
			}
		Window->Buttons[5] = NewRadioButton(Window->ScreenID,"64",BUTTON64X,BUTTON64Y,
			BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[5] == NIL)
			{
			 FailurePoint8:
				DisposeRadioButton(Window->Buttons[4]);
				goto FailurePoint7;
			}
		Window->Buttons[6] = NewRadioButton(Window->ScreenID,"128",BUTTON128X,
			BUTTON128Y,BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[6] == NIL)
			{
			 FailurePoint9:
				DisposeRadioButton(Window->Buttons[5]);
				goto FailurePoint8;
			}
		Window->Buttons[7] = NewRadioButton(Window->ScreenID,"256",BUTTON256X,
			BUTTON256Y,BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[7] == NIL)
			{
			 FailurePoint10:
				DisposeRadioButton(Window->Buttons[6]);
				goto FailurePoint9;
			}
		Window->Buttons[8] = NewRadioButton(Window->ScreenID,"512",BUTTON512X,
			BUTTON512Y,BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[8] == NIL)
			{
			 FailurePoint11:
				DisposeRadioButton(Window->Buttons[7]);
				goto FailurePoint10;
			}
		Window->Buttons[9] = NewRadioButton(Window->ScreenID,"1024",BUTTON1024X,
			BUTTON1024Y,BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[9] == NIL)
			{
			 FailurePoint12:
				DisposeRadioButton(Window->Buttons[8]);
				goto FailurePoint11;
			}
		Window->Buttons[10] = NewRadioButton(Window->ScreenID,"2048",BUTTON2048X,
			BUTTON2048Y,BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[10] == NIL)
			{
			 FailurePoint13:
				DisposeRadioButton(Window->Buttons[9]);
				goto FailurePoint12;
			}
		Window->Buttons[11] = NewRadioButton(Window->ScreenID,"4096",BUTTON4096X,
			BUTTON4096Y,BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[11] == NIL)
			{
			 FailurePoint14:
				DisposeRadioButton(Window->Buttons[10]);
				goto FailurePoint13;
			}
		Window->Buttons[12] = NewRadioButton(Window->ScreenID,"8192",BUTTON8192X,
			BUTTON8192Y,BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[12] == NIL)
			{
			 FailurePoint15:
				DisposeRadioButton(Window->Buttons[11]);
				goto FailurePoint14;
			}
		Window->Buttons[13] = NewRadioButton(Window->ScreenID,"16384",BUTTON16384X,
			BUTTON16384Y,BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[13] == NIL)
			{
			 FailurePoint16:
				DisposeRadioButton(Window->Buttons[12]);
				goto FailurePoint15;
			}
		Window->Buttons[14] = NewRadioButton(Window->ScreenID,"32768",BUTTON32768X,
			BUTTON32768Y,BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[14] == NIL)
			{
			 FailurePoint17:
				DisposeRadioButton(Window->Buttons[13]);
				goto FailurePoint16;
			}
		Window->Buttons[15] = NewRadioButton(Window->ScreenID,"65536",BUTTON65536X,
			BUTTON65536Y,BUTTONWIDTH,BUTTONHEIGHT);
		if (Window->Buttons[15] == NIL)
			{
			 FailurePoint18:
				DisposeRadioButton(Window->Buttons[14]);
				goto FailurePoint17;
			}
		Window->CancelButton = NewSimpleButton(Window->ScreenID,"Cancel",CANCELBUTTONX,
			CANCELBUTTONY,CANCELBUTTONWIDTH,CANCELBUTTONHEIGHT);
		if (Window->CancelButton == NIL)
			{
			 FailurePoint19:
				DisposeRadioButton(Window->Buttons[15]);
				goto FailurePoint18;
			}
		Window->OKButton = NewSimpleButton(Window->ScreenID,"OK",OKBUTTONX,
			OKBUTTONY,OKBUTTONWIDTH,OKBUTTONHEIGHT);
		if (Window->OKButton == NIL)
			{
			 FailurePoint20:
				DisposeSimpleButton(Window->CancelButton);
				goto FailurePoint19;
			}
		SetDefaultButtonState(Window->OKButton,True);

		/* set the button */
		switch (CurrentSize)
			{
				default:
					EXECUTE(PRERR(ForceAbort,"AskForNewWaveTableSize:  bad input value [2]"));
					break;
				case 2:
					SetRadioButtonState(Window->Buttons[0],True);
					break;
				case 4:
					SetRadioButtonState(Window->Buttons[1],True);
					break;
				case 8:
					SetRadioButtonState(Window->Buttons[2],True);
					break;
				case 16:
					SetRadioButtonState(Window->Buttons[3],True);
					break;
				case 32:
					SetRadioButtonState(Window->Buttons[4],True);
					break;
				case 64:
					SetRadioButtonState(Window->Buttons[5],True);
					break;
				case 128:
					SetRadioButtonState(Window->Buttons[6],True);
					break;
				case 256:
					SetRadioButtonState(Window->Buttons[7],True);
					break;
				case 512:
					SetRadioButtonState(Window->Buttons[8],True);
					break;
				case 1024:
					SetRadioButtonState(Window->Buttons[9],True);
					break;
				case 2048:
					SetRadioButtonState(Window->Buttons[10],True);
					break;
				case 4096:
					SetRadioButtonState(Window->Buttons[11],True);
					break;
				case 8192:
					SetRadioButtonState(Window->Buttons[12],True);
					break;
				case 16384:
					SetRadioButtonState(Window->Buttons[13],True);
					break;
				case 32768:
					SetRadioButtonState(Window->Buttons[14],True);
					break;
				case 65536:
					SetRadioButtonState(Window->Buttons[15],True);
					break;
			}

		/* process user input */
		LoopFlag = True;
		while (LoopFlag)
			{
				OrdType						XLoc;
				OrdType						YLoc;
				ModifierFlags			Modifiers;
				WinType*					Crap;
				char							KeyPress;
				MenuItemType*			MenuItem;
				EventType					TheEvent;

				TheEvent = GetAnEvent(&XLoc,&YLoc,&Modifiers,&Crap,&MenuItem,&KeyPress);
				switch (TheEvent)
					{
						default:
							break;
						case eCheckCursor:
							SetArrowCursor();
							break;
						case eNoEvent:
							break;
						case eKeyPressed:
							if (KeyPress == eCancelKey)
								{
									FlashButton(Window->CancelButton);
									LoopFlag = False;
									ReturnValue = CurrentSize;
								}
							else if (KeyPress == 13)
								{
									FlashButton(Window->OKButton);
									LoopFlag = False;
								}
							break;
						case eMouseDown:
							for (Scan = 0; Scan < 16; Scan += 1)
								{
									if (RadioButtonHitTest(Window->Buttons[Scan],XLoc,YLoc))
										{
											if (RadioButtonMouseDown(Window->Buttons[Scan],XLoc,YLoc))
												{
													long							Index;

													for (Index = 0; Index < 16; Index += 1)
														{
															SetRadioButtonState(Window->Buttons[Index],False);
														}
													SetRadioButtonState(Window->Buttons[Scan],True);
													ReturnValue = (1L << (Scan + 1));
												}
											goto JumpOutQuickPoint;
										}
								}
							if (SimpleButtonHitTest(Window->CancelButton,XLoc,YLoc))
								{
									if (SimpleButtonMouseDown(Window->CancelButton,XLoc,YLoc,NIL,NIL))
										{
											LoopFlag = False;
											ReturnValue = CurrentSize;
										}
								}
							else if (SimpleButtonHitTest(Window->OKButton,XLoc,YLoc))
								{
									if (SimpleButtonMouseDown(Window->OKButton,XLoc,YLoc,NIL,NIL))
										{
											LoopFlag = False;
										}
								}
						 JumpOutQuickPoint:
							break;
					}
			}

		/* verify value */
		ERROR((ReturnValue != 2) && (ReturnValue != 4)
			&& (ReturnValue != 8) && (ReturnValue != 16) && (ReturnValue != 32)
			&& (ReturnValue != 64) && (ReturnValue != 128) && (ReturnValue != 256)
			&& (ReturnValue != 512) && (ReturnValue != 1024) && (ReturnValue != 2048)
			&& (ReturnValue != 4096) && (ReturnValue != 8192) && (ReturnValue != 16384)
			&& (ReturnValue != 32768) && (ReturnValue != 65536),PRERR(ForceAbort,
			"AskForNewWaveTableSize:  bad resulting value"));

		DisposeSimpleButton(Window->CancelButton);
		DisposeSimpleButton(Window->OKButton);
		for (Scan = 0; Scan < 16; Scan += 1)
			{
				DisposeRadioButton(Window->Buttons[Scan]);
			}
		KillWindow(Window->ScreenID);
		ReleasePtr((char*)Window);

		return ReturnValue;
	}
