/****************************************************************************
File    : PerformanceDlg.cpp
/*
@(#) #SY# Atari800Win PLus
@(#) #IS# CPerformanceDlg implementation file
@(#) #BY# Tomasz Szymankowski
@(#) #LM# 17.03.2002
*/

#include "StdAfx.h"
#include "Atari800Win.h"
#include "Helpers.h"
#include "WarningDlg.h"
#include "PerformanceDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define IDC_PERFORMANCE_FIRST		IDC_PERFORMANCE_REFRESHRATE
#define IDC_PERFORMANCE_LAST		IDC_PERFORMANCE_CANCEL


/////////////////////////////////////////////////////////////////////////////
// Static objects

static const int s_anAvailableSpeed[] =
{
	 10,  20,  30,  40,  50,  60,  70,  80,  90, 100,
	110, 120, 130, 140, 150, 160, 170, 180, 190, 200
};

static const int s_nAvailableSpeedNo = sizeof(s_anAvailableSpeed)/sizeof(s_anAvailableSpeed[0]);


/////////////////////////////////////////////////////////////////////////////
// CPerformanceDlg dialog

BEGIN_MESSAGE_MAP(CPerformanceDlg, CCommonDlg)
	//{{AFX_MSG_MAP(CPerformanceDlg)
	ON_CBN_SELCHANGE(IDC_PERFORMANCE_SPEEDPERCENT, OnSelchangeSpeedPercent)
	ON_BN_CLICKED(IDC_PERFORMANCE_FULLSPEED, OnFullSpeed)
	ON_EN_KILLFOCUS(IDC_PERFORMANCE_REFRESHRATE, OnKillfocusRefreshRate)
	ON_NOTIFY(UDN_DELTAPOS, IDC_PERFORMANCE_REFRESHSPIN, OnDeltaposRefreshSpin)
	ON_BN_CLICKED(IDC_PERFORMANCE_DOUBLEREFRESHCHECK, OnDoubleRefreshCheck)
	ON_EN_KILLFOCUS(IDC_PERFORMANCE_DOUBLEREFRESHRATE, OnKillfocusDoubleRefreshRate)
	ON_NOTIFY(UDN_DELTAPOS, IDC_PERFORMANCE_DOUBLEREFRESHSPIN, OnDeltaposDoubleRefreshSpin)
	ON_BN_CLICKED(IDC_PERFORMANCE_NODRAWDISPLAY, OnNoDrawDisplay)
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_PERFORMANCE_OK, OnOK)
	ON_BN_CLICKED(IDC_PERFORMANCE_CANCEL, CCommonDlg::OnCancel)
END_MESSAGE_MAP()

/*========================================================
Method   : CPerformanceDlg::CPerformanceDlg
=========================================================*/
/* #FN#
   Standard constructor */
CPerformanceDlg::
CPerformanceDlg(
	CWnd *pParent /*=NULL*/ /* #IN# Pointer to the parent window */
)
	: CCommonDlg( CPerformanceDlg::IDD, pParent )
{
	//{{AFX_DATA_INIT(CPerformanceDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT

	m_nFirstCtrl = IDC_PERFORMANCE_FIRST;
	m_nLastCtrl  = IDC_PERFORMANCE_LAST;
} /* #OF# CPerformanceDlg::CPerformanceDlg */

/*========================================================
Method   : CPerformanceDlg::DoDataExchange
=========================================================*/
/* #FN#
   Dynamic Data Exchange (not used) */
void
/* #AS#
   Nothing */
CPerformanceDlg::
DoDataExchange(
	CDataExchange *pDX /* #IN# Pointer to CDataExchange object */
)
{
	CCommonDlg::DoDataExchange( pDX );
	//{{AFX_DATA_MAP(CPerformanceDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
} /* #OF# CPerformanceDlg::DoDataExchange */


/////////////////////////////////////////////////////////////////////////////
// CPerformanceDlg implementation

