//
// Copyright 1997 Nicholas J. Irias. All rights reserved.
//
//
// HistoryDlg.cpp : implementation file
//
#include "stdafx.h"
#include "p4win.h"
#include "HistoryDlg.h"
#include "viewerdlg.h"
#include "Mainfrm.h"
#include <process.h>
#include "cmd_diff.h"
#include "cmd_diff2.h"
#include "cmd_get.h"
#include "cmd_history.h"
#include "cmd_prepbrowse.h"
#include "DepotTreeCtrl.h"
#include "SpecDescDlg.h"
#include "hlp\p4win.hh"
#include "RegKeyEx.h"
#include "StringUtil.h"
#include "strops.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static LPCTSTR sRegKey = _T("Software\\Perforce\\P4Win\\Layout\\RevisionHistoryDlg");
static LPCTSTR sRegValue_ColumnWidths = _T("Column Widths");
#define FILELOGdashH 1
#define HOLD_LOCK_IF_HAVE_KEY (m_Key ? HOLD_LOCK : LOSE_LOCK)
#define UPDATE_STATUS(x) ((CMainFrame *)AfxGetMainWnd())->UpdateStatus(x)
int CALLBACK ListSort(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
static BOOL bReady = FALSE;
// Module global for use in sort callback
CHistoryDlg *pDlg;
/////////////////////////////////////////////////////////////////////////////
// HistoryDlg dialog
CHistoryDlg::CHistoryDlg(CWnd* pParent /*=NULL*/)
: CDialog(CHistoryDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CHistoryDlg)
m_CompleteHist = m_CompleteHistIC = m_CompleteHistI = FALSE;
//}}AFX_DATA_INIT
m_pParent = pParent;
m_Busy = m_Rerun = m_InitiallyNotBusy = FALSE;
m_SizeSet = FALSE;
m_SortAscending=FALSE;
m_LastSortColumn=1;
pDlg=this;
m_InitRect.SetRect(0,0,100,100);
m_WinPos.SetWindow( this, _T("RevisionHistoryDlg") );
m_listHeight = m_dlgHeight = m_lorgHeight = m_Key = 0;
m_EnableShowIntegs = TheApp()->m_RevHistEnableShowIntegs;
m_IsMinimized = FALSE;
m_More = FALSE;
m_pFRDlg = NULL;
m_FindWhatFlags = FR_DOWN | FR_HIDEWHOLEWORD;
}
CHistoryDlg::~CHistoryDlg()
{
// can't use MainFrame()-> construct
// because mainfram might have closed.
CMainFrame * mainWnd = MainFrame();
if (mainWnd)
mainWnd->SetGotUserInput( );
}
void CHistoryDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CHistoryDlg)
DDX_Control(pDX, IDC_REVFILETYPE, m_RevFileType);
DDX_Control(pDX, IDC_REVISIONACTION, m_RevisionAction);
DDX_Control(pDX, IDC_REVISIONINFO, m_RevisionInfo);
DDX_Control(pDX, IDC_REVISIONLIST, m_ListCtl);
DDX_Check(pDX, IDC_COMPLETEHIST, m_CompleteHistI);
DDX_Radio(pDX, IDC_RADIO1, m_CompleteHistIC);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CHistoryDlg, CDialog)
//{{AFX_MSG_MAP(CHistoryDlg)
ON_NOTIFY(LVN_COLUMNCLICK, IDC_REVISIONLIST, OnColumnclickRevlist)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_REVISIONLIST, OnItemchangedRevlist)
ON_UPDATE_COMMAND_UI(ID_FILEREVISION_DIFF2, OnUpdateDiff2)
ON_UPDATE_COMMAND_UI(ID_FILE_RECOVER, OnUpdateRecover)
ON_UPDATE_COMMAND_UI(ID_FILEREVISION_GET, OnUpdateGet)
ON_UPDATE_COMMAND_UI(ID_CHANGE_DESCRIBE, OnUpdateDescribeChg)
ON_UPDATE_COMMAND_UI(ID_POSITIONDEPOT, OnUpdatePositionDepot)
ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateCopyRows)
ON_UPDATE_COMMAND_UI(ID_FILE_REVISIONTREE, OnUpdateFileRevisiontree)
ON_UPDATE_COMMAND_UI(ID_FILE_ANNOTATIONS, OnUpdateFileAnnotate)
ON_UPDATE_COMMAND_UI(ID_FILE_ANNOTATE, OnUpdateFileAnnotate)
ON_UPDATE_COMMAND_UI(ID_FILE_ANNOTATEALL, OnUpdateFileAnnotate)
ON_UPDATE_COMMAND_UI(ID_FILE_ANNOTATECHG, OnUpdateFileAnnotate)
ON_UPDATE_COMMAND_UI(ID_FILE_ANNOTATECHGALL, OnUpdateFileAnnotate)
ON_COMMAND(ID_FILEREVISION_DIFF2, OnDiff2)
ON_COMMAND(ID_FILE_RECOVER, OnRecover)
ON_COMMAND(ID_FILEREVISION_GET, OnGet)
ON_COMMAND(ID_CHANGE_DESCRIBE, OnDescribeChg)
ON_COMMAND(ID_POSITIONDEPOT, OnPositionDepot)
ON_COMMAND(ID_EDIT_COPY, OnCopyRows)
ON_COMMAND(ID_FILE_REVISIONTREE, OnFileRevisionTree)
ON_COMMAND(ID_FILE_ANNOTATIONS, OnFileTimeLapseView)
ON_COMMAND(ID_FILE_ANNOTATE, OnFileAnnotate)
ON_COMMAND(ID_FILE_ANNOTATEALL, OnFileAnnotateAll)
ON_COMMAND(ID_FILE_ANNOTATECHG, OnFileAnnotateChg)
ON_COMMAND(ID_FILE_ANNOTATECHGALL, OnFileAnnotateChgAll)
ON_COMMAND(ID_PERFORCE_OPTIONS, OnPerforceOptions)
ON_UPDATE_COMMAND_UI(ID_POSITIONTOPATTERN, OnUpdatePositionToPattern)
ON_COMMAND(ID_POSITIONTOPATTERN, OnPositionToPattern)
ON_UPDATE_COMMAND_UI(ID_FINDNEXT, OnUpdatePositionToNext)
ON_COMMAND(ID_FINDNEXT, OnPositionToNext)
ON_UPDATE_COMMAND_UI(ID_FINDPREV, OnUpdatePositionToPrev)
ON_COMMAND(ID_FINDPREV, OnPositionToPrev)
ON_WM_SETCURSOR()
ON_WM_SIZE()
ON_WM_GETMINMAXINFO()
ON_BN_CLICKED(IDB_DIFFVSCLIENT, OnDiffvsclient)
ON_BN_CLICKED(IDC_COMPLETEHIST, OnCompletehist)
ON_BN_CLICKED(IDC_RADIO1, OnCompletehist)
ON_BN_CLICKED(IDC_RADIO2, OnCompletehist)
ON_BN_CLICKED(IDC_RADIO3, OnCompletehist)
ON_BN_CLICKED(IDHELP, OnHelp)
ON_BN_CLICKED(IDC_MORE, OnMore)
ON_BN_CLICKED(IDB_BROWSE, OnFileAutobrowse)
ON_BN_CLICKED(IDB_DIFFREVISIONS, OnDiff2)
ON_BN_CLICKED(IDB_GET, OnGet)
ON_NOTIFY(LVN_KEYDOWN, IDC_REVISIONLIST, OnKeydownRevisionlist)
ON_WM_CLOSE()
ON_WM_DESTROY()
ON_WM_SYSCOMMAND()
//}}AFX_MSG_MAP
ON_COMMAND_RANGE(ID_FILE_BROWSER_1, ID_FILE_BROWSER_1+MAX_MRU_VIEWERS-1, OnFileMRUBrowser)
ON_COMMAND(ID_FILE_NEWBROWSER, OnFileNewBrowser)
ON_COMMAND(ID_FILE_QUICKBROWSE, OnFileQuickbrowse)
ON_MESSAGE(WM_P4PREPBROWSE, OnP4ViewFile )
ON_MESSAGE(WM_P4GET, OnP4Get )
ON_MESSAGE(WM_P4DIFF, OnP4Diff )
ON_MESSAGE(WM_P4DIFF2, OnP4Diff2 )
ON_MESSAGE(WM_P4DESCRIBE, OnP4Describe )
ON_MESSAGE(WM_P4ENDDESCRIBE, OnP4EndDescribe )
ON_MESSAGE(WM_UPDATEHAVEREV, OnUpdateHaveRev )
ON_MESSAGE(WM_QUITTING, OnQuitting )
ON_WM_HELPINFO()
ON_REGISTERED_MESSAGE( WM_FINDREPLACE, OnFindReplace )
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// HistoryDlg message handlers
int CHistoryDlg::DoModal()
{
return CDialog::DoModal();
}
void CHistoryDlg::Init(CHistory *hist, CString &ftype, BOOL isText,
HWND depotWnd, int haveRev,
BOOL myOpenFile, const int initialRev /*=-1*/,
LPCTSTR initialName /*=NULL*/, int key /*=0*/)
{
ASSERT(IsWindow(depotWnd));
ASSERT( haveRev > 0 || !myOpenFile );
m_pHistory=hist;
m_FileType=ftype;
m_ViewFileIsText= isText;
m_DepotWnd=depotWnd;
m_HaveRev= haveRev;
m_MyOpenFile= myOpenFile;
m_InitialRev= initialRev;
m_InitialName = initialName ? initialName : _T("");
m_Key = key;
}
void CHistoryDlg::OnContextMenu(CPoint screen, int index)
{
if(m_Busy)
return;
// make a new selection new if reqd
if(m_ListCtl.GetItemState(index,LVIS_SELECTED) != LVIS_SELECTED)
{
for(int i=m_ListCtl.GetItemCount(); i>=0; i-- )
m_ListCtl.SetItemState(i, 0, LVIS_SELECTED);
m_ListCtl.SetItemState(index, LVIS_SELECTED, LVIS_SELECTED);
}
// create an empty context menu
CMenu popMenu;
popMenu.CreatePopupMenu();
CMenu viewMenu;
viewMenu.CreatePopupMenu();
int i;
int actualMRUs=0;
switch(m_ListCtl.GetSelectedCount())
{
case 1:
{
// If revision is not deleted, create a view file submenu
CRevision *rev= (CRevision *) m_ListCtl.GetItemData(index);
ASSERT(rev);
int bAnn = 0;
BOOL bTxt = FALSE;
if ((rev->m_ChangeType.Find(_T("delete")) != 0)
&& (rev->m_ChangeType.Find(_T("purge")) != 0))
{
for(i=0; i < MAX_MRU_VIEWERS; i++)
{
if( GET_P4REGPTR()->GetMRUViewerName(i).GetLength() > 0 )
{
viewMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_FILE_BROWSER_1+i,
CString ( _T("&") + GET_P4REGPTR()->GetMRUViewerName(i)) );
actualMRUs++;
}
}
if( actualMRUs > 0)
viewMenu.AppendMenu(MF_SEPARATOR);
viewMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_FILE_QUICKBROWSE,
LoadStringResource( IDS_ASSOCVIEWER ));
viewMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_FILE_NEWBROWSER,
LoadStringResource( IDS_OTHERVIEWER ));
if (GET_SERVERLEVEL() >= 14)
{
bAnn = MainFrame()->HaveTLV();
if (bAnn)
{
CString fname = GetSelectedFileName();
bAnn = ((CDepotTreeCtrl *)m_pParent)->IsInRemoteDepot(&fname) ? 0 : bAnn;
}
bTxt = ((m_FileType.Find(_T("text")) != -1)
|| (m_FileType.Find(_T("symlink")) != -1)) ? TRUE : FALSE;
if (bTxt)
{
viewMenu.AppendMenu(MF_SEPARATOR);
viewMenu.AppendMenu( stringsON, ID_FILE_ANNOTATE,
LoadStringResource ( IDS_FILE_ANNOTATE ) );
viewMenu.AppendMenu( stringsON, ID_FILE_ANNOTATEALL,
LoadStringResource ( IDS_FILE_ANNOTATEALL ) );
viewMenu.AppendMenu( stringsON, ID_FILE_ANNOTATECHG,
LoadStringResource ( IDS_FILE_ANNOTATECHG ) );
viewMenu.AppendMenu( stringsON, ID_FILE_ANNOTATECHGALL,
LoadStringResource ( IDS_FILE_ANNOTATECHGALL ) );
}
}
popMenu.AppendMenu(MF_POPUP, (UINT) viewMenu.GetSafeHmenu(),
LoadStringResource(IDS_VIEW_THIS_REVISION_USING));
}
if (rev->m_FName == m_LatestName)
popMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_FILEREVISION_GET, LoadStringResource(IDS_SYNC_TO_THIS_REVISION));
if (m_LatestIsDeleted && rev->m_ChangeType.Find(_T("delete")) != 0)
popMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_FILE_RECOVER, LoadStringResource(IDS_RECOVERDELFILE));
if (!((CDepotTreeCtrl *)m_pParent)->IsInRemoteDepot(&(rev->m_FName)))
popMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_CHANGE_DESCRIBE, LoadStringResource(IDS_DESCRIBESUBMITTED) );
if (bAnn == 1)
{
popMenu.AppendMenu( stringsON, ID_FILE_REVISIONTREE, LoadStringResource( IDS_REVISIONTREE ));
if (bTxt)
popMenu.AppendMenu( stringsON, ID_FILE_ANNOTATIONS, LoadStringResource ( IDS_ANNOTATIONS ) );
}
popMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_POSITIONDEPOT, LoadStringResource(IDS_POSITIONDEPOT) );
break;
}
case 2:
{
CRevision *rev1 = 0;
CRevision *rev2 = 0;
for(int i= 0; i < m_ListCtl.GetItemCount(); i++)
{
if(m_ListCtl.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED)
{
if (!rev1)
{
rev1= (CRevision *) m_ListCtl.GetItemData(i);
}
else
{
rev2= (CRevision *) m_ListCtl.GetItemData(i);
break;
}
}
}
ASSERT(rev1);
ASSERT(rev2);
if (rev1->m_ChangeType.Find(_T("delete")) != 0
&& rev1->m_ChangeType.Find(_T("purge")) != 0
&& rev2->m_ChangeType.Find(_T("delete")) != 0
&& rev2->m_ChangeType.Find(_T("purge")) != 0)
popMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_FILEREVISION_DIFF2, LoadStringResource(IDS_DIFF_TWO_REVISIONS));
break;
}
default:
break;
}
if (m_ListCtl.GetSelectedCount())
popMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_EDIT_COPY, LoadStringResource(IDS_amp_Copy_tab_Ctrl_C));
popMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_POSITIONTOPATTERN, LoadStringResource(IDS_FINDPATTERN));
// Finally blast the menu onto the screen
if(popMenu.GetMenuItemCount() > 0)
popMenu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, screen.x, screen.y, this);
}
void CHistoryDlg::OnUpdateDiff2(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!m_Busy && m_ListCtl.GetSelectedCount()==2);
}
void CHistoryDlg::OnUpdateRecover(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!m_Busy && m_ListCtl.GetSelectedCount()==1
&& m_LatestIsDeleted);
}
void CHistoryDlg::OnUpdateGet(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!m_Busy && m_ListCtl.GetSelectedCount()==1);
}
void CHistoryDlg::OnUpdateDescribeChg(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!m_Busy && m_ListCtl.GetSelectedCount()==1);
}
void CHistoryDlg::OnUpdatePositionDepot(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!m_Busy && m_ListCtl.GetSelectedCount());
}
void CHistoryDlg::OnUpdateCopyRows(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!m_Busy && m_ListCtl.GetSelectedCount());
}
void CHistoryDlg::OnUpdateFileRevisiontree(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!SERVER_BUSY() && GET_SERVERLEVEL() >= 14
&& m_ListCtl.GetSelectedCount()==1);
}
void CHistoryDlg::OnUpdateFileAnnotate(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!SERVER_BUSY() && GET_SERVERLEVEL() >= 14
&& m_ListCtl.GetSelectedCount()==1);
}
void CHistoryDlg::OnFileMRUBrowser(UINT nID)
{
if(m_ListCtl.GetSelectedCount() != 1)
{ ASSERT(0); return; }
// Note which viewer is to be used
m_Viewer= GET_P4REGPTR()->GetMRUViewer( nID - ID_FILE_BROWSER_1 );
GET_P4REGPTR()->AddMRUViewer(m_Viewer);
// Fetch the head revision of the file to a temp filename
CCmd_PrepBrowse *pCmd= new CCmd_PrepBrowse;
pCmd->Init( m_hWnd, RUN_ASYNC, HOLD_LOCK_IF_HAVE_KEY, m_Key);
if( pCmd->Run( GetSelectedFileName(), m_FileType, GetSelectedRevision() ) )
{
m_Busy=TRUE;
EnableButtons();
UPDATE_STATUS(LoadStringResource(IDS_FETCHING_FILE));
}
else
delete pCmd;
}
void CHistoryDlg::OnFileNewBrowser()
{
if(m_ListCtl.GetSelectedCount() != 1)
{ ASSERT(0); return; }
// Fire up a common dlg to find new file
CFileDialog fDlg(TRUE, _T("exe"), NULL,
OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NONETWORKBUTTON | OFN_PATHMUSTEXIST,
LoadStringResource(IDS_HISTORY_BROWSE_FILTER), this,
MainFrame()->m_osVer.dwMajorVersion < 5 ? OPENFILENAME_SIZE_VERSION_400 : sizeof(OPENFILENAME));
if(fDlg.DoModal() == IDOK)
{
m_Viewer= fDlg.GetPathName();
if(m_Viewer.GetLength() > 0)
{
// User selected a valid viewer, so try to run it
GET_P4REGPTR()->AddMRUViewer(m_Viewer);
OnFileMRUBrowser(ID_FILE_BROWSER_1);
}
}
}
void CHistoryDlg::OnFileQuickbrowse()
{
FileQuickbrowse(FALSE);
}
void CHistoryDlg::FileQuickbrowse(BOOL ckifdeleted)
{
if(m_ListCtl.GetSelectedCount() != 1)
{ ASSERT(0); return; }
if(ckifdeleted)
{
// don't allow quickbrowse for deleted files
CRevision *rev = 0;
for(int i= 0; i < m_ListCtl.GetItemCount(); i++)
{
if(m_ListCtl.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED)
{
rev= (CRevision *) m_ListCtl.GetItemData(i);
break;
}
}
ASSERT(rev);
if (rev->m_ChangeType.Find(_T("delete")) == 0
|| rev->m_ChangeType.Find(_T("purge")) == 0)
{
MessageBeep(0);
return;
}
}
m_Viewer=_T("SHELLEXEC");
// Fetch the selected revision of the file to a temp filename
CCmd_PrepBrowse *pCmd= new CCmd_PrepBrowse;
pCmd->Init( m_hWnd, RUN_ASYNC, HOLD_LOCK_IF_HAVE_KEY, m_Key);
if( pCmd->Run( GetSelectedFileName(), m_FileType, GetSelectedRevision() ) )
{
m_Busy=TRUE;
EnableButtons();
UPDATE_STATUS( LoadStringResource(IDS_FETCHING_FILE) );
}
else
delete pCmd;
}
void CHistoryDlg::OnFileAutobrowse()
{
if(m_ListCtl.GetSelectedCount() != 1)
{ ASSERT(0); return; }
// Ask the user to pick a viewer
CViewerDlg dlg;
if(dlg.DoModal() == IDCANCEL)
return;
m_Viewer=dlg.GetViewer();
if(m_Viewer != _T("SHELLEXEC"))
GET_P4REGPTR()->AddMRUViewer(m_Viewer);
// Fetch the head revision of the file to a temp filename
CCmd_PrepBrowse *pCmd= new CCmd_PrepBrowse;
pCmd->Init( m_hWnd, RUN_ASYNC, HOLD_LOCK_IF_HAVE_KEY, m_Key);
if( pCmd->Run( GetSelectedFileName(), m_FileType, GetSelectedRevision() ) )
{
m_Busy=TRUE;
EnableButtons();
UPDATE_STATUS( LoadStringResource(IDS_FETCHING_FILE) );
}
else
delete pCmd;
}
void CHistoryDlg::OnFileRevisionTree()
{
if(m_ListCtl.GetSelectedCount() != 1)
{ ASSERT(0); return; }
CString filename = GetSelectedFileName();
TheApp()->CallP4RevisionTree(filename); // use p4v.exe for revision tree
}
void CHistoryDlg::OnFileTimeLapseView()
{
if(m_ListCtl.GetSelectedCount() != 1)
{ ASSERT(0); return; }
CString filename = GetSelectedFileName();
TheApp()->CallP4A(filename, _T(""), 0); // use p4v.exe for annotate
}
void CHistoryDlg::OnFileAnnotate()
{
FileAnnotate(FALSE);
}
void CHistoryDlg::OnFileAnnotateAll()
{
FileAnnotate(TRUE);
}
void CHistoryDlg::OnFileAnnotateChg()
{
FileAnnotate(FALSE, TRUE);
}
void CHistoryDlg::OnFileAnnotateChgAll()
{
FileAnnotate(TRUE, TRUE);
}
void CHistoryDlg::FileAnnotate(BOOL bAll, BOOL bChg/*=FALSE*/)
{
if(m_ListCtl.GetSelectedCount() != 1)
{ ASSERT(0); return; }
CString filename = GetSelectedFileName();
CString tempfilelogname;
// Fetch the annotated file to a temp filename
CCmd_PrepBrowse *pCmd= new CCmd_PrepBrowse;
if (tempfilelogname.GetLength() > 0)
{
pCmd->Init(MainFrame()->GetDepotWnd(), RUN_ASYNC, HOLD_LOCK_IF_HAVE_KEY, m_Key);
pCmd->SetTempFilelog(tempfilelogname);
bAll = TRUE;
bChg = FALSE;
}
else
pCmd->Init( m_hWnd, RUN_ASYNC, HOLD_LOCK_IF_HAVE_KEY, m_Key );
if( pCmd->Run( FALSE, filename, m_FileType,
bAll, bChg, FALSE, GetSelectedRevision(),
GET_P4REGPTR()->GetAnnotateWhtSpace(),
bChg ? GET_P4REGPTR()->GetAnnotateIncInteg() : FALSE ) )
{
m_Busy = tempfilelogname.GetLength() > 0 ? FALSE : TRUE;
EnableButtons();
UPDATE_STATUS( LoadStringResource(IDS_FETCHING_FILE) );
m_Viewer=GET_P4REGPTR()->GetEditApp();
}
else
delete pCmd;
}
CString CHistoryDlg::WriteTempHistFile()
{
Error e;
FileSys *pOutputFile= FileSys::Create( FST_TEXT );
CString TempPath= GET_P4REGPTR()->GetTempDir();
CString TempName;
CString FileName = m_InitialName;
int i;
if (((i = FileName.ReverseFind(_T('\\'))) != -1)
|| ((i = FileName.ReverseFind(_T('/'))) != -1))
FileName = FileName.Mid(i+1);
for(i=0; i< 100; i++)
{
e.Clear();
TempName.Format(_T("%s\\FileLog-Rev-%d-%s.txt"), TempPath, i, FileName);
pOutputFile->Set(CharFromCString(TempName));
if( !e.Test() )
pOutputFile->MkDir( &e );// Prepare write (makes dir as required)
if( !e.Test() )
{
pOutputFile->Perms( FPM_RW ); // Open it
pOutputFile->Open( FOM_WRITE, &e );
}
if(!e.Test())
break;
}
if(e.Test())
{
CString txt;
txt.Format(_T("Error opening temporary file:\n %s"), TempName);
TheApp()->StatusAdd(txt, SV_ERROR);
delete pOutputFile;
return _T("");;
}
StrBuf sptr;
CString str = m_InitialName + _T('\n');
sptr.Set(const_cast<char*>((const char*)CharFromCString(str)));
pOutputFile->Write( &sptr, &e );
if(e.Test())
{
CString txt;
txt.Format(_T("Error writing temporary file header:\n %s"), TempName);
TheApp()->StatusAdd(txt, SV_ERROR);
delete pOutputFile;
return _T("");
}
BOOL b = FALSE;
CRevision *rev=m_pHistory->GetHeadRevision();
int prevrev;
do
{
prevrev = rev->m_RevisionNum;
if (m_InitialName == rev->m_FName)
{
b = TRUE;
CString chgType = rev->m_ChangeType;
CString integs = _T("");
if ((i = chgType.Find(_T(": "))) != -1)
{
integs = chgType.Mid(i + 2);
chgType = chgType.Left(i);
}
str.Format(_T("... #%d change %d %s on %s by %s %s"),
rev->m_RevisionNum, rev->m_ChangeNum, chgType,
rev->m_Date, rev->m_User, rev->m_ChangeDescription);
str.Replace(_T("\n"), _T("\n "));
if (integs.GetLength() > 0)
{
integs.Replace(_T("; "), _T("\n... ... "));
str += _T("\n\n... ... ") + integs;
}
str += _T("\n\n");
str.Remove(_T('\r'));
sptr.Set(const_cast<char*>((const char*)CharFromCString(str)));
pOutputFile->Write( &sptr, &e );
if(e.Test())
{
CString txt;
txt.Format(_T("Error writing temporary file:\n %s"), TempName);
TheApp()->StatusAdd(txt, SV_ERROR);
delete pOutputFile;
return _T("");
}
}
rev=m_pHistory->GetPrevRevision();
} while (rev && (rev->m_RevisionNum < prevrev));
pOutputFile->ClearDeleteOnClose();
pOutputFile->Close(&e);
delete pOutputFile;
return TempName;
}
LRESULT CHistoryDlg::OnP4Diff(WPARAM wParam, LPARAM lParam)
{
CCmd_Diff *pCmd= (CCmd_Diff *) wParam;
if(pCmd->GetDiffRunCount() == 0)
{
AfxMessageBox(pCmd->GetDiffErrCount() ? pCmd->GetDiffErrBuf() : LoadStringResource(IDS_FILES_ARE_IDENTICAL),
MB_ICONINFORMATION);
}
UPDATE_STATUS(_T(""));
m_Busy=FALSE;
EnableButtons();
delete pCmd;
return 0;
}
LRESULT CHistoryDlg::OnP4Diff2(WPARAM wParam, LPARAM lParam)
{
CCmd_Diff2 *pCmd= (CCmd_Diff2 *) wParam;
CString msg= pCmd->GetInfoText();
if( ! msg.IsEmpty() )
{
AfxMessageBox( msg, MB_ICONINFORMATION);
}
UPDATE_STATUS(_T(""));
m_Busy=FALSE;
EnableButtons();
delete pCmd;
return 0;
}
LRESULT CHistoryDlg::OnP4Get(WPARAM wParam, LPARAM lParam)
{
UPDATE_STATUS(_T(""));
::SendMessage(m_DepotWnd, WM_P4GET, wParam, lParam);
m_Busy=FALSE;
EnableButtons();
return 0;
}
// TODO: This code is pretty much a copy of the code in CDepotView::RunViewer()
// Might want to craft a single file viewing class that can be instantiated from
// anywhere, or perhaps make CMainFrame be responsible for all file viewing.
LRESULT CHistoryDlg::OnP4ViewFile(WPARAM wParam, LPARAM lParam)
{
UPDATE_STATUS(_T(""));
CString tempName;
CString msg;
m_Busy=FALSE;
EnableButtons();
CCmd_PrepBrowse *pCmd= (CCmd_PrepBrowse *) wParam;
if(!pCmd->GetError())
{
m_ViewFilePath= pCmd->GetTempName();
// First, get the file extension, if any, and find out if
// its a text file
CString extension;
int slash= m_ViewFilePath.ReverseFind(_T('\\'));
if(slash != -1)
extension=m_ViewFilePath.Mid(slash+1);
else
extension=m_ViewFilePath;
int dot= extension.ReverseFind(_T('.'));
if(dot == -1)
extension=_T("");
else
extension=extension.Mid(dot+1);
// We have the file, m_ViewFilePath, try to display it
while(1)
{
if(m_Viewer == _T("SHELLEXEC"))
{
CString assocViewer=_T("");
// First, see if there a P4win file association
if(!extension.IsEmpty())
assocViewer= GET_P4REGPTR()->GetAssociatedApp(extension);
// If we still havent found a viewer, set viewer to default text app
// if user wishes to ignore windows associations
if(assocViewer.IsEmpty() && m_ViewFileIsText && GET_P4REGPTR()->GetIgnoreWinAssoc())
assocViewer= GET_P4REGPTR()->GetEditApp();
// Let windows take a crack at finding a viewer
if(assocViewer.IsEmpty() && !extension.IsEmpty())
{
// Quick check for executeable extension, which will make ShellExec try to run the file
HINSTANCE hinst=0;
if( extension.CompareNoCase(_T("com")) != 0 && extension.CompareNoCase(_T("exe")) != 0 &&
extension.CompareNoCase(_T("bat")) != 0 && extension.CompareNoCase(_T("cmd")) != 0)
{
// first try the non-standard M$ IDE's - Have to be done first they're so BAAAD
// give VS .NET (non-standard!) a try.
hinst= ShellExecute( m_hWnd, _T("Open.VisualStudio.7.1"), m_ViewFilePath, NULL, NULL, SW_SHOWNORMAL);
if( (int) hinst > 32 )
break; // successfull VS .NET editor launch
if( (int) hinst == SE_ERR_NOASSOC) // give MSDEV (non-standard!) a try
{
hinst= ShellExecute( m_hWnd, _T("&Open with MSDEV"), m_ViewFilePath, NULL, NULL, SW_SHOWNORMAL);
if( (int) hinst > 32 )
break; // successfull MSDEV editor launch
}
hinst= ShellExecute( m_hWnd, _T("open"), m_ViewFilePath, NULL, NULL, SW_SHOWNORMAL);
if( (int) hinst > 32)
{
break; // successfull viewer launch
}
}
}
// If windows doesnt have an associated viewer for a text file, we use the
// default text editor
if(assocViewer.IsEmpty() && m_ViewFileIsText)
assocViewer= GET_P4REGPTR()->GetEditApp();
if ( TheApp()->RunViewerApp( assocViewer, m_ViewFilePath ) )
break; // successfull viewer launch
}
else
{
if ( TheApp()->RunViewerApp( m_Viewer, m_ViewFilePath ) )
break; // successfull viewer launch
}
CString msg;
msg.FormatMessage(IDS_UNABLE_TO_LAUNCH_VIEWER_s, m_ViewFilePath);
if(AfxMessageBox(msg, MB_YESNO | MB_ICONEXCLAMATION) == IDNO)
break;
// Try to find an alternate viewer
CViewerDlg dlg;
if(dlg.DoModal() == IDCANCEL)
break;
m_Viewer=dlg.GetViewer();
if(m_Viewer != _T("SHELLEXEC"))
GET_P4REGPTR()->AddMRUViewer(m_Viewer);
} // while
} // no command error
delete pCmd;
UPDATE_STATUS(_T(""));
return 0;
}
LRESULT CHistoryDlg::OnUpdateHaveRev(WPARAM wParam, LPARAM lParam)
{
int ctr=2;
m_HaveRev = lParam;
CString revStr;
revStr.Format(_T("%d"), m_HaveRev);
for(int iItem=0; ctr && iItem < m_pHistory->GetRevisionCount(); iItem++)
{
if (m_InitialName != m_ListCtl.GetItemText(iItem, 1))
continue;
CString txt = m_ListCtl.GetItemText(iItem, 0);
if (txt.Find(_T('*')) != -1)
{
txt.TrimRight(_T("* "));
m_ListCtl.SetItemText(iItem, 0, txt);
ctr--;
}
CString txtr = txt;
txtr.TrimLeft();
if (txtr == revStr)
{
txt += _T('*');
m_ListCtl.SetItemText(iItem, 0, txt);
ctr--;
}
}
return 0;
}
LRESULT CHistoryDlg::OnQuitting(WPARAM wParam, LPARAM lParam)
{
if (m_pParent)
m_pParent->SendMessage(WM_P4ENDHISTORY, 0, (LPARAM)this);
return 0;
}
void CHistoryDlg::OnClose()
{
OnOK();
}
void CHistoryDlg::OnCancel()
{
// What happens when the user accidentally hits escape
OnOK(); // Now if they hit Escape, the window closes.
}
void CHistoryDlg::OnDiff2()
{
if(m_ListCtl.GetSelectedCount() != 2)
{ ASSERT(0); return; }
CRevision *rev[2];
int i, revindex;
// Get the two file revs - (in reverse order so newer is the 2nd diff arg)
for(revindex=0, i=m_ListCtl.GetItemCount()-1; revindex < 2 && i >=0; i--)
{
if(m_ListCtl.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED)
{
rev[revindex]= (CRevision *) m_ListCtl.GetItemData(i);
revindex++;
}
}
ASSERT(revindex==2);
CString ft0;
CString ft1;
if ((i = rev[0]->m_ChangeDescription.Find(_T(')'))) != -1)
ft0 = rev[0]->m_ChangeDescription.Left(i+1);
else ft0 = m_FileType;
if ((i = rev[1]->m_ChangeDescription.Find(_T(')'))) != -1)
ft1 = rev[1]->m_ChangeDescription.Left(i+1);
else ft1 = m_FileType;
if (!GET_P4REGPTR()->GetDiffAppIsBinary())
{
if (((ft0.Find(_T("text")) != -1) && (ft1.Find(_T("binary")) != -1))
|| ((ft0.Find(_T("binary")) != -1) && (ft1.Find(_T("text")) != -1)))
{
CString txt;
txt.FormatMessage(IDS_ONLY_DIFF_SAME_TYPES_s_n_s_s_n_s,
rev[0]->m_FName, rev[0]->m_RevisionNum, ft0,
rev[1]->m_FName, rev[1]->m_RevisionNum, ft1);
AfxMessageBox(txt);
return;
}
}
if ((ft0.GetAt(0) == _T('(')) && (ft0.Find(_T(' ')) == -1))
{
ft0.TrimLeft(_T('('));
ft0.TrimRight(_T(')'));
}
else ft0 = m_FileType;
if ((ft1.GetAt(0) == _T('(')) && (ft1.Find(_T(' ')) == -1))
{
ft1.TrimLeft(_T('('));
ft1.TrimRight(_T(')'));
}
else ft1 = m_FileType;
CCmd_Diff2 *pCmd= new CCmd_Diff2;
pCmd->Init( m_hWnd, RUN_ASYNC, HOLD_LOCK_IF_HAVE_KEY, m_Key);
if( pCmd->Run( rev[0]->m_FName, rev[1]->m_FName,
rev[0]->m_RevisionNum, rev[1]->m_RevisionNum, ft0, ft1) )
{
m_Busy=TRUE;
EnableButtons();
UPDATE_STATUS( LoadStringResource(IDS_DIFFING_FILES) );
}
else
delete pCmd;
}
void CHistoryDlg::OnDiffvsclient()
{
if( m_ListCtl.GetSelectedCount() != 1 || m_HaveRev == 0)
{ ASSERT(0); return; }
if (!m_CompleteHist || (GetSelectedFileName() == m_LatestName))
{
CString depotName;
depotName.Format(_T("%s#%d"), GetSelectedFileName(), GetSelectedRevision());
m_FileList.RemoveAll();
m_FileList.AddHead(depotName);
CCmd_Diff *pCmd= new CCmd_Diff;
pCmd->Init( m_hWnd, RUN_ASYNC, HOLD_LOCK_IF_HAVE_KEY, m_Key);
if( pCmd->Run( &m_FileList, ( !m_MyOpenFile && m_HaveRev == GetSelectedRevision() )
? _T("-f") : NULL ) )
{
m_Busy=TRUE;
EnableButtons();
UPDATE_STATUS( LoadStringResource(IDS_DIFFING_FILE) );
}
else
delete pCmd;
}
else
{
// Get the rev
CRevision *rev = 0;
int i;
for(i= 0; i < m_ListCtl.GetItemCount(); i++)
{
if(m_ListCtl.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED)
{
rev= (CRevision *) m_ListCtl.GetItemData(i);
break;
}
}
CString ft0;
if ((i = rev->m_ChangeDescription.Find(_T(')'))) != -1)
ft0 = rev->m_ChangeDescription.Left(i+1);
else ft0 = m_FileType;
if (!GET_P4REGPTR()->GetDiffAppIsBinary())
{
if (((ft0.Find(_T("text")) != -1) && (m_FileType.Find(_T("binary")) != -1))
|| ((ft0.Find(_T("binary")) != -1) && (m_FileType.Find(_T("text")) != -1)))
{
CString txt;
txt.FormatMessage(IDS_ONLY_DIFF_SAME_TYPES_s_n_s_s_n_s,
rev->m_FName, rev->m_RevisionNum, ft0,
m_LatestName, m_HaveRev, m_FileType);
AfxMessageBox(txt);
return;
}
}
if ((ft0.GetAt(0) == _T('(')) && (ft0.Find(_T(' ')) == -1))
{
ft0.TrimLeft(_T('('));
ft0.TrimRight(_T(')'));
}
else ft0 = m_FileType;
CCmd_Diff2 *pCmd= new CCmd_Diff2;
pCmd->Init( m_hWnd, RUN_ASYNC, HOLD_LOCK_IF_HAVE_KEY, m_Key);
if( pCmd->Run( rev->m_FName, m_LatestName,
rev->m_RevisionNum, m_HaveRev, ft0, m_FileType, FALSE, TRUE) )
{
m_Busy=TRUE;
EnableButtons();
UPDATE_STATUS( LoadStringResource(IDS_DIFFING_FILES) );
}
else
delete pCmd;
}
}
void CHistoryDlg::OnRecover()
{
if(m_ListCtl.GetSelectedCount() != 1)
{ ASSERT(0); return; }
m_Recover.AddHead(m_LatestName);
OnGet();
}
void CHistoryDlg::OnGet()
{
if(m_ListCtl.GetSelectedCount() != 1)
{ ASSERT(0); m_Recover.RemoveAll(); return; }
CRevision *rev = 0;
for(int i= 0; i < m_ListCtl.GetItemCount(); i++)
{
if(m_ListCtl.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED)
{
rev= (CRevision *) m_ListCtl.GetItemData(i);
break;
}
}
ASSERT(rev);
CString name;
name.Format(_T("%s#%ld"), rev->m_FName, rev->m_RevisionNum);
m_FileList.AddHead(name);
CCmd_Get *pCmd= new CCmd_Get;
pCmd->Init( m_hWnd, RUN_ASYNC, HOLD_LOCK_IF_HAVE_KEY, m_Key);
if( m_Recover.GetCount() > 0 )
{
for (POSITION pos = m_Recover.GetHeadPosition(); pos != NULL; )
{
CString str = m_Recover.GetNext(pos);
if (str.Find(_T('%')) != -1)
{
StrBuf b;
StrBuf f;
f << CharFromCString(str);
StrPtr *p = &f;
StrOps::StrToWild(*p, b);
str = CharToCString(b.Value());
}
pCmd->Add2Recover(str);
}
m_Recover.RemoveAll();
}
pCmd->SetRevHistWnd(m_hWnd);
pCmd->SetRevReq(rev->m_RevisionNum);
if( pCmd->Run( &m_FileList, FALSE ) )
{
m_Busy=TRUE;
EnableButtons();
}
else
delete pCmd;
GotoDlgCtrl(GetDlgItem(IDC_REVISIONLIST));
}
void CHistoryDlg::OnDescribeChg()
{
long changeNumber = GetSelectedChgNbr();
if(changeNumber != 0)
{
CString nbr;
nbr.Format(_T("%ld"), changeNumber);
CCmd_Describe *pCmd= new CCmd_Describe;
pCmd->Init( m_hWnd, RUN_ASYNC, HOLD_LOCK_IF_HAVE_KEY, m_Key);
if( pCmd->Run( P4DESCRIBE, nbr) )
UPDATE_STATUS(LoadStringResource(IDS_FETCHING_CHANGELIST_DESCRIPTION));
else
delete pCmd;
}
}
void CHistoryDlg::OnDescribeChgLong(long changeNumber, int flag /*= 0*/)
{
if(changeNumber != 0)
{
CString nbr;
nbr.Format(_T("%ld"), changeNumber);
CCmd_Describe *pCmd= new CCmd_Describe;
pCmd->Init( m_hWnd, RUN_ASYNC, HOLD_LOCK_IF_HAVE_KEY, m_Key);
if( pCmd->Run( P4DESCRIBELONG, nbr, NULL, FALSE, flag) )
UPDATE_STATUS(LoadStringResource(IDS_FETCHING_CHANGELIST_DESCRIPTION));
else
delete pCmd;
}
}
LRESULT CHistoryDlg::OnP4Describe(WPARAM wParam, LPARAM lParam)
{
CCmd_Describe *pCmd= (CCmd_Describe *) wParam;
if(!pCmd->GetError())
{
CString desc= MakeCRs(pCmd->GetDescription());
int key;
CSpecDescDlg *dlg = new CSpecDescDlg(this);
dlg->SetIsModeless(TRUE);
dlg->SetKey(key = pCmd->HaveServerLock()? pCmd->GetServerKey() : 0);
dlg->SetItemName( pCmd->GetReference() );
dlg->SetDescription(desc);
dlg->SetCaption(LoadStringResource(IDS_PERFORCE_CHANGELIST_DESCRIPTION));
dlg->SetShowNextPrev(TRUE);
dlg->SetShowShowDiffs(TRUE);
dlg->SetDiffFlag(pCmd->GetFlag());
dlg->SetViewType(P4CHANGE_SPEC);
dlg->SetFindStrFlags(&m_FindWhatStr, m_FindWhatFlags);
dlg->SetKey(m_Key);
if (!dlg->Create(IDD_SPECDESC, this)) // display the description dialog box
{
dlg->DestroyWindow(); // some error! clean up
delete dlg;
}
}
else // had an error - need to turn painting back on
{
EnumChildWindows(AfxGetMainWnd()->m_hWnd, ChildSetRedraw, TRUE);
}
delete pCmd;
UPDATE_STATUS(_T(""));
return 0;
}
LRESULT CHistoryDlg::OnP4EndDescribe(WPARAM wParam, LPARAM lParam)
{
CSpecDescDlg *dlg = (CSpecDescDlg *)lParam;
CString ref = dlg->GetItemName();
ASSERT(!ref.IsEmpty());
switch(wParam) // which button did they click to close the box?
{
case ID_SHOWDIFFS_NORMAL:
case ID_SHOWDIFFS_SUMMARY:
case ID_SHOWDIFFS_UNIFIED:
case ID_SHOWDIFFS_CONTEXT:
case ID_SHOWDIFFS_RCS:
case ID_SHOWDIFFS_NONE:
{
long l = _ttol(ref);
OnDescribeChgLong(l, wParam);
break;
}
case IDC_NEXTITEM:
case IDC_PREVITEM:
{
BOOL b = FALSE;
CRevision *rev;
long l = _ttol(ref);
// Get the rev
int np = wParam == IDC_NEXTITEM ? 1 : -1;
int count = m_ListCtl.GetItemCount();
for(int ix = -1; ++ix < count; )
{
rev = (CRevision *) m_ListCtl.GetItemData(ix);
if (rev && rev->m_ChangeNum == l)
{
if((ix + np < 0) || (ix + np >= count))
break;
// clear all previous selections
for (int i= 0; m_ListCtl.GetSelectedCount(); i++)
m_ListCtl.SetItemState(i, 0, LVIS_SELECTED|LVIS_FOCUSED);
// select the one we want
m_ListCtl.SetItemState(ix + np, LVIS_SELECTED|LVIS_FOCUSED,
LVIS_SELECTED|LVIS_FOCUSED);
OnDescribeChg(); // display the next/prev in the list on the screen
b = TRUE;
break;
}
}
if (b)
break;
// fall thru to turn painting back on
}
default: // clicked OK, pressed ESC or ENTER - need to turn painting back on
EnumChildWindows(AfxGetMainWnd()->m_hWnd, ChildSetRedraw, TRUE);
break;
}
dlg->DestroyWindow();
return TRUE;
}
int CHistoryDlg::GetSelectedRevision()
{
if(m_ListCtl.GetSelectedCount() != 1)
{ ASSERT(0); return 0; }
CRevision *rev = 0;
// Get the rev
for(int i= 0; i < m_ListCtl.GetItemCount(); i++)
{
if(m_ListCtl.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED)
{
rev= (CRevision *) m_ListCtl.GetItemData(i);
break;
}
}
ASSERT(rev);
return rev->m_RevisionNum;
}
CString CHistoryDlg::GetSelectedFileName()
{
if(m_ListCtl.GetSelectedCount() != 1)
{ ASSERT(0); return m_pHistory->GetFileName(); }
CRevision *rev = 0;
// Get the rev
for(int i= 0; i < m_ListCtl.GetItemCount(); i++)
{
if(m_ListCtl.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED)
{
rev= (CRevision *) m_ListCtl.GetItemData(i);
break;
}
}
ASSERT(rev);
return rev->m_FName;
}
int CHistoryDlg::GetSelectedChgNbr()
{
if(m_ListCtl.GetSelectedCount() != 1)
{ ASSERT(0); return 0; }
CRevision *rev = 0;
// Get the rev
for(int i= 0; i < m_ListCtl.GetItemCount(); i++)
{
if(m_ListCtl.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED)
{
rev= (CRevision *) m_ListCtl.GetItemData(i);
break;
}
}
ASSERT(rev);
return rev->m_ChangeNum;
}
BOOL CHistoryDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if(SERVER_BUSY() && m_InitiallyNotBusy)
return SET_BUSYCURSOR();
else
return CDialog::OnSetCursor(pWnd, nHitTest, message);
}
BOOL CHistoryDlg::OnInitDialog()
{
CRect rect;
bReady = FALSE;
CDialog::OnInitDialog();
if (m_pParent)
MainFrame()->SetModelessWnd(this);
m_listHeight = GET_P4REGPTR()->GetHistListHeight();
if (!m_EnableShowIntegs || !GET_P4REGPTR()->GetEnableRevHistShowIntegs( ))
{
GetDlgItem(IDC_COMPLETEHIST)->EnableWindow(FALSE);
GetDlgItem(IDC_COMPLETEHIST)->ShowWindow(SW_HIDE);
m_CompleteHist = FALSE;
}
else
{
m_CompleteHist = m_CompleteHistIC = m_CompleteHistI = GET_P4REGPTR()->GetFetchCompleteHist();
#ifdef FILELOGdashH
if (GET_SERVERLEVEL() >= 24) // 2007.3 or later?
{
GetDlgItem(IDC_COMPLETEHIST)->EnableWindow(FALSE);
GetDlgItem(IDC_COMPLETEHIST)->ShowWindow(SW_HIDE);
if (!m_Key)
{
GetDlgItem(IDC_STATIC_1)->EnableWindow(TRUE);
GetDlgItem(IDC_STATIC_1)->ShowWindow(SW_SHOW);
GetDlgItem(IDC_RADIO1)->EnableWindow(TRUE);
GetDlgItem(IDC_RADIO1)->ShowWindow(SW_SHOW);
GetDlgItem(IDC_RADIO2)->EnableWindow(TRUE);
GetDlgItem(IDC_RADIO2)->ShowWindow(SW_SHOW);
GetDlgItem(IDC_RADIO3)->EnableWindow(TRUE);
GetDlgItem(IDC_RADIO3)->ShowWindow(SW_SHOW);
}
}
else
#endif
if (m_CompleteHist > 1)
m_CompleteHist = m_CompleteHistI = 1;
}
UpdateData(FALSE);
// if this is being called from an in-progress command (such as p4 resolve)
// don't show the Complete History checkbox because it's too difficult
// to close and reopen this dialog without dropping the lock
if (m_Key)
{
GetDlgItem(IDC_COMPLETEHIST)->EnableWindow(FALSE);
GetDlgItem(IDC_COMPLETEHIST)->ShowWindow(SW_HIDE);
}
// Set the dialog caption
CString caption;
caption.FormatMessage(IDS_REVISION_HISTORY_FOR_s,
!TheApp()->m_RevHistPath.IsEmpty() ? TheApp()->m_RevHistPath
: !m_InitialName.IsEmpty() ? m_InitialName : m_pHistory->GetFileName());
SetWindowText(caption);
// Modify the list control style so that the entire selected row is highlighted
DWORD dwStyle = ::SendMessage(m_ListCtl.m_hWnd,LVM_GETEXTENDEDLISTVIEWSTYLE,0,0);
dwStyle |= LVS_EX_FULLROWSELECT;
::SendMessage(m_ListCtl.m_hWnd,LVM_SETEXTENDEDLISTVIEWSTYLE,0,dwStyle);
// Make sure list control shows selection when not the focused control
m_ListCtl.ModifyStyle(0, LVS_SHOWSELALWAYS, 0);
// Get original size of controls
CWnd *pBtn=GetDlgItem(IDHELP);
pBtn->GetWindowRect(&rect);
m_SmlWidth = rect.Width();
m_ListCtl.GetWindowRect(&rect);
m_lorgHeight = rect.Height();
int colwidth[7] = {16,5,18,18,18,10,15}; // these start out as %-ages and are converted to pixels
colwidth[0] = colwidth[0] * rect.Width()/100; // 1st 5 cols widths are based on orig size
colwidth[1] = colwidth[1] * rect.Width()/100;
colwidth[2] = colwidth[2] * rect.Width()/100;
colwidth[3] = colwidth[3] * rect.Width()/100;
colwidth[4] = colwidth[4] * rect.Width()/100;
// Record the initial window size, then see if there is a registry preference
GetWindowRect(&m_InitRect);
m_WinPos.RestoreWindowPosition();
// Get new size of control after resized as specified in the registry
m_ListCtl.GetWindowRect(&rect);
colwidth[5] = colwidth[5] * rect.Width()/100; // last 2 col widths are based on reg size
colwidth[6] = colwidth[6] * rect.Width()/100;
// Get any saved column widths from registry
RestoreSavedWidths(colwidth, 7);
// Make sure no column completely disappeared (because you can't get it back then)
for (int i=-1; ++i < 7; )
{
if (colwidth[i] < 5)
colwidth[i] = 5;
}
// Handle one-time case of going from fewer than 7 cols to 7 cols
if (!colwidth[6])
{
int j = 0;
for (int i = -1; ++i < 6; )
{
if (colwidth[i] > 7)
{
colwidth[i] -= colwidth[i]/8;
j += colwidth[i]/8;
}
else if (!colwidth[i] && j)
{
colwidth[i] += j/(7-i);
j -= j/(7-i);
}
}
colwidth[6] = j;
}
// Insert the columns
int headers[7] = {IDS_P4REVISION, IDS_P4FILE_NAME, IDS_CHANGELIST, IDS_DATE, IDS_P4USER, IDS_P4ACTION, IDS_DESCRIPTION};
int width= GetSystemMetrics(SM_CXVSCROLL);
int retval;
LV_COLUMN lvCol;
int subItem;
for(subItem=0; subItem < 7; subItem++)
{
lvCol.mask= LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT |LVCF_WIDTH;
lvCol.fmt=LVCFMT_LEFT;
CString header = LoadStringResource(headers[subItem]);
lvCol.pszText=const_cast<LPTSTR>((LPCTSTR)header);
lvCol.iSubItem=subItem;
if(subItem < 6)
{
lvCol.cx=colwidth[subItem];
width+=lvCol.cx;
}
else
lvCol.cx=rect.Width() - width - 4; // expand last column to fill window
retval=m_ListCtl.InsertColumn(subItem, &lvCol);
}
// Add the data
CRevision *rev = 0;
LV_ITEM lvItem;
int iActualItem = -1;
CString txt;
BOOL bMultiFileNames = FALSE;
int fnbr= 0;
for(int iItem=0; iItem < m_pHistory->GetRevisionCount(); iItem++)
{
if(iItem==0)
{
rev=m_pHistory->GetLatestRevision();
lvItem.pszText= const_cast<LPTSTR>((LPCTSTR)txt);
txt=rev->m_ChangeDescription;
if (txt.GetAt(0) == _T('('))
{
int i = txt.Find(_T(')'));
if (i != -1)
{
txt.SetAt(0, _T(' '));
m_RevFileType.SetWindowText(LoadStringResource(IDS_FILETYPE) + (LPCTSTR)txt.Left(i));
txt = txt.Right(txt.GetLength() - i - 1);
txt.TrimLeft();
}
}
else m_RevFileType.SetWindowText(_T(""));
m_RevisionInfo.SetWindowText((LPCTSTR)txt);
txt=rev->m_ChangeType;
txt.Replace(_T("; "), _T("\r\n"));
m_RevisionAction.SetWindowText(txt);
fnbr = rev->m_FNbr;
}
else
{
rev=m_pHistory->GetNextRevision();
if (fnbr != rev->m_FNbr)
bMultiFileNames = TRUE;
}
for(subItem=0; subItem < 7; subItem++)
{
lvItem.mask=LVIF_TEXT |
((subItem==0) ? LVIF_PARAM : 0);
lvItem.iItem= (subItem==0) ? iItem : iActualItem;
ASSERT(lvItem.iItem != -1);
lvItem.iSubItem= subItem;
lvItem.lParam=(LPARAM) rev;
switch(subItem)
{
case 0:
{
int r = rev->m_RevisionNum;
txt.Format(_T("%4d"), r);
if (r == m_HaveRev && rev->m_FName == m_InitialName)
txt += _T('*');
lvItem.pszText= const_cast<LPTSTR>((LPCTSTR)txt); break;
}
case 1: lvItem.pszText= const_cast<LPTSTR>((LPCTSTR)rev->m_FName); break;
case 2:
if (rev->m_ChangeNum >= 0) // chg# == -1 is a flag to NOT display chg#
txt.Format(_T("%5d"),rev->m_ChangeNum);
else txt.Empty();
lvItem.pszText= const_cast<LPTSTR>((LPCTSTR)txt); break;
case 3: lvItem.pszText= const_cast<LPTSTR>((LPCTSTR)rev->m_Date); break;
case 4: lvItem.pszText= const_cast<LPTSTR>((LPCTSTR)rev->m_User); break;
case 5: lvItem.pszText= const_cast<LPTSTR>((LPCTSTR)rev->m_ChangeType); break;
case 6: txt=PadCRs(rev->m_ChangeDescription);
if (txt.GetAt(0) == _T('('))
{
int i = txt.Find(_T(')'));
if (i != -1)
{
txt = txt.Right(txt.GetLength() - i - 1);
txt.TrimLeft();
}
}
lvItem.pszText= const_cast<LPTSTR>((LPCTSTR)txt);
break;
}
if(subItem==0)
iActualItem=m_ListCtl.InsertItem(&lvItem);
else
m_ListCtl.SetItem(&lvItem);
}
}
// remember the latest name because that's the only
// name we can use to diff a revision against the client
m_LatestName = rev->m_FName;
m_LatestIsDeleted = rev->m_ChangeType.Find(_T("delete")) == 0;
// Sort the list
m_ListCtl.Sort( m_LastSortColumn = bMultiFileNames ? 1 : 0, m_SortAscending );
// Make sure desired item is selected
int iPos = 0;
if (m_InitialRev != -1)
{
TCHAR initrev[16];
_stprintf(initrev, _T("%4d"), m_InitialRev);
LVFINDINFO lvfindinfo;
lvfindinfo.flags = LVFI_STRING;
lvfindinfo.psz = initrev;
lvfindinfo.lParam = 0;
lvfindinfo.pt.x = 0;
lvfindinfo.pt.y = 0;
lvfindinfo.vkDirection = VK_DOWN;
iPos = m_ListCtl.FindItem( &lvfindinfo, -1 );
if (iPos < 0)
iPos = 0;
else
{
rev= (CRevision *) m_ListCtl.GetItemData(iPos);
if (rev->m_FName != m_InitialName) // != means duplicate rev#s - gotta check names
{
int cnt = m_ListCtl.GetItemCount();
for (iPos = -1; ++iPos < cnt; )
{
rev= (CRevision *) m_ListCtl.GetItemData(iPos);
if ((rev->m_RevisionNum == m_InitialRev)
&& (rev->m_FName == m_InitialName))
break;
}
if (iPos >= m_ListCtl.GetItemCount())
iPos = 0;
}
}
}
m_ListCtl.SetItemState(iPos, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
if (iPos)
m_ListCtl.EnsureVisible(iPos, FALSE);
// Set change description to match selected item in list
rev= (CRevision *) m_ListCtl.GetItemData(iPos);
txt= rev->m_ChangeDescription;
if (txt.GetAt(0) == _T('('))
{
int i = txt.Find(_T(')'));
if (i != -1)
{
txt.SetAt(0, _T(' '));
m_RevFileType.SetWindowText(LoadStringResource(IDS_FILETYPE) + (LPCTSTR)txt.Left(i));
txt = txt.Right(txt.GetLength() - i - 1);
txt.TrimLeft();
}
}
else m_RevFileType.SetWindowText(_T(""));
m_RevisionInfo.SetWindowText(txt);
txt=rev->m_ChangeType;
txt.Replace(_T("; "), _T("\r\n"));
m_RevisionAction.SetWindowText(txt);
m_RevHistCount = m_ListCtl.GetItemCount();
// if we are showing all records for this file
// or this is being called from an in-progress command (such as p4 resolve)
// remove the More button.
if (!TheApp()->m_RevHistLast || TheApp()->m_RevHistLast > m_RevHistCount || m_Key)
{
GetDlgItem(IDC_MORE)->EnableWindow(FALSE);
GetDlgItem(IDC_MORE)->ShowWindow(SW_HIDE);
}
// And finally, set focus to the list control so that the first 'down'
// keystroke can be used to scroll down
m_ListCtl.SetFocus();
EnableButtons();
m_InitiallyNotBusy = !SERVER_BUSY();
bReady = TRUE;
ShowWindow(SW_SHOW);
return TRUE;
}
void CHistoryDlg::OnColumnclickRevlist(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if(pNMListView->iSubItem != m_LastSortColumn)
m_LastSortColumn=pNMListView->iSubItem;
else
m_SortAscending= !m_SortAscending;
if(pNMListView->iItem == -1)
m_ListCtl.Sort( m_LastSortColumn, m_SortAscending );
POSITION pos = m_ListCtl.GetFirstSelectedItemPosition();
if (pos != NULL)
m_ListCtl.EnsureVisible(m_ListCtl.GetNextSelectedItem(pos), FALSE);
*pResult = 0;
}
int CALLBACK ListSort(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
CRevision const *rev1 = (CRevision const *)lParam1;
CRevision const *rev2 = (CRevision const *)lParam2;
CString txt1, txt2;
int retval;
switch(lParamSort)
{
case 0: // rev Number
retval=( rev1->m_RevisionNum -
rev2->m_RevisionNum );
break;
case 1: // filename
retval= 0 - ( rev1->m_FNbr -
rev2->m_FNbr );
if (!retval)
retval=( rev1->m_ChangeNum -
rev2->m_ChangeNum );
break;
case 2: // change Number
case 3: // date
retval=( rev1->m_ChangeNum -
rev2->m_ChangeNum );
break;
case 4: // user
txt1= rev2->m_User;
txt2= rev1->m_User;
retval= txt2.Compare(txt1);
break;
case 5: // action
txt1= rev2->m_ChangeType;
txt2= rev1->m_ChangeType;
retval= txt2.Compare(txt1);
break;
case 6: // description
txt1= rev2->m_ChangeDescription;
txt2= rev1->m_ChangeDescription;
retval= txt2.Compare(txt1);
break;
default:
ASSERT(0);
return 0;
}
if(pDlg->m_SortAscending)
return retval;
else
return -retval;
}
void CHistoryDlg::OnItemchangedRevlist(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
CString txt, txt1;
// Update display of revision description
if(pNMListView->uNewState==3)
{
txt=((CRevision *) pNMListView->lParam)->m_ChangeDescription;
if (txt.GetAt(0) == _T('('))
{
int i = txt.Find(_T(')'));
if (i != -1)
{
txt.SetAt(0, _T(' '));
m_RevFileType.SetWindowText(LoadStringResource(IDS_FILETYPE) + (LPCTSTR)txt.Left(i));
txt = txt.Right(txt.GetLength() - i - 1);
txt.TrimLeft();
}
}
else m_RevFileType.SetWindowText(_T(""));
m_RevisionInfo.SetWindowText(txt);
txt=((CRevision *) pNMListView->lParam)->m_ChangeType;
txt.Replace(_T("; "), _T("\r\n"));
m_RevisionAction.SetWindowText(txt);
txt.FormatMessage(IDS_ACTIONLABEL, ((CRevision *) pNMListView->lParam)->m_ChangeNum);
GetDlgItem(IDC_ACTIONLABEL)->SetWindowText(txt);
txt.FormatMessage(IDS_SUMMARYLABEL, ((CRevision *) pNMListView->lParam)->m_ChangeNum);
GetDlgItem(IDC_SUMMARYLABEL)->SetWindowText(txt);
}
EnableButtons();
*pResult = 0;
}
void CHistoryDlg::EnableButtons()
{
if(m_Busy)
{
EnableCtrl( GetDlgItem(IDB_BROWSE), FALSE );
EnableCtrl( GetDlgItem(IDB_GET), FALSE );
EnableCtrl( GetDlgItem(IDB_DIFFVSCLIENT), FALSE );
EnableCtrl( GetDlgItem(IDB_DIFFREVISIONS), FALSE );
EnableCtrl( GetDlgItem(ID_CHANGE_DESCRIBE), FALSE );
EnableCtrl( GetDlgItem(ID_FILE_RECOVER), FALSE );
EnableCtrl( GetDlgItem(IDOK), FALSE );
}
else
{
BOOL bDeleted = FALSE;
CRevision *rev = 0;
EnableCtrl( GetDlgItem(IDOK), TRUE );
switch(m_ListCtl.GetSelectedCount())
{
case 1:
for(int i= 0; i < m_ListCtl.GetItemCount(); i++)
{
if(m_ListCtl.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED)
{
rev= (CRevision *) m_ListCtl.GetItemData(i);
break;
}
}
ASSERT(rev);
bDeleted = (rev->m_ChangeType.Find(_T("delete")) == 0)
|| (rev->m_ChangeType.Find(_T("purge")) == 0);
EnableCtrl( GetDlgItem(IDB_BROWSE), !bDeleted );
EnableCtrl( GetDlgItem(IDB_GET), !m_CompleteHist || rev->m_FName == m_LatestName );
EnableCtrl( GetDlgItem(IDB_DIFFVSCLIENT), m_HaveRev && !bDeleted );
EnableCtrl( GetDlgItem(IDB_DIFFREVISIONS), FALSE );
EnableCtrl( GetDlgItem(ID_CHANGE_DESCRIBE),
!((CDepotTreeCtrl *)m_pParent)->IsInRemoteDepot(&(rev->m_FName)) );
EnableCtrl( GetDlgItem(ID_FILE_RECOVER), m_LatestIsDeleted && !bDeleted);
break;
case 2:
{
CRevision *rev1 = 0;
CRevision *rev2 = 0;
for(int i= 0; i < m_ListCtl.GetItemCount(); i++)
{
if(m_ListCtl.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED)
{
if (!rev1)
{
rev1= (CRevision *) m_ListCtl.GetItemData(i);
}
else
{
rev2= (CRevision *) m_ListCtl.GetItemData(i);
break;
}
}
}
ASSERT(rev1);
ASSERT(rev2);
EnableCtrl( GetDlgItem(IDB_BROWSE), FALSE );
EnableCtrl( GetDlgItem(IDB_GET), FALSE );
EnableCtrl( GetDlgItem(IDB_DIFFVSCLIENT), FALSE );
EnableCtrl( GetDlgItem(IDB_DIFFREVISIONS),
rev1->m_ChangeType.Find(_T("delete")) != 0
&& rev1->m_ChangeType.Find(_T("purge")) != 0
&& rev2->m_ChangeType.Find(_T("delete")) != 0
&& rev2->m_ChangeType.Find(_T("purge")) != 0 );
EnableCtrl( GetDlgItem(ID_CHANGE_DESCRIBE), FALSE );
EnableCtrl( GetDlgItem(ID_FILE_RECOVER), FALSE );
break;
}
default:
EnableCtrl( GetDlgItem(IDB_BROWSE), FALSE );
EnableCtrl( GetDlgItem(IDB_GET), FALSE );
EnableCtrl( GetDlgItem(IDB_DIFFVSCLIENT), FALSE );
EnableCtrl( GetDlgItem(IDB_DIFFREVISIONS), FALSE );
EnableCtrl( GetDlgItem(ID_CHANGE_DESCRIBE), FALSE );
EnableCtrl( GetDlgItem(ID_FILE_RECOVER), FALSE );
}
}
}
void CHistoryDlg::EnableCtrl( CWnd *ctl, BOOL enable )
{
// Avoid flicker by only calling EnableWindow as reqd
if(enable != ctl->IsWindowEnabled())
ctl->EnableWindow(enable);
}
void CHistoryDlg::OnCompletehist()
{
OnOK();
}
/////////////////////////////////////////////////////////////////////////////
// CHistList
CHistList::CHistList()
{
}
CHistList::~CHistList()
{
}
BEGIN_MESSAGE_MAP(CHistList, CListCtrl)
//{{AFX_MSG_MAP(CHistList)
ON_WM_RBUTTONUP()
ON_WM_RBUTTONDOWN()
ON_WM_GETMINMAXINFO()
ON_WM_WINDOWPOSCHANGING()
ON_WM_SIZE()
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
ON_MESSAGE( WM_FINDPATTERN, OnFindPattern )
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CHistList message handlers
void CHistList::OnLButtonDblClk(UINT nFlags, CPoint point)
{
CListCtrl::OnLButtonDblClk(nFlags, point);
((CHistoryDlg *)GetParent())->FileQuickbrowse(TRUE);
}
void CHistList::OnRButtonUp(UINT nFlags, CPoint local)
{
// find out what was hit
LV_HITTESTINFO ht;
ht.pt=local;
int index= HitTest(&ht);
if(index == -1)
return;
CPoint screen=local;
ClientToScreen(&screen);
((CHistoryDlg *)GetParent())->OnContextMenu(screen, index);
}
void CHistList::OnRButtonDown(UINT nFlags, CPoint point)
{
// Just eat the event, so a dbl click not required
}
void CHistList::Sort( int column, BOOL ascending )
{
SortItems( ListSort, column );
m_headerctrl.SetSortImage(column, ascending);
}
void CHistList::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
RECT rectW, rectB;
((CHistoryDlg *)GetParent())->GetWindowRect(&rectW);
((CHistoryDlg *)GetParent())->GetDlgItem(IDOK)->GetWindowRect(&rectB);
lpMMI->ptMinTrackSize.x = lpMMI->ptMaxSize.x + lpMMI->ptMaxPosition.x * 2;
lpMMI->ptMinTrackSize.y = ((CHistoryDlg *)GetParent())->GetListTop() + 20;
lpMMI->ptMaxTrackSize.y = (rectW.bottom - rectW.top) - (rectB.bottom - rectB.top) * 7;
CListCtrl::OnGetMinMaxInfo(lpMMI);
}
void CHistList::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
if (bReady)
lpwndpos->flags |= SWP_NOMOVE;
CListCtrl::OnWindowPosChanging(lpwndpos);
}
void CHistList::OnSize(UINT nType, int cx, int cy)
{
CListCtrl::OnSize(nType, cx, cy);
((CHistoryDlg *)GetParent())->RePaintMiddleWindows();
}
LRESULT CHistList::OnFindPattern(WPARAM wParam, LPARAM lParam)
{
TCHAR str[ 1024 ];
CString text;
CString what = (TCHAR *)lParam;
int flags = (int)wParam;
int cnt = GetItemCount();
int prv = -1;
if (!(flags & FR_MATCHCASE))
what.MakeLower();
int i = -1;
for( int k = 0; k < cnt; k++ )
{
if( GetItemState( k, LVIS_SELECTED ) == LVIS_SELECTED )
{
SetItemState( k, 0, LVIS_SELECTED|LVIS_FOCUSED );
prv = i = k;
};
}
int j;
if (i == -1)
i = 0;
int columns = GetHeaderCtrl()->GetItemCount();
if (flags & FR_DOWN)
{
if (flags < 0)
i++;
while( i < cnt )
{
for (j =-1; ++j < columns; )
{
GetItemText( i, j, str, sizeof(str)/sizeof(TCHAR) );
text = str;
if (!(flags & FR_MATCHCASE))
text.MakeLower();
if (text.Find(what) != -1)
{
SetItemState( i, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED );
EnsureVisible(i, FALSE);
MainFrame()->SetMessageText(LoadStringResource(IDS_FOUND));
return 0;
}
}
i++;
}
}
else
{
if (flags < 0)
i--;
while( i >= 0 )
{
for (j =-1; ++j < columns; )
{
GetItemText( i, j, str, sizeof(str)/sizeof(TCHAR) );
text = str;
if (!(flags & FR_MATCHCASE))
text.MakeLower();
if (text.Find(what) != -1)
{
SetItemState( i, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED );
EnsureVisible(i, FALSE);
MainFrame()->SetMessageText(LoadStringResource(IDS_FOUND));
return 0;
}
}
i--;
}
}
MessageBeep(0);
MainFrame()->SetMessageText(LoadStringResource(IDS_NOT_FOUND));
if (prv != -1)
SetItemState( prv, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED );
return 0;
}
//
/////////////////////////////////////////////////////////////////////////////
void CHistoryDlg::OnUpdatePositionToPattern(CCmdUI* pCmdUI)
{
CString txt = LoadStringResource(IDS_FINDPATTERN);
pCmdUI->SetText( txt );
pCmdUI->Enable( !m_Busy && NULL == m_pFRDlg );
}
void CHistoryDlg::OnPositionToPattern()
{
if ( NULL == m_pFRDlg )
{
m_pFRDlg = new CFindReplaceDialog(); // Must be created on the heap
m_pFRDlg->m_fr.lStructSize = sizeof(FINDREPLACE);
m_pFRDlg->m_fr.hwndOwner = this->m_hWnd;
m_pFRDlg->Create( TRUE, m_FindWhatStr, _T(""), m_FindWhatFlags | FR_HIDEWHOLEWORD, this );
}
}
void CHistoryDlg::OnUpdatePositionToNext(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!m_Busy);
}
void CHistoryDlg::OnPositionToNext()
{
if (!m_FindWhatStr.IsEmpty())
{
::PostMessage(m_ListCtl.m_hWnd, WM_FINDPATTERN,
(WPARAM)m_FindWhatFlags | 0x80000000, (LPARAM)m_FindWhatStr.GetBuffer(0));
}
}
void CHistoryDlg::OnUpdatePositionToPrev(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!m_Busy);
}
void CHistoryDlg::OnPositionToPrev()
{
if (!m_FindWhatStr.IsEmpty())
{
::PostMessage(m_ListCtl.m_hWnd, WM_FINDPATTERN,
((WPARAM)m_FindWhatFlags | 0x80000000) ^ FR_DOWN,
(LPARAM)m_FindWhatStr.GetBuffer(0));
}
}
LRESULT CHistoryDlg::OnFindReplace(WPARAM wParam, LPARAM lParam)
{
LPFINDREPLACE lpfp = (LPFINDREPLACE)lParam;
if (m_pFRDlg->FindNext() || m_pFRDlg->IsTerminating())
{
m_FindWhatStr = lpfp->lpstrFindWhat;
m_FindWhatFlags = lpfp->Flags;
if (m_pFRDlg->FindNext())
{
::PostMessage(m_ListCtl.m_hWnd, WM_FINDPATTERN,
(WPARAM)(lpfp->Flags), (LPARAM)m_FindWhatStr.GetBuffer(0));
delete m_pFRDlg;
}
m_pFRDlg = NULL;
}
return 0;
}
void CHistoryDlg::RePaintMiddleWindows()
{
CWnd *pWin=GetDlgItem(IDC_ACTIONLABEL);
pWin->InvalidateRect( NULL, TRUE );
pWin=GetDlgItem(IDC_COMPLETEHIST);
pWin->InvalidateRect( NULL, TRUE );
#ifdef FILELOGdashH
if (GET_SERVERLEVEL() >= 24) // 2007.3 or later?
{
pWin=GetDlgItem(IDC_STATIC_1);
pWin->InvalidateRect( NULL, TRUE );
pWin=GetDlgItem(IDC_RADIO1);
pWin->InvalidateRect( NULL, TRUE );
pWin=GetDlgItem(IDC_RADIO2);
pWin->InvalidateRect( NULL, TRUE );
pWin=GetDlgItem(IDC_RADIO3);
pWin->InvalidateRect( NULL, TRUE );
}
#endif
}
void CHistoryDlg::OnSize(UINT nType, int cx, int cy)
{
CRect rect;
CDialog::OnSize(nType, cx, cy);
if (nType == SIZE_MINIMIZED)
{
m_IsMinimized = TRUE;
return;
}
else if (m_IsMinimized)
{
m_IsMinimized = FALSE;
return;
}
GetClientRect(&rect);
int x=rect.Width();
int y=rect.Height();
// find the bottom of the buttons
CWnd *pBtn=GetDlgItem(IDB_GET);
if (!pBtn)
return;
pBtn->GetWindowRect(&rect);
ScreenToClient(&rect);
int bottomButtons= rect.bottom;
// Increase the size of the list below buttons
if (!m_listHeight)
m_listHeight = y*4/10;
else if ((m_dlgHeight != y) && m_dlgHeight)
m_listHeight = max(m_lorgHeight,
(m_listHeight + (y > m_dlgHeight ? 1 : 0)) * y/m_dlgHeight);
m_dlgHeight = y;
CWnd *pList=GetDlgItem(IDC_REVISIONLIST);
pList->MoveWindow(0, m_listTop = bottomButtons+4, x, m_listHeight, TRUE);
pList->GetWindowRect(&rect);
m_listHeight = rect.Height();
SizeBottonOfHistory(x, y);
InvalidateRect(NULL, TRUE);
}
void CHistoryDlg::SizeBottonOfHistory(int x, int y)
{
int bottomList= m_listTop + m_listHeight - 1;
CRect rect;
int h;
int w;
// Position the rev file type text box
CWnd *pText=GetDlgItem(IDC_REVFILETYPE);
pText->GetWindowRect(&rect);
pText->ScreenToClient(&rect);
pText->MoveWindow(x - rect.Width() - 6, bottomList + rect.Height()/2 - 2,
rect.Width(), rect.Height(), TRUE);
// Position the action label
CWnd *pLabel=GetDlgItem(IDC_ACTIONLABEL);
pLabel->GetClientRect(&rect);
pLabel->MoveWindow(4, bottomList+rect.Height()/2, rect.Width(), rect.Height(), TRUE);
int bottomLabel= bottomList + rect.Height()*3/2;
// Calculate some heights
CWnd *pBtn=GetDlgItem(IDOK);
pBtn->GetWindowRect(&rect);
int btnWidth = rect.Width();
int btnHeight= rect.Height();
h = (y-bottomLabel)/2 - btnHeight - 6;
// Position the action text box
pText=GetDlgItem(IDC_REVISIONACTION);
pText->MoveWindow(2, bottomLabel+4, x-4, h, TRUE);
bottomList = bottomLabel+4 + h;
// Position the description label
pLabel=GetDlgItem(IDC_SUMMARYLABEL);
pLabel->GetClientRect(&rect);
pLabel->MoveWindow(4, bottomList+rect.Height()/2, x, rect.Height(), TRUE);
bottomLabel= bottomList + rect.Height()*3/2;
// Position the description text box
pText=GetDlgItem(IDC_REVISIONINFO);
pText->MoveWindow(2, bottomLabel+4, x-4, h, TRUE);
int bottomDesc = bottomLabel+4 + h + 4;
// Position the complete history checkbox
pLabel=GetDlgItem(IDC_COMPLETEHIST);
pLabel->GetClientRect(&rect);
pLabel->MoveWindow(4, bottomDesc, rect.Width(), rect.Height(), TRUE);
if (GET_SERVERLEVEL() < 8)
pLabel->ShowWindow(SW_HIDE);
// Position the branching history radio buttons
pLabel=GetDlgItem(IDC_STATIC_1);
pLabel->GetClientRect(&rect);
pLabel->MoveWindow(4, bottomDesc, w = rect.Width(), rect.Height(), TRUE);
if (GET_SERVERLEVEL() < 24) // 2007.3 or later?
pLabel->ShowWindow(SW_HIDE);
pBtn=GetDlgItem(IDC_RADIO1);
pBtn->GetClientRect(&rect);
pBtn->MoveWindow(4 + w + 4, bottomDesc, rect.Width(), rect.Height(), TRUE);
if (GET_SERVERLEVEL() < 24) // 2007.3 or later?
pBtn->ShowWindow(SW_HIDE);
w += rect.Width();
pBtn=GetDlgItem(IDC_RADIO2);
pBtn->GetClientRect(&rect);
pBtn->MoveWindow(4 + w + 8, bottomDesc, rect.Width(), rect.Height(), TRUE);
if (GET_SERVERLEVEL() < 24) // 2007.3 or later?
pBtn->ShowWindow(SW_HIDE);
w += rect.Width();
pBtn=GetDlgItem(IDC_RADIO3);
pBtn->GetClientRect(&rect);
pBtn->MoveWindow(4 + w + 12, bottomDesc, rect.Width(), rect.Height(), TRUE);
if (GET_SERVERLEVEL() < 24) // 2007.3 or later?
pBtn->ShowWindow(SW_HIDE);
w += rect.Width();
// Position the More, Close and Help buttons
pBtn=GetDlgItem(IDHELP);
pBtn->GetWindowRect(&rect);
ScreenToClient(&rect);
x = x - btnWidth - 5;
pBtn->SetWindowPos(NULL, x, bottomDesc, btnWidth, rect.Height(), SWP_NOZORDER);
pBtn=GetDlgItem(IDOK);
pBtn->SetWindowPos(NULL, x-btnWidth-5, bottomDesc, btnWidth, rect.Height(), SWP_NOZORDER);
pBtn=GetDlgItem(IDC_MORE);
pBtn->SetWindowPos(NULL, x-(btnWidth*2)-10, bottomDesc, btnWidth, rect.Height(), SWP_NOZORDER);
m_SizeSet = TRUE;
}
BOOL CHistoryDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
if ((wParam == IDC_REVISIONLIST) && m_SizeSet)
{
CRect rect;
CWnd *pList=GetDlgItem(IDC_REVISIONLIST);
pList->GetWindowRect(&rect);
if (m_listHeight != rect.Height())
{
m_listHeight = rect.Height();
GetClientRect(&rect);
int x=rect.Width();
int y=rect.Height();
SizeBottonOfHistory(x, y);
}
}
return CDialog::OnNotify(wParam, lParam, pResult);
}
void CHistoryDlg::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
lpMMI->ptMinTrackSize.x= m_InitRect.Width();
lpMMI->ptMinTrackSize.y= m_InitRect.Height();
}
void CHistList::PreSubclassWindow()
{
CListCtrl::PreSubclassWindow();
// Add initialization code
m_headerctrl.SubclassWindow( ::GetDlgItem(m_hWnd,0) );
}
void CHistoryDlg::OnOK()
{
UpdateData(TRUE);
#ifdef FILELOGdashH
m_CompleteHist = GET_SERVERLEVEL() >= 24 ? m_CompleteHistIC : m_CompleteHistI; // 2007.3 or later?
#else
m_CompleteHist = m_CompleteHistI;
#endif
m_SizeSet = FALSE;
m_WinPos.SaveWindowPosition();
SaveColumnWidths();
if(!GET_P4REGPTR()->SetHistListHeight( m_listHeight ) )
AfxMessageBox( IDS_BAD_REGISTRY, MB_ICONSTOP );
if (m_pParent)
m_pParent->PostMessage(WM_P4ENDHISTORY, 0, (LPARAM)this);
CDialog::OnOK();
}
void CHistoryDlg::SaveColumnWidths()
{
// Save the column widths
CString str;
for(int i=0; i < 10; i++)
{
// Note that GetColumnWidth returns zero if i > numcols
CString num;
num.Format(_T("%d"), m_ListCtl.GetColumnWidth(i));
if(i)
str+=_T(",");
str+=num;
}
CRegKeyEx key;
if(ERROR_SUCCESS == key.Create(HKEY_CURRENT_USER, sRegKey))
key.SetValueString(str, sRegValue_ColumnWidths);
}
// Check the registry to see if we have recorded the column widths last
// used for this list view
void CHistoryDlg::RestoreSavedWidths(int *width, int numcols)
{
CRegKeyEx key;
if(ERROR_SUCCESS == key.Open(HKEY_CURRENT_USER, sRegKey, KEY_READ))
{
CString result = key.QueryValueString(sRegValue_ColumnWidths);
if(!result.IsEmpty())
{
// things can go wrong with the registry setting of the
// widths. Use the defaults if the entry is all zeroes.
//
if ( result != _T("0,0,0,0,0,0,0,0,0,0") )
for(int i=0; i< numcols; i++)
width[i]= GetPositiveNumber(result);
}
}
}
void CHistoryDlg::OnHelp()
{
GotoDlgCtrl(GetDlgItem(IDC_REVISIONLIST));
AfxGetApp()->WinHelp(TASK_DISPLAYING_REVISION_HISTORY);
}
BOOL CHistoryDlg::OnHelpInfo(HELPINFO* pHelpInfo)
{
OnHelp();
return(FALSE);
}
void CHistoryDlg::OnMore()
{
m_More = m_Rerun = TRUE;
OnOK();
}
void CHistoryDlg::OnPositionDepot()
{
if(m_ListCtl.GetSelectedCount() != 1)
{ ASSERT(0); return; }
for(int i= 0; i < m_ListCtl.GetItemCount(); i++)
{
if(m_ListCtl.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED)
{
CRevision *rev= (CRevision *) m_ListCtl.GetItemData(i);
CString itemStr = rev->m_FName;
if ((i = itemStr.Find(_T('#'))) != -1)
itemStr = itemStr.Left( i ); // trim off rev# info
else if ((i = itemStr.Find(_T("/..."))) != -1)
itemStr = itemStr.Left( i ); // trim off "/..."
((CMainFrame *) AfxGetMainWnd())->ExpandDepotString( itemStr, TRUE );
break;
}
}
}
void CHistoryDlg::OnCopyRows()
{
CString txt;
if(!m_ListCtl.GetSelectedCount())
{ ASSERT(0); return; }
CRevision *rev;
// Get the rev
for(int i= 0; i < m_ListCtl.GetItemCount(); i++)
{
if(m_ListCtl.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED)
{
rev= (CRevision *) m_ListCtl.GetItemData(i);
CString item;
item.Format(_T("%d\t%s\t%d\t%s\t%s\t%s\t%s\r\n"), rev->m_RevisionNum,
rev->m_FName, rev->m_ChangeNum, rev->m_Date,
rev->m_User, rev->m_ChangeType, PadCRs(rev->m_ChangeDescription));
txt += item;
}
}
CopyTextToClipboard(txt);
}
void CHistoryDlg::OnKeydownRevisionlist(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
if ((pLVKeyDow->wVKey == _T('C')) && ( ::GetKeyState(VK_CONTROL) & 0x8000 ))
OnCopyRows();
else if ((pLVKeyDow->wVKey == _T('F')) && ( ::GetKeyState(VK_CONTROL) & 0x8000 ))
OnPositionToPattern();
else if ((pLVKeyDow->wVKey == VK_F3) && ( !(::GetKeyState(VK_SHIFT) & 0x8000 )))
OnPositionToNext();
else if ((pLVKeyDow->wVKey == VK_F3) && ( ::GetKeyState(VK_SHIFT) & 0x8000 ))
OnPositionToPrev();
else if ((pLVKeyDow->wVKey == _T('T')) && ( ::GetKeyState(VK_CONTROL) & 0x8000 ))
OnPerforceOptions();
*pResult = 0;
}
void CHistoryDlg::OnPerforceOptions()
{
if (m_Key)
{
MessageBeep(0);
return;
}
BOOL allState = GET_P4REGPTR()->GetFetchAllHist();
int histCount = GET_P4REGPTR()->GetFetchHistCount();
BOOL enableRevHistShowIntegs = GET_P4REGPTR()->GetEnableRevHistShowIntegs( );
MainFrame()->OnPerforceOptions(TRUE, FALSE, 0, IDS_PAGE_REVISIONHISTORY);
if (enableRevHistShowIntegs != GET_P4REGPTR()->GetEnableRevHistShowIntegs( )
|| histCount != GET_P4REGPTR()->GetFetchHistCount()
|| allState != GET_P4REGPTR()->GetFetchAllHist())
{
m_Rerun = TRUE;
OnOK();
}
}
// This signals the closing of a modeless dialog
// to MainFrame which will delete the 'this' object
void CHistoryDlg::OnDestroy()
{
if (m_pParent)
::PostMessage(MainFrame()->m_hWnd, WM_P4DLGDESTROY, 0, (LPARAM)this);
}
void CHistoryDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
switch(nID)
{
case SC_MINIMIZE:
GetDesktopWindow()->ArrangeIconicWindows();
break;
}
CDialog::OnSysCommand(nID, lParam);
}
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #1 | 19924 | YourUncleBob |
Populate -o //guest/perforce_software/p4win/... //guest/YourUncleBob/p4win/..... |
||
| //guest/perforce_software/p4win/main/gui/HistoryDlg.cpp | |||||
| #1 | 16169 | perforce_software | Move files to follow new path scheme for branches. | ||
| //guest/perforce_software/p4win/gui/HistoryDlg.cpp | |||||
| #1 | 8562 | Matt Attaway |
These feet never stop running. Initial commit of the P4Win source code. To the best of our knowledge this compiles and runs using the 2013.3 P4 API and VS 2010. Expect a few changes as we refine the build process. Please post any build issues to the forums. |
||