/*
** 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> --- March 1998
 */

/*
 * LogDlg.cpp : the cvs log dialog
 */

#include "stdafx.h"

#ifdef WIN32
#	include "wincvs.h"
#	include "OptionalPropertySheet.h"
#endif /* WIN32 */

#ifdef qMacCvsPP
#	include <UModalDialogs.h>
#	include <LMultiPanelView.h>
#	include <LCheckBox.h>
#	include <LEditText.h>
#	include <LPopupGroupBox.h>
#	include <LRadioButton.h>
#	include "LPopupFiller.h"

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

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

#if qUnix
#	include "UCvsDialogs.h"
#endif

#include "LogDlg.h"
#include "CvsPrefs.h"
#include "MultiFiles.h"
#include "MultiString.h"
#include "ItemListDlg.h"

char *sDefLogTagNames[] = 
{
	"1.32:1.35",
	"1.32:",
	":1.35",
	"branch-release1-0",
	"HEAD",
	0L
};

char *sDefLogDateNames[] = 
{
	">1998-3-24",
	"<1998-1-24",
	"1998-1-24<1998-3-24",
	"<=3-24",
	0L
};

char *sDefLogStateNames[] = 
{
	"mystate",
	"dead",
	"exp",
	"mystate,mystate2",
	0L
};

char *sDefLogUserNames[] = 
{
	"johna",
	"garyb",
	"johna,garyb",
	0L
};

static CMString gLogRevNames(10, "P_LogTagNames", sDefLogTagNames);
static CMString gLogDateNames(10, "P_LogDateNames", sDefLogDateNames);
static CMString gLogStateNames(10, "P_LogStateNames", sDefLogStateNames);
static CMString gLogUserNames(10, "P_LogUserNames", sDefLogUserNames);

#ifdef WIN32
#include "GetPrefs.h"

IMPLEMENT_DYNAMIC(CLogMain, CPropertyPage)

CLogMain::CLogMain() : CPropertyPage(CLogMain::IDD)
{
	//{{AFX_DATA_INIT(CLogMain)
	m_defbranch = FALSE;
	m_norecurs = FALSE;
	m_notags = FALSE;
	m_nousers = FALSE;
	m_onlyrcs = FALSE;
	//}}AFX_DATA_INIT
}

CLogMain::~CLogMain()
{
}

void CLogMain::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CLogMain)
	DDX_Check(pDX, IDC_DEFBRANCH, m_defbranch);
	DDX_Check(pDX, IDC_NORECURS, m_norecurs);
	DDX_Check(pDX, IDC_NOTAGS, m_notags);
	DDX_Check(pDX, IDC_NOUSERS, m_nousers);
	DDX_Check(pDX, IDC_ONLYRCS, m_onlyrcs);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CLogMain, CPropertyPage)
	//{{AFX_MSG_MAP(CLogMain)
		// NOTE: the ClassWizard will add message map macros here
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

IMPLEMENT_DYNAMIC(CLogFilters, CPropertyPage)

CLogFilters::CLogFilters(const MultiFiles* mf,
						 const char* sLastDate, const char* sLastRev,
						 const char* sLastUsers, const char* sLastStates) 
						 : m_mf(mf), CPropertyPage(CLogFilters::IDD)
{
	//{{AFX_DATA_INIT(CLogFilters)
	m_date = sLastDate;
	m_rev = sLastRev;
	m_state = sLastStates;
	m_user = sLastUsers;
	//}}AFX_DATA_INIT

	m_hasdate = FALSE;
	m_hasrev = FALSE;
	m_hasstate = FALSE;
	m_hasuser = FALSE;

	m_revCombo.SetItems(&gLogRevNames);
	m_dateCombo.SetItems(&gLogDateNames);
	m_userCombo.SetItems(&gLogUserNames);
	m_stateCombo.SetItems(&gLogStateNames);
}

CLogFilters::~CLogFilters()
{
}

