/*
** 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 1, 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.
*/

/*
 * Author : Alexandre Parenteau <aubonbeurre@hotmail.com> --- December 1997
 */

// GetPrefs.cpp : implementation file
//

#include "stdafx.h"

#ifdef qMacCvsPP
#	include <UModalDialogs.h>
#	include <LMultiPanelView.h>
#	include <LEditText.h>
#	include <LPushButton.h>
#	include <LPopupGroupBox.h>

#	include "MacCvsConstant.h"
#	include "MacBinEncoding.h"
#	include "uwidget.h"
#endif /* qMacCvsPP */

#if qUnix
#	include "UCvsDialogs.h"
#	include <gtk/gtk.h>
#   include <gtk/gtkmain.h>
#   include <gtk/gtkfontsel.h>
#endif

#ifdef WIN32
#	include "wincvs.h"
#	include "umain.h"
#	include <afxdao.h>
#	include "wincvs_winutil.h"
#	include "BrowseFileView.h"
#endif /* WIN32 */

#include "GetPrefs.h"
#include "CvsPrefs.h"
#include "Authen.h"
#include "AppConsole.h"
#include "AppGlue.h"
#include "PromptFiles.h"
#include "MultiFiles.h"
#include "CvsArgs.h"
#include "FileTraversal.h"
#include "CvsCommands.h"
#include "CvsAlert.h"

CMString gPrevAltCvs(20, "P_PrevAltCvs");

/*!
	Browse for file
	\param prompt Caption for the dialog
	\param selectionType Selection type
	\param fullpath The initial selection path, return the selected path
	\return true if selection was made, false otherwise
*/
bool BrowseForFile(const char* prompt, const kFilesSelectionType selectionType, CStr& fullpath)
{
	bool res = false;

	MultiFiles mf;
	
	if( !fullpath.empty() )
	{
		if( fullpath.endsWith(kPathDelimiter) )
		{
			mf.newdir(fullpath);
		}
		else
		{
			CStr uppath;
			CStr file;
			
			if( SplitPath(fullpath.c_str(), uppath, file) )
			{
				mf.newdir(uppath);
				mf.newfile(file);
			}
		}
	}
	
	if( BrowserGetMultiFiles(prompt, mf, true, selectionType) )
	{
		CvsArgs args(false);
		
		const char* dir = (*mf.begin()).add(args);
		char* const* argv = args.Argv();
		
		fullpath = dir;
		
		if( !fullpath.endsWith(kPathDelimiter) )
			fullpath << kPathDelimiter;
		
		fullpath << argv[0];

		res = true;
	}

	return res;
}

#ifdef WIN32   //{ Windows-Part

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// Globals options page
IMPLEMENT_DYNCREATE(CGetPrefs_GLOBALS, CHHelpPropertyPage)

CGetPrefs_GLOBALS::CGetPrefs_GLOBALS() 
	: CHHelpPropertyPage(CGetPrefs_GLOBALS::IDD), m_didInteract(false)
{
	//{{AFX_DATA_INIT(CGetPrefs_GLOBALS)
	m_checkoutro = gCvsPrefs.CheckoutRO();
	m_prune = gCvsPrefs.PruneOption();
	m_tcpip = gCvsPrefs.Z9Option();
	m_quiet = gCvsPrefs.QuietOption();
	m_cntladd = gCvsPrefs.AddControl();
	m_alwaysroot = gCvsPrefs.AlwaysUseCvsroot();
	m_logout = gCvsPrefs.LogoutTimeOut() > 0;
	m_unixlf = gCvsPrefs.UnixLF();
	m_zlevel = gCvsPrefs.ZLevel();
	m_disableSplashScreen = gCvsPrefs.DisableSplashScreen();
	m_logoutTime = gCvsPrefs.LogoutTimeOut();
	m_matchEntriesCase = gCvsPrefs.MatchEntriesCase();
	m_encryptCommunication = gCvsPrefs.EncryptCommunication();
	//}}AFX_DATA_INIT
}

CGetPrefs_GLOBALS::~CGetPrefs_GLOBALS()
{
}

void CGetPrefs_GLOBALS::DoDataExchange(CDataExchange* pDX)
{
	m_didInteract = true;

	CHHelpPropertyPage::DoDataExchange(pDX);

	//{{AFX_DATA_MAP(CGetPrefs_GLOBALS)
	DDX_Control(pDX, IDC_SPIN_AUTO_LOGOUT_TIME, m_logoutSpinButton);
	DDX_Control(pDX, IDC_AUTO_LOGOUT_TIME, m_logoutEdit);
	DDX_Control(pDX, IDC_AUTO_LOGOUT, m_logoutCheck);
	DDX_Control(pDX, IDC_SPIN_COMPRESSION, m_zspinSpinButton);
	DDX_Control(pDX, IDC_COMPRESSION, m_zlevelEdit);
	DDX_Control(pDX, IDC_HAS_COMPRESSION, m_tcpipCheck);
	DDX_Check(pDX, IDC_CHECKOUT_READ_ONLY, m_checkoutro);
	DDX_Check(pDX, IDC_PRUNE_EMPTY_DIR, m_prune);
	DDX_Check(pDX, IDC_HAS_COMPRESSION, m_tcpip);
	DDX_Check(pDX, IDC_QUIET, m_quiet);
	DDX_Check(pDX, IDC_CONTROL_ADDED_FILES, m_cntladd);
	DDX_Check(pDX, IDC_ALWAYSROOT, m_alwaysroot);
	DDX_Check(pDX, IDC_AUTO_LOGOUT, m_logout);
	DDX_Check(pDX, IDC_UNIX_LF, m_unixlf);
	DDX_Text(pDX, IDC_COMPRESSION, m_zlevel);
	DDV_MinMaxUInt(pDX, m_zlevel, 1, 9);
	DDX_Check(pDX, IDC_NO_SPLASH_SCREEN, m_disableSplashScreen);
	DDX_Text(pDX, IDC_AUTO_LOGOUT_TIME, m_logoutTime);
	DDV_MinMaxUInt(pDX, m_logoutTime, 0, 999999);
	DDX_Check(pDX, IDC_MATCH_ENTRIES_CASE, m_matchEntriesCase);
	DDX_Check(pDX, IDC_ENCRYPTION, m_encryptCommunication);
	//}}AFX_DATA_MAP

	if( !pDX->m_bSaveAndValidate )
	{
		OnTcpip();
		OnLogout();
	}
}

/// Save the values
void CGetPrefs_GLOBALS::StoreValues()
{
	if( !m_didInteract )
		return;

	bool needsRefresh = gCvsPrefs.MatchEntriesCase() != (m_matchEntriesCase != 0);

	gCvsPrefs.SetCheckoutRO(m_checkoutro ? true : false);
	gCvsPrefs.SetPruneOption(m_prune ? true : false);
	gCvsPrefs.SetZ9Option(m_tcpip ? true : false);
	gCvsPrefs.SetQuietOption(m_quiet ? true : false);
	gCvsPrefs.SetAddControl(m_cntladd ? true : false);
	gCvsPrefs.SetAlwaysUseCvsroot(m_alwaysroot ? true : false);
	gCvsPrefs.SetLogoutTimeOut(m_logout ? (int)m_logoutTime : 0);
	gCvsPrefs.SetUnixLF(m_unixlf != 0);
	gCvsPrefs.SetZLevel(m_zlevel);
	gCvsPrefs.SetDisableSplashScreen(m_disableSplashScreen ? true : false);
	gCvsPrefs.SetMatchEntriesCase(m_matchEntriesCase ? true : false);
	gCvsPrefs.SetEncryptCommunication(m_encryptCommunication ? true : false);

	if( needsRefresh )
	{
		if( CWincvsApp* app = (CWincvsApp*)AfxGetApp() )
		{
			app->GetFileView()->ResetView(true);
		}
	}
}

BEGIN_MESSAGE_MAP(CGetPrefs_GLOBALS, CHHelpPropertyPage)
	//{{AFX_MSG_MAP(CGetPrefs_GLOBALS)
	ON_BN_CLICKED(IDC_AUTO_LOGOUT, OnLogout)
	ON_BN_CLICKED(IDC_UNIX_LF, OnCheckunixlf)
	ON_BN_CLICKED(IDC_HAS_COMPRESSION, OnTcpip)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/// OnInitDialog virtual override, setup help IDs and spin controls