/*========================================================
Method   : CPerformanceDlg::SetDlgState
=========================================================*/
/* #FN#
   Sets up the state of the dialog controls */
void
/* #AS#
   Nothing */
CPerformanceDlg::
SetDlgState()
{
	CComboBox *pCombo  = (CComboBox *)GetDlgItem( IDC_PERFORMANCE_SPEEDPERCENT );
	CButton   *pButton = NULL;
	CWnd      *pWnd    = NULL;

	char szItem[ 4 ];
	int  nSel = 5;

	/* Set up "Speed Percent" combo */
	ASSERT(pCombo);
	pCombo->ResetContent();

	for( int i = 0; i < s_nAvailableSpeedNo; i++ )
	{
		sprintf( szItem, "%d", s_anAvailableSpeed[ i ] );
		pCombo->AddString( szItem );
		if( s_anAvailableSpeed[ i ] == m_nSpeedPercent )
			nSel = i;
	}
	pCombo->SetCurSel( nSel );
	pCombo->EnableWindow( !(m_ulMiscState & MS_FULL_SPEED) );

	pWnd = GetDlgItem( IDC_PERFORMANCE_SPEEDPERCENT_LABEL );
	ASSERT(pWnd);
	pWnd->EnableWindow( !(m_ulMiscState & MS_FULL_SPEED) );

	/* Set up check buttons states */
	if( m_ulMiscState & MS_FULL_SPEED )
	{
		pButton = (CButton *)GetDlgItem( IDC_PERFORMANCE_FULLSPEED );
		ASSERT(pButton);
		pButton->SetCheck( 1 );
	}
	if( m_ulMiscState & MS_USE_DOUBLE_REFRESH )
	{
		pButton = (CButton*)GetDlgItem( IDC_PERFORMANCE_DOUBLEREFRESHCHECK );
		ASSERT(pButton);
		pButton->SetCheck( 1 );
	}

	pButton = (CButton*)GetDlgItem( IDC_PERFORMANCE_NODRAWDISPLAY );
	ASSERT(pButton);
	pButton->SetCheck( (m_ulMiscState & MS_NO_DRAW_DISPLAY) != 0 );
	pButton->EnableWindow( m_nRefreshRate > 1 || (m_ulMiscState & MS_USE_DOUBLE_REFRESH && m_nDoubleRate > 1) );

	/* Set up refresh rate stuff */
	SetDlgItemInt( IDC_PERFORMANCE_REFRESHRATE, m_nRefreshRate, FALSE );

	/* For double-windowed mode */
	SetDlgItemInt( IDC_PERFORMANCE_DOUBLEREFRESHRATE, m_nDoubleRate, FALSE );

	pWnd = GetDlgItem( IDC_PERFORMANCE_DOUBLEREFRESHRATE );
	ASSERT(pWnd);
	pWnd->EnableWindow( m_ulMiscState & MS_USE_DOUBLE_REFRESH );

	pWnd = GetDlgItem( IDC_PERFORMANCE_DOUBLEREFRESHSPIN );
	ASSERT(pWnd);
	pWnd->EnableWindow( m_ulMiscState & MS_USE_DOUBLE_REFRESH );
} /* #OF# CPerformanceDlg::SetDlgState */


/////////////////////////////////////////////////////////////////////////////
// CPerformanceDlg message handlers

/*========================================================
Method   : CPerformanceDlg::OnInitDialog
=========================================================*/
/* #FN#
   Performs special processing when the dialog box is initialized */
BOOL
/* #AS#
   TRUE unless you set the focus to a control */
CPerformanceDlg::
OnInitDialog()
{
	CCommonDlg::OnInitDialog();

	m_ulMiscState   = g_Misc.ulState;
	m_nSpeedPercent = g_nSpeedPercent;
	m_nRefreshRate  = refresh_rate;
	m_nDoubleRate   = g_nDoubleRate;

	SetDlgState();

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
} /* #OF# CPerformanceDlg::OnInitDialog */