void CLogFilters::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CLogFilters)
	DDX_Control(pDX, IDC_COMBOUSER, m_userCombo);
	DDX_Control(pDX, IDC_COMBOSTATE, m_stateCombo);
	DDX_Control(pDX, IDC_COMBOREV, m_revCombo);
	DDX_Control(pDX, IDC_COMBODATE, m_dateCombo);
	DDX_CBString(pDX, IDC_COMBODATE, m_date);
	DDX_CBString(pDX, IDC_COMBOREV, m_rev);
	DDX_CBString(pDX, IDC_COMBOSTATE, m_state);
	DDX_CBString(pDX, IDC_COMBOUSER, m_user);
	DDX_Check(pDX, IDC_DATE, m_hasdate);
	DDX_Check(pDX, IDC_REV, m_hasrev);
	DDX_Check(pDX, IDC_STATE, m_hasstate);
	DDX_Check(pDX, IDC_USER, m_hasuser);
	//}}AFX_DATA_MAP
	
	if( m_hasstate )
	{
		DDV_MinChars(pDX, m_state, 1);
	}

	if( m_hasdate )
	{
		DDV_MinChars(pDX, m_date, 1);
	}

	if( !pDX->m_bSaveAndValidate )
	{
		OnRev();
		OnDate();
		OnState();
		OnUser();
	}

	DDX_ComboMString(pDX, IDC_COMBOREV, m_revCombo);
	DDX_ComboMString(pDX, IDC_COMBODATE, m_dateCombo);
	DDX_ComboMString(pDX, IDC_COMBOUSER, m_userCombo);
	DDX_ComboMString(pDX, IDC_COMBOSTATE, m_stateCombo);
}


BEGIN_MESSAGE_MAP(CLogFilters, CPropertyPage)
	//{{AFX_MSG_MAP(CLogFilters)
	ON_BN_CLICKED(IDC_DATE, OnDate)
	ON_BN_CLICKED(IDC_REV, OnRev)
	ON_BN_CLICKED(IDC_STATE, OnState)
	ON_BN_CLICKED(IDC_USER, OnUser)
	ON_BN_CLICKED(IDC_BROWSE_TAG, OnBrowseTag)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CLogFilters message handlers

void CLogFilters::OnDate() 
{
	CButton* but = (CButton *)GetDlgItem(IDC_DATE);
	CWnd* wnd = GetDlgItem(IDC_COMBODATE);
	wnd->EnableWindow(but->GetCheck() == 1);
}

void CLogFilters::OnRev() 
{
	CButton* but = (CButton*)GetDlgItem(IDC_REV);
	
	CWnd* wnd = GetDlgItem(IDC_COMBOREV);
	if( wnd )
	{
		wnd->EnableWindow(but->GetCheck());
	}

	wnd = GetDlgItem(IDC_BROWSE_TAG);
	if( wnd )
	{
		wnd->EnableWindow(but->GetCheck());
	}
}

void CLogFilters::OnBrowseTag() 
{
	CPStr tagName;
	if( CompatGetTagListItem(m_mf, tagName) )
	{
		m_rev = (const char*)tagName;
		m_revCombo.SetWindowText(m_rev);
	}
}

void CLogFilters::OnState() 
{
	CButton* but = (CButton *)GetDlgItem(IDC_STATE);
	CWnd* wnd = GetDlgItem(IDC_COMBOSTATE);
	wnd->EnableWindow(but->GetCheck() == 1);
}

void CLogFilters::OnUser() 
{
	CButton* but = (CButton *)GetDlgItem(IDC_USER);
	CWnd* wnd = GetDlgItem(IDC_COMBOUSER);
	wnd->EnableWindow(but->GetCheck() == 1);
}
#endif /* WIN32 */