BOOL CGetPrefs_GLOBALS::OnInitDialog() 
{
	CHHelpPropertyPage::OnInitDialog();
	
	// Extra initialization
	m_logoutSpinButton.SetBase(10);
	m_logoutSpinButton.SetRange(0, 30000);
	
	m_zspinSpinButton.SetBase(1);
	m_zspinSpinButton.SetRange(1, 9);
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CGetPrefs_GLOBALS::InitHelpID()
{
	SetCtrlHelpID(IDC_CHECKOUT_READ_ONLY,		IDH_IDC_CHECKOUT_READ_ONLY);
	SetCtrlHelpID(IDC_QUIET,					IDH_IDC_QUIET);
	SetCtrlHelpID(IDC_PRUNE_EMPTY_DIR,			IDH_IDC_PRUNE_EMPTY_DIR);
	SetCtrlHelpID(IDC_HAS_COMPRESSION,			IDH_IDC_HAS_COMPRESSION);
	SetCtrlHelpID(IDC_COMPRESSION,				IDH_IDC_COMPRESSION);
	SetCtrlHelpID(IDC_SPIN_COMPRESSION,			IDH_IDC_SPIN_COMPRESSION);
	SetCtrlHelpID(IDC_ENCRYPTION,				IDH_IDC_ENCRYPTION);
	SetCtrlHelpID(IDC_UNIX_LF,					IDH_IDC_UNIX_LF);
	SetCtrlHelpID(IDC_NO_SPLASH_SCREEN,			IDH_IDC_NO_SPLASH_SCREEN);
	SetCtrlHelpID(IDC_CONTROL_ADDED_FILES,		IDH_IDC_CONTROL_ADDED_FILES);
	SetCtrlHelpID(IDC_MATCH_ENTRIES_CASE,		IDH_IDC_MATCH_ENTRIES_CASE);
	SetCtrlHelpID(IDC_AUTO_LOGOUT,				IDH_IDC_AUTO_LOGOUT);
	SetCtrlHelpID(IDC_AUTO_LOGOUT_TIME,			IDH_IDC_AUTO_LOGOUT_TIME);
	SetCtrlHelpID(IDC_SPIN_AUTO_LOGOUT_TIME,	IDH_IDC_SPIN_AUTO_LOGOUT_TIME);
}

/// BN_CLICKED message handler, enable controls
void CGetPrefs_GLOBALS::OnTcpip() 
{
	m_zlevelEdit.EnableWindow(m_tcpipCheck.GetCheck() != 0);
	m_zspinSpinButton.EnableWindow(m_tcpipCheck.GetCheck() != 0);
}

/// BN_CLICKED message handler, enable controls
void CGetPrefs_GLOBALS::OnLogout() 
{
	m_logoutEdit.EnableWindow(m_logoutCheck.GetCheck() != 0);
	m_logoutSpinButton.EnableWindow(m_logoutCheck.GetCheck() != 0);
}

/// BN_CLICKED message handler, display the warning about changing the line endings
void CGetPrefs_GLOBALS::OnCheckunixlf() 
{
	CvsAlert(kCvsAlertNoteIcon, "File-translation mode change.", 
		"Be careful when using this option!\n"
		"You can't use WinCvs in both modes - you have to use either Unix or DOS line feeds. "
		"If you experience some problems try to remove the global CVS files (such as .cvspass) because "
		"they probably don't match the new line feeds setting.").ShowAlert();
}

// WinCvs options page
IMPLEMENT_DYNCREATE(CGetPrefs_WINCVS, CHHelpPropertyPage)

CGetPrefs_WINCVS::CGetPrefs_WINCVS() 
	: CHHelpPropertyPage(CGetPrefs_WINCVS::IDD), m_didInteract(false)
{
	//{{AFX_DATA_INIT(CGetPrefs_WINCVS)
	m_viewer = gCvsPrefs.Viewer() != 0L ? gCvsPrefs.Viewer() : "";
	m_useExtDiff = gCvsPrefs.ExtDiff() != 0L;
	m_diffProg = gCvsPrefs.ExtDiff();
	m_useSettingsFolder = gCvsPrefs.SettingsFolder() != 0L;
	m_settingsFolder = gCvsPrefs.SettingsFolder() != 0L ? gCvsPrefs.SettingsFolder() : "";
	m_tclDll = gCvsPrefs.TclLibrary() != 0L ? gCvsPrefs.TclLibrary() : "";
	m_pythonDll = gCvsPrefs.PythonLibrary() != 0L ? gCvsPrefs.PythonLibrary() : "";
	//}}AFX_DATA_INIT
}

CGetPrefs_WINCVS::~CGetPrefs_WINCVS()
{
}

void CGetPrefs_WINCVS::DoDataExchange(CDataExchange* pDX)
{
	m_didInteract = true;

	CHHelpPropertyPage::DoDataExchange(pDX);

	//{{AFX_DATA_MAP(CGetPrefs_WINCVS)
	DDX_Control(pDX, IDC_PYTHONDLL, m_pythonDllEdit);
	DDX_Control(pDX, IDC_TCLDLL, m_tclDllEdit);
	DDX_Control(pDX, IDC_EXTERNAL_EDITOR, m_viewerEdit);
	DDX_Control(pDX, IDC_BROWSE_EXTERNAL_DIFF, m_extDiffSelButton);
	DDX_Control(pDX, IDC_EXTERNAL_DIFF, m_diffProgEdit);
	DDX_Control(pDX, IDC_HAS_EXTERNAL_DIFF, m_useExtDiffCheck);
	DDX_Control(pDX, IDC_ALTERNATE_SETTINGS, m_settingsFolderEdit);
	DDX_Control(pDX, IDC_BROWSE_ALTERNATE_SETTINGS, m_settingsFolderButton);
	DDX_Control(pDX, IDC_HAS_ALTERNATE_SETTINGS, m_useSettingsFolderCheck);
	DDX_Text(pDX, IDC_EXTERNAL_EDITOR, m_viewer);
	DDX_Check(pDX, IDC_HAS_EXTERNAL_DIFF, m_useExtDiff);
	DDX_Text(pDX, IDC_EXTERNAL_DIFF, m_diffProg);
	DDX_Check(pDX, IDC_HAS_ALTERNATE_SETTINGS, m_useSettingsFolder);
	DDX_Text(pDX, IDC_ALTERNATE_SETTINGS, m_settingsFolder);
	DDX_Text(pDX, IDC_TCLDLL, m_tclDll);
	DDX_Text(pDX, IDC_PYTHONDLL, m_pythonDll);
	//}}AFX_DATA_MAP

	if( m_useSettingsFolder )
	{
		DDV_MinChars(pDX, m_settingsFolder, 1);
		DDV_CheckPathExists(pDX, IDC_ALTERNATE_SETTINGS, m_settingsFolder);
	}

	if( !pDX->m_bSaveAndValidate )
	{
		OnExtdiff();
		OnAltsettingschk();
	}
}

/// Save the values
void CGetPrefs_WINCVS::StoreValues()
{
	if( !m_didInteract )
		return;

	gCvsPrefs.SetViewer(!m_viewer.IsEmpty() ? (LPCTSTR)m_viewer : 0L);
	gCvsPrefs.SetExtDiff(m_useExtDiff && !m_diffProg.IsEmpty() ? (LPCTSTR)m_diffProg : 0L);
	gCvsPrefs.SetSettingsFolder(m_useSettingsFolder && !m_settingsFolder.IsEmpty() ? (LPCTSTR)m_settingsFolder : 0L);

	const bool restartScriptEngine = m_tclDll != CString(gCvsPrefs.TclLibrary()) || m_pythonDll != CString(gCvsPrefs.PythonLibrary());

	gCvsPrefs.SetTclLibrary(!m_tclDll.IsEmpty() ? (LPCTSTR)m_tclDll : 0L);
	gCvsPrefs.SetPythonLibrary(!m_pythonDll.IsEmpty() ? (LPCTSTR)m_pythonDll : 0L);

	if( restartScriptEngine )
	{
		CWincvsApp* app = (CWincvsApp*)AfxGetApp();
		if( app )
		{
			app->RestartScriptEngine();
		}
	}
}

BEGIN_MESSAGE_MAP(CGetPrefs_WINCVS, CHHelpPropertyPage)
	//{{AFX_MSG_MAP(CGetPrefs_WINCVS)
	ON_BN_CLICKED(IDC_BROWSE_EXTERNAL_EDITOR, OnBtnviewer)
	ON_BN_CLICKED(IDC_BROWSE_EXTERNAL_DIFF, OnExtdiffsel)
	ON_BN_CLICKED(IDC_HAS_EXTERNAL_DIFF, OnExtdiff)
	ON_BN_CLICKED(IDC_HAS_ALTERNATE_SETTINGS, OnAltsettingschk)
	ON_BN_CLICKED(IDC_BROWSE_ALTERNATE_SETTINGS, OnBtnsettings)
	ON_BN_CLICKED(IDC_BROWSE_TCLDLL, OnTcldllsel)
	ON_BN_CLICKED(IDC_BROWSE_PYTHONDLL, OnPythondllsel)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/// OnInitDialog virtual override, setup autocomplete and help IDs
BOOL CGetPrefs_WINCVS::OnInitDialog() 
{
	CHHelpPropertyPage::OnInitDialog();
	
	// Extra initialization
	EnableEditAutoComplete(&m_pythonDllEdit);
	EnableEditAutoComplete(&m_tclDllEdit);
	EnableEditAutoComplete(&m_viewerEdit);
	EnableEditAutoComplete(&m_diffProgEdit);
	EnableEditAutoComplete(&m_settingsFolderEdit);
	
	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

void CGetPrefs_WINCVS::InitHelpID()
{
	SetCtrlHelpID(IDC_HAS_EXTERNAL_DIFF,			IDH_IDC_HAS_EXTERNAL_DIFF);
	SetCtrlHelpID(IDC_EXTERNAL_DIFF,				IDH_IDC_EXTERNAL_DIFF);
	SetCtrlHelpID(IDC_BROWSE_EXTERNAL_DIFF,			IDH_IDC_BROWSE_FILENAME);
	SetCtrlHelpID(IDC_EXTERNAL_EDITOR,				IDH_IDC_EXTERNAL_EDITOR);
	SetCtrlHelpID(IDC_BROWSE_EXTERNAL_EDITOR,		IDH_IDC_BROWSE_FILENAME);
	SetCtrlHelpID(IDC_PYTHONDLL,					IDH_IDC_PYTHONDLL);
	SetCtrlHelpID(IDC_BROWSE_PYTHONDLL,				IDH_IDC_BROWSE_FILENAME);
	SetCtrlHelpID(IDC_TCLDLL,						IDH_IDC_TCLDLL);
	SetCtrlHelpID(IDC_BROWSE_TCLDLL,				IDH_IDC_BROWSE_FILENAME);
	SetCtrlHelpID(IDC_HAS_ALTERNATE_SETTINGS,		IDH_IDC_HAS_ALTERNATE_SETTINGS);
	SetCtrlHelpID(IDC_ALTERNATE_SETTINGS,			IDH_IDC_ALTERNATE_SETTINGS);
	SetCtrlHelpID(IDC_BROWSE_ALTERNATE_SETTINGS,	IDH_IDC_BROWSE_FILENAME);
}

/// BN_CLICKED message handler, change default viewer used to open files
void CGetPrefs_WINCVS::OnBtnviewer()
{
	CString viewerPath;
	m_viewerEdit.GetWindowText(viewerPath);
	
	CStr fullpath = viewerPath;
	if( BrowseForFile("Select the viewer application", kSelectExecutable, fullpath) )
	{
		m_viewerEdit.SetWindowText(fullpath);
	}
}

/// BN_CLICKED message handler, change external diff program
void CGetPrefs_WINCVS::OnExtdiffsel()
{
	CString diffProg;
	m_diffProgEdit.GetWindowText(diffProg);

	CStr fullpath = diffProg;
	if( BrowseForFile("Select the external diff application", kSelectExecutable, fullpath) )
	{
		m_diffProgEdit.SetWindowText(fullpath);
	}
}

/// BN_CLICKED message handler, select TCL DLL path
void CGetPrefs_WINCVS::OnTcldllsel() 
{
	CString tclDll;
	m_tclDllEdit.GetWindowText(tclDll);
	
	CStr fullpath = tclDll;
	if( BrowseForFile("Select the TCL DLL", kSelectDll, fullpath) )
	{
		m_tclDllEdit.SetWindowText(fullpath);
	}
}

/// BN_CLICKED message handler, select Python DLL path
void CGetPrefs_WINCVS::OnPythondllsel() 
{
	CString pythonDll;
	m_pythonDllEdit.GetWindowText(pythonDll);
	
	CStr fullpath = pythonDll;
	if( BrowseForFile("Select the Python DLL", kSelectDll, fullpath) )
	{
		m_pythonDllEdit.SetWindowText(fullpath);
	}
}

/// BN_CLICKED message handler, enable to change external diff program
void CGetPrefs_WINCVS::OnExtdiff() 
{
	m_diffProgEdit.EnableWindow(m_useExtDiffCheck.GetCheck() != 0);
	m_extDiffSelButton.EnableWindow(m_useExtDiffCheck.GetCheck() != 0);
}

/// BN_CLICKED message handler, enable to change settings folder
void CGetPrefs_WINCVS::OnAltsettingschk() 
{
	const bool useSettingsFolder = m_useSettingsFolderCheck.GetCheck() != 0;
	
	m_settingsFolderEdit.EnableWindow(useSettingsFolder);
	m_settingsFolderButton.EnableWindow(useSettingsFolder);

	if( useSettingsFolder )
	{
		CString strSettingsFolder;
		m_settingsFolderEdit.GetWindowText(strSettingsFolder);

		if( strSettingsFolder.IsEmpty() )
		{
			CStr settingsFolder;
			if( FormatDefaultSettingsLoc(settingsFolder) )
			{
				m_settingsFolderEdit.SetWindowText(settingsFolder);
			}
		}
	}
}

/// BN_CLICKED message handler, change settings folder
void CGetPrefs_WINCVS::OnBtnsettings() 
{
	CString strSettingsFolder;
    m_settingsFolderEdit.GetWindowText(strSettingsFolder);
	
	CStr settingsFolder(strSettingsFolder);
	if( BrowserGetDirectory("Select the settings directory", settingsFolder, IsWindow(m_hWnd) ? this : NULL) )
	{
		m_settingsFolderEdit.SetWindowText(settingsFolder);
	}
}

//////////////////////////////////////////////////////////////////////////
// CGetPrefs_CVS

IMPLEMENT_DYNCREATE(CGetPrefs_CVS, CHHelpPropertyPage)

CGetPrefs_CVS::CGetPrefs_CVS() 
	: CHHelpPropertyPage(CGetPrefs_CVS::IDD), m_didInteract(false), m_showCvsCombo(CSmartComboBox::AutoDropWidth)
{
	UStr cvsPath;

	//{{AFX_DATA_INIT(CGetPrefs_CVS)
	m_home = gCvsPrefs.Home() != 0L ? gCvsPrefs.Home() : "";
	m_useAltCvs = gCvsPrefs.WhichCvs(cvsPath, true) != 0L;
	m_cvsConsole = gCvsPrefs.CvsConsole();
	m_showCvs = gCvsPrefs.ShowCvs();
	m_altCvs = gCvsPrefs.WhichCvs(cvsPath);
	//}}AFX_DATA_INIT

	m_altCvsCombo.SetItems(&gPrevAltCvs);
}

CGetPrefs_CVS::~CGetPrefs_CVS()
{
}

void CGetPrefs_CVS::DoDataExchange(CDataExchange* pDX)
{
	m_didInteract = true;

	CHHelpPropertyPage::DoDataExchange(pDX);

	//{{AFX_DATA_MAP(CGetPrefs_CVS)
	DDX_Control(pDX, IDC_ALTERNATE_CVS, m_altCvsCombo);
	DDX_Control(pDX, IDC_CONSOLE, m_cvsConsoleCheck);
	DDX_Control(pDX, IDC_SHOW_CVS_METHOD, m_showCvsCombo);
	DDX_Control(pDX, IDC_BROWSE_FILENAME, m_selAltCvsButton);
	DDX_Control(pDX, IDC_HAS_ALTERNATE_CVS, m_useAltCvsCheck);
	DDX_Control(pDX, IDC_HOME, m_homeEdit);
	DDX_Text(pDX, IDC_HOME, m_home);
	DDX_Check(pDX, IDC_HAS_ALTERNATE_CVS, m_useAltCvs);
	DDX_Check(pDX, IDC_CONSOLE, m_cvsConsole);
	DDX_CBIndex(pDX, IDC_SHOW_CVS_METHOD, m_showCvs);
	DDX_CBString(pDX, IDC_ALTERNATE_CVS, m_altCvs);
	//}}AFX_DATA_MAP

	DDV_CheckPathExists(pDX, IDC_HOME, m_home);
	
	if( !pDX->m_bSaveAndValidate )
	{
		OnAltcvschk();
	}

	if( m_useAltCvs )
	{
		DDV_MinChars(pDX, m_altCvs, 1);
		DDX_ComboMString(pDX, IDC_ALTERNATE_CVS, m_altCvsCombo);
	}
}

BEGIN_MESSAGE_MAP(CGetPrefs_CVS, CHHelpPropertyPage)
	//{{AFX_MSG_MAP(CGetPrefs_CVS)
	ON_BN_CLICKED(IDC_BROWSE_PATH, OnBtnhome)
	ON_BN_CLICKED(IDC_HAS_ALTERNATE_CVS, OnAltcvschk)
	ON_BN_CLICKED(IDC_BROWSE_FILENAME, OnAltcvssel)
	ON_BN_CLICKED(IDC_CONSOLE, OnConsole)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/// OnInitDialog virtual override, initialize controls
BOOL CGetPrefs_CVS::OnInitDialog() 
{
	CHHelpPropertyPage::OnInitDialog();
	
	// Extra initialization
	EnableEditAutoComplete(m_altCvsCombo.GetEditCtrl());
	EnableEditAutoComplete(&m_homeEdit);

	m_showCvsCombo.AddString("Hidden");
	m_showCvsCombo.AddString("Normal Window");
	m_showCvsCombo.AddString("Non-active Window");
	m_showCvsCombo.AddString("Minimized non-active Window");

	m_showCvsCombo.SetCurSel(gCvsPrefs.ShowCvs());

	if( m_cvsConsole )
	{
		m_showCvsCombo.EnableWindow(FALSE);
	}
	
	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

void CGetPrefs_CVS::InitHelpID()
{
	SetCtrlHelpID(IDC_HOME,					IDH_IDC_HOME);
	SetCtrlHelpID(IDC_BROWSE_PATH,			IDH_IDC_BROWSE_PATH);
	SetCtrlHelpID(IDC_HAS_ALTERNATE_CVS,	IDH_IDC_HAS_ALTERNATE_CVS);
	SetCtrlHelpID(IDC_ALTERNATE_CVS,		IDH_IDC_ALTERNATE_CVS);
	SetCtrlHelpID(IDC_BROWSE_FILENAME,		IDH_IDC_BROWSE_FILENAME);
	SetCtrlHelpID(IDC_CONSOLE,				IDH_IDC_CONSOLE);
	SetCtrlHelpID(IDC_SHOW_CVS_METHOD,		IDH_IDC_SHOW_CVS_METHOD);
}

/// BN_CLICKED message handler, enable show console combo box
void CGetPrefs_CVS::OnConsole() 
{
	m_showCvsCombo.EnableWindow(!m_cvsConsoleCheck.GetCheck());
}

/// Save the values
void CGetPrefs_CVS::StoreValues()
{
	if( !m_didInteract )
		return;

	gCvsPrefs.SetHome(m_home);
	gCvsPrefs.SetWhichCvs(m_useAltCvs && !m_altCvs.IsEmpty() ? (LPCTSTR)m_altCvs : "");
	gCvsPrefs.SetCvsConsole(m_cvsConsole != 0);
	gCvsPrefs.SetShowCvs((SHOWCVS_TYPE)m_showCvs);
}

/// BN_CLICKED message handler, change HOME directory
void CGetPrefs_CVS::OnBtnhome()
{
	CString strHome;
    m_homeEdit.GetWindowText(strHome);
	
	CStr home(strHome);
	if( BrowserGetDirectory("Select the HOME directory", home, IsWindow(m_hWnd) ? this : NULL) )
	{
		m_homeEdit.SetWindowText(home);
	}
}

/// BN_CLICKED message handler, enable to change alternate CVS executable
void CGetPrefs_CVS::OnAltcvschk() 
{
	m_altCvsCombo.EnableWindow(m_useAltCvsCheck.GetCheck() != 0);
	m_selAltCvsButton.EnableWindow(m_useAltCvsCheck.GetCheck() != 0);
}

/// BN_CLICKED message handler, change alternate CVS executable
void CGetPrefs_CVS::OnAltcvssel() 
{
	CString altCvs;
	m_altCvsCombo.GetWindowText(altCvs);
	
	CStr fullpath = altCvs;
	if( BrowseForFile("Select the CVS client application", kSelectExecutable, fullpath) )
	{
		m_altCvsCombo.SetWindowText(fullpath);
	}
}

//////////////////////////////////////////////////////////////////////////
// CGetPrefs_CVSCMD_DIALOGS

// Command Dialogs options page
IMPLEMENT_DYNCREATE(CGetPrefs_CVSCMD_DIALOGS, CHHelpPropertyPage)

CGetPrefs_CVSCMD_DIALOGS::CGetPrefs_CVSCMD_DIALOGS() 
	: CHHelpPropertyPage(CGetPrefs_CVSCMD_DIALOGS::IDD), m_didInteract(false)
{
	//{{AFX_DATA_INIT(CGetPrefs_CVSCMD_DIALOGS)
	m_hideUpdate = gCvsPrefs.HideCommandDlgUpdate() != 0L;
	m_hideDiff = gCvsPrefs.HideCommandDlgDiff() != 0L;
	m_hideGraph = gCvsPrefs.HideCommandDlgGraph() != 0L;
	m_hideLog = gCvsPrefs.HideCommandDlgLog() != 0L;
	m_keyForce = gCvsPrefs.HideCommandDlgUseShift() != 0L ? 0 : 1;
	m_hideAnnotate = gCvsPrefs.HideCommandDlgAnnotate() != 0L;
	m_hideStatus = gCvsPrefs.HideCommandDlgStatus() != 0L;
	m_fileAction = gCvsPrefs.HideCommandDlgFileAction() != 0L;
	m_ctrlPressedOnOK = gCvsPrefs.CtrlPressedOnOK() != 0L;
	//}}AFX_DATA_INIT
}

CGetPrefs_CVSCMD_DIALOGS::~CGetPrefs_CVSCMD_DIALOGS()
{
}

void CGetPrefs_CVSCMD_DIALOGS::DoDataExchange(CDataExchange* pDX)
{
	m_didInteract = true;

	CHHelpPropertyPage::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CGetPrefs_CVSCMD_DIALOGS)
	DDX_Check(pDX, IDC_SKIP_UPDATE, m_hideUpdate);
	DDX_Check(pDX, IDC_SKIP_DIFF, m_hideDiff);
	DDX_Check(pDX, IDC_SKIP_GRAPH, m_hideGraph);
	DDX_Check(pDX, IDC_SKIP_LOG, m_hideLog);
	DDX_Radio(pDX, IDC_FORCE_KEY_SHIFT, m_keyForce);
	DDX_Check(pDX, IDC_SKIP_ANNOTATE, m_hideAnnotate);
	DDX_Check(pDX, IDC_SKIP_STATUS, m_hideStatus);
	DDX_Check(pDX, IDC_CTRL_PRESSED_ON_OK, m_ctrlPressedOnOK);
	DDX_Check(pDX, IDC_SKIP_FILEACTION, m_fileAction);
	//}}AFX_DATA_MAP
}

/// Save the values
void CGetPrefs_CVSCMD_DIALOGS::StoreValues()
{
	if( !m_didInteract )
		return;

	gCvsPrefs.SetHideCommandDlgUpdate(m_hideUpdate ? true : false);
	gCvsPrefs.SetHideCommandDlgDiff(m_hideDiff ? true : false);
	gCvsPrefs.SetHideCommandDlgGraph(m_hideGraph ? true : false);
	gCvsPrefs.SetHideCommandDlgAnnotate(m_hideAnnotate ? true : false);
	gCvsPrefs.SetHideCommandDlgLog(m_hideLog ? true : false);
	gCvsPrefs.SetHideCommandDlgStatus(m_hideStatus ? true : false);
	gCvsPrefs.SetHideCommandDlgFileAction(m_fileAction ? true : false);
	gCvsPrefs.SetHideCommandDlgUseShift(m_keyForce == 0);
	gCvsPrefs.SetCtrlPressedOnOK(m_ctrlPressedOnOK ? true : false);
}

BEGIN_MESSAGE_MAP(CGetPrefs_CVSCMD_DIALOGS, CHHelpPropertyPage)
//{{AFX_MSG_MAP(CGetPrefs_CVSCMD_DIALOGS)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CGetPrefs_CVSCMD_DIALOGS::InitHelpID()
{
	SetCtrlHelpID(IDC_SKIP_UPDATE,			IDH_IDC_SKIP_UPDATE);
	SetCtrlHelpID(IDC_SKIP_DIFF,			IDH_IDC_SKIP_DIFF);
	SetCtrlHelpID(IDC_SKIP_GRAPH,			IDH_IDC_SKIP_GRAPH);
	SetCtrlHelpID(IDC_SKIP_LOG,				IDH_IDC_SKIP_LOG);
	SetCtrlHelpID(IDC_SKIP_ANNOTATE,		IDH_IDC_SKIP_ANNOTATE);
	SetCtrlHelpID(IDC_SKIP_STATUS,			IDH_IDC_SKIP_STATUS);
	SetCtrlHelpID(IDC_SKIP_FILEACTION,		IDH_IDC_SKIP_FILEACTION);
	SetCtrlHelpID(IDC_FORCE_KEY_SHIFT,		IDH_IDC_FORCE_KEY_SHIFT);
	SetCtrlHelpID(IDC_FORCE_KEY_CTRL,		IDH_IDC_FORCE_KEY_CTRL);
	SetCtrlHelpID(IDC_CTRL_PRESSED_ON_OK,	IDH_IDC_CTRL_PRESSED_ON_OK);
}

/////////////////////////////////////////////////////////////////////////////
// CGetPrefs_General property page

IMPLEMENT_DYNCREATE(CGetPrefs_General, CHHelpPropertyPage)

CGetPrefs_General::CGetPrefs_General() : CHHelpPropertyPage(CGetPrefs_General::IDD)
{
	//{{AFX_DATA_INIT(CGetPrefs_General)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}

CGetPrefs_General::~CGetPrefs_General()
{
}

void CGetPrefs_General::DoDataExchange(CDataExchange* pDX)
{
	CHHelpPropertyPage::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CGetPrefs_General)
	DDX_Control(pDX, IDC_CVSROOT_MIGRATION_URL, m_cvsrootMigration);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CGetPrefs_General, CHHelpPropertyPage)
	//{{AFX_MSG_MAP(CGetPrefs_General)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGetPrefs_General message handlers

BOOL CGetPrefs_General::OnInitDialog() 
{
	CHHelpPropertyPage::OnInitDialog();
	
	// Extra initialization
	m_cvsrootMigration.SetURL("http://cvsgui.sourceforge.net/newfaq.htm#CvsrootWizard");
	
	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

void CGetPrefs_General::InitHelpID()
{
	SetCtrlHelpID(IDC_CVSROOT_MIGRATION_URL, helpTopicIgnore);
}

#endif //} WIN32

#if qUnix    //{ Unix-Part
class UCvsPrefs_MAIN : public UWidget
{
	UDECLARE_DYNAMIC(UCvsPrefs_MAIN)
public:
	UCvsPrefs_MAIN() : UWidget(::UEventGetWidID()) {}
	virtual ~UCvsPrefs_MAIN() {}

	enum
	{
		kOK = EV_COMMAND_START,	// 0
		kCancel,				// 1
		kTabGeneral				// 2
	};

	virtual void DoDataExchange(bool fill);
	
protected:
	ev_msg int OnOK(void);
	ev_msg int OnCancel(void);

	UDECLARE_MESSAGE_MAP()
};

UIMPLEMENT_DYNAMIC(UCvsPrefs_MAIN, UWidget)

UBEGIN_MESSAGE_MAP(UCvsPrefs_MAIN, UWidget)
	ON_UCOMMAND(UCvsPrefs_MAIN::kOK, UCvsPrefs_MAIN::OnOK)
	ON_UCOMMAND(UCvsPrefs_MAIN::kCancel, UCvsPrefs_MAIN::OnCancel)
UEND_MESSAGE_MAP()

int UCvsPrefs_MAIN::OnOK(void)
{
	EndModal(true);
	return 0;
}

int UCvsPrefs_MAIN::OnCancel(void)
{
	EndModal(false);
	return 0;
}

void UCvsPrefs_MAIN::DoDataExchange(bool fill)
{
	if(fill)
	{
	}
	else
	{
	}
}

class UCvsPrefs_CVSROOT : public UWidget
{
	UDECLARE_DYNAMIC(UCvsPrefs_CVSROOT)
public:
	UCvsPrefs_CVSROOT();
	virtual ~UCvsPrefs_CVSROOT() {}

	enum
	{
		kCvsrootCombo = EV_COMMAND_START,	// 0
		kRshRadio,				// 1
		kPserverRadio,			// 2
		kLocalRadio,			// 3
		kSshRadio,				// 4
		kKerberosRadio,			// 5
		kCvsVersionCombo,		// 6
		kCvsConsoleRadio		// 7
	};

	virtual void DoDataExchange(bool fill);

	void StoreValues(void);
	
protected:
	UStr m_cvsroot;
	AuthenKind m_kind;
	bool m_console;
	int m_versCombo;

	UDECLARE_MESSAGE_MAP()
};

UIMPLEMENT_DYNAMIC(UCvsPrefs_CVSROOT, UWidget)

UBEGIN_MESSAGE_MAP(UCvsPrefs_CVSROOT, UWidget)
UEND_MESSAGE_MAP()

UCvsPrefs_CVSROOT::UCvsPrefs_CVSROOT() : UWidget(::UEventGetWidID())
{
	if(!gCvsPrefs.empty())
		m_cvsroot = (const char *)gCvsPrefs;
	m_kind    = gAuthen.kind();
	m_console = gCvsPrefs.CvsConsole();
	m_versCombo = gCvsPrefs.CvsVersion();
}

void UCvsPrefs_CVSROOT::StoreValues(void)
{
	gCvsPrefs = m_cvsroot;
	gAuthen.setkind(m_kind);
	gCvsPrefs.SetCvsConsole(m_console != 0);
	gCvsPrefs.SetCvsVersion(m_versCombo);
}

void UCvsPrefs_CVSROOT::DoDataExchange(bool fill)
{
	::DoDataExchange(fill, GetWidID(), kCvsrootCombo, gOldCvsroots);
		
	if(fill)
	{
		UEventSendMessage(GetWidID(), EV_SETTEXT, kCvsrootCombo, (void *)(const char *)m_cvsroot);

		int item = kLocalRadio;
		
		switch(m_kind)
		{
		case local: item = kLocalRadio; break;
		case kserver: item = kKerberosRadio; break;
		case rhosts: item = kRshRadio; break;
		case pserver: item = kPserverRadio; break;
		case ssh: item = kSshRadio; break;
		case ntserver: break;	// not supported under *nix
		case gserver: break;	// not supported under *nix
		case server: break;		// not supported under *nix
		case sspi: break;		// not supported under *nix
		}
		
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(item, 1), 0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kCvsConsoleRadio, m_console), 0L);
		UEventSendMessage(GetWidID(), EV_COMBO_SETSEL, UMAKEINT(kCvsVersionCombo,m_versCombo), 0L);

	}
	else
	{
		UEventSendMessage(GetWidID(), EV_GETTEXT, kCvsrootCombo, &m_cvsroot);

		m_kind = local;
		if(UEventSendMessage(GetWidID(), EV_QUERYSTATE, kLocalRadio, 0L))
			m_kind = local;
		else if(UEventSendMessage(GetWidID(), EV_QUERYSTATE, kKerberosRadio, 0L))
			m_kind = kserver;
		else if(UEventSendMessage(GetWidID(), EV_QUERYSTATE, kRshRadio, 0L))
			m_kind = rhosts;
		else if(UEventSendMessage(GetWidID(), EV_QUERYSTATE, kPserverRadio, 0L))
			m_kind = pserver;
		else if(UEventSendMessage(GetWidID(), EV_QUERYSTATE, kSshRadio, 0L))
			m_kind = ssh;
		
		m_console = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kCvsConsoleRadio, 0L) != 0;
		m_versCombo = UEventSendMessage(GetWidID(), EV_COMBO_GETSEL, kCvsVersionCombo, 0L);
	}
}