/*========================================================
Method   : CPerformanceDlg::OnSelchangeSpeedPercent
=========================================================*/
/* #FN#
   Sets a state of the object regarding to an appropriate combo box */
void
/* #AS#
   Nothing */
CPerformanceDlg::
OnSelchangeSpeedPercent()
{
	CComboBox *pCombo = (CComboBox *)GetDlgItem( IDC_PERFORMANCE_SPEEDPERCENT );
	ASSERT(pCombo != NULL);
	m_nSpeedPercent = s_anAvailableSpeed[ pCombo->GetCurSel() ];
} /* #OF# CPerformanceDlg::OnSelchangeSpeedPercent */

/*========================================================
Method   : CPerformanceDlg::OnFullSpeed
=========================================================*/
/* #FN#
   Sets a state of the object regarding to an appropriate check box */
void
/* #AS#
   Nothing */
CPerformanceDlg::
OnFullSpeed() 
{
	_ClickButton( IDC_PERFORMANCE_FULLSPEED, m_ulMiscState, MS_FULL_SPEED );
	SetDlgState();
} /* #OF# CPerformanceDlg::OnFullSpeed */

/*========================================================
Method   : CPerformanceDlg::OnDeltaposRefreshSpin
=========================================================*/
/* #FN#
   Sets a state of the object regarding to an appropriate spin control */
void
/* #AS#
   Nothing */
CPerformanceDlg::
OnDeltaposRefreshSpin(
	NMHDR   *pNMHDR, /* #IN#  */
	LRESULT *pResult /* #OUT# */
)
{
	_DeltaposSpin( pNMHDR, IDC_PERFORMANCE_REFRESHRATE, m_nRefreshRate, 1, 99 );
	SetDlgState();

	*pResult = 0;
} /* #OF# CPerformanceDlg::OnDeltaposRefreshSpin */

/*========================================================
Method   : CPerformanceDlg::OnKillfocusRefreshRate
=========================================================*/
/* #FN#
   Sets a state of the object regarding to an appropriate edit control */
void
/* #AS#
   Nothing */
CPerformanceDlg::
OnKillfocusRefreshRate()
{
	_KillfocusSpin( IDC_PERFORMANCE_REFRESHRATE, m_nRefreshRate, 1, 99 );
	SetDlgState();
} /* #OF# CPerformanceDlg::OnKillfocusRefreshRate */

/*========================================================
Method   : CPerformanceDlg::OnDoubleRefreshCheck
=========================================================*/
/* #FN#
   Sets a state of the object regarding to an appropriate check box */
void
/* #AS#
   Nothing */
CPerformanceDlg::
OnDoubleRefreshCheck()
{
	_ClickButton( IDC_PERFORMANCE_DOUBLEREFRESHCHECK, m_ulMiscState, MS_USE_DOUBLE_REFRESH );
	SetDlgState();
} /* #OF# CPerformanceDlg::OnDoubleRefreshCheck */

/*========================================================
Method   : CPerformanceDlg::OnDeltaposDoubleRefreshSpin
=========================================================*/
/* #FN#
   Sets a state of the object regarding to an appropriate spin control */
void
/* #AS#
   Nothing */
CPerformanceDlg::
OnDeltaposDoubleRefreshSpin(
	NMHDR   *pNMHDR, /* #IN#  */
	LRESULT *pResult /* #OUT# */
)
{
	_DeltaposSpin( pNMHDR, IDC_PERFORMANCE_DOUBLEREFRESHRATE, m_nDoubleRate, 1, 99 );
	SetDlgState();

	*pResult = 0;
} /* #OF# CPerformanceDlg::OnDeltaposRefreshSpin */

/*========================================================
Method   : CPerformanceDlg::OnKillfocusDoubleRefreshRate
=========================================================*/
/* #FN#
   Sets a state of the object regarding to an appropriate edit control */
void
/* #AS#
   Nothing */