#ifdef qMacCvsPP
static void DoDataExchange_LogFilters(LWindow *theDialog, bool & hasDate, bool & hasStates,
		bool & hasRev, bool & hasUsers,
		CPStr & sLastDate, CPStr & sLastRev,
		CPStr & sLastUsers, CPStr & sLastStates, bool putValue)
{
	LCheckBox *chkd = dynamic_cast<LCheckBox*>
		(theDialog->FindPaneByID(item_LogCheckByDate));
	LEditText *editd = dynamic_cast<LEditText*>
		(theDialog->FindPaneByID(item_LogEditByDate));
	LCheckBox *chks = dynamic_cast<LCheckBox*>
		(theDialog->FindPaneByID(item_LogCheckByState));
	LEditText *edits = dynamic_cast<LEditText*>
		(theDialog->FindPaneByID(item_LogEditByState));
	LCheckBox *chkr = dynamic_cast<LCheckBox*>
		(theDialog->FindPaneByID(item_LogCheckByRev));
	LEditText *editr = dynamic_cast<LEditText*>
		(theDialog->FindPaneByID(item_LogEditByRev));
	LCheckBox *chku = dynamic_cast<LCheckBox*>
		(theDialog->FindPaneByID(item_LogCheckByUser));
	LEditText *editu = dynamic_cast<LEditText*>
		(theDialog->FindPaneByID(item_LogEditByUser));
	LPopupFiller *fillDate = dynamic_cast<LPopupFiller*>
		(theDialog->FindPaneByID(item_LogFillByDate));
	LPopupFiller *fillState = dynamic_cast<LPopupFiller*>
		(theDialog->FindPaneByID(item_LogFillByState));
	LPopupFiller *fillRev = dynamic_cast<LPopupFiller*>
		(theDialog->FindPaneByID(item_LogFillByRev));
	LPopupFiller *fillUser = dynamic_cast<LPopupFiller*>
		(theDialog->FindPaneByID(item_LogFillByUser));

	fillDate->DoDataExchange(gLogDateNames, putValue);
	fillState->DoDataExchange(gLogStateNames, putValue);
	fillRev->DoDataExchange(gLogRevNames, putValue);
	fillUser->DoDataExchange(gLogUserNames, putValue);

	if(putValue)
	{
		chkd->SetValue(hasDate ? Button_On : Button_Off);
		editd->SetText((Ptr)(const char *)sLastDate, sLastDate.length());

		chks->SetValue(hasStates ? Button_On : Button_Off);
		edits->SetText((Ptr)(const char *)sLastStates, sLastStates.length());

		chkr->SetValue(hasRev ? Button_On : Button_Off);
		editr->SetText((Ptr)(const char *)sLastRev, sLastRev.length());

		chku->SetValue(hasUsers ? Button_On : Button_Off);
		editu->SetText((Ptr)(const char *)sLastUsers, sLastUsers.length());
	}
	else
	{
		char str[255];
		Size len;

		hasDate = chkd->GetValue() == Button_On;
		editd->GetText(str, 254, &len);
		sLastDate.set(str, len);

		hasStates = chks->GetValue() == Button_On;
		edits->GetText(str, 254, &len);
		sLastStates.set(str, len);

		hasRev = chkr->GetValue() == Button_On;
		editr->GetText(str, 254, &len);
		sLastRev.set(str, len);

		hasUsers = chku->GetValue() == Button_On;
		editu->GetText(str, 254, &len);
		sLastUsers.set(str, len);
	}
}

static void DoDataExchange_LogSettings(LWindow *theDialog, bool & noRecurs, bool & defBranch,
	bool & headerOnly, bool & noTags, bool & onlyRCSfile, bool putValue)
{
	LCheckBox *chkNoRecurs = dynamic_cast<LCheckBox*>
		(theDialog->FindPaneByID(item_NoRecurs));
	LCheckBox *chkDefBranch = dynamic_cast<LCheckBox*>
		(theDialog->FindPaneByID(item_LogDefBranch));
	LCheckBox *chkHeaderOnly = dynamic_cast<LCheckBox*>
		(theDialog->FindPaneByID(item_LogNoUserLogs));
	LCheckBox *chkNoTags = dynamic_cast<LCheckBox*>
		(theDialog->FindPaneByID(item_LogNoTags));
	LCheckBox *chkOnlyRCSfile = dynamic_cast<LCheckBox*>
		(theDialog->FindPaneByID(item_LogOnlyRcs));

	if(putValue)
	{
		chkNoRecurs->SetValue(noRecurs ? Button_On : Button_Off);
		chkDefBranch->SetValue(defBranch ? Button_On : Button_Off);
		chkHeaderOnly->SetValue(headerOnly ? Button_On : Button_Off);
		chkNoTags->SetValue(noTags ? Button_On : Button_Off);
		chkOnlyRCSfile->SetValue(onlyRCSfile ? Button_On : Button_Off);
	}
	else
	{
		noRecurs = chkNoRecurs->GetValue() == Button_On;
		defBranch = chkDefBranch->GetValue() == Button_On;
		headerOnly = chkHeaderOnly->GetValue() == Button_On;
		noTags = chkNoTags->GetValue() == Button_On;
		onlyRCSfile = chkOnlyRCSfile->GetValue() == Button_On;
	}
}
#endif /* qMacCvsPP */