class UCvsPrefs_GLOBALS : public UWidget
{
	UDECLARE_DYNAMIC(UCvsPrefs_GLOBALS)
public:
	UCvsPrefs_GLOBALS();
	virtual ~UCvsPrefs_GLOBALS() {}

	enum
	{
		kcheckoutro = EV_COMMAND_START,	// 0
		kdirty,					// 1
		ktcpip,					// 2
		kprune,					// 3
		kquiet,					// 4
		kcntladd,				// 5
		kzlevel                 // 6
	};

	virtual void DoDataExchange(bool fill);
	
	void StoreValues(void);
	int  OnTcpip(void);

protected:
	bool m_checkoutro;
	bool m_dirty;
	bool m_tcpip;
	bool m_prune;
	bool m_quiet;
	bool m_cntladd;
	int  m_zlevel;

	UDECLARE_MESSAGE_MAP()
};

UIMPLEMENT_DYNAMIC(UCvsPrefs_GLOBALS, UWidget)

UBEGIN_MESSAGE_MAP(UCvsPrefs_GLOBALS, UWidget)
	ON_UCOMMAND(UCvsPrefs_GLOBALS::ktcpip, UCvsPrefs_GLOBALS::OnTcpip)
UEND_MESSAGE_MAP()

UCvsPrefs_GLOBALS::UCvsPrefs_GLOBALS() : UWidget(::UEventGetWidID())
{
	m_checkoutro = gCvsPrefs.CheckoutRO();
	m_prune      = gCvsPrefs.PruneOption();
	m_tcpip      = gCvsPrefs.Z9Option();
	m_quiet      = gCvsPrefs.QuietOption();
	m_cntladd    = gCvsPrefs.AddControl();
	m_dirty      = gCvsPrefs.DirtySupport();
	m_zlevel     = gCvsPrefs.ZLevel();
}