CPerformanceDlg::
OnKillfocusDoubleRefreshRate()
{
	_KillfocusSpin( IDC_PERFORMANCE_DOUBLEREFRESHRATE, m_nDoubleRate, 1, 99 );
	SetDlgState();
} /* #OF# CPerformanceDlg::OnKillfocusRefreshRate */

/*========================================================
Method   : CPerformanceDlg::OnNoDrawDisplay
=========================================================*/
/* #FN#
   Sets a state of the object regarding to an appropriate check box */
void
/* #AS#
   Nothing */
CPerformanceDlg::
OnNoDrawDisplay()
{
	_ClickButton( IDC_PERFORMANCE_NODRAWDISPLAY, m_ulMiscState, MS_NO_DRAW_DISPLAY );
	SetDlgState();
} /* #OF# CPerformanceDlg::OnNoDrawDisplay */

/*========================================================
Method   : CPerformanceDlg::ReceiveFocused
=========================================================*/
/* #FN#
   Receive the edit controls content again. The user could press
   'Enter' or 'Alt-O' and then all changes he's made in the last
   edited control would be lost. */
void
/* #AS#
   Nothing */
CPerformanceDlg::
ReceiveFocused()
{
	CWnd *pWnd    = GetFocus();
	UINT  nCtrlID = pWnd ? pWnd->GetDlgCtrlID() : 0;

	switch( nCtrlID )
	{
		case IDC_PERFORMANCE_REFRESHRATE:
			OnKillfocusRefreshRate();
			break;
		case IDC_PERFORMANCE_DOUBLEREFRESHRATE:
			OnKillfocusDoubleRefreshRate();
			break;
	}
} /* #OF# CPerformanceDlg::ReceiveFocused */

/*========================================================
Method   : CPerformanceDlg::OnOK
=========================================================*/
/* #FN#
   Called when the user clicks the OK button */
void
/* #AS#
   Nothing */
CPerformanceDlg::
OnOK()
{
	/* Unfortunately, edit controls do not lose the focus before
	   handling this when the user uses accelerators */
	ReceiveFocused();

	if( m_nRefreshRate != refresh_rate )
	{
		refresh_rate = m_nRefreshRate;
		WriteRegDWORD( NULL, REG_REFRESH_RATE, refresh_rate );

		if( !ST_DOUBLE_REFRESH )
			g_nTestVal = refresh_rate - 1;
	}
	if( m_nDoubleRate != g_nDoubleRate )
	{
		g_nDoubleRate = m_nDoubleRate;
		WriteRegDWORD( NULL, REG_DOUBLE_RATE, g_nDoubleRate );

		if( ST_DOUBLE_REFRESH )
			g_nTestVal = g_nDoubleRate - 1;
	}
	if( m_ulMiscState != g_Misc.ulState )
	{
		BOOL bFullSpeed = g_Misc.ulState & MS_FULL_SPEED;

		g_Misc.ulState = m_ulMiscState;
		WriteRegDWORD( NULL, REG_MISC_STATE, g_Misc.ulState );

		if( !bFullSpeed && g_Misc.ulState & MS_FULL_SPEED )
			Sound_Clear( FALSE, FALSE );
		else
		if( bFullSpeed && !(g_Misc.ulState & MS_FULL_SPEED) )
			Sound_Restart();
	}
	if( m_nSpeedPercent != g_nSpeedPercent )
	{
		g_nSpeedPercent = m_nSpeedPercent;
		WriteRegDWORD( NULL, REG_SPEED_PERCENT, g_nSpeedPercent );

		g_Timer.nPalFreq  = (DEF_PAL_FREQUENCY  * m_nSpeedPercent) / 100;
		g_Timer.nNtscFreq = (DEF_NTSC_FREQUENCY * m_nSpeedPercent) / 100;

		/* The Atari timer stuff has to be reinitialised */
		Timer_Reset();

		/* Sound depends on the timer settings */
		Sound_Initialise();

		/* Start an Atari timer */
		Timer_Start( FALSE );
	}
	CCommonDlg::OnOK();
} /* #OF# CPerformanceDlg::OnOK */