#if qUnix
class UCvsLog : public UWidget
{
	UDECLARE_DYNAMIC(UCvsLog)
public:
	UCvsLog() : UWidget(::UEventGetWidID()) {}
	virtual ~UCvsLog() {}

	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(UCvsLog, UWidget)

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

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

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

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

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

	enum
	{
		kCheckBranch = EV_COMMAND_START,	// 0
		kCheckRecurs,			// 1
		kCheckRCS,				// 2
		kCheckTags,				// 3
		kCheckUsers				// 4
	};

	virtual void DoDataExchange(bool fill);

	bool m_defbranch;
	bool m_norecurs;
	bool m_notags;
	bool m_nousers;
	bool m_onlyrcs;

protected:
	UDECLARE_MESSAGE_MAP()
};

UIMPLEMENT_DYNAMIC(UCvsLog_MAIN, UWidget)

UBEGIN_MESSAGE_MAP(UCvsLog_MAIN, UWidget)
UEND_MESSAGE_MAP()

UCvsLog_MAIN::UCvsLog_MAIN() : UWidget(::UEventGetWidID())
{
	m_defbranch = false;
	m_norecurs = false;
	m_notags = false;
	m_nousers = false;
	m_onlyrcs = false;
}

void UCvsLog_MAIN::DoDataExchange(bool fill)
{
	if(fill)
	{
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kCheckBranch, m_defbranch), 0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kCheckRecurs, m_norecurs), 0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kCheckTags, m_notags), 0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kCheckUsers, m_nousers), 0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kCheckRCS, m_onlyrcs), 0L);
	}
	else
	{
		m_defbranch = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kCheckBranch, 0L);
		m_norecurs = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kCheckRecurs, 0L);
		m_notags = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kCheckTags, 0L);
		m_nousers = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kCheckUsers, 0L);
		m_onlyrcs = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kCheckRCS, 0L);
	}
}

class UCvsLog_FILTERS : public UWidget
{
	UDECLARE_DYNAMIC(UCvsLog_FILTERS)
public:
	UCvsLog_FILTERS(const char * sLastDate, const char * sLastRev,
		const char * sLastUsers, const char * sLastStates);
	virtual ~UCvsLog_FILTERS() {}

	enum
	{
		kCheckTag = EV_COMMAND_START,	// 0
		kCheckDate,			// 1
		kCheckState,		// 2
		kCheckUser,			// 3
		kComboTag,			// 4
		kComboDate,			// 5
		kComboState,		// 6
		kComboUser			// 7
	};

	virtual void DoDataExchange(bool fill);

	UStr m_date;
	UStr m_rev;
	UStr m_state;
	UStr m_user;
	bool m_hasrev;
	bool m_hasuser;
	bool m_hasdate;
	bool m_hasstate;
protected:

	ev_msg int OnSelect(int cmd);

	UDECLARE_MESSAGE_MAP()
};

UIMPLEMENT_DYNAMIC(UCvsLog_FILTERS, UWidget)

UBEGIN_MESSAGE_MAP(UCvsLog_FILTERS, UWidget)
	ON_UCOMMAND_RANGE(UCvsLog_FILTERS::kCheckTag, UCvsLog_FILTERS::kCheckUser, UCvsLog_FILTERS::OnSelect)
UEND_MESSAGE_MAP()

UCvsLog_FILTERS::UCvsLog_FILTERS(const char * sLastDate, const char * sLastRev,
		const char * sLastUsers, const char * sLastStates) : UWidget(::UEventGetWidID())
{
	m_date = sLastDate;
	m_rev = sLastRev;
	m_state = sLastStates;
	m_user = sLastUsers;
	m_hasrev = false;
	m_hasuser = false;
	m_hasdate = false;
	m_hasstate = false;
}