void UCvsPrefs_GLOBALS::StoreValues(void)
{
	gCvsPrefs.SetCheckoutRO(m_checkoutro);
	gCvsPrefs.SetPruneOption(m_prune);
	gCvsPrefs.SetZ9Option(m_tcpip);
	gCvsPrefs.SetQuietOption(m_quiet);
	gCvsPrefs.SetAddControl(m_cntladd);
	gCvsPrefs.SetDirtySupport(m_dirty);
	gCvsPrefs.SetZLevel(m_zlevel);
}

void UCvsPrefs_GLOBALS::DoDataExchange(bool fill)
{
	if(fill)
	{
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kcheckoutro, m_checkoutro), 0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kprune,      m_prune),      0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(ktcpip,      m_tcpip),      0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kquiet,      m_quiet),      0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kcntladd,    m_cntladd),    0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kdirty,      m_dirty),      0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kzlevel,     m_zlevel),     0L);
	}
	else
	{
		m_checkoutro = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kcheckoutro, 0L) != 0;
		m_prune      = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kprune,      0L) != 0;
		m_tcpip      = UEventSendMessage(GetWidID(), EV_QUERYSTATE, ktcpip,      0L) != 0;
		m_quiet      = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kquiet,      0L) != 0;
		m_cntladd    = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kcntladd,    0L) != 0;
		m_dirty      = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kdirty,      0L) != 0;
		m_zlevel     = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kzlevel,     0L);
	}
}


