From: Perry Rapp Date: Sat, 23 Aug 2003 17:22:06 +0000 (+0000) Subject: PATCH: [ 781529 ] Make column info array, and add new columns X-Git-Tag: 2.16.5~7838 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=f9b92c07340c20497a2ce117891ee03b8d423e24;p=winmerge-jp%2Fwinmerge-jp.git PATCH: [ 781529 ] Make column info array, and add new columns --- diff --git a/Src/Common/version.cpp b/Src/Common/version.cpp index ba1a666dd..1d8b347bc 100644 --- a/Src/Common/version.cpp +++ b/Src/Common/version.cpp @@ -1,7 +1,9 @@ -/******************************************************************************* -FILE: version.cpp +/** + * @file version.cpp + * + * @brief Implementation of CVersionInfo class + */ -*******************************************************************************/ #include "stdafx.h" #include "version.h" @@ -119,10 +121,22 @@ CString CVersionInfo::GetFixedProductVersion() { if (!m_bQueryDone) GetVersionInfo(); + if (!m_dwVerInfoSize) + return _T(""); return MakeVersionString(m_FixedFileInfo.dwProductVersionMS , m_FixedFileInfo.dwProductVersionLS); } +CString CVersionInfo::GetFixedFileVersion() +{ + if (!m_bQueryDone) + GetVersionInfo(); + if (!m_dwVerInfoSize) + return _T(""); + return MakeVersionString(m_FixedFileInfo.dwFileVersionMS + , m_FixedFileInfo.dwFileVersionLS); +} + CString CVersionInfo::GetComments() { if (!m_bQueryDone) @@ -132,7 +146,6 @@ CString CVersionInfo::GetComments() void CVersionInfo::GetVersionInfo() { - DWORD dwVerInfoSize; // Size of version information block DWORD dwVerHnd=0; // An 'ignored' parameter, always '0' TCHAR szFileName[MAX_PATH]; @@ -142,12 +155,12 @@ void CVersionInfo::GetVersionInfo() else _tcscpy(szFileName, m_strFileName); - dwVerInfoSize = GetFileVersionInfoSize(szFileName, &dwVerHnd); - if (dwVerInfoSize) { + m_dwVerInfoSize = GetFileVersionInfoSize(szFileName, &dwVerHnd); + if (m_dwVerInfoSize) { HANDLE hMem; - hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize); + hMem = GlobalAlloc(GMEM_MOVEABLE, m_dwVerInfoSize); m_lpstrVffInfo = (LPTSTR)GlobalLock(hMem); - if (GetFileVersionInfo(szFileName, dwVerHnd, dwVerInfoSize, m_lpstrVffInfo)) + if (GetFileVersionInfo(szFileName, dwVerHnd, m_dwVerInfoSize, m_lpstrVffInfo)) { GetFixedVersionInfo(); if (m_strLanguage.IsEmpty() diff --git a/Src/Common/version.h b/Src/Common/version.h index 9e3887559..283c7a867 100644 --- a/Src/Common/version.h +++ b/Src/Common/version.h @@ -1,15 +1,21 @@ -/******************************************************************************* -FILE: version.h +/** + * @file version.h + * + * @brief Declaration of CVersionInfo class + */ -*******************************************************************************/ #ifndef VERSIONTOOLS_H #define VERSIONTOOLS_H +/** + * @brief Class providing access to version information of a file + */ class CVersionInfo { LPTSTR m_lpstrVffInfo; BOOL m_bQueryDone; VS_FIXEDFILEINFO m_FixedFileInfo; + DWORD m_dwVerInfoSize; /**< Size of version information block (0 if missing) */ CString m_strFileName; CString m_strLanguage; @@ -43,6 +49,7 @@ public: CString GetSpecialBuild(); CString GetPrivateBuild(); CString GetFixedProductVersion(); + CString GetFixedFileVersion(); protected: void GetVersionInfo(); void GetFixedVersionInfo(); diff --git a/Src/DiffContext.cpp b/Src/DiffContext.cpp index 9172e0ff2..3276ad159 100644 --- a/Src/DiffContext.cpp +++ b/Src/DiffContext.cpp @@ -18,13 +18,21 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // ///////////////////////////////////////////////////////////////////////////// -// DiffContext.cpp: implementation of the CDiffContext class. -// +/** + * @file DiffContext.cpp + * + * @brief Implementation of CDiffContext + */ +// RCS ID line follows -- this is updated by CVS +// $Id$ ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "merge.h" +#include "version.h" #include "DiffContext.h" +#include "paths.h" +#include "coretools.h" #ifdef _DEBUG #undef THIS_FILE @@ -78,18 +86,40 @@ CDiffContext::~CDiffContext() if (pNamesRight != NULL) free(pNamesRight); } - -void CDiffContext::AddDiff(LPCTSTR pszFilename, LPCTSTR pszLeftDir, LPCTSTR pszRightDir, - long ltime, long rtime, BYTE code) +/** + * @brief Fetch & return the fixed file version as a dotted string + */ +static CString GetFixedFileVersion(const CString & path) +{ + CVersionInfo ver(path); + return ver.GetFixedFileVersion(); +} + +/** + * @brief Add new diffitem to CDiffContext array + */ +void CDiffContext::AddDiff(LPCTSTR pszFilename, LPCTSTR szSubdir + , LPCTSTR pszLeftDir, LPCTSTR pszRightDir + , long lmtime, long rmtime + , long lctime, long rctime + , __int64 lsize, __int64 rsize + , BYTE code + ) { DIFFITEM di; di.sfilename = pszFilename; - di.slpath = pszLeftDir; - di.srpath = pszRightDir; - di.ltime = ltime; - di.rtime = rtime; + di.left.spath = pszLeftDir; + di.right.spath = pszRightDir; + di.left.mtime = lmtime; + di.right.mtime = rmtime; + di.left.ctime = lctime; + di.right.ctime = rctime; di.code = code; + di.left.size = lsize; + di.right.size = rsize; + UpdateFieldsNeededForNewItems(di, di.left); + UpdateFieldsNeededForNewItems(di, di.right); AddDiff(di); } @@ -160,11 +190,87 @@ void CDiffContext::UpdateStatusCode(POSITION diffpos, BYTE status) di.code = status; } -void CDiffContext::UpdateTimes(POSITION diffpos, long leftTime, long rightTime) +/** + * @brief Load all fields not provided in initial AddDiff call + */ +void CDiffContext::UpdateFieldsNeededForNewItems(DIFFITEM & di, DiffFileInfo & dfi) { - DIFFITEM & di = m_pList->GetAt(diffpos); - if (leftTime) - di.ltime = leftTime; - if (rightTime) - di.rtime = rightTime; + // attributes weren't passed, which means reading the file status + // so we may as well do them all + UpdateInfoFromDiskHalf(di, dfi); } + +/** + * @brief Update information from disk + */ +void CDiffContext::UpdateInfoFromDisk(DIFFITEM & di) +{ + UpdateInfoFromDiskHalf(di, di.left); + UpdateInfoFromDiskHalf(di, di.right); +} + +/** + * @brief Convert a FILETIME to a long (standard time) + */ +static long FileTimeToLong(FILETIME & ft) +{ + return CTime(ft).GetTime(); +} + +/** + * @brief Update information from disk (for one side) + */ +void CDiffContext::UpdateInfoFromDiskHalf(DIFFITEM & di, DiffFileInfo & dfi) +{ + UpdateVersion(di, dfi); + + CString filepath = paths_ConcatPath(dfi.spath, di.sfilename); + + // CFileFind doesn't expose the attributes + // CFileStatus doesn't expose 64 bit size + + WIN32_FIND_DATA wfd; + HANDLE h = FindFirstFile(filepath, &wfd); + if (h != INVALID_HANDLE_VALUE) + { + dfi.mtime = FileTimeToLong(wfd.ftLastWriteTime); + dfi.flags.reset(); + if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) + dfi.flags.flags += FileFlags::RO; + dfi.size = (wfd.nFileSizeHigh << 32) + wfd.nFileSizeLow; + FindClose(h); + } + else + { + dfi.mtime = 0; + dfi.size = 0; + dfi.flags.reset(); + } +} + +/** + * @brief Load file versions from disk + */ +void CDiffContext::UpdateVersion(DIFFITEM & di, DiffFileInfo & dfi) +{ + // Would be better to not check any text files + // but binary files are flagged as FILE_SAME not FILE_BINSAME + // when this is called (Perry 2003-08-21) + // and we also didn't flag binary for uniques + if (1) + { + CString filepath = paths_ConcatPath(dfi.spath, di.sfilename); + dfi.version = GetFixedFileVersion(filepath); + } +} + +CString DIFFITEM::getLeftFilepath() const +{ + return paths_ConcatPath(left.spath, sfilename); +} + +CString DIFFITEM::getRightFilepath() const +{ + return paths_ConcatPath(right.spath, sfilename); +} + diff --git a/Src/DiffContext.h b/Src/DiffContext.h index 191c8bda4..0c4fb718e 100644 --- a/Src/DiffContext.h +++ b/Src/DiffContext.h @@ -1,13 +1,14 @@ -// DiffContext.h: interface for the CDiffContext class. -// -////////////////////////////////////////////////////////////////////// +/** + * @file DiffContext.h + * + * @brief Declarations of CDiffContext and diff structures + */ +// RCS ID line follows -- this is updated by CVS +// $Id$ #if !defined(AFX_DIFFCONTEXT_H__D3CC86BE_F11E_11D2_826C_00A024706EDC__INCLUDED_) #define AFX_DIFFCONTEXT_H__D3CC86BE_F11E_11D2_826C_00A024706EDC__INCLUDED_ - -#if _MSC_VER > 1000 #pragma once -#endif // _MSC_VER > 1000 #include "RegExp.h" @@ -30,15 +31,48 @@ struct dirdata #define FILE_SKIP 9 #define FILE_DIRSKIP 10 +struct FileFlags +{ + int flags; + FileFlags() : flags(0) { } + void reset() { flags = 0; } + CString toString() const { return flags ? _T("RO") : _T(""); } + + enum { RO=1 }; +}; + +struct DIFFITEM; + +/** + * @brief information for file on one side of a diff + */ +struct DiffFileInfo +{ + long mtime; /**< time of last modification */ + long ctime; /**< time of creation */ + __int64 size; /**< file size in bytes */ + CString version; /**< string of fixed file version, eg, 1.2.3.4 */ + CString spath; /**< fully qualified directory of file */ + FileFlags flags; /**< file attributes */ + DiffFileInfo() : mtime(0), ctime(0), size(0) { } + // We could stash a pointer here to the parent DIFFITEM + // but, I ran into trouble with, I think, the DIFFITEM copy constructor +}; + +/** + * @brief information about one diff (including files on both sides) + */ struct DIFFITEM { + DiffFileInfo left; + DiffFileInfo right; CString sfilename; + CString sSubdir; //*< Common subdirectory from root of comparison */ CString sext; - CString slpath; - CString srpath; - long ltime, rtime; BYTE code; - DIFFITEM() : ltime(0), rtime(0), code(FILE_ERROR) { } + CString getLeftFilepath() const; + CString getRightFilepath() const; + DIFFITEM() : code(0) { } }; // Interface for reporting current file, as diff traverses file tree @@ -66,10 +100,14 @@ public: void SetRegExp(LPCTSTR pszExp); // add & remove differences - void AddDiff(LPCTSTR pszFilename, LPCTSTR pszLeftDir, LPCTSTR pszRightDir, long ltime, long rtime, BYTE code); + void AddDiff(LPCTSTR pszFilename, LPCTSTR szSubdir, LPCTSTR pszLeftDir, LPCTSTR pszRightDir + , long lmtime, long rmtime, long lctime, long rctime + , __int64 lsize, __int64 rsize, BYTE code); void AddDiff(DIFFITEM di); void RemoveDiff(POSITION diffpos); void RemoveAll(); + void UpdateFieldsNeededForNewItems(DIFFITEM & di, DiffFileInfo & dfi); + void UpdateVersion(DIFFITEM & di, DiffFileInfo & dfi); // to iterate over all differences on list POSITION GetFirstDiffPosition(); @@ -81,8 +119,8 @@ public: // change an existing difference void UpdateStatusCode(POSITION diffpos, BYTE status); - - void UpdateTimes(POSITION diffpos, long leftTime, long rightTime); + void UpdateInfoFromDisk(DIFFITEM & di); + void UpdateInfoFromDiskHalf(DIFFITEM & di, DiffFileInfo & dfi); BOOL m_bRecurse; CString m_strLeft; diff --git a/Src/DirActions.cpp b/Src/DirActions.cpp index 70a7f2026..a37a18282 100644 --- a/Src/DirActions.cpp +++ b/Src/DirActions.cpp @@ -2,7 +2,14 @@ // see Merge.cpp for license (GPLv2+) statement // ///////////////////////////////////////////////////////////////////////////// -// DirActions.cpp : implementation file +/** + * @file DirActions.cpp + * + * @brief Implementation of methods of CDirView that copy/move/delete files + */ +// RCS ID line follows -- this is updated by CVS +// $Id$ + // It would be nice to make this independent of the UI (CDirView) // but it needs access to the list of selected items. // One idea would be to provide an iterator over them. @@ -552,8 +559,8 @@ void CDirView::GetItemFileNames(int sel, CString& strLeft, CString& strRight) co const CDiffContext * ctxt = GetDiffContext(); const DIFFITEM & di = ctxt->GetDiffAt(diffpos); - strLeft = paths_ConcatPath(di.slpath, di.sfilename); - strRight = paths_ConcatPath(di.srpath, di.sfilename); + strLeft = di.getLeftFilepath(); + strRight = di.getRightFilepath(); } // Open selected file on specified side diff --git a/Src/DirDoc.cpp b/Src/DirDoc.cpp index 2c8ea8450..a55df74bb 100644 --- a/Src/DirDoc.cpp +++ b/Src/DirDoc.cpp @@ -18,7 +18,14 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // ///////////////////////////////////////////////////////////////////////////// -// DirDoc.cpp : implementation file +/** + * @file DirDoc.cpp + * + * @brief Implementation file for CDirDoc + * + */ +// RCS ID line follows -- this is updated by CVS +// $Id$ // #include "stdafx.h" @@ -267,19 +274,19 @@ static LPCTSTR GetItemPathIfShowable(const DIFFITEM & di, int llen, int rlen) case FILE_DIFF: if (mf->m_bShowDiff) { - p = _tcsninc(di.slpath, llen); + p = _tcsninc(di.getLeftFilepath(), llen); } break; case FILE_BINSAME: if (mf->m_bShowIdent && mf->m_bShowBinaries) { - p = _tcsninc(di.slpath, llen); + p = _tcsninc(di.getLeftFilepath(), llen); } break; case FILE_BINDIFF: if (mf->m_bShowDiff && mf->m_bShowBinaries) { - p = _tcsninc(di.slpath, llen); + p = _tcsninc(di.getLeftFilepath(), llen); } break; case FILE_LUNIQUE: @@ -290,19 +297,23 @@ static LPCTSTR GetItemPathIfShowable(const DIFFITEM & di, int llen, int rlen) || (mf->m_bShowUniqueRight && rightside)) { if (di.code==FILE_LUNIQUE || di.code==FILE_LDIRUNIQUE) - p = _tcsninc(di.slpath, llen); + { + p = _tcsninc(di.getLeftFilepath(), llen); + } else - p = _tcsninc(di.srpath, rlen); + { + p = _tcsninc(di.getRightFilepath(), rlen); + } } break; case FILE_SAME: if (mf->m_bShowIdent) { - p = _tcsninc(di.slpath, llen); + p = _tcsninc(di.getLeftFilepath(), llen); } break; default: // error - p = _tcsninc(di.slpath, llen); + p = _tcsninc(di.getLeftFilepath(), llen); break; } return p; @@ -310,6 +321,8 @@ static LPCTSTR GetItemPathIfShowable(const DIFFITEM & di, int llen, int rlen) void CDirDoc::Redisplay() { +m_pDirView->ToDoDeleteThisValidateColumnOrdering(); + if (m_pCtxt == NULL) return; @@ -330,17 +343,12 @@ void CDirDoc::Redisplay() if (p) { - int i = m_pDirView->AddNewItem(cnt); - m_pDirView->SetSubitem(i, DV_NAME, di.sfilename); - m_pDirView->SetSubitem(i, DV_EXT, di.sext); - s = _T("."); - s += p; - m_pDirView->SetSubitem(i, DV_PATH, s); - m_pDirView->SetItemKey(i, curdiffpos); - UpdateItemStatus(i, di); + int i = m_pDirView->AddDiffItem(cnt, di, p, curdiffpos); + UpdateScreenItemStatus(i, di); cnt++; } } +m_pDirView->ToDoDeleteThisValidateColumnOrdering(); } CDirView * CDirDoc::GetMainView() @@ -372,80 +380,27 @@ static long GetModTime(LPCTSTR szPath) return mystats.st_mtime; } -static void UpdateTimes(DIFFITEM * pdi) -{ - CString sLeft = (CString)pdi->slpath + _T("\\") + pdi->sfilename; - pdi->ltime = GetFileModTime(sLeft); - - CString sRight = (CString)pdi->srpath + _T("\\") + pdi->sfilename; - pdi->rtime = GetFileModTime(sRight); -} - -static CString -TimeString(const time_t * tim) -{ - if (!tim) return _T("---"); - // _tcsftime does not respect user date customizations from - // Regional Options/Configuration Regional; COleDateTime::Format does so. - COleDateTime odt = *tim; - return odt.Format(); -} -void CDirDoc::SetItemStatus(UINT nIdx, LPCTSTR szStatus, int image, const time_t * ltime, const time_t * rtime) -{ - m_pDirView->SetSubitem(nIdx, DV_STATUS, szStatus); - m_pDirView->SetImage(nIdx, image); - m_pDirView->SetSubitem(nIdx, DV_LTIME, TimeString(ltime)); - m_pDirView->SetSubitem(nIdx, DV_RTIME, TimeString(rtime)); -} - -void CDirDoc::UpdateItemStatus(UINT nIdx) +/** + * @brief Update in-memory diffitem status from disk + */ +void CDirDoc::ReloadItemStatus(UINT nIdx) { POSITION diffpos = m_pDirView->GetItemKey(nIdx); DIFFITEM di = m_pCtxt->GetDiffAt(diffpos); - UpdateTimes(&di); // in case just copied (into existence) or modified - UpdateItemStatus(nIdx, di); + m_pCtxt->UpdateInfoFromDisk(di); // in case just copied (into existence) or modified + UpdateScreenItemStatus(nIdx, di); } - -void CDirDoc::UpdateItemStatus(UINT nIdx, DIFFITEM di) +/** + * @brief Push current in-memory diffitem status out to screen for selected item + */ +void CDirDoc::UpdateScreenItemStatus(UINT nIdx, DIFFITEM di) { - CString s; - switch (di.code) - { - case FILE_DIFF: - VERIFY(s.LoadString(IDS_FILES_ARE_DIFFERENT)); - SetItemStatus(nIdx, s, FILE_DIFF, &di.ltime, &di.rtime); - break; - case FILE_BINDIFF: - VERIFY(s.LoadString(IDS_BIN_FILES_DIFF)); - SetItemStatus(nIdx, s, FILE_BINDIFF, &di.ltime, &di.rtime); - break; - case FILE_BINSAME: - VERIFY(s.LoadString(IDS_BIN_FILES_SAME)); - SetItemStatus(nIdx, s, FILE_BINSAME, &di.ltime, &di.rtime); - break; - case FILE_LUNIQUE: - case FILE_LDIRUNIQUE: - AfxFormatString1(s, IDS_ONLY_IN_FMT, di.slpath); - SetItemStatus(nIdx, s, di.code, &di.ltime, NULL); - break; - case FILE_RUNIQUE: - case FILE_RDIRUNIQUE: - AfxFormatString1(s, IDS_ONLY_IN_FMT, di.srpath); - SetItemStatus(nIdx, s, di.code, NULL, &di.rtime); - break; - case FILE_SAME: - VERIFY(s.LoadString(IDS_IDENTICAL)); - SetItemStatus(nIdx, s, FILE_SAME, &di.ltime, &di.rtime); - break; - default: // error - VERIFY(s.LoadString(IDS_CANT_COMPARE_FILES)); - SetItemStatus(nIdx, s, FILE_ERROR, (di.ltime>0 ? &di.ltime : NULL), (di.rtime>0 ? &di.rtime : NULL)); - break; - } -} + m_pDirView->UpdateDiffItemStatus(nIdx, di); +} + void CDirDoc::InitStatusStrings() { @@ -492,15 +447,13 @@ CString GetPathOnly( const CString& sString ) return sReturn; } -BOOL CDirDoc::UpdateItemStatus(LPCTSTR pathLeft, LPCTSTR pathRight, - UINT status) +/** + * @brief Find the CDiffContext diffpos of an item from its left & right paths + */ +POSITION CDirDoc::FindItemFromPaths(LPCTSTR pathLeft, LPCTSTR pathRight) { POSITION pos = m_pCtxt->GetFirstDiffPosition(); POSITION currentPos; - DIFFITEM current; - int count = m_pCtxt->GetDiffCount(); - int i = 0; - BOOL found = FALSE; CString path1, file1; SplitFilename(pathLeft, &path1, &file1, 0); @@ -514,38 +467,26 @@ BOOL CDirDoc::UpdateItemStatus(LPCTSTR pathLeft, LPCTSTR pathRight, // Filenames must be identical if (file1 != file2) - return FALSE; + return NULL; // Get first item - current = m_pCtxt->GetDiffAt(pos); + DIFFITEM current = m_pCtxt->GetDiffAt(pos); - while (i < count && found == FALSE) + int count = m_pCtxt->GetDiffCount(); + for (int i=0; i < count; ++i) { // Save our current pos before getting next currentPos = pos; current = m_pCtxt->GetNextDiffPosition(pos); - // Path can contain (because of difftools?) '/' and '\' - // so for comparing purposes, convert whole path to use '\' - current.srpath.Replace('/', '\\'); - current.slpath.Replace('/', '\\'); - - if (path1 == current.slpath && - path2 == current.srpath && + if (path1 == current.getLeftFilepath() && + path2 == current.getRightFilepath() && file1 == current.sfilename) { - // Right item found! - // Get index at view, update status to context - // and tell view to update found item - int ind = m_pDirView->GetItemIndex((DWORD)currentPos); - current.code = (BYTE)status; - m_pCtxt->UpdateStatusCode(currentPos, (BYTE)status); - UpdateItemStatus(ind, current); - found = TRUE; + return currentPos; } - i++; } - return found; + return NULL; } // stash away our view pointer @@ -575,61 +516,6 @@ void CDirDoc::MergeDocClosing(CMergeDoc * pMergeDoc) m_MergeDocs.RemoveAt(pos); } -BOOL CDirDoc::UpdateItemTimes(LPCTSTR pathLeft, LPCTSTR pathRight) -{ - POSITION pos = m_pCtxt->GetFirstDiffPosition(); - POSITION currentPos; - DIFFITEM current; - int count = m_pCtxt->GetDiffCount(); - int i = 0; - BOOL found = FALSE; - - CString path1, file1; - SplitFilename(pathLeft, &path1, &file1, 0); - CString path2, file2; - SplitFilename(pathRight, &path2, &file2, 0); - - // Filenames must be identical - if (file1 != file2) - return FALSE; - - // Path can contain (because of difftools?) '/' and '\' - // so for comparing purposes, convert whole path to use '\\' - path1.Replace('/', '\\'); - path2.Replace('/', '\\'); - - // Get first item - current = m_pCtxt->GetDiffAt(pos); - - while (i < count && found == FALSE) - { - // Save our current pos before getting next - currentPos = pos; - current = m_pCtxt->GetNextDiffPosition( pos ); - - // Path can contain (because of difftools?) '/' and '\' - // so for comparing purposes, convert whole path to use '\' - current.srpath.Replace('/', '\\'); - current.slpath.Replace('/', '\\'); - - if (path1 == current.slpath && - path2 == current.srpath && - file1 == current.sfilename) - { - // Right item found! - // Get index at view, update filetimes to context - // and tell view to update found item - int ind = m_pDirView->GetItemIndex((DWORD) currentPos); - UpdateTimes(¤t); - m_pCtxt->UpdateTimes(currentPos, current.ltime, current.rtime); - UpdateItemStatus(ind, current); - found = TRUE; - } - i++; - } - return found; -} - // Prepare for reuse // Close all our merge docs (which gives them chance to save) // This may fail if user cancels a Save dialog @@ -674,3 +560,26 @@ CMergeDoc * CDirDoc::GetMergeDocForDiff(BOOL * pNew) return pMergeDoc; } +/** + * @brief Item specified has changed on disk (and is now the same if unified==true). + */ +void CDirDoc::UpdateChangedItem(LPCTSTR pathLeft, LPCTSTR pathRight, bool unified) +{ + POSITION pos = FindItemFromPaths(pathLeft, pathRight); + ASSERT(pos); + int ind = m_pDirView->GetItemIndex((DWORD)pos); + + // Get index at view, update filetimes to context + // and tell view to update found item + DIFFITEM current = m_pCtxt->GetDiffAt(pos); + m_pCtxt->UpdateInfoFromDisk(current); + + if (unified) + { + // files have been unified -- that is, they are now identical + UINT status = FILE_SAME; + m_pCtxt->UpdateStatusCode(pos, (BYTE)status); + } + + UpdateScreenItemStatus(ind, current); +} diff --git a/Src/DirDoc.h b/Src/DirDoc.h index b645a9ca6..ef2de275f 100644 --- a/Src/DirDoc.h +++ b/Src/DirDoc.h @@ -17,14 +17,20 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // ///////////////////////////////////////////////////////////////////////////// +/** + * @file DirDoc.h + * + * @brief Declaration file for CDirDoc + * + */ +// RCS ID line follows -- this is updated by CVS +// $Id$ + #if !defined(AFX_DIRDOC_H__0B17B4C1_356F_11D1_95CD_444553540000__INCLUDED_) #define AFX_DIRDOC_H__0B17B4C1_356F_11D1_95CD_444553540000__INCLUDED_ - -#if _MSC_VER >= 1000 #pragma once -#endif // _MSC_VER >= 1000 -// DirDoc.h : header file -// + + #include "Merge.h" // DirDocFilter theApp #include "DirView.h" #include "DiffContext.h" @@ -66,13 +72,12 @@ public: // Implementation public: - BOOL UpdateItemTimes(LPCTSTR pathLeft, LPCTSTR pathRight); - BOOL UpdateItemStatus( LPCTSTR pathLeft, LPCTSTR pathRight, UINT status ); + void UpdateChangedItem(LPCTSTR pathLeft, LPCTSTR pathRight, bool unified); + POSITION FindItemFromPaths(LPCTSTR pathLeft, LPCTSTR pathRight); void SetDiffContext(CDiffContext *pCtxt); void UpdateResources(); void InitStatusStrings(); - void UpdateItemStatus(UINT nIdx); - void SetItemStatus(UINT nIdx, LPCTSTR szStatus, int image, const time_t * ltime, const time_t * rtime); + void ReloadItemStatus(UINT nIdx); void Redisplay(); void Rescan(); CDiffContext *m_pCtxt; @@ -88,7 +93,7 @@ public: #endif protected: - void UpdateItemStatus(UINT nIdx, DIFFITEM di); + void UpdateScreenItemStatus(UINT nIdx, DIFFITEM di); // Generated message map functions //{{AFX_MSG(CDirDoc) diff --git a/Src/DirScan.cpp b/Src/DirScan.cpp index c05e57024..b9cc301af 100644 --- a/Src/DirScan.cpp +++ b/Src/DirScan.cpp @@ -1,6 +1,10 @@ -///////////////////////////////////////////////////////////////////////////// -// DirScan.cpp : implementation file -// +/** + * @file DirScan.cpp + * + * @brief Implementation of DirScan and helper functions + */ +// RCS ID line follows -- this is updated by CVS +// $Id$ #include "stdafx.h" #include "DirScan.h" @@ -17,11 +21,14 @@ extern CLogFile gLog; static char THIS_FILE[] = __FILE__; #endif -// directory or file info +/** + * @brief directory or file info for one row in diff result + */ struct fentry { CString name; long mtime; + long ctime; _int64 size; }; typedef CArray fentryArray;; @@ -213,7 +220,10 @@ void LoadFiles(const CString & sDir, fentryArray * dirs, fentryArray * files) fentry ent; CTime mtim; finder.GetLastWriteTime(mtim); + CTime ctim; + finder.GetCreationTime(ctim); ent.mtime = mtim.GetTime(); + ent.ctime = ctim.GetTime(); ent.size = finder.GetLength64(); ent.name = finder.GetFileName(); if (finder.IsDirectory()) @@ -261,23 +271,26 @@ static int collstr(const CString & s1, const CString & s2, bool casesensitive) static void FilterAdd(const CString & sDir, const fentry * lent, const fentry * rent, int code, CDiffContext * pCtxt) { CString name, leftdir, rightdir; - long rtime=0, ltime=0; + long rmtime=0, lmtime=0, rctime=0, lctime=0; _int64 lsize=0, rsize=0; if (lent) { leftdir = paths_ConcatPath(pCtxt->m_strNormalizedLeft, sDir); - ltime = lent->mtime; + lmtime = lent->mtime; + lctime = lent->ctime; lsize = lent->size; name = lent->name; } if (rent) { rightdir = paths_ConcatPath(pCtxt->m_strNormalizedRight, sDir); - rtime = rent->mtime; + rmtime = rent->mtime; + rctime = rent->ctime; rsize = rent->size; name = rent->name; } gLog.Write(_T("name=<%s>, leftdir=<%s>, rightdir=<%s>, code=%d") , (LPCTSTR)name, (LPCTSTR)leftdir, (LPCTSTR)rightdir, code); - pCtxt->AddDiff(name, leftdir, rightdir, ltime, rtime, code); + pCtxt->AddDiff(name, sDir, leftdir, rightdir + , lmtime, rmtime, lctime, rctime, lsize, rsize, code); } diff --git a/Src/DirView.cpp b/Src/DirView.cpp index fb7f5f0f9..2fc475e3c 100644 --- a/Src/DirView.cpp +++ b/Src/DirView.cpp @@ -18,8 +18,12 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // ///////////////////////////////////////////////////////////////////////////// -// DirView.cpp : implementation file -// +/** + * @file DirView.cpp + * + * @brief Main implementation file for CDirView + */ +// RCS ID line follows -- this is updated by CVS // $Id$ #include "stdafx.h" @@ -48,6 +52,9 @@ IMPLEMENT_DYNCREATE(CDirView, CListViewEx) CDirView::CDirView() : m_numcols(-1) +, m_dispcols(-1) +, m_bSortAscending(true) +, m_pHeaderPopup(NULL) { m_pList = NULL; } @@ -102,6 +109,7 @@ BEGIN_MESSAGE_MAP(CDirView, CListViewEx) ON_UPDATE_COMMAND_UI(ID_REFRESH, OnUpdateRefresh) ON_WM_TIMER() ON_WM_MOUSEMOVE() + ON_COMMAND(ID_EDIT_COLUMNS, OnEditColumns) //}}AFX_MSG_MAP ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick) ON_NOTIFY_REFLECT(LVN_GETINFOTIP, OnInfoTip) @@ -113,8 +121,8 @@ END_MESSAGE_MAP() void CDirView::OnDraw(CDC* /*pDC*/) { - CDocument* pDoc = GetDocument(); - // TODO: add draw code here + // This is a CListView, so it is wrapped around a Windows common control + // which does the drawing } ///////////////////////////////////////////////////////////////////////////// @@ -162,9 +170,6 @@ void CDirView::OnInitialUpdate() if (HWND hWnd = ListView_GetHeader(m_pList->m_hWnd)) m_ctlSortHeader.SubclassWindow(hWnd); - LoadColumnOrders(); - AddColumns(); - CBitmap bm; VERIFY (m_imageList.Create (16, 16, ILC_MASK, 0, 1)); VERIFY (bm.LoadBitmap (IDB_LFILE)); @@ -196,8 +201,9 @@ void CDirView::OnInitialUpdate() bm.Detach(); m_pList->SetImageList (&m_imageList, LVSIL_SMALL); - UpdateColumnNames(); - SetColumnWidths(); + LoadColumnOrders(); + + ReloadColumns(); //m_ctlSortHeader.SetSortImage(m_sortColumn, m_bSortAscending); @@ -218,51 +224,135 @@ void CDirView::OnLButtonDblClk(UINT nFlags, CPoint point) CListViewEx::OnLButtonDblClk(nFlags, point); } +/** + * @brief Load or reload the columns (headers) of the list view + */ +void CDirView::ReloadColumns() +{ + LoadColumnHeaderItems(); +ToDoDeleteThisValidateColumnOrdering(); + +ToDoDeleteThisValidateColumnOrdering(); + UpdateColumnNames(); +ToDoDeleteThisValidateColumnOrdering(); + SetColumnWidths(); +ToDoDeleteThisValidateColumnOrdering(); +} +/** + * @brief User right-clicked somewhere in this view + */ void CDirView::OnContextMenu(CWnd*, CPoint point) { - // CG: This block was added by the Pop-up Menu component + if (!GetListCtrl().GetItemCount()) + return; + int i=0; + if (point.x == -1 && point.y == -1) { - if (point.x == -1 && point.y == -1){ - //keystroke invocation - CRect rect; - GetClientRect(rect); - ClientToScreen(rect); - - point = rect.TopLeft(); - point.Offset(5, 5); + //keystroke invocation + CRect rect; + GetClientRect(rect); + ClientToScreen(rect); + + point = rect.TopLeft(); + point.Offset(5, 5); + } else { + // Check if user right-clicked on header + // convert screen coordinates to client coordinates of listview + CPoint insidePt = point; + GetListCtrl().ScreenToClient(&insidePt); + // TODO: correct for hscroll ? + // Ask header control if click was on one of its header items + HDHITTESTINFO hhti; + memset(&hhti, 0, sizeof(hhti)); + hhti.pt = insidePt; + int col = GetListCtrl().GetHeaderCtrl()->SendMessage(HDM_HITTEST, 0, (LPARAM)&hhti); + if (col >= 0) + { + // Presumably hhti.flags & HHT_ONHEADER is true + HeaderContextMenu(point, ColPhysToLog(col)); + return; } + // bail out if point is not in any row + LVHITTESTINFO lhti; + memset(&lhti, 0, sizeof(lhti)); + insidePt = point; + ScreenToClient(&insidePt); + lhti.pt = insidePt; + i = GetListCtrl().HitTest(insidePt); + TRACE("i=%d\n", i); + if (i<0) + return; + } + + ListContextMenu(point, i); +} - CMenu menu; - VERIFY(menu.LoadMenu(IDR_POPUP_DIRVIEW)); +/** + * @brief Return nearest ancestor which is not a child window + */ +static CWnd * GetNonChildAncestor(CWnd * w) +{ + CWnd* parent = w; + while (parent->GetStyle() & WS_CHILD) + parent = parent->GetParent(); + return parent; +} - CMenu* pPopup = menu.GetSubMenu(0); - ASSERT(pPopup != NULL); +/** + * @brief User right-clicked in listview rows + */ +void CDirView::ListContextMenu(CPoint point, int /*i*/) +{ + CMenu menu; + VERIFY(menu.LoadMenu(IDR_POPUP_DIRVIEW)); - // set the menu items with the proper directory names - CString sl, sr; - GetSelectedDirNames(sl, sr); + // 1st submenu of IDR_POPUP_DIRVIEW is for header popup + CMenu* pPopup = menu.GetSubMenu(0); + ASSERT(pPopup != NULL); - // find non-child ancestor to use as menu parent - CWnd* pWndPopupOwner = this; - while (pWndPopupOwner->GetStyle() & WS_CHILD) - pWndPopupOwner = pWndPopupOwner->GetParent(); + // set the menu items with the proper directory names + CString sl, sr; + GetSelectedDirNames(sl, sr); - // TODO: It would be more efficient to set - // all the popup items now with one traverse over selected items - // instead of using updates, in which we make a traverse for every item - // Perry, 2002-12-04 - // + // find non-child ancestor to use as menu parent + CWnd * pWndPopupOwner = GetNonChildAncestor(this); + // TODO: It would be more efficient to set + // all the popup items now with one traverse over selected items + // instead of using updates, in which we make a traverse for every item + // Perry, 2002-12-04 - // invoke context menu - // this will invoke all the OnUpdate methods to enable/disable the individual items - pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, - pWndPopupOwner); - } + // invoke context menu + // this will invoke all the OnUpdate methods to enable/disable the individual items + pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, + pWndPopupOwner); } +/** + * @brief User right-clicked on specified logical column + */ +void CDirView::HeaderContextMenu(CPoint point, int /*i*/) +{ +ToDoDeleteThisValidateColumnOrdering(); + CMenu menu; + VERIFY(menu.LoadMenu(IDR_POPUP_DIRVIEW)); + + // 2nd submenu of IDR_POPUP_DIRVIEW is for header popup + CMenu* pPopup = menu.GetSubMenu(1); + ASSERT(pPopup != NULL); + + // find non-child ancestor to use as menu parent + CWnd * pWndPopupOwner = GetNonChildAncestor(this); + + // invoke context menu + // this will invoke all the OnUpdate methods to enable/disable the individual items + pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, + pWndPopupOwner); + +} + // Make a string out of a number // TODO: Ought to introduce commas every three digits, except this is locale-specific // How to do this with locale sensitivity ? @@ -283,13 +373,17 @@ void CDirView::ModifyPopup(CMenu * pPopup, int nStringResource, int nMenuId, LPC } -// User chose (main menu) Copy from right to left -void CDirView::OnDirCopyFileToLeft() +/** + * @brief User chose (main menu) Copy from right to left + */ +void CDirView::OnDirCopyFileToLeft() { DoCopyFileToLeft(); } -// User chose (main menu) Copy from left to right -void CDirView::OnDirCopyFileToRight() +/** + * @brief User chose (main menu) Copy from left to right + */ +void CDirView::OnDirCopyFileToRight() { DoCopyFileToRight(); } @@ -368,71 +462,14 @@ void CDirView::DoUpdateDirCopyFileToRight(CCmdUI* pCmdUI, eMenuType menuType) } } -/// Assign column name, using string resource & current column ordering -void CDirView::NameColumn(int id, int subitem) -{ - CString s; - VERIFY(s.LoadString(id)); - LV_COLUMN lvc; - lvc.mask = LVCF_TEXT; - lvc.pszText = (LPTSTR)((LPCTSTR)s); - m_pList->SetColumn(m_colorder[subitem], &lvc); -} - -/// Load column names from string table -void CDirView::UpdateColumnNames() -{ - NameColumn(IDS_FILENAME_HEADER, DV_NAME); - NameColumn(IDS_EXTENSION_HEADER, DV_EXT); - NameColumn(IDS_DIR_HEADER, DV_PATH); - NameColumn(IDS_RESULT_HEADER, DV_STATUS); - NameColumn(IDS_LTIME_HEADER, DV_LTIME); - NameColumn(IDS_RTIME_HEADER, DV_RTIME); -} - -/// Update any language-dependent data +/** + * @brief Update any language-dependent data + */ void CDirView::UpdateResources() { UpdateColumnNames(); } -/// Compare two specified rows during a sort operation (windows callback) -int CALLBACK CDirView::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) -{ - // initialize structures to obtain required information - CDirView* pView = reinterpret_cast(lParamSort); - POSITION diffposl = pView->GetItemKeyFromData(lParam1); - POSITION diffposr = pView->GetItemKeyFromData(lParam2); - DIFFITEM lDi = pView->GetDiffContext()->GetDiffAt(diffposl); - DIFFITEM rDi = pView->GetDiffContext()->GetDiffAt(diffposr); - - // compare 'left' and 'right' parameters as appropriate - int retVal = 0; // initialize for default case - switch (pView->m_sortColumn) - { - case DV_NAME: // File name. - retVal = lDi.sfilename.CompareNoCase(rDi.sfilename); - break; - case DV_PATH: // File Path. - retVal = lDi.slpath.CompareNoCase(rDi.slpath); - break; - case DV_STATUS: // Diff Status. - retVal = rDi.code-lDi.code; - break; - case DV_LTIME: // Time of left item - retVal = rDi.ltime-lDi.ltime; - break; - case DV_RTIME: // Time of right item - retVal = rDi.rtime-lDi.rtime; - break; - case DV_EXT: // File extension. - retVal = lDi.sext.CompareNoCase(rDi.sext); - break; - } - // return compare result, considering sort direction - return (pView->m_bSortAscending)?retVal:-retVal; -} - void CDirView::OnColumnClick(NMHDR *pNMHDR, LRESULT *pResult) { // set sort parameters and handle ascending/descending @@ -445,15 +482,8 @@ void CDirView::OnColumnClick(NMHDR *pNMHDR, LRESULT *pResult) else { m_sortColumn = sortcol; - // date columns get default descending sort. - if(m_sortColumn==DV_LTIME || m_sortColumn==DV_RTIME) - { - m_bSortAscending = false; - } - else - { - m_bSortAscending = true; - } + // most columns start off ascending, but not dates + m_bSortAscending = IsDefaultSortAscending(m_sortColumn); } m_ctlSortHeader.SetSortImage(m_sortColumn, m_bSortAscending); @@ -467,6 +497,7 @@ void CDirView::OnDestroy() { DeleteAllDisplayItems(); + ValidateColumnOrdering(); SaveColumnOrders(); SaveColumnWidths(); @@ -1116,27 +1147,6 @@ void CDirView::OnUpdateUIMessage(WPARAM wParam, LPARAM lParam) if (mf->m_bScrollToFirst) OnFirstdiff(); } -// Add new item to list view -int CDirView::AddNewItem(int i) -{ - LV_ITEM lvItem; - memset(&lvItem, 0, sizeof(lvItem)); - lvItem.iItem = i; - return GetListCtrl().InsertItem(&lvItem); - -} - -// Set a subitem on an existing item -void CDirView::SetSubitem(int item, int subitem, LPCTSTR sz) -{ - LV_ITEM lvItem; - memset(&lvItem, 0, sizeof(lvItem)); - lvItem.mask = LVIF_TEXT; - lvItem.iItem = item; - lvItem.iSubItem = m_colorder[subitem]; - lvItem.pszText = const_cast(sz); - GetListCtrl().SetItem(&lvItem); -} BOOL CDirView::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { @@ -1149,7 +1159,9 @@ BOOL CDirView::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) return CListViewEx::OnNotify(wParam, lParam, pResult); } -/// User is starting to drag a column header +/** + * @brief User is starting to drag a column header + */ BOOL CDirView::OnHeaderBeginDrag(LPNMHEADER hdr, LRESULT* pResult) { // save column widths before user reorders them @@ -1158,7 +1170,9 @@ BOOL CDirView::OnHeaderBeginDrag(LPNMHEADER hdr, LRESULT* pResult) return TRUE; } -/// User just finished dragging a column header +/** + * @brief User just finished dragging a column header + */ BOOL CDirView::OnHeaderEndDrag(LPNMHEADER hdr, LRESULT* pResult) { int src = hdr->iItem; @@ -1167,23 +1181,14 @@ BOOL CDirView::OnHeaderEndDrag(LPNMHEADER hdr, LRESULT* pResult) *pResult = !allowDrop; if (allowDrop && src!=dest) { - // actually moved column - m_colorder[m_invcolorder[src]] = dest; - // shift all other affected columns - int dir = src > dest ? +1 : -1; - for (int i=dest; i!=src; i += dir) - { - m_colorder[m_invcolorder[i]] = i+dir; - } - // fix inverse mapping - for (i=0; iInsertColumn(i, &lvcol); - } -} - -/// Update all column widths (from registry to screen) -// Necessary when user reorders columns -void CDirView::SetColumnWidths() +/** @brief Add columns to display, loading width & order from registry. */ +void CDirView::LoadColumnHeaderItems() { - LVCOLUMN lvcol; - memset(&lvcol, 0, sizeof(lvcol)); - lvcol.mask = LVCF_WIDTH; - CString sWidthKey; - int cols = GetListCtrl().GetHeaderCtrl()->GetItemCount(); - int i; + bool dummyflag = false; - for (i=0; iGetHeaderCtrl(); + if (h->GetItemCount()) { - sWidthKey.Format(_T("WDirHdr%d"), i); - int w = max(10, theApp.GetProfileInt(_T("DirView"), sWidthKey, 150)); - GetListCtrl().SetColumnWidth(m_colorder[i], w); + dummyflag = true; + while (m_pList->GetHeaderCtrl()->GetItemCount()>1) + m_pList->DeleteColumn(1); } -} - -/// store current column widths into registry -void CDirView::SaveColumnWidths() -{ - int cols = GetListCtrl().GetHeaderCtrl()->GetItemCount(); - for (int i=0; i < cols; i++) + for (int i=0; iInsertColumn(i, &lvc); } -} + if (dummyflag) + m_pList->DeleteColumn(1); -/// store current column orders into registry -void CDirView::SaveColumnOrders() -{ - ASSERT(m_colorder.GetSize() == m_numcols); - ASSERT(m_invcolorder.GetSize() == m_numcols); - int cols = GetListCtrl().GetHeaderCtrl()->GetItemCount(); - for (int i=0; i < cols; i++) - { - CString key; - key.Format(_T("WDirHdrOrder%d"), i); - int ord = m_colorder[i]; - theApp.WriteProfileInt(_T("DirView"), key, ord); - } } -/// load column orders from registry -void CDirView::LoadColumnOrders() +/// Update all column widths (from registry to screen) +// Necessary when user reorders columns +void CDirView::SetColumnWidths() { - ASSERT(m_numcols == -1); - m_numcols = 6; - m_colorder.SetSize(m_numcols); - m_invcolorder.SetSize(m_numcols); for (int i=0; i=0 && m_colorder[i]=0 && m_invcolorder[i]= 0) { - valid=FALSE; - break; + CString sWidthKey = GetColRegValueNameBase(i) + _T("_Width"); + int w = max(10, theApp.GetProfileInt(_T("DirView"), sWidthKey, 150)); + GetListCtrl().SetColumnWidth(m_colorder[i], w); } } - if (!valid) +} + +/** @brief store current column widths into registry */ +void CDirView::SaveColumnWidths() +{ + for (int i=0; i < m_numcols; i++) { - // reset to identity - for (int i=0; i= 0) { - m_colorder[i] = i; - m_invcolorder[i] = i; + CString sWidthKey = GetColRegValueNameBase(i) + _T("_Width"); + int w = GetListCtrl().GetColumnWidth(phy); + theApp.WriteProfileInt(_T("DirView"), sWidthKey, w); } } } +/** @brief Fire off a resort of the data, to take place when things stabilize. */ +void CDirView::InitiateSort() +{ + PostMessage(WM_TIMER, COLUMN_REORDER); +} + void CDirView::OnTimer(UINT nIDEvent) { if (nIDEvent == COLUMN_REORDER) @@ -1382,13 +1338,13 @@ void CDirView::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) { // Set text color based on timestamps // Do not color unique items - if (ditem.ltime == 0 || ditem.rtime == 0) + if (ditem.left.mtime == 0 || ditem.right.mtime == 0) lplvcd->clrText = GetSysColor(COLOR_WINDOWTEXT); else { - if (ditem.ltime < ditem.rtime) + if (ditem.left.mtime < ditem.right.mtime) lplvcd->clrText = RGB(53, 164, 34); - else if (ditem.ltime > ditem.rtime) + else if (ditem.left.mtime > ditem.right.mtime) lplvcd->clrText = RGB(234, 21, 64); else // Make sure we use default color for ident. items diff --git a/Src/DirView.h b/Src/DirView.h index 7f9884ee5..5d38d19cf 100644 --- a/Src/DirView.h +++ b/Src/DirView.h @@ -17,7 +17,13 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // ///////////////////////////////////////////////////////////////////////////// +/** + * @file DirView.h + * + * @brief Declaration of class CDirView + */ // +// RCS ID line follows -- this is updated by CVS // $Id$ #if !defined(AFX_DirView_H__16E7C721_351C_11D1_95CD_444553540000__INCLUDED_) @@ -26,15 +32,17 @@ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 -// DirView.h : header file -// +// TODO delete +/* #define DV_NAME 0 #define DV_PATH 1 #define DV_STATUS 2 #define DV_LTIME 3 #define DV_RTIME 4 #define DV_EXT 5 +*/ + ///////////////////////////////////////////////////////////////////////////// // CDirView view @@ -52,6 +60,7 @@ typedef enum { eMain, eContext } eMenuType; class CDirDoc; class CDirFrame; +/** View displaying results of a diff, one row per file */ class CDirView : public CListViewEx { protected: @@ -70,18 +79,15 @@ private: public: CDirFrame * GetParentFrame(); - static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); + void UpdateResources(); - void UpdateColumnNames(); - void AddColumns(); + void LoadColumnHeaderItems(); POSITION GetItemKey(int idx) const; void SetItemKey(int idx, POSITION diffpos); int GetItemIndex(DWORD key); // for populating list void DeleteAllDisplayItems(); void SetColumnWidths(); - int AddNewItem(int i); - void SetSubitem(int item, int subitem, LPCTSTR sz); UINT GetSelectedCount() const; int GetFirstSelectedInd(); @@ -136,6 +142,31 @@ private: void PerformAndRemoveTopAction(ActionList & actions); // End DirActions.cpp +// Implementation in DirViewCols.cpp +public: + void UpdateColumnNames(); + static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); + int AddDiffItem(int index, const DIFFITEM & di, LPCTSTR szPath, POSITION curdiffpos); + void UpdateDiffItemStatus(UINT nIdx, const DIFFITEM & di); + void ToDoDeleteThisValidateColumnOrdering() { ValidateColumnOrdering(); } +private: + void InitiateSort(); + void NameColumn(int id, int subitem); + int AddNewItem(int i); + void SetSubitem(int item, int phy, LPCTSTR sz); + bool IsDefaultSortAscending(int col) const; + int ColPhysToLog(int i) const { return m_invcolorder[i]; } + int ColLogToPhys(int i) const { return m_colorder[i]; } /**< -1 if not displayed */ + CString GetColDisplayName(int col) const; + int GetColLogCount() const; + void LoadColumnOrders(); + void ValidateColumnOrdering(); + void ClearColumnOrders(); + void ResetColumnOrdering(); + void MoveColumn(int psrc, int pdest); + CString GetColRegValueNameBase(int col) const; + int GetColDefaultOrder(int col) const; +// End DirViewCols.cpp // Overrides // ClassWizard generated virtual function overrides @@ -161,15 +192,17 @@ protected: // Implementation data protected: - CSortHeaderCtrl m_ctlSortHeader; + CSortHeaderCtrl m_ctlSortHeader; CImageList m_imageList; - bool m_bSortAscending; // is currently sorted ascending. - int m_sortColumn; // index to column which is sorted + bool m_bSortAscending; /** < current column sort is ascending ? */ + int m_sortColumn; /**< index of column currently used for sorting */ CListCtrl * m_pList; int m_numcols; - CArray m_colorder; - CArray m_invcolorder; + int m_dispcols; + CArray m_colorder; /**< colorder[logical#]=physical# */ + CArray m_invcolorder; /**< invcolorder[physical]=logical# */ CPoint m_ptLastMousePos; + CMenu * m_pHeaderPopup; // Generated message map functions afx_msg void OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult); @@ -216,6 +249,7 @@ protected: afx_msg void OnUpdateRefresh(CCmdUI* pCmdUI); afx_msg void OnTimer(UINT nIDEvent); afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnEditColumns(); //}}AFX_MSG DECLARE_MESSAGE_MAP() BOOL OnHeaderBeginDrag(LPNMHEADER hdr, LRESULT* pResult); @@ -242,9 +276,10 @@ private: void MoveSelection(int currentInd, int i, int selCount); void SaveColumnWidths(); void SaveColumnOrders(); - void LoadColumnOrders(); - void NameColumn(int id, int subitem); void FixReordering(); + void HeaderContextMenu(CPoint point, int i); + void ListContextMenu(CPoint point, int i); + void ReloadColumns(); }; diff --git a/Src/MainFrm.cpp b/Src/MainFrm.cpp index 5356b7cc6..adff100f0 100644 --- a/Src/MainFrm.cpp +++ b/Src/MainFrm.cpp @@ -18,8 +18,12 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // ///////////////////////////////////////////////////////////////////////////// -// MainFrm.cpp : implementation of the CMainFrame class -// +/** + * @file MainFrm.cpp + * + * @brief Implementation of the CMainFrame class + */ +// RCS ID line follows -- this is updated by CVS // $Id$ #include "stdafx.h" @@ -1238,7 +1242,7 @@ void CMainFrame::UpdateCurrentFileStatus(CDirDoc * pDirDoc, UINT nStatus, int id // update DIFFITEM code pDirDoc->m_pCtxt->UpdateStatusCode(diffpos, (BYTE)nStatus); // update DIFFITEM time, and also tell views - pDirDoc->UpdateItemStatus(idx); + pDirDoc->ReloadItemStatus(idx); //m_pDirDoc->Redisplay(); } diff --git a/Src/Merge.dsp b/Src/Merge.dsp index e9933984a..566f9eee1 100644 --- a/Src/Merge.dsp +++ b/Src/Merge.dsp @@ -204,6 +204,10 @@ SOURCE=.\DirActions.cpp # End Source File # Begin Source File +SOURCE=.\DirColsDlg.cpp +# End Source File +# Begin Source File + SOURCE=.\DirDoc.cpp !IF "$(CFG)" == "Merge - Win32 Release" @@ -263,6 +267,14 @@ SOURCE=.\DirView.cpp # End Source File # Begin Source File +SOURCE=.\DirViewColHandler.cpp +# End Source File +# Begin Source File + +SOURCE=.\DirViewColItems.cpp +# End Source File +# Begin Source File + SOURCE=.\dllver.cpp # End Source File # Begin Source File @@ -680,6 +692,10 @@ SOURCE=.\DiffWrapper.h # End Source File # Begin Source File +SOURCE=.\DirColsDlg.h +# End Source File +# Begin Source File + SOURCE=.\DirDoc.h # End Source File # Begin Source File @@ -700,6 +716,10 @@ SOURCE=.\DirView.h # End Source File # Begin Source File +SOURCE=.\DirViewColItems.h +# End Source File +# Begin Source File + SOURCE=.\dllver.h # End Source File # Begin Source File diff --git a/Src/Merge.rc b/Src/Merge.rc index dbb039197..fa03d446d 100644 --- a/Src/Merge.rc +++ b/Src/Merge.rc @@ -175,7 +175,7 @@ END IDR_POPUP_DIRVIEW MENU DISCARDABLE BEGIN - POPUP "_POPUP_" + POPUP "_ITEM_POPUP_" BEGIN MENUITEM "Copy file to left", ID_DIR_COPY_FILE_TO_LEFT MENUITEM "Copy file to right", ID_DIR_COPY_FILE_TO_RIGHT @@ -188,6 +188,10 @@ BEGIN MENUITEM "Open right", ID_DIR_OPEN_RIGHT MENUITEM "Open right with...", ID_DIR_OPEN_RIGHT_WITH END + POPUP "_HDR_POPUP_" + BEGIN + MENUITEM "Edit columns", ID_EDIT_COLUMNS + END END IDR_POPUP_EDITOR_HEADERBAR MENU DISCARDABLE @@ -524,6 +528,25 @@ BEGIN WS_TABSTOP,WS_EX_STATICEDGE END +IDD_DIRCOLS DIALOG DISCARDABLE 0, 0, 273, 162 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Display Columns" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,141,129,50,14 + PUSHBUTTON "Cancel",IDCANCEL,81,129,50,14 + GROUPBOX "Show columns",IDC_GROUP_SHOW,7,17,124,100 + LISTBOX IDC_LIST_SHOW,42,31,83,79,LBS_NOINTEGRALHEIGHT | + LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "&Up",IDC_UP,13,43,23,13 + PUSHBUTTON "&Down",IDC_DOWN,13,67,23,13 + GROUPBOX "Hide columns",IDC_GROUP_HIDE,181,17,85,103 + LISTBOX IDC_LIST_HIDE,192,31,66,79,LBS_NOINTEGRALHEIGHT | + LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "<==",IDC_ADD,141,41,29,11 + PUSHBUTTON "==>",IDC_REMOVE,141,76,29,11 +END + #ifndef _MAC ///////////////////////////////////////////////////////////////////////////// @@ -664,6 +687,14 @@ BEGIN TOPMARGIN, 7 BOTTOMMARGIN, 4 END + + IDD_DIRCOLS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 266 + TOPMARGIN, 7 + BOTTOMMARGIN, 155 + END END #endif // APSTUDIO_INVOKED @@ -1127,9 +1158,9 @@ END STRINGTABLE DISCARDABLE BEGIN - IDS_FILENAME_HEADER "Filename" - IDS_DIR_HEADER "Directory" - IDS_RESULT_HEADER "Comparison result" + IDS_COLHDR_FILENAME "Filename" + IDS_COLHDR_DIR "Directory" + IDS_COLHDR_RESULT "Comparison result" IDS_FILE_COMPARISON_TITLE "File Comparison" IDS_DIFF_NUMBER_STATUS_FMT "Difference %1 of %2" IDS_NO_DIFF_SEL_FMT "%1 Differences Found" @@ -1139,9 +1170,9 @@ BEGIN IDS_VSS_RUN_ERROR "Error executing versioning system command." IDS_DIFF_OPEN_NO_SET_PROPS "Modifications have been made to the current file comparison session. Some settings may not take place until the current file comparison is restarted." - IDS_LTIME_HEADER "Left Date" - IDS_RTIME_HEADER "Right Date" - IDS_EXTENSION_HEADER "Extension" + IDS_COLHDR_LTIMEM "Left Date" + IDS_COLHDR_RTIMEM "Right Date" + IDS_COLHDR_EXTENSION "Extension" IDS_CONFIRM_DELETE_ITEMS "Are you sure you want to delete %1 of %2 selected item(s) ?" IDS_DEL_LEFT_FMT "Delete left side %1 of %2 selected item(s)" @@ -1189,6 +1220,12 @@ BEGIN IDS_STATUS_COPYALL2L "Copying All to Left" IDS_STATUS_COPYALL2R "Copying All to Right" IDS_PROGRAMFILES "Programs|*.exe;*.bat;*.cmd|All Files (*.*)|*.*||" + IDS_COLHDR_RSIZE "Right Size" + IDS_COLHDR_LTIMEC "Left Creation Time" + IDS_COLHDR_RTIMEC "Right Creation Time" + IDS_COLHDR_NEWER "Newer File" + IDS_COLHDR_LVERSION "Left File Version" + IDS_COLHDR_RVERSION "Right File Version" END STRINGTABLE DISCARDABLE @@ -1205,6 +1242,16 @@ BEGIN IDC_STATIC_TITLE_RIGHT "Right click on the path to copy" END +STRINGTABLE DISCARDABLE +BEGIN + IDS_LEFTONLY "Left Only" + IDS_RIGHTONLY "Right Only" + IDS_COLHDR_RESULT_ABBR "Short Result" + IDS_COLHDR_LATTRIBUTES "Left Attributes" + IDS_COLHDR_RATTRIBUTES "Right Attributes" + IDS_COLHDR_LSIZE "Left Size" +END + #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/Src/MergeDoc.cpp b/Src/MergeDoc.cpp index bf72f9bd6..aa2fdd48b 100644 --- a/Src/MergeDoc.cpp +++ b/Src/MergeDoc.cpp @@ -1315,11 +1315,8 @@ void CMergeDoc::OnFileSave() // If DirDoc contains diffs if (m_pDirDoc->m_pCtxt) { - m_pDirDoc->UpdateItemTimes(m_strLeftFile, - m_strRightFile); - if (m_nDiffs == 0) - m_pDirDoc->UpdateItemStatus(m_strLeftFile, - m_strRightFile, FILE_SAME); + bool unified = (m_nDiffs==0); // true if status should be set to identical + m_pDirDoc->UpdateChangedItem(m_strLeftFile, m_strRightFile, unified); } } } @@ -1533,10 +1530,8 @@ BOOL CMergeDoc::SaveHelper() // If DirDoc contains diffs if (m_pDirDoc->m_pCtxt) { - m_pDirDoc->UpdateItemTimes(m_strLeftFile, m_strRightFile); - if (m_nDiffs == 0) - m_pDirDoc->UpdateItemStatus(m_strLeftFile, - m_strRightFile, FILE_SAME); + bool unified = (m_nDiffs==0); // true if status should be set to identical + m_pDirDoc->UpdateChangedItem(m_strLeftFile, m_strRightFile, unified); } } return result; diff --git a/Src/readme.txt b/Src/readme.txt index cf0db0120..ad73d50fd 100644 --- a/Src/readme.txt +++ b/Src/readme.txt @@ -6,6 +6,13 @@ WinMerge\Merge.rc Correction#1 værktøylinje(n)->verktøylinje(n) Languages\Norwegian: MergeNorwegian.rc + PATCH: [ 781529 ] Make column info array, and add new columns + common: version.cpp version.h + WinMerge: DiffContext.cpp DiffContext.h DirActions.cpp DirDoc.cpp DirDoc.h + DirScan.cpp DirView.cpp DirView.h MainFrm.cpp Merge.dsp Merge.rc + MergeDoc.cpp resource.h + WinMerge new files: DirColsDlg.cpp DirColsDlg.h DirViewColHandler.cpp + DirViewColItems.cpp DirViewColItems.h 2003-08-22 Kimmo PATCH: [ 787495 ] Create diffutils class (CDiffWrapper) diff --git a/Src/resource.h b/Src/resource.h index a7810b726..2c36296cd 100644 --- a/Src/resource.h +++ b/Src/resource.h @@ -24,6 +24,7 @@ #define IDD_PROPPAGE_REGISTRY 113 #define IDD_EDITOR_HEADERBAR 114 #define IDR_POPUP_EDITOR_HEADERBAR 115 +#define IDD_DIRCOLS 117 #define IDS_VERSION_FMT 130 #define IDS_ALLFILES 131 #define IDS_CONFIRM_ALL_LEFT 132 @@ -55,9 +56,9 @@ #define IDS_SAVEVSS_FMT 157 #define IDS_VSSERROR 158 #define IDS_NOPROJECT 159 -#define IDS_FILENAME_HEADER 160 -#define IDS_DIR_HEADER 161 -#define IDS_RESULT_HEADER 162 +#define IDS_COLHDR_FILENAME 160 +#define IDS_COLHDR_DIR 161 +#define IDS_COLHDR_RESULT 162 #define IDS_FILE_COMPARISON_TITLE 163 #define IDS_DIFF_NUMBER_STATUS_FMT 164 #define IDS_NO_DIFF_SEL 165 @@ -67,9 +68,9 @@ #define IDS_VSS_CMD 168 #define IDS_VSS_RUN_ERROR 169 #define IDS_DIFF_OPEN_NO_SET_PROPS 170 -#define IDS_LTIME_HEADER 171 -#define IDS_RTIME_HEADER 172 -#define IDS_EXTENSION_HEADER 173 +#define IDS_COLHDR_LTIMEM 171 +#define IDS_COLHDR_RTIMEM 172 +#define IDS_COLHDR_EXTENSION 173 #define IDS_CONFIRM_DELETE_ITEMS 174 #define IDS_DEL_LEFT_FMT 175 #define IDS_DEL_RIGHT_FMT 176 @@ -82,6 +83,7 @@ #define IDS_DEL_BOTH_FMT 181 #define IDS_COPY_TO_RIGHT 182 #define IDS_COPY_TO_RIGHT_MAIN 183 +#define IDS_COLHDR_LSIZE 183 #define IDS_DELETE_DIR_FAILED 184 #define IDS_COPY_FILE_FAILED 185 #define IDS_COPY_DIR_FAILED 186 @@ -100,6 +102,17 @@ #define IDS_STATUS_COPYALL2L 199 #define IDS_STATUS_COPYALL2R 200 #define IDS_PROGRAMFILES 201 +#define IDS_COLHDR_RSIZE 202 +#define IDS_COLHDR_LTIMEC 203 +#define IDS_COLHDR_RTIMEC 204 +#define IDS_COLHDR_NEWER 205 +#define IDS_COLHDR_LVERSION 206 +#define IDS_COLHDR_RVERSION 207 +#define IDS_LEFTONLY 208 +#define IDS_RIGHTONLY 209 +#define IDS_COLHDR_RESULT_ABBR 210 +#define IDS_COLHDR_LATTRIBUTES 211 +#define IDS_COLHDR_RATTRIBUTES 212 #define IDB_EQUAL 213 #define IDB_NOTEQUAL 214 #define IDB_RFOLDER 215 @@ -167,6 +180,14 @@ #define IDC_WINMERGE_PATH_SAVE 1047 #define IDC_STATIC_TITLE_LEFT 1048 #define IDC_STATIC_TITLE_RIGHT 1049 +#define IDC_GROUP_SHOW 1053 +#define IDC_LIST_SHOW 1054 +#define IDC_UP 1055 +#define IDC_DOWN 1056 +#define IDC_GROUP_HIDE 1057 +#define IDC_LIST_HIDE 1058 +#define IDC_ADD 1059 +#define IDC_REMOVE 1060 #define IDS_NUM_REPLACED 8501 #define IDS_EDIT_TEXT_NOT_FOUND 8502 #define IDS_LINE_STATUS_INFO 8503 @@ -366,16 +387,17 @@ #define ID_EDIT_FIND_PREVIOUS 32820 #define ID_SHOWLINEDIFF 32821 #define ID_EDITOR_COPY_PATH 32822 +#define ID_EDIT_COLUMNS 32822 #define ID_EDITOR_COPY_FILENAME 32823 // Next default values for new objects -// +// #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 -#define _APS_NEXT_RESOURCE_VALUE 116 -#define _APS_NEXT_COMMAND_VALUE 32822 -#define _APS_NEXT_CONTROL_VALUE 1050 +#define _APS_NEXT_RESOURCE_VALUE 118 +#define _APS_NEXT_COMMAND_VALUE 32823 +#define _APS_NEXT_CONTROL_VALUE 1061 #define _APS_NEXT_SYMED_VALUE 108 #endif #endif