int UCvsLog_FILTERS::OnSelect(int cmd)
{
	int state = UEventSendMessage(GetWidID(), EV_QUERYSTATE, cmd, 0L);
	UEventSendMessage(GetWidID(), EV_ENABLECMD, UMAKEINT(cmd + 4, state), 0L);
	return 0;
}

void UCvsLog_FILTERS::DoDataExchange(bool fill)
{
	::DoDataExchange(fill, GetWidID(), kComboTag, gLogRevNames);
	::DoDataExchange(fill, GetWidID(), kComboDate, gLogDateNames);
	::DoDataExchange(fill, GetWidID(), kComboUser, gLogUserNames);
	::DoDataExchange(fill, GetWidID(), kComboState, gLogStateNames);

	if(fill)
	{
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kCheckDate, m_hasdate), 0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kCheckTag, m_hasrev), 0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kCheckState, m_hasstate), 0L);
		UEventSendMessage(GetWidID(), EV_SETSTATE, UMAKEINT(kCheckUser, m_hasuser), 0L);

		UEventSendMessage(GetWidID(), EV_SETTEXT, kComboDate, (void *)(const char *)m_date);
		UEventSendMessage(GetWidID(), EV_SETTEXT, kComboTag, (void *)(const char *)m_rev);
		UEventSendMessage(GetWidID(), EV_SETTEXT, kComboState, (void *)(const char *)m_state);
		UEventSendMessage(GetWidID(), EV_SETTEXT, kComboUser, (void *)(const char *)m_user);

		OnSelect(kCheckDate);
		OnSelect(kCheckTag);
		OnSelect(kCheckUser);
		OnSelect(kCheckState);
	}
	else
	{
		m_hasdate = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kCheckDate, 0L);
		m_hasrev = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kCheckTag, 0L);
		m_hasstate = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kCheckState, 0L);
		m_hasuser = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kCheckUser, 0L);

		UEventSendMessage(GetWidID(), EV_GETTEXT, kComboDate, &m_date);
		UEventSendMessage(GetWidID(), EV_GETTEXT, kComboTag, &m_rev);
		UEventSendMessage(GetWidID(), EV_GETTEXT, kComboState, &m_state);
		UEventSendMessage(GetWidID(), EV_GETTEXT, kComboUser, &m_user);
	}
}
#endif // qUnix

