/*
** 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/gtkmain.h"
#endif

#ifdef WIN32
#	include "wincvs.h"
#	include "umain.h"
#	include <afxdao.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"

#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_cvsconsole = gCvsPrefs.CvsConsole();
	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);
	DDX_Check(pDX, IDC_CONSOLE, m_cvsconsole);
	//}}AFX_DATA_MAP

	DDV_CheckCVSROOT(pDX, m_cvsroot);

	if( pDX->m_bSaveAndValidate )
	{
		//in case the CVSROOT was modified by DDV rutine 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);
	gCvsPrefs.SetCvsConsole(m_cvsconsole != 0);
}

/// 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_dirty = gCvsPrefs.DirtySupport();
	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();
	//}}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_DIRTYSUPPORT, m_dirty);
	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);
	//}}AFX_DATA_MAP

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

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

	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.SetDirtySupport(m_dirty ? 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);
}

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() 
{
	AfxMessageBox("Be careful when toggling this option : you *CANNOT* use WinCvs in"
		" both mode. You got to use either one or the other. 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.", MB_ICONEXCLAMATION | MB_OK);
}

// 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_useViewerAlways = gCvsPrefs.UseViewerAlways();
	m_useExtDiff = gCvsPrefs.ExtDiff() != 0L;
	m_diffProg = gCvsPrefs.ExtDiff();
	m_useSettingsFolder = gCvsPrefs.SettingsFolder() != 0L;
	m_settingsFolder = gCvsPrefs.SettingsFolder() != 0L ? gCvsPrefs.SettingsFolder() : "";
	//}}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_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_USE_VIEWER_ALWAYS, m_useViewerAlways);
	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);
	//}}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.SetUseViewerAlways(m_useViewerAlways ? true : false);
	gCvsPrefs.SetSettingsFolder(m_useSettingsFolder && !m_settingsFolder.IsEmpty() ? (LPCTSTR)m_settingsFolder : 0L);
}

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)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/// BN_CLICKED message handler, change default viewer used to open files
void CGetPrefs_WINCVS::OnBtnviewer()
{
	MultiFiles mf;

	CString viewerPath;
	m_viewerEdit.GetWindowText(viewerPath);

	if( !viewerPath.IsEmpty() )
	{
		CStr uppath;
		CStr file;

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

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

	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];

	m_viewerEdit.SetWindowText(fullpath);
}

/// BN_CLICKED message handler, change external diff program
void CGetPrefs_WINCVS::OnExtdiffsel()
{
	MultiFiles mf;

	CString diffProg;
	m_diffProgEdit.GetWindowText(diffProg);

	if( !diffProg.IsEmpty() )
	{
		CStr uppath;
		CStr file;

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

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

	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];

	m_diffProgEdit.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)
{
	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);
	//}}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_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);
	//}}AFX_DATA_MAP

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

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

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)
	//}}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() 
{
	MultiFiles mf;

	CString altCvs;
	m_altCvsEdit.GetWindowText(altCvs);

	if( !altCvs.IsEmpty() )
	{
		CStr uppath;
		CStr file;

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

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

	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];

	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;
	//}}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);
	//}}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.SetHideCommandDlgUseShift(m_keyForce == 0);
}

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;

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

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

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

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

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

	enum
	{
		// program paths
		kdiffApp = EV_COMMAND_START,  // 0
		kviewerApp,		              // 1
		kbrowserApp,	              // 2
		khelpApp,		              // 3
		kcvsApp,                      // 4

		// browse button
		kdiffBtn, 	                  // 5
		kviewerBtn,	 	              // 6
		kbrowserBtn,	              // 7
		khelpBtn,		              // 8
		kcvsBtn,                      // 9

		kuseAltCvs                    // 10
	};

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

protected:
	UStr m_diffApp;
	UStr m_viewerApp;
	UStr m_browserApp;
	UStr m_helpApp;
	bool m_useAltCvs;
    UStr m_cvsApp;

	ev_msg int OnPickProgram(int cmd);
	ev_msg int OnUseAlternateCvs(void);
	
	bool checkCVS(const char* filename);

	UDECLARE_MESSAGE_MAP()
};

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


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

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, 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);
		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;

		if (hitMessage == item_BrowseExtDiff)
		{
			MultiFiles mf;
			if( BrowserGetMultiFiles("Select the external diff application", mf, true, kSelectExecutable) )
			{
				CvsArgs args(false);
				const char *dir = (*mf.begin()).add(args);
				char * const *argv = args.Argv();
				UStr fullpath;
				fullpath = dir;
				if(!fullpath.endsWith(kPathDelimiter))
					fullpath << kPathDelimiter;
				fullpath << argv[0];

				LEditText *editdiff = dynamic_cast<LEditText*>
					(theDialog->FindPaneByID(item_EditExtDiff));
				editdiff->SetText(LStr255(fullpath.c_str()));
			}
		}
		else if ( hitMessage == /*item_UseExtDiff*/0 /*popup group box doesn't send value message?*/ )
		{
		  LPane*  useExtDiff = theDialog->FindPaneByID(item_UseExtDiff);
	    if ( useExtDiff  &&  useExtDiff->GetValue() != lastDiffToolValue )
	    {
	      lastDiffToolValue = useExtDiff->GetValue();
  	    LPane*  customDiffView = theDialog->FindPaneByID(item_EditExtDiffView);
  		  if ( lastDiffToolValue != 4 ) // %%% should better not check by item position!
  		  {
  		    if ( customDiffView ) customDiffView->Disable();
  		  }
  		  else
  		  {
  		    if ( customDiffView ) customDiffView->Enable();
  		  }
      }
		}
	}
	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();
	}
}