int UCvsPrefs_GLOBALS::OnTcpip(void)
{
	int state = UEventSendMessage(GetWidID(), EV_QUERYSTATE, ktcpip, 0L);
	UEventSendMessage(GetWidID(), EV_ENABLECMD, UMAKEINT(kzlevel, state), 0L);
	return 0;
}

class UCvsPrefs_PORTS : public UWidget
{
	UDECLARE_DYNAMIC(UCvsPrefs_PORTS)
public:
	UCvsPrefs_PORTS();
	virtual ~UCvsPrefs_PORTS() {}

	enum
	{
		kcheckrhost = EV_COMMAND_START,	// 0
		kcheckpserver,			// 1
		kcheckkserver,			// 2
		kchecksname,			// 3
		kcheckrsh,				// 4

		kportrhost,				// 5
		kportpserver,			// 6
		kportkserver,			// 7

		ksname,					// 8
		krshname				// 9
	};

	virtual void DoDataExchange(bool fill);
	
	void StoreValues(void);

protected:
	bool m_checkrhost;
	bool m_checkpserver;
	bool m_checkkserver;
	bool m_checksname;
	bool m_checkrsh;
	int m_portrhost;
	int m_portpserver;
	int m_portkserver;
	UStr m_sname;
	UStr m_rshname;

	ev_msg int OnCheckPorts(int cmd);

	UDECLARE_MESSAGE_MAP()
};

UIMPLEMENT_DYNAMIC(UCvsPrefs_PORTS, UWidget)

UBEGIN_MESSAGE_MAP(UCvsPrefs_PORTS, UWidget)
	ON_UCOMMAND_RANGE(UCvsPrefs_PORTS::kcheckrhost, UCvsPrefs_PORTS::kcheckrsh, UCvsPrefs_PORTS::OnCheckPorts)
UEND_MESSAGE_MAP()

UCvsPrefs_PORTS::UCvsPrefs_PORTS() : UWidget(::UEventGetWidID())
{
	m_checkkserver = gCvsPrefs.KserverPort() != -1;
	m_checkpserver = gCvsPrefs.PserverPort() != -1;
	m_checkrhost = gCvsPrefs.RhostPort() != -1;
	m_checksname = gCvsPrefs.ServerName() != 0L;
	m_checkrsh = gCvsPrefs.RshName() != 0L;
		
	m_portkserver = gCvsPrefs.KserverPort() != -1 ? gCvsPrefs.KserverPort() : 0;
	m_portpserver = gCvsPrefs.PserverPort() != -1 ? gCvsPrefs.PserverPort() : 0;
	m_portrhost = gCvsPrefs.RhostPort() != -1 ? gCvsPrefs.RhostPort() : 0;
	m_sname = gCvsPrefs.ServerName() == 0L ? "cvs" : gCvsPrefs.ServerName();
	m_rshname = gCvsPrefs.RshName() == 0L ? "ssh" : gCvsPrefs.RshName();
}

