/*
** 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"

/*!
	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

// CVSROOT page
IMPLEMENT_DYNCREATE(CGetPrefs_CVSROOT, CPropertyPage)

CGetPrefs_CVSROOT::CGetPrefs_CVSROOT() 
	: m_versCombo(USmartCombo::AutoDropWidth), m_authenCombo(USmartCombo::AutoDropWidth), 
	CPropertyPage(CGetPrefs_CVSROOT::IDD), m_didInteract(false)
{
	//{{AFX_DATA_INIT(CGetPrefs_CVSROOT)
	m_cvsroot = (const char*)gCvsPrefs;
	m_cvsvers = gCvsPrefs.CvsVersion();
	m_authen = gAuthen.kind();
	m_host = _T("");
	m_login = _T("");
	m_path = _T("");
	//}}AFX_DATA_INIT
	
	m_flag = false;
	m_cvsrootCombo.SetItems(&gOldCvsroots);
}

CGetPrefs_CVSROOT::~CGetPrefs_CVSROOT()
{
}


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

	CPropertyPage::DoDataExchange(pDX);

	//{{AFX_DATA_MAP(CGetPrefs_CVSROOT)
	DDX_Control(pDX, IDC_AUTHENDESC, m_authenDescEdit);
	DDX_Control(pDX, IDC_SETTINGS, m_settingsButton);
	DDX_Control(pDX, IDC_PATH, m_pathEdit);
	DDX_Control(pDX, IDC_LOGIN, m_loginEdit);
	DDX_Control(pDX, IDC_HOST, m_hostEdit);
	DDX_Control(pDX, IDC_CVSVERS, m_versCombo);
	DDX_Control(pDX, IDC_AUTHEN, m_authenCombo);
	DDX_Control(pDX, IDC_COMBOROOT, m_cvsrootCombo);
	DDX_CBString(pDX, IDC_COMBOROOT, m_cvsroot);
	DDV_MinChars(pDX, m_cvsroot, 1);
	DDX_Text(pDX, IDC_HOST, m_host);
	DDX_Text(pDX, IDC_LOGIN, m_login);
	DDX_Text(pDX, IDC_PATH, m_path);
	//}}AFX_DATA_MAP

	DDV_CheckCVSROOT(pDX, m_cvsroot);

	if( pDX->m_bSaveAndValidate )
	{
		//in case the CVSROOT was modified by DDV runtine we need to refill the fields
		FillFields();

		m_cvsvers = m_versCombo.GetCurSel();

		if( !m_cvsroot.IsEmpty() )
		{
			gOldCvsroots.Insert(m_cvsroot);
		}
	}
	else
	{
		DDX_ComboMString(pDX, IDC_COMBOROOT, m_cvsrootCombo);

		m_versCombo.SetCurSel(m_cvsvers);

		m_authenCombo.ResetContent();
		std::vector<AuthenModel*>& allAuthen = AuthenModel::GetAllInstances();
		std::vector<AuthenModel*>::iterator j;
		for(j = allAuthen.begin(); j != allAuthen.end(); ++j)
		{
			m_authenCombo.InsertString(-1, (*j)->GetToken());
		}
		
		AuthenModel* model = AuthenModel::GetInstance(m_authen);
		m_authenCombo.SetCurSel(Authen::kindToNum(m_authen));

		FillFields();
		OnSelchangeAuthen();
	}
}

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

	gCvsPrefs = (const char*)m_cvsroot;
	gAuthen.setkind(m_authen);
	gCvsPrefs.SetCvsVersion(m_cvsvers);
}

/// CBN_SELCHANGE message handler, change authentication
void CGetPrefs_CVSROOT::OnSelchangeAuthen() 
{
	m_authen = Authen::numToKind(m_authenCombo.GetCurSel());

	AuthenModel* model = AuthenModel::GetInstance(m_authen);

	m_hostEdit.EnableWindow(model->HasHost());
	m_loginEdit.EnableWindow(model->HasUser());
	m_settingsButton.EnableWindow(model->HasSettings());
	
	if( !model->HasHost() )
		m_hostEdit.SetWindowText("");
	
	if( !model->HasUser() )
		m_loginEdit.SetWindowText("");

	UStr desc;
	model->GetSettingsDesc(desc);
	m_authenDescEdit.SetWindowText(desc);
}

/// EN_CHANGE message handler, update fields
void CGetPrefs_CVSROOT::OnChangePath() 
{
	OnChangeFields();
}

/// EN_CHANGE message handler, update fields
void CGetPrefs_CVSROOT::OnChangeHost() 
{
	OnChangeFields();
}

/// EN_CHANGE message handler, update fields
void CGetPrefs_CVSROOT::OnChangeLogin() 
{
	OnChangeFields();
}

/// BN_CLICKED message handler, display settings dialog
void CGetPrefs_CVSROOT::OnSettings() 
{
	AuthenModel* model = AuthenModel::GetInstance(m_authen);
	model->DoSettings();

	UStr desc;
	model->GetSettingsDesc(desc);
	m_authenDescEdit.SetWindowText(desc);
}

/// Parse entered CVSROOT and fill the authentication fields
void CGetPrefs_CVSROOT::FillFields(void)
{
	UStr theMethod, theUser, theHost, thePath;
	USemaphore policeman(m_flag);
	if( policeman.IsEnteredTwice() )
		return;

	UStr root;
	root = Authen::token(m_authen);
	root << Authen::skiptoken(m_cvsroot);

	if( Authen::parse_cvsroot(root, theMethod, theUser, theHost, thePath) )
	{
		m_pathEdit.SetWindowText(thePath);
		m_hostEdit.SetWindowText(theHost);
		m_loginEdit.SetWindowText(theUser);
	}
}

/// CBN_EDITCHANGE message handler, update fields
void CGetPrefs_CVSROOT::OnEditchangeComboroot() 
{
	m_cvsrootCombo.GetWindowText(m_cvsroot);
	FillFields();
}

/// Update CVSROOT from changed fields
void CGetPrefs_CVSROOT::OnChangeFields(void)
{
	USemaphore policeman(m_flag);
	if( policeman.IsEnteredTwice() )
		return;

	CString theUser, theHost, thePath;

	m_pathEdit.GetWindowText(thePath);
	m_hostEdit.GetWindowText(theHost);
	m_loginEdit.GetWindowText(theUser);
	
	m_cvsroot = "";
	AuthenModel* model = AuthenModel::GetInstance(m_authen);
	if( model->HasUser() )
	{
		m_cvsroot += theUser;
		
		if( model->HasHost() && !(theUser.IsEmpty() || theHost.IsEmpty()) )
		{
			m_cvsroot += '@';
		}
	}

	if( model->HasHost() )
	{
		m_cvsroot += theHost;
	}

	if( model->HasUser() || model->HasHost() )
		m_cvsroot += ':';

	m_cvsroot += thePath;

	m_cvsrootCombo.SetWindowText(m_cvsroot);
}

/// CBN_SELCHANGE message handler, update fields
void CGetPrefs_CVSROOT::OnSelchangeComboroot() 
{
	int nCurSel = m_cvsrootCombo.GetCurSel();
	m_cvsrootCombo.GetLBText(nCurSel, m_cvsroot);
	FillFields();
}

BEGIN_MESSAGE_MAP(CGetPrefs_CVSROOT, CPropertyPage)
	//{{AFX_MSG_MAP(CGetPrefs_CVSROOT)
	ON_CBN_SELCHANGE(IDC_AUTHEN, OnSelchangeAuthen)
	ON_EN_CHANGE(IDC_PATH, OnChangePath)
	ON_EN_CHANGE(IDC_HOST, OnChangeHost)
	ON_EN_CHANGE(IDC_LOGIN, OnChangeLogin)
	ON_BN_CLICKED(IDC_SETTINGS, OnSettings)
	ON_CBN_SELCHANGE(IDC_COMBOROOT, OnSelchangeComboroot)
	ON_CBN_EDITCHANGE(IDC_COMBOROOT, OnEditchangeComboroot)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

// Globals options page
IMPLEMENT_DYNCREATE(CGetPrefs_GLOBALS, CPropertyPage)

CGetPrefs_GLOBALS::CGetPrefs_GLOBALS() : CPropertyPage(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();
	//}}AFX_DATA_INIT
}

CGetPrefs_GLOBALS::~CGetPrefs_GLOBALS()
{
}

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

	CPropertyPage::DoDataExchange(pDX);

	//{{AFX_DATA_MAP(CGetPrefs_GLOBALS)
	DDX_Control(pDX, IDC_SPINLOGOUT, m_logoutSpinButton);
	DDX_Control(pDX, IDC_EDITLOGOUT, m_logoutEdit);
	DDX_Control(pDX, IDC_LOGOUT, m_logoutCheck);
	DDX_Control(pDX, IDC_ZSPIN, m_zspinSpinButton);
	DDX_Control(pDX, IDC_ZLEVEL, m_zlevelEdit);
	DDX_Control(pDX, IDC_TCPIP, m_tcpipCheck);
	DDX_Check(pDX, IDC_CHECKOUTRO, m_checkoutro);
	DDX_Check(pDX, IDC_PRUNE, m_prune);
	DDX_Check(pDX, IDC_TCPIP, m_tcpip);
	DDX_Check(pDX, IDC_QUIET, m_quiet);
	DDX_Check(pDX, IDC_CTNLADD, m_cntladd);
	DDX_Check(pDX, IDC_ALWAYSROOT, m_alwaysroot);
	DDX_Check(pDX, IDC_LOGOUT, m_logout);
	DDX_Check(pDX, IDC_CHECKUNIXLF, m_unixlf);
	DDX_Text(pDX, IDC_ZLEVEL, m_zlevel);
	DDV_MinMaxUInt(pDX, m_zlevel, 1, 9);
	DDX_Check(pDX, IDC_DISABLESPLASHSCREEN, m_disableSplashScreen);
	DDX_Text(pDX, IDC_EDITLOGOUT, m_logoutTime);
	DDV_MinMaxUInt(pDX, m_logoutTime, 0, 999999);
	DDX_Check(pDX, IDC_MATCHENTRIESCASE, m_matchEntriesCase);
	//}}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);

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

BEGIN_MESSAGE_MAP(CGetPrefs_GLOBALS, CPropertyPage)
	//{{AFX_MSG_MAP(CGetPrefs_GLOBALS)
	ON_BN_CLICKED(IDC_LOGOUT, OnLogout)
	ON_BN_CLICKED(IDC_CHECKUNIXLF, OnCheckunixlf)
	ON_BN_CLICKED(IDC_TCPIP, OnTcpip)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/// OnInitDialog virtual override, setup spin controls
BOOL CGetPrefs_GLOBALS::OnInitDialog() 
{
	CPropertyPage::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
}

/// 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, CPropertyPage)

CGetPrefs_WINCVS::CGetPrefs_WINCVS() : CPropertyPage(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;

	CPropertyPage::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_PROGRAM, m_viewerEdit);
	DDX_Control(pDX, IDC_EXTDIFFSEL, m_extDiffSelButton);
	DDX_Control(pDX, IDC_DIFFPROG, m_diffProgEdit);
	DDX_Control(pDX, IDC_EXTDIFF, m_useExtDiffCheck);
	DDX_Control(pDX, IDC_SETTINGS, m_settingsFolderEdit);
	DDX_Control(pDX, IDC_BTNSETTINGS, m_settingsFolderButton);
	DDX_Control(pDX, IDC_ALTSETTINGSCHK, m_useSettingsFolderCheck);
	DDX_Text(pDX, IDC_PROGRAM, m_viewer);
	DDX_Check(pDX, IDC_EXTDIFF, m_useExtDiff);
	DDX_Text(pDX, IDC_DIFFPROG, m_diffProg);
	DDX_Check(pDX, IDC_ALTSETTINGSCHK, m_useSettingsFolder);
	DDX_Text(pDX, IDC_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_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, CPropertyPage)
	//{{AFX_MSG_MAP(CGetPrefs_WINCVS)
	ON_BN_CLICKED(IDC_BTNPROGRAM, OnBtnviewer)
	ON_BN_CLICKED(IDC_EXTDIFFSEL, OnExtdiffsel)
	ON_BN_CLICKED(IDC_EXTDIFF, OnExtdiff)
	ON_BN_CLICKED(IDC_ALTSETTINGSCHK, OnAltsettingschk)
	ON_BN_CLICKED(IDC_BTNSETTINGS, OnBtnsettings)
	ON_BN_CLICKED(IDC_TCLDLLSEL, OnTcldllsel)
	ON_BN_CLICKED(IDC_PYTHONDLLSEL, OnPythondllsel)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/// OnInitDialog virtual override, setup autocomplete
BOOL CGetPrefs_WINCVS::OnInitDialog() 
{
	CPropertyPage::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
}

/// 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, CPropertyPage)

CGetPrefs_CVS::CGetPrefs_CVS() 
	: CPropertyPage(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_altCvs = gCvsPrefs.WhichCvs(cvsPath);
	m_cvsConsole = gCvsPrefs.CvsConsole();
	m_showCvs = gCvsPrefs.ShowCvs();
	//}}AFX_DATA_INIT
}

CGetPrefs_CVS::~CGetPrefs_CVS()
{
}

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

	CPropertyPage::DoDataExchange(pDX);

	//{{AFX_DATA_MAP(CGetPrefs_CVS)
	DDX_Control(pDX, IDC_CONSOLE, m_cvsConsoleCheck);
	DDX_Control(pDX, IDC_SHOWCVS, m_showCvsCombo);
	DDX_Control(pDX, IDC_ALTCVSPROG, m_altCvsEdit);
	DDX_Control(pDX, IDC_ALTCVSSEL, m_selAltCvsButton);
	DDX_Control(pDX, IDC_ALTCVSCHK, m_useAltCvsCheck);
	DDX_Control(pDX, IDC_HOME, m_homeEdit);
	DDX_Text(pDX, IDC_HOME, m_home);
	DDX_Check(pDX, IDC_ALTCVSCHK, m_useAltCvs);
	DDX_Text(pDX, IDC_ALTCVSPROG, m_altCvs);
	DDX_Check(pDX, IDC_CONSOLE, m_cvsConsole);
	DDX_CBIndex(pDX, IDC_SHOWCVS, m_showCvs);
	//}}AFX_DATA_MAP

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

/// OnInitDialog virtual override, setup autocomplete
BOOL CGetPrefs_CVS::OnInitDialog() 
{
	CPropertyPage::OnInitDialog();
	
	// Extra initialization
	EnableEditAutoComplete(&m_altCvsEdit);
	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
}

/// 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);
}

BEGIN_MESSAGE_MAP(CGetPrefs_CVS, CPropertyPage)
	//{{AFX_MSG_MAP(CGetPrefs_CVS)
	ON_BN_CLICKED(IDC_BTNHOME, OnBtnhome)
	ON_BN_CLICKED(IDC_ALTCVSCHK, OnAltcvschk)
	ON_BN_CLICKED(IDC_ALTCVSSEL, OnAltcvssel)
	ON_BN_CLICKED(IDC_CONSOLE, OnConsole)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/// 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_altCvsEdit.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_altCvsEdit.GetWindowText(altCvs);
	
	CStr fullpath = altCvs;
	if( BrowseForFile("Select the CVS client application", kSelectExecutable, fullpath) )
	{
		m_altCvsEdit.SetWindowText(fullpath);
	}
}

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

CGetPrefs_CVSCMD_DIALOGS::CGetPrefs_CVSCMD_DIALOGS() : CPropertyPage(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;

	CPropertyPage::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CGetPrefs_CVSCMD_DIALOGS)
	DDX_Check(pDX, IDC_CHECKUPDATE, m_hideUpdate);
	DDX_Check(pDX, IDC_CHECKDIFF, m_hideDiff);
	DDX_Check(pDX, IDC_CHECKGRAPH, m_hideGraph);
	DDX_Check(pDX, IDC_CHECKLOG, m_hideLog);
	DDX_Radio(pDX, IDC_RADIOSHIFT, m_keyForce);
	DDX_Check(pDX, IDC_CHECKANNOTATE, m_hideAnnotate);
	DDX_Check(pDX, IDC_CHECKSTATUS, m_hideStatus);
	DDX_Check(pDX, IDC_CHECK_CTRLPRESSEDONOK, m_ctrlPressedOnOK);
	DDX_Check(pDX, IDC_CHECKFILEACTION, 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, CPropertyPage)
//{{AFX_MSG_MAP(CGetPrefs_CVSCMD_DIALOGS)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

#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
	const UStr prevCvsroot((const char*)gCvsPrefs);
	const AuthenKind prevKind = gAuthen.kind();

#ifdef WIN32   //{ WIN32
	CPropertySheet pages("WinCvs Preferences");
	pages.m_psh.dwFlags |= PSH_NOAPPLYNOW;
	
	CGetPrefs_CVSROOT page1;
	CGetPrefs_GLOBALS page2;
	CGetPrefs_CVS page3;
	CGetPrefs_WINCVS page4;
	CGetPrefs_CVSCMD_DIALOGS 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();
		page5.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 && !gCvsPrefs.empty() )
	{
		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());
		}

		gCvsPrefs.save();
	}
}