/// Get the log options
bool CompatGetLog(const MultiFiles* mf,
				  bool& noRecurs, bool& defBranch, CPStr& date,
				  bool& headerOnly, bool& noTags, bool& onlyRCSfile, bool& hasRev,
				  CPStr& rev, CPStr& states, bool& hasUsers, CPStr& users,
				  bool outGraph /*= false*/)
{
	bool userHitOK = false;

	static CPStr sLastDate;
	static CPStr sLastRev;
	static CPStr sLastUsers;
	static CPStr sLastStates;

	bool hasDate = false;
	bool hasStates = false;

	hasRev = false;
	hasUsers = false;
	date = "";
	rev = "";
	states = "";
	users = "";
	noRecurs = false;
	defBranch = false;
	headerOnly = false;
	noTags = false;
	onlyRCSfile = false;
	
#ifdef WIN32
	COptionalPropertySheet pages(outGraph ? gCvsPrefs.HideCommandDlgGraph() : gCvsPrefs.HideCommandDlgLog(), 
		outGraph ? "Graph settings" : "Log settings");
	pages.m_psh.dwFlags |= PSH_NOAPPLYNOW;
	CLogMain page1;
	CLogFilters page2(mf, sLastDate, sLastRev, sLastUsers, sLastStates);
	CGetPrefs_GLOBALS page3;
	pages.AddPage(&page1);
	pages.AddPage(&page2);
	pages.AddPage(&page3);
	if(pages.DoModal() == IDOK)
	{
		noRecurs = page1.m_norecurs == TRUE;
		defBranch = page1.m_defbranch == TRUE;
		headerOnly = page1.m_nousers == TRUE;
		noTags = page1.m_notags == TRUE;
		onlyRCSfile = page1.m_onlyrcs == TRUE;

		sLastDate = page2.m_date;
		sLastRev = page2.m_rev;
		sLastUsers = page2.m_user;
		sLastStates = page2.m_state;

		hasRev = page2.m_hasrev == TRUE;
		hasUsers = page2.m_hasuser == TRUE;
		hasDate = page2.m_hasdate == TRUE;
		hasStates = page2.m_hasstate == TRUE;

		page3.StoreValues();
		if( outGraph )
		{
			gCvsPrefs.SetHideCommandDlgGraph(pages.GetHideCommandDlg());
		}
		else
		{
			gCvsPrefs.SetHideCommandDlgLog(pages.GetHideCommandDlg());
		}
		userHitOK = true;
	}
#endif /* WIN32 */
#ifdef qMacCvsPP
	StDialogHandler	theHandler(dlg_Log, 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);
	
	multiView->SwitchToPanel(3);
	DoDataExchange_Globals(theDialog, true);
	multiView->SwitchToPanel(2);
	DoDataExchange_LogFilters(theDialog, hasDate, hasStates, hasRev, hasUsers,
		sLastDate, sLastRev, sLastUsers, sLastStates, true);
	multiView->SwitchToPanel(1);
	DoDataExchange_LogSettings(theDialog, noRecurs, defBranch, headerOnly, noTags, onlyRCSfile, true);

	groupView->SetValue(sRuntimePanel);
	theDialog->Show();
	MessageT hitMessage;
	while (true)
	{		// Let DialogHandler process events
		hitMessage = theHandler.DoDialog();
		
		if (hitMessage == msg_OK || hitMessage == msg_Cancel)
			break;
	}
	theDialog->Hide();
	sRuntimePanel = groupView->GetValue();
	
	if(hitMessage == msg_OK)
	{
		multiView->SwitchToPanel(1);
		DoDataExchange_LogSettings(theDialog, noRecurs, defBranch, headerOnly, noTags, onlyRCSfile, false);
		multiView->SwitchToPanel(2);
		DoDataExchange_LogFilters(theDialog, hasDate, hasStates, hasRev, hasUsers,
		sLastDate, sLastRev, sLastUsers, sLastStates, false);
		multiView->SwitchToPanel(3);
		DoDataExchange_Globals(theDialog, false);
		userHitOK = true;
	}
#endif /* qMacCvsPP */
#if qUnix
	void *wid = UCreate_LogDlg();

	UCvsLog *dlg = new UCvsLog();
	UCvsLog_MAIN *tab1 = new UCvsLog_MAIN();
	UCvsLog_FILTERS *tab2 = new UCvsLog_FILTERS(sLastDate, sLastRev, sLastUsers, sLastStates);
	UEventSendMessage(dlg->GetWidID(), EV_INIT_WIDGET, kUMainWidget, wid);	
	dlg->AddPage(tab1, UCvsLog::kTabGeneral, 0);
	dlg->AddPage(tab2, UCvsLog::kTabGeneral, 1);

	if(dlg->DoModal())
	{
		noRecurs = tab1->m_norecurs;
		defBranch = tab1->m_defbranch;
		headerOnly = tab1->m_nousers;
		noTags = tab1->m_notags;
		onlyRCSfile = tab1->m_onlyrcs;

		sLastDate = tab2->m_date;
		sLastRev = tab2->m_rev;
		sLastUsers = tab2->m_user;
		sLastStates = tab2->m_state;

		hasRev = tab2->m_hasrev;
		hasUsers = tab2->m_hasuser;
		hasDate = tab2->m_hasdate;
		hasStates = tab2->m_hasstate;

		userHitOK = true;
	}

	delete dlg;
#endif // qUnix

	if(userHitOK)
	{
		if(hasDate && !sLastDate.empty())
			date = sLastDate;
		if(hasRev)
			rev = sLastRev;
		if(hasUsers)
			users = sLastUsers;
		if(hasStates && !sLastStates.empty())
			states = sLastStates;

		gCvsPrefs.save();
	}

	return userHitOK;
}