void UCvsPrefs_PORTS::StoreValues(void)
{
	gCvsPrefs.SetKserverPort(m_checkkserver ? m_portkserver : -1);
	gCvsPrefs.SetPserverPort(m_checkpserver ? m_portpserver : -1);
	gCvsPrefs.SetRhostPort(m_checkrhost ? m_portrhost : -1);
	
	gCvsPrefs.SetServerName(m_checksname ? (const char *)m_sname : 0L);
	gCvsPrefs.SetRshName(m_checkrsh ? (const char *)m_rshname : 0L);
}

int UCvsPrefs_PORTS::OnCheckPorts(int cmd)
{
	int state = UEventSendMessage(GetWidID(), EV_QUERYSTATE, cmd, 0L);
	UEventSendMessage(GetWidID(), EV_ENABLECMD, UMAKEINT(cmd + (kportrhost-kcheckrhost), state), 0L);
	
	if( cmd == kcheckrhost ) {
		UEventSendMessage(GetWidID(), EV_ENABLECMD, UMAKEINT(kchecksname, state), 0L);
		UEventSendMessage(GetWidID(), EV_ENABLECMD, UMAKEINT(kcheckrsh, state), 0L);
	}
	
	return 0;
}

void UCvsPrefs_PORTS::DoDataExchange(bool fill)
{
	if(fill)
	{
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kcheckkserver, m_checkkserver), 0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kcheckpserver, m_checkpserver), 0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kcheckrhost, m_checkrhost), 0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kchecksname, m_checksname), 0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kcheckrsh, m_checkrsh), 0L);
		
		UEventSendMessage(GetWidID(), EV_SETINTEGER, UMAKEINT(kportkserver, m_portkserver), 0L);
		UEventSendMessage(GetWidID(), EV_SETINTEGER, UMAKEINT(kportpserver, m_portpserver), 0L);
		UEventSendMessage(GetWidID(), EV_SETINTEGER, UMAKEINT(kportrhost, m_portrhost), 0L);
		UEventSendMessage(GetWidID(), EV_SETTEXT, ksname, (void *)(const char *)m_sname);
		UEventSendMessage(GetWidID(), EV_SETTEXT, krshname, (void *)(const char *)m_rshname);

		OnCheckPorts(kcheckrhost);
		OnCheckPorts(kcheckpserver);
		OnCheckPorts(kcheckkserver);
		OnCheckPorts(kchecksname);
		OnCheckPorts(kcheckrsh);
	}
	else
	{
		m_checkkserver = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kcheckkserver, 0L) != 0;
		m_portkserver = UEventSendMessage(GetWidID(), EV_GETINTEGER, kportkserver, 0L);
		m_checkpserver = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kcheckpserver, 0L) != 0;
		m_portpserver = UEventSendMessage(GetWidID(), EV_GETINTEGER, kportpserver, 0L);
		m_checkrhost = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kcheckrhost, 0L) != 0;
		m_portrhost = UEventSendMessage(GetWidID(), EV_GETINTEGER, kportrhost, 0L);

		UEventSendMessage(GetWidID(), EV_GETTEXT, ksname, &m_sname);
		m_checksname = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kchecksname, 0L) != 0;
		UEventSendMessage(GetWidID(), EV_GETTEXT, krshname, &m_rshname);
		m_checkrsh = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kcheckrsh, 0L) != 0;
	}
}

class UCvsPrefs_PROXY : public UWidget
{
	UDECLARE_DYNAMIC(UCvsPrefs_PROXY)
public:
	UCvsPrefs_PROXY();
	virtual ~UCvsPrefs_PROXY() {}

	enum
	{
		kuseproxy = EV_COMMAND_START,	// 0
		kproxyhost,				// 1
		kproxyport				// 2
	};

	virtual void DoDataExchange(bool fill);
	
	void StoreValues(void);

protected:
	bool m_useproxy;
	UStr m_proxyhost;
	int m_proxyport;

	ev_msg int OnUseProxy(void);

	UDECLARE_MESSAGE_MAP()
};

UIMPLEMENT_DYNAMIC(UCvsPrefs_PROXY, UWidget)

UBEGIN_MESSAGE_MAP(UCvsPrefs_PROXY, UWidget)
	ON_UCOMMAND(UCvsPrefs_PROXY::kuseproxy, UCvsPrefs_PROXY::OnUseProxy)
UEND_MESSAGE_MAP()

UCvsPrefs_PROXY::UCvsPrefs_PROXY() : UWidget(::UEventGetWidID())
{
	m_useproxy = gCvsPrefs.UseProxy();
	m_proxyport = gCvsPrefs.ProxyPort();
	m_proxyhost = gCvsPrefs.ProxyHost();
}

void UCvsPrefs_PROXY::StoreValues(void)
{
	gCvsPrefs.SetUseProxy(m_useproxy);
	gCvsPrefs.SetProxyHost(m_proxyhost);
	gCvsPrefs.SetProxyPort(m_proxyport);
}

int UCvsPrefs_PROXY::OnUseProxy(void)
{
	int state = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kuseproxy, 0L);
	UEventSendMessage(GetWidID(), EV_ENABLECMD, UMAKEINT(kproxyhost, state), 0L);
	UEventSendMessage(GetWidID(), EV_ENABLECMD, UMAKEINT(kproxyport, state), 0L);
	return 0;
}

void UCvsPrefs_PROXY::DoDataExchange(bool fill)
{
	if(fill)
	{
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kuseproxy, m_useproxy), 0L);
		UEventSendMessage(GetWidID(), EV_SETINTEGER, UMAKEINT(kproxyport, m_proxyport), 0L);
		UEventSendMessage(GetWidID(), EV_SETTEXT, kproxyhost, (void *)(const char *)m_proxyhost);

		OnUseProxy();
	}
	else
	{
		CStr str;
		m_useproxy = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kuseproxy, 0L) != 0;
		UEventSendMessage(GetWidID(), EV_GETTEXT, kproxyhost, &m_proxyhost);
		m_proxyport = UEventSendMessage(GetWidID(), EV_GETINTEGER, kproxyport, 0L);
	}
}

UIMPLEMENT_DYNAMIC(UCvsPrefs_GCVS, UWidget)

UBEGIN_MESSAGE_MAP(UCvsPrefs_GCVS, UWidget)
	ON_UCOMMAND_RANGE(UCvsPrefs_GCVS::kdiffBtn, UCvsPrefs_GCVS::kcvsBtn, UCvsPrefs_GCVS::OnPickProgram)
	ON_UCOMMAND(UCvsPrefs_GCVS::kuseAltCvs, UCvsPrefs_GCVS::OnUseAlternateCvs)
	ON_UCOMMAND(UCvsPrefs_GCVS::kconsoleFontBtn, UCvsPrefs_GCVS::OnSelectFont)
UEND_MESSAGE_MAP()

UCvsPrefs_GCVS::UCvsPrefs_GCVS() : UWidget(::UEventGetWidID())
{
	UStr cvsPath;
	m_diffApp     = gCvsPrefs.ExtDiff();
	m_viewerApp   = gCvsPrefs.Viewer();
	m_browserApp  = gCvsPrefs.Browser();
	m_helpApp     = gCvsPrefs.Helper();
	m_useAltCvs   = gCvsPrefs.UseAltCvs();
	m_cvsApp      = gCvsPrefs.WhichCvs(cvsPath);
	m_consoleFont = gCvsPrefs.ConsoleFont();
}

bool UCvsPrefs_GCVS::checkCVS(const char *filename)
{
	CvsArgs args;
	int status;
	
	cvs_out("checking cvs\n");
	
	args.add("-v");
	
	status = testCVS(filename, args.Argc(), args.Argv());
	switch( status ) {
		case 0:
			break; // all OK
		case errNoCvsguiProtocol: 
			cvs_err( "actual cvs binary has no support for GUI-pipes.\n");
			cvs_err( "Please select another binary and check the 'alternate cvs' settings!\n\n");
			break;
		default:
			break;
	}
	
	return ( status == 0 ? true : false );
}
void UCvsPrefs_GCVS::StoreValues(void)
{
	gCvsPrefs.SetExtDiff(m_diffApp);
	gCvsPrefs.SetViewer(m_viewerApp);
	gCvsPrefs.SetBrowser(m_browserApp);
	gCvsPrefs.SetHelper(m_helpApp);
	gCvsPrefs.SetUseAltCvs(m_useAltCvs);
	
#ifdef qUnix
	gCvsPrefs.SetConsoleFont(m_consoleFont);
	
	// use selected cvs only if it supports '-cvsgui'
	if( m_useAltCvs ) {
		if( checkCVS( m_cvsApp ) ) {
			gCvsPrefs.SetWhichCvs( m_cvsApp );
		}
	} else {
		CStr cvscmd;
	
		// check if actual cvs binary supports cvsgui protocol
		checkCVS( gCvsPrefs.WhichCvs(cvscmd, m_useAltCvs) );
	}
#else
	gCvsPrefs.SetWhichCvs(m_cvsApp);
#endif
}

#ifdef qGTK  //{ GTK - Part	
static CStr gtksel;
static bool gtkModalLoop;

static gint gtkcancel(GtkWidget *widget, gpointer data)
{
	gtkModalLoop = false;
	return TRUE;
}

static void font_ok_sel (GtkWidget *w, gpointer data)
{
	gtkModalLoop = false;
	gtksel = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG (data));
}

static void font_cancel_sel (GtkWidget *w, gpointer data)
{
	gtkModalLoop = false;
}

int UCvsPrefs_GCVS::OnSelectFont(void)
{
	/* Create a new file selection widget */
	GtkWidget* fontw = gtk_font_selection_dialog_new ("choice console font");
	
	gtk_signal_connect(GTK_OBJECT(fontw), "delete_event",
					   GTK_SIGNAL_FUNC(gtkcancel), 0L);

	/* Connect the ok_button to file_ok_sel function */
	gtk_signal_connect(GTK_OBJECT (GTK_FONT_SELECTION_DIALOG (fontw)->ok_button),
					  "clicked", (GtkSignalFunc) font_ok_sel, fontw);
	gtk_signal_connect(GTK_OBJECT (GTK_FONT_SELECTION_DIALOG (fontw)->cancel_button),
					  "clicked", (GtkSignalFunc) font_cancel_sel, fontw);
	
	gtkModalLoop = true;
	gtksel = "";
	gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG (fontw), m_consoleFont);
	gtk_widget_show(fontw);
	gtk_grab_add(fontw);

	while( gtkModalLoop )
	{
		gtk_main_iteration_do(TRUE);
	}

	gtk_grab_remove (fontw);
	
	gtk_widget_destroy(fontw);

	if( !gtksel.empty() )
	{
		UEventSendMessage(GetWidID(), EV_SETTEXT, kconsoleFont, (void*)(const char*)gtksel);
	}
	
	return 0;
}
#endif /* qGTK */

int UCvsPrefs_GCVS::OnPickProgram(int cmd)
{
	UStr appPath;
	UEventSendMessage(GetWidID(), EV_GETTEXT, cmd - kdiffBtn + kdiffApp, &appPath);
	
	MultiFiles mf;
	if( !appPath.empty() )
	{
		CStr uppath;
		CStr file;

		if( SplitPath(appPath, uppath, file) )
		{
			mf.newdir(uppath);
			mf.newfile(file);
		}
	}

	if( !BrowserGetMultiFiles("Select the application", mf, true, kSelectExecutable) )
		return 0;

	CvsArgs args(false);
	const char* dir = (*mf.begin()).add(args);
	char* const* argv = args.Argv();
	CStr fullpath;
	fullpath = dir;
	if( !fullpath.endsWith(kPathDelimiter) )
		fullpath << kPathDelimiter;

	fullpath << argv[0];
	
#ifdef qUnix
	// use selected cvs only if it supports '-cvsgui'
	if( ( cmd == kcvsBtn ) && !checkCVS( fullpath.c_str() ) )
		return 0;
#endif
	
	UEventSendMessage(GetWidID(), EV_SETTEXT, cmd - kdiffBtn + kdiffApp, (void*)(const char*)fullpath);
	
	return 0;
}

int UCvsPrefs_GCVS::OnUseAlternateCvs(void)
{
	int state = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kuseAltCvs, 0L);
	UEventSendMessage(GetWidID(), EV_ENABLECMD, UMAKEINT(kcvsApp, state), 0L);
	UEventSendMessage(GetWidID(), EV_ENABLECMD, UMAKEINT(kcvsBtn, state), 0L);
	return 0;
}

void UCvsPrefs_GCVS::DoDataExchange(bool fill)
{
	if(fill)
	{
		UEventSendMessage(GetWidID(), EV_SETTEXT, kdiffApp, (void *)(const char *)m_diffApp);
		UEventSendMessage(GetWidID(), EV_SETTEXT, kviewerApp, (void *)(const char *)m_viewerApp);
		UEventSendMessage(GetWidID(), EV_SETTEXT, kbrowserApp, (void *)(const char *)m_browserApp);
		UEventSendMessage(GetWidID(), EV_SETTEXT, khelpApp, (void *)(const char *)m_helpApp);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kuseAltCvs, m_useAltCvs), 0L);
		UEventSendMessage(GetWidID(), EV_SETTEXT, kconsoleFont, (void *)(const char *)m_consoleFont);
		UEventSendMessage(GetWidID(), EV_SETTEXT, kcvsApp, (void *)(const char *)m_cvsApp);
		OnUseAlternateCvs();
	}
	else
	{
		UEventSendMessage(GetWidID(), EV_GETTEXT, kdiffApp, &m_diffApp);
		UEventSendMessage(GetWidID(), EV_GETTEXT, kviewerApp, &m_viewerApp);
		UEventSendMessage(GetWidID(), EV_GETTEXT, kbrowserApp, &m_browserApp);
		UEventSendMessage(GetWidID(), EV_GETTEXT, khelpApp, &m_helpApp);
		UEventSendMessage(GetWidID(), EV_GETTEXT, kconsoleFont, &m_consoleFont);
		m_useAltCvs = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kuseAltCvs, 0L) != 0;
		UEventSendMessage(GetWidID(), EV_GETTEXT, kcvsApp, &m_cvsApp);
	}
}

#endif //} qUnix

#if qMacCvsPP   //{ Mac-Part

class UCvsPrefs_CVSROOT : public UWidget
{
	UDECLARE_DYNAMIC(UCvsPrefs_CVSROOT)
public:
	UCvsPrefs_CVSROOT();
	virtual ~UCvsPrefs_CVSROOT() {}

	enum
	{
		kAuthenPopup = EV_COMMAND_START + 40,	// 40
		kPath,				// 41
		kHost,				// 42
		kUser,				// 43
		kRootPopup,			// 44
		kRootStat,			// 45
		kCvsVers,			// 46
		kAuthenSettings,	// 47
		kAuthenDesc			// 48
	};

	virtual void DoDataExchange(bool fill);
	
protected:
	UStr m_cvsroot;
	AuthenKind m_kind;

	ev_msg void OnAuthenPopup(int pos, const char *txt);
	ev_msg void OnRootPopup(int pos, const char *txt);
	ev_msg void OnEditChange(int cmd);
	ev_msg int OnAuthenSettings(void);
	ev_msg void OnDestroy(void);
	
	UDECLARE_MESSAGE_MAP()
};

UIMPLEMENT_DYNAMIC(UCvsPrefs_CVSROOT, UWidget)

UBEGIN_MESSAGE_MAP(UCvsPrefs_CVSROOT, UWidget)
	ON_COMBO_SEL(kAuthenPopup, UCvsPrefs_CVSROOT::OnAuthenPopup)
	ON_COMBO_SEL(kRootPopup, UCvsPrefs_CVSROOT::OnRootPopup)
	ON_EDITCHANGE_RANGE(kPath, kUser, UCvsPrefs_CVSROOT::OnEditChange)
	ON_UCOMMAND(kAuthenSettings, UCvsPrefs_CVSROOT::OnAuthenSettings)
	ON_UDESTROY(UCvsPrefs_CVSROOT)
UEND_MESSAGE_MAP()

UCvsPrefs_CVSROOT::UCvsPrefs_CVSROOT() : UWidget(::UEventGetWidID())
{
}

void UCvsPrefs_CVSROOT::OnAuthenPopup(int pos, const char *txt)
{
	m_kind = Authen::numToKind(pos);
	AuthenModel *model = AuthenModel::GetInstance(m_kind);
	UEventSendMessage(GetWidID(), EV_ENABLECMD, UMAKEINT(kHost, model->HasHost()), 0L);
	UEventSendMessage(GetWidID(), EV_ENABLECMD, UMAKEINT(kUser, model->HasUser()), 0L);
	UEventSendMessage(GetWidID(), EV_ENABLECMD, UMAKEINT(kAuthenSettings, model->HasSettings()), 0L);
	
	if(!model->HasHost())
		UEventSendMessage(GetWidID(), EV_SETTEXT, kHost, (void *)"");
	if(!model->HasUser())
		UEventSendMessage(GetWidID(), EV_SETTEXT, kUser, (void *)"");
	UStr desc;
	model->GetSettingsDesc(desc);
	UEventSendMessage(GetWidID(), EV_SETTEXT, kAuthenDesc, (void *)(const char *)desc);
}

void UCvsPrefs_CVSROOT::OnRootPopup(int pos, const char *txt)
{
	m_cvsroot = txt;
	UEventSendMessage(GetWidID(), EV_SETTEXT, kRootStat, (void *)txt);

	UStr theMethod, theUser, theHost, thePath;
	
	if(Authen::parse_cvsroot(txt, theMethod, theUser, theHost, thePath))
	{
		UEventSendMessage(GetWidID(), EV_SETTEXT, kPath, (void *)(const char *)thePath);
		UEventSendMessage(GetWidID(), EV_SETTEXT, kHost, (void *)(const char *)theHost);
		UEventSendMessage(GetWidID(), EV_SETTEXT, kUser, (void *)(const char *)theUser);
		if (theMethod.length () > 0)
			UEventSendMessage(GetWidID(), EV_COMBO_SETSEL,
							  UMAKEINT(kAuthenPopup, Authen::kindToNum(Authen::tokenToKind (theMethod.c_str ()))), 0L);
	}
}

void UCvsPrefs_CVSROOT::OnEditChange(int cmd)
{
	UStr theUser, theHost, thePath;

	UEventSendMessage(GetWidID(), EV_GETTEXT, kPath, &thePath);
	UEventSendMessage(GetWidID(), EV_GETTEXT, kHost, &theHost);
	UEventSendMessage(GetWidID(), EV_GETTEXT, kUser, &theUser);
	
	m_cvsroot = "";
	AuthenModel *model = AuthenModel::GetInstance(m_kind);
	if(model->HasUser())
		m_cvsroot << theUser;
	if(model->HasHost())
	{
		m_cvsroot << '@';
		m_cvsroot << theHost;
	}
	if(model->HasUser() || model->HasHost())
		m_cvsroot << ':';
	m_cvsroot << thePath;
	UEventSendMessage(GetWidID(), EV_SETTEXT, kRootStat, (void *)(const char *)m_cvsroot);
}

int UCvsPrefs_CVSROOT::OnAuthenSettings(void)
{
	AuthenModel *model = AuthenModel::GetInstance(m_kind);
	model->DoSettings();
	UStr desc;
	model->GetSettingsDesc(desc);
	UEventSendMessage(GetWidID(), EV_SETTEXT, kAuthenDesc, (void *)(const char *)desc);
	return 0;
}

void UCvsPrefs_CVSROOT::OnDestroy(void)
{
	delete this;
}

void UCvsPrefs_CVSROOT::DoDataExchange(bool fill)
{
	if(fill)
	{		
		if(!gCvsPrefs.empty())
			m_cvsroot = (const char *)gCvsPrefs;
		m_kind = gAuthen.kind();

		UEventSendMessage(GetWidID(), EV_COMBO_RESETALL, kAuthenPopup, 0L);
		std::vector<AuthenModel *> & allAuthen = AuthenModel::GetAllInstances();
		std::vector<AuthenModel *>::iterator i;
		for(i = allAuthen.begin(); i != allAuthen.end(); ++i)
		{
			UEventSendMessage(GetWidID(), EV_COMBO_APPEND,
							  kAuthenPopup, (void *)(*i)->GetToken());
		}
		
		AuthenModel *model = AuthenModel::GetInstance(m_kind);
		UEventSendMessage(GetWidID(), EV_COMBO_SETSEL,
						  UMAKEINT(kAuthenPopup, Authen::kindToNum(model->GetKind())), 0L);
		
		UEventSendMessage(GetWidID(), EV_COMBO_RESETALL, kRootPopup, 0L);

		std::vector<CStr>::const_iterator haley;
		const std::vector<CStr> & alex = gOldCvsroots.GetList();
		for(haley = alex.begin(); haley != alex.end(); ++haley)
		{
			if(!(*haley).empty())
				UEventSendMessage(GetWidID(), EV_COMBO_APPEND,
								  kRootPopup, (void *)(*haley).c_str());
		}
		
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kCvsVers, 1), 0L);

		UStr tmp(m_cvsroot);
		OnRootPopup(0, tmp);
		OnAuthenPopup(Authen::kindToNum(m_kind), 0L);

		UEventSendMessage(GetWidID(), EV_CHGFOCUS, kPath, 0L);
	}
	else
	{
		gAuthen.setkind(m_kind);

		UStr theUser, theHost, thePath;

		UEventSendMessage(GetWidID(), EV_GETTEXT, kPath, &thePath);
		UEventSendMessage(GetWidID(), EV_GETTEXT, kHost, &theHost);
		UEventSendMessage(GetWidID(), EV_GETTEXT, kUser, &theUser);

		UStr root;
		if(m_kind != local)
		{
			root << theUser;
			root << '@';
			root << theHost;
			root << ':';
			root << thePath;
		}
		else
			root = thePath;
		
		gCvsPrefs = root;
		
		if( !root.empty() )
			gOldCvsroots.Insert(root);
	}
}

static void DoDataExchange_Cvsroot(UCvsPrefs_CVSROOT *handler, bool putValue)
{
	handler->DoDataExchange(putValue);
}
#endif //} qMacCvsPP

/// Get the CVSROOT, authentication, and misc options
void CompatGetPrefs(void)
{
	bool userHitOK = false;

	// Store current CVSROOT
#if INTERNAL_AUTHEN
	const UStr prevCvsroot((const char*)gCvsPrefs);
	const AuthenKind prevKind = gAuthen.kind();
#endif /* INTERNAL_AUTHEN */

#ifdef WIN32   //{ WIN32
	CHHelpPropertySheet pages("WinCvs Preferences");
	pages.m_psh.dwFlags |= PSH_NOAPPLYNOW;
	
	CGetPrefs_GLOBALS page1;
	CGetPrefs_CVS page2;
	CGetPrefs_WINCVS page3;
	CGetPrefs_CVSCMD_DIALOGS page4;
	CGetPrefs_General page5;

	pages.AddPage(&page1);
	pages.AddPage(&page2);
	pages.AddPage(&page3);
	pages.AddPage(&page4);
	pages.AddPage(&page5);

	if( pages.DoModal() == IDOK )
	{
		page1.StoreValues();
		page2.StoreValues();
		page3.StoreValues();
		page4.StoreValues();

		userHitOK = true;
	}
#endif //} WIN32 

#ifdef qMacCvsPP  //{ qMacCvsPP
	MacBinMaps maps;
	maps.LoadDefaults();
	CMacBinTable::SetCurrentMap(&maps);

	StDialogHandler	theHandler(dlg_Prefs, LCommander::GetTopCommander());
	LWindow *theDialog = theHandler.GetDialog();
	ThrowIfNil_(theDialog);
	static UInt16 sRuntimePanel = 1;
	
	LMultiPanelView *multiView = dynamic_cast<LMultiPanelView*>
		(theDialog->FindPaneByID(item_MultiViewPrefs));
	LPane *groupView = theDialog->FindPaneByID(item_GroupViewPrefs);
	
	UCvsPrefs_CVSROOT *handler = new UCvsPrefs_CVSROOT;
	ThrowIfNil_(handler);
	
	UEventSendMessage(handler->GetWidID(), EV_INIT_WIDGET, 0, theDialog);
	
	multiView->SwitchToPanel(5);
	DoDataExchange_Fonts(theDialog, true);
	multiView->SwitchToPanel(4);
	DoDataExchange_BinFiles(theDialog, maps, true);
	multiView->SwitchToPanel(3);
	DoDataExchange_TextFiles(theDialog, true);
	LPushButton *diffbtn = dynamic_cast<LPushButton*>(theDialog->FindPaneByID(item_BrowseExtDiff));
	diffbtn->AddListener(&theHandler);
	multiView->SwitchToPanel(2);
	DoDataExchange_Globals(theDialog, true);
	multiView->SwitchToPanel(1);
	DoDataExchange_Cvsroot(handler, true);
	
	groupView->SetValue(sRuntimePanel);
	theDialog->Show();
	MessageT hitMessage;
	SInt32    lastDiffToolValue(0);
	while (true)
	{		// Let DialogHandler process events
		hitMessage = theHandler.DoDialog();
		
		if (hitMessage == msg_OK || hitMessage == msg_Cancel)
			break;

    HandleHitMessage_DiffTool(theDialog, hitMessage);
	}
	theDialog->Hide();
	sRuntimePanel = groupView->GetValue();
	
	if(hitMessage == msg_OK)
	{
		userHitOK = true;

		multiView->SwitchToPanel(1);
		DoDataExchange_Cvsroot(handler, false);
		multiView->SwitchToPanel(2);
		DoDataExchange_Globals(theDialog, false);
		multiView->SwitchToPanel(3);
		DoDataExchange_TextFiles(theDialog, false);
		multiView->SwitchToPanel(4);
		DoDataExchange_BinFiles(theDialog, maps, false);
		multiView->SwitchToPanel(5);
		DoDataExchange_Fonts(theDialog, false);

		maps.SaveDefaults();
	}
#endif //} qMacCvsPP

#if qUnix  //{ Unix-Part
	void *wid = UCreate_gcvs_Settings();

	UCvsPrefs_MAIN *dlg = new UCvsPrefs_MAIN();
	UCvsPrefs_CVSROOT *tab1 = new UCvsPrefs_CVSROOT();
	UCvsPrefs_GLOBALS *tab2 = new UCvsPrefs_GLOBALS();
	UCvsPrefs_PORTS *tab3 = new UCvsPrefs_PORTS();
	UCvsPrefs_PROXY *tab4 = new UCvsPrefs_PROXY();
	UCvsPrefs_GCVS *tab5 = new UCvsPrefs_GCVS();
	UEventSendMessage(dlg->GetWidID(), EV_INIT_WIDGET, kUMainWidget, wid);
	dlg->AddPage(tab1, UCvsPrefs_MAIN::kTabGeneral, 0);
	dlg->AddPage(tab2, UCvsPrefs_MAIN::kTabGeneral, 1);
	dlg->AddPage(tab3, UCvsPrefs_MAIN::kTabGeneral, 2);
	dlg->AddPage(tab4, UCvsPrefs_MAIN::kTabGeneral, 3);
	dlg->AddPage(tab5, UCvsPrefs_MAIN::kTabGeneral, 4);

	if(dlg->DoModal())
	{
		tab1->StoreValues();
		tab2->StoreValues();
		tab3->StoreValues();
		tab4->StoreValues();
		tab5->StoreValues();

		userHitOK = true;
	}
	delete dlg;
#endif //} qUnix

	if( userHitOK 
#if INTERNAL_AUTHEN
		&& !gCvsPrefs.empty() 
#endif /* INTERNAL_AUTHEN */
		)
	{
#if INTERNAL_AUTHEN
		if( prevCvsroot != (const char*)gCvsPrefs || prevKind != gAuthen.kind() )
		{
			cvs_out("NEW CVSROOT: %s (%s)\n", (const char*)gCvsPrefs, gAuthen.kindstr());
			cvs_err("CVSROOT change will only take effect when commands are run from a non-CVS folder.\n"
				"To change the CVSROOT of an existing sandbox please use the ChangeRoot macro.\n");
		}
		else
		{
			cvs_out("CVSROOT: %s (%s)\n", (const char*)gCvsPrefs, gAuthen.kindstr());
		}
#endif /* INTERNAL_AUTHEN */

		gCvsPrefs.save();
	}
}
