OSDN Git Service

PATCH: [ 1205724 ] Two-phase directory compare
authorKimmo Varis <kimmov@gmail.com>
Wed, 8 Jun 2005 21:09:29 +0000 (21:09 +0000)
committerKimmo Varis <kimmov@gmail.com>
Wed, 8 Jun 2005 21:09:29 +0000 (21:09 +0000)
12 files changed:
Src/DiffItemList.cpp [new file with mode: 0644]
Src/DiffItemList.h [new file with mode: 0644]
Src/DiffThread.cpp
Src/DirActions.cpp
Src/DirDoc.h
Src/DirScan.cpp
Src/DirScan.h
Src/DirView.cpp
Src/DirView.h
Src/DirViewColHandler.cpp
Src/Merge.dsp
Src/readme.txt

diff --git a/Src/DiffItemList.cpp b/Src/DiffItemList.cpp
new file mode 100644 (file)
index 0000000..2ef0f6e
--- /dev/null
@@ -0,0 +1,110 @@
+/**
+ *  @file DiffItemList.cpp
+ *
+ *  @brief Implementation of DiffItemList
+ */ 
+// RCS ID line follows -- this is updated by CVS
+// $Id$
+
+#include "stdafx.h"
+#include "DiffItemList.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+/**
+ * @brief Add new diffitem to CDiffContext array
+ */
+void DiffItemList::AddDiff(const DIFFITEM & di)
+{
+       m_dirlist.AddTail(const_cast<DIFFITEM &>(di));
+}
+
+/**
+ * @brief Remove diffitem from CDiffContext array
+ * @param diffpos position of item to remove
+ */
+void DiffItemList::RemoveDiff(POSITION diffpos)
+{
+       m_dirlist.RemoveAt(diffpos);
+}
+
+/**
+ * @brief Empty CDiffContext array
+ */
+void DiffItemList::RemoveAll()
+{
+       m_dirlist.RemoveAll();
+}
+
+/**
+ * @brief Get position of first item in CDiffContext array
+ */
+POSITION DiffItemList::GetFirstDiffPosition() const
+{
+       return m_dirlist.GetHeadPosition();
+}
+
+/**
+ * @brief Get position of next item in CDiffContext array
+ * @param diffpos position of current item, updated to next item position
+ * @return Diff Item in current position
+ */
+DIFFITEM DiffItemList::GetNextDiffPosition(POSITION & diffpos) const
+{
+       return m_dirlist.GetNext(diffpos);
+}
+
+/**
+ * @brief Get Diff Item at given position of CDiffContext array
+ * @param diffpos position of item to return
+ */
+DIFFITEM DiffItemList::GetDiffAt(POSITION diffpos) const
+{
+       DIFFITEM di = m_dirlist.GetAt(diffpos);
+       return di;
+}
+
+/**
+ * @brief Get number of items in CDiffContext array
+ */
+int DiffItemList::GetDiffCount() const
+{
+       return m_dirlist.GetCount();
+}
+
+/**
+ * @brief Alter some bit flags of the diffcode.
+ *
+ * Examples:
+ *  SetDiffStatusCode(pos, DIFFCODE::SAME, DIFFCODE::COMPAREFLAGS)
+ *   changes the comparison result to be the same.
+ * 
+ *  SetDiffStatusCode(pos, DIFFCODE::BOTH, DIFFCODE::SIDEFLAG)
+ *   changes the side status to be both (sides).
+ *
+ * SetDiffStatusCode(pos, DIFFCODE::SAME+DIFFCODE::BOTH, DIFFCODE::COMPAREFLAGS+DIFFCODE::SIDEFLAG);
+ *  changes the comparison result to be the same and the side status to be both
+ */
+void DiffItemList::SetDiffStatusCode(POSITION diffpos, UINT diffcode, UINT mask)
+{
+       ASSERT(diffpos);
+       DIFFITEM & di = m_dirlist.GetAt(diffpos);
+       ASSERT(! ((~mask) & diffcode) ); // make sure they only set flags in their mask
+       di.diffcode &= (~mask); // remove current data
+       di.diffcode |= diffcode; // add new data
+}
+
+/**
+ * @brief Update difference counts.
+ */
+void DiffItemList::SetDiffCounts(POSITION diffpos, UINT diffs, UINT ignored)
+{
+       ASSERT(diffpos);
+       DIFFITEM & di = m_dirlist.GetAt(diffpos);
+       di.ndiffs = diffs + ignored; // see StoreDiffResult() in DirScan.cpp
+       di.nsdiffs = diffs;
+}
\ No newline at end of file
diff --git a/Src/DiffItemList.h b/Src/DiffItemList.h
new file mode 100644 (file)
index 0000000..1705c86
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ *  @file DiffItemList.h
+ *
+ *  @brief Declaration of DiffItemList
+ */
+// RCS ID line follows -- this is updated by CVS
+// $Id$
+
+#ifndef _DIFF_ITEM_LIST_H_
+#define _DIFF_ITEM_LIST_H_
+
+#ifndef _DIFF_ITEM_H_
+#include "DiffItem.h"
+#endif
+
+/**
+ * @brief List of DiffItems
+ */
+class DiffItemList
+{
+public:
+       // add & remove differences
+       virtual void AddDiff(const DIFFITEM & di);
+       virtual void RemoveDiff(POSITION diffpos);
+       virtual void RemoveAll();
+
+       // to iterate over all differences on list
+       POSITION GetFirstDiffPosition() const;
+       DIFFITEM GetNextDiffPosition(POSITION & diffpos) const;
+       DIFFITEM GetDiffAt(POSITION diffpos) const;
+
+       int GetDiffCount() const;
+
+       void SetDiffStatusCode(POSITION diffpos, UINT diffcode, UINT mask);
+       void SetDiffCounts(POSITION diffpos, UINT diffs, UINT ignored);
+
+protected:
+       CList<DIFFITEM,DIFFITEM&> m_dirlist; /**< List of diffitems */
+};
+
+#endif // _DIFF_ITEM_LIST_H_
\ No newline at end of file
index aa1176c..864bee8 100644 (file)
@@ -28,6 +28,8 @@
 #include "diff.h"
 #include "DirScan.h"
 #include "Plugins.h"
+#include "DiffItemList.h"
+#include "PathContext.h"
 
 
 // Set this to true in order to single step
@@ -170,6 +172,8 @@ UINT CDiffThread::GetThreadState() const
  */
 UINT DiffThread(LPVOID lpParam)
 {
+       DiffItemList itemList;
+       PathContext paths;
        DiffFuncStruct *myStruct = (DiffFuncStruct *) lpParam;
        HWND hWnd = myStruct->hWindow;
        UINT msgID = myStruct->msgUIUpdate;
@@ -181,8 +185,12 @@ UINT DiffThread(LPVOID lpParam)
        bool casesensitive = false;
        int depth = myStruct->bRecursive ? -1 : 0;
        CString subdir; // blank to start at roots specified in diff context
-       DirScan(subdir, myStruct->context, casesensitive, depth, myStruct->m_pAbortgate);
-       
+
+       paths.SetLeft(myStruct->context->GetNormalizedLeft());
+       paths.SetRight(myStruct->context->GetNormalizedRight());
+       DirScan_GetItems(paths, subdir, &itemList, casesensitive, depth, myStruct->m_pAbortgate);
+       DirScan_CompareItems(itemList, myStruct->context, myStruct->m_pAbortgate);
+
        // Send message to UI to update
        myStruct->nThreadState = THREAD_COMPLETED;
        PostMessage(hWnd, msgID, NULL, NULL);
index 20d6853..87dac3f 100644 (file)
@@ -979,6 +979,32 @@ void CDirView::GetItemFileNames(int sel, CString& strLeft, CString& strRight) co
        }
 }
 
+/**
+ * @brief Get the file names on both sides for specified item.
+ * @note Return empty strings if item is special item.
+ */
+void CDirView::GetItemFileNames(int sel, PathContext * paths) const
+{
+       ASSERT(paths);
+       POSITION diffpos = GetItemKey(sel);
+       if (diffpos == (POSITION)-1)
+       {
+               paths->SetLeft(_T(""));
+               paths->SetRight(_T(""));
+       }
+       else
+       {
+               const DIFFITEM & di = GetDocument()->GetDiffByKey(diffpos);
+               const CString relpath = paths_ConcatPath(di.sSubdir, di.sfilename);
+               const CString & leftpath = GetDocument()->GetLeftBasePath();
+               const CString & rightpath = GetDocument()->GetRightBasePath();
+               CString strLeft = paths_ConcatPath(leftpath, relpath);
+               CString strRight = paths_ConcatPath(rightpath, relpath);
+               paths->SetLeft(strLeft);
+               paths->SetRight(strRight);
+       }
+}
+
 /// Open selected file on specified side
 void CDirView::DoOpen(SIDE_TYPE stype)
 {
index 222536d..672252a 100644 (file)
@@ -118,9 +118,9 @@ public:
 
        BOOL HasDiffs() const { return m_pCtxt != NULL; }
        const CDiffContext & GetDiffContext() const { return *m_pCtxt; }
-       const DIFFITEM & GetDiffByKey(POSITION key) const { return m_pCtxt->GetDiffAt(key); }
-       const CString & GetLeftBasePath() const { return m_pCtxt->GetNormalizedLeft(); }
-       const CString & GetRightBasePath() const { return m_pCtxt->GetNormalizedRight(); }
+       DIFFITEM GetDiffByKey(POSITION key) const { return m_pCtxt->GetDiffAt(key); }
+       CString GetLeftBasePath() const { return m_pCtxt->GetNormalizedLeft(); }
+       CString GetRightBasePath() const { return m_pCtxt->GetNormalizedRight(); }
        void RemoveDiffByKey(POSITION key) { m_pCtxt->RemoveDiff(key); }
 
 protected:
index 263e93b..a713b82 100644 (file)
@@ -17,6 +17,8 @@
 #include "paths.h"
 #include "FileTransform.h"
 #include "codepage.h"
+#include "DiffItemList.h"
+#include "PathContext.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
@@ -42,12 +44,15 @@ struct fentry
 typedef CArray<fentry, fentry&> fentryArray;
 
 // Static functions (ie, functions only used locally)
+void CompareDiffItem(DIFFITEM di, CDiffContext * pCtxt);
 static void LoadFiles(const CString & sDir, fentryArray * dirs, fentryArray * files);
 void LoadAndSortFiles(const CString & sDir, fentryArray * dirs, fentryArray * files, bool casesensitive);
 static void Sort(fentryArray * dirs, bool casesensitive);;
 static int collstr(const CString & s1, const CString & s2, bool casesensitive);
-static void StoreDiffResult(const CString & sDir, const fentry * lent, const fentry *rent, 
-                           int code, CDiffContext *, const DiffFileData * = 0);
+static void StoreDiffResult(DIFFITEM &di, CDiffContext * pCtxt,
+               const DiffFileData * pDiffFileData);
+static void AddToList(CString sDir, const fentry * lent, const fentry * rent,
+       int code, DiffItemList * pList);
 
 /** @brief cmpmth is a typedef for a pointer to a method */
 typedef int (CString::*cmpmth)(LPCTSTR sz) const;
@@ -56,21 +61,22 @@ typedef int (CString::*cmpmth)(LPCTSTR sz) const;
 
 
 /**
- * @brief Compare two directories and store results (via the context)
- *
- * Compare two directories & output all results found via calls to StoreDiffResult
- * base directories to compare are in the CDiffContext
- * and this call is responsible for diff'ing just the subdir specified
- * (ie, if subdir is empty, this is the base call)
- * return 1 normally, return -1 if aborting
+ * @brief Collect file- and directory-names to list.
+ * 
+ * @param [in] paths Root paths of compare
+ * @param [in] subdir Current subdirectory under root paths
+ * @param [in,out] list List where found items are added
+ * @param [in] casesensitive Is filename compare casesensitive?
+ * @param [in] depth Levels of subdirectories to scan, -1 scans all
+ * @param [in] piAbortable Interface allowing compare to be aborted
+ * @return 1 normally, -1 if compare was aborted
  */
-int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive,
-       int depth, IAbortable * piAbortable)
+int DirScan_GetItems(const PathContext &paths, const CString & subdir, DiffItemList *pList,
+               bool casesensitive, int depth, IAbortable * piAbortable)
 {
-       //int (WINAPI *collstr)(LPCTSTR, LPCTSTR) = casesensitive ? lstrcmp : lstrcmpi;
        static const TCHAR backslash[] = _T("\\");
-       CString sLeftDir = pCtxt->GetNormalizedLeft();
-       CString sRightDir = pCtxt->GetNormalizedRight();
+       CString sLeftDir = paths.GetLeft();
+       CString sRightDir = paths.GetRight();
        CString subprefix;
        if (!subdir.IsEmpty())
        {
@@ -83,7 +89,9 @@ int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive,
        LoadAndSortFiles(sLeftDir, &leftDirs, &leftFiles, casesensitive);
        LoadAndSortFiles(sRightDir, &rightDirs, &rightFiles, casesensitive);
 
-       if (piAbortable && piAbortable->ShouldAbort()) return -1;
+       // Allow user to abort scanning
+       if (piAbortable && piAbortable->ShouldAbort())
+               return -1;
 
        // Handle directories
        // i points to current directory in left list (leftDirs)
@@ -100,15 +108,10 @@ int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive,
                        TRACE(_T("Candidate right: rightDirs[j]=%s\n"), (LPCTSTR)rightDirs[j].name);
                if (i<leftDirs.GetSize() && (j==rightDirs.GetSize() || collstr(leftDirs[i].name, rightDirs[j].name, casesensitive)<0))
                {
-                       int nDiffCode = DIFFCODE::LEFT | DIFFCODE::DIR | DIFFCODE::INCLUDED;
-
-                       // Test against filter
-                       CString newsub = subprefix + leftDirs[i].name;
-                       if (!pCtxt->m_piFilterGlobal->includeDir(newsub))
-                               nDiffCode = DIFFCODE::LEFT | DIFFCODE::DIR | DIFFCODE::SKIPPED;
+                       int nDiffCode = DIFFCODE::LEFT | DIFFCODE::DIR;
 
                        // Advance left pointer over left-only entry, and then retest with new pointers
-                       StoreDiffResult(subdir, &leftDirs[i], 0, nDiffCode, pCtxt);
+                       AddToList(subdir, &leftDirs[i], 0, nDiffCode, pList);
                        ++i;
                        continue;
                }
@@ -116,15 +119,8 @@ int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive,
                {
                        int nDiffCode = DIFFCODE::RIGHT | DIFFCODE::DIR;
 
-                       // Test against filter
-                       CString newsub = subprefix + rightDirs[j].name;
-                       if (!pCtxt->m_piFilterGlobal->includeDir(newsub))
-                               nDiffCode = DIFFCODE::RIGHT | DIFFCODE::DIR | DIFFCODE::SKIPPED;
-                       else
-                               nDiffCode = DIFFCODE::RIGHT | DIFFCODE::DIR | DIFFCODE::INCLUDED;
-
                        // Advance right pointer over right-only entry, and then retest with new pointers
-                       StoreDiffResult(subdir, 0, &rightDirs[j], nDiffCode, pCtxt);
+                       AddToList(subdir, 0, &rightDirs[j], nDiffCode, pList);
                        ++j;
                        continue;
                }
@@ -132,27 +128,24 @@ int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive,
                {
                        ASSERT(j<rightDirs.GetSize());
                        CString newsub = subprefix + leftDirs[i].name;
-                       if (!pCtxt->m_piFilterGlobal->includeDir(newsub))
-                       {
-                               int nDiffCode = DIFFCODE::BOTH | DIFFCODE::SKIPPED | DIFFCODE::DIR;
-                               StoreDiffResult(subdir, &leftDirs[i], &rightDirs[j], nDiffCode, pCtxt);
-                       }
-                       else
                        {
                                if (!depth)
                                {
                                        // Non-recursive compare
                                        // We are only interested about list of subdirectories to show - user can open them
                                        // TODO: scan one level deeper to see if directories are identical/different
-                                       int nDiffCode = DIFFCODE::BOTH | DIFFCODE::DIR | DIFFCODE::INCLUDED;
-                                       StoreDiffResult(subdir, &leftDirs[i], &rightDirs[j], nDiffCode, pCtxt);
+                                       int nDiffCode = DIFFCODE::BOTH | DIFFCODE::DIR;
+                                       AddToList(subdir, &leftDirs[i], &rightDirs[j], nDiffCode, pList);
                                }
                                else
                                {
                                        // Recursive compare
                                        // Scan recursively all subdirectories too, we are not adding folders
-                                       if (DirScan(newsub, pCtxt, casesensitive, depth-1, piAbortable) == -1)
+                                       if (DirScan_GetItems(paths, newsub, pList, casesensitive,
+                                                       depth - 1, piAbortable) == -1)
+                                       {
                                                return -1;
+                                       }
                                }
                        }
                        ++i;
@@ -167,64 +160,37 @@ int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive,
        i=0, j=0;
        while (1)
        {
-               if (piAbortable && piAbortable->ShouldAbort()) return -1;
+               if (piAbortable && piAbortable->ShouldAbort())
+                       return -1;
 
                // In debug mode, send current status to debug window
                if (i<leftFiles.GetSize())
                        TRACE(_T("Candidate left: leftFiles[i]=%s\n"), (LPCTSTR)leftFiles[i].name);
                if (j<rightFiles.GetSize())
                        TRACE(_T("Candidate right: rightFiles[j]=%s\n"), (LPCTSTR)rightFiles[j].name);
-               if (i<leftFiles.GetSize() && (j==rightFiles.GetSize() || collstr(leftFiles[i].name, rightFiles[j].name, casesensitive)<0))
+               
+               if (i<leftFiles.GetSize() && (j==rightFiles.GetSize() ||
+                               collstr(leftFiles[i].name, rightFiles[j].name, casesensitive) < 0))
                {
                        // Test against filter
                        CString newsubfile = subprefix + leftFiles[i].name;
                        int nDiffCode = DIFFCODE::LEFT | DIFFCODE::FILE;
-                       if (!pCtxt->m_piFilterGlobal->includeFile(newsubfile))
-                       {
-                               nDiffCode |= DIFFCODE::SKIPPED;
-                               StoreDiffResult(subdir, &leftFiles[i], 0, nDiffCode, pCtxt);
-                       }
-                       else if (pCtxt->m_nCompMethod != CMP_DATE)
                        {
-                               // Compare file to itself to detect encoding
-                               CString filepath = sLeftDir + backslash + leftFiles[i].name;
-                               DiffFileData diffdata;
-                               nDiffCode |= DIFFCODE::INCLUDED;
-                               diffdata.prepAndCompareTwoFiles(pCtxt, filepath, filepath);
-                               StoreDiffResult(subdir, &leftFiles[i], 0, nDiffCode, pCtxt, &diffdata);
-                       }
-                       else
-                       {
-                               nDiffCode |= DIFFCODE::INCLUDED;
-                               StoreDiffResult(subdir, &leftFiles[i], 0, nDiffCode, pCtxt);
+                               AddToList(subdir, &leftFiles[i], 0, nDiffCode, pList);
                        }
+
                        // Advance left pointer over left-only entry, and then retest with new pointers
                        ++i;
                        continue;
                }
-               if (j<rightFiles.GetSize() && (i==leftFiles.GetSize() || collstr(leftFiles[i].name, rightFiles[j].name, casesensitive)>0))
+               if (j<rightFiles.GetSize() && (i==leftFiles.GetSize() ||
+                               collstr(leftFiles[i].name, rightFiles[j].name, casesensitive) > 0))
                {
                        // Test against filter
                        CString newsubfile = subprefix + rightFiles[j].name;
                        int nDiffCode = DIFFCODE::RIGHT | DIFFCODE::FILE;
-                       if (!pCtxt->m_piFilterGlobal->includeFile(newsubfile))
-                       {
-                               nDiffCode |= DIFFCODE::SKIPPED;
-                               StoreDiffResult(subdir, 0, &rightFiles[j], nDiffCode, pCtxt);
-                       }
-                       else if (pCtxt->m_nCompMethod != CMP_DATE)
-                       {
-                               // Compare file to itself to detect encoding
-                               CString filepath = sRightDir + backslash + rightFiles[j].name;
-                               DiffFileData diffdata;
-                               nDiffCode |= DIFFCODE::INCLUDED;
-                               diffdata.prepAndCompareTwoFiles(pCtxt, filepath, filepath);
-                               StoreDiffResult(subdir, 0, &rightFiles[j], nDiffCode, pCtxt, &diffdata);
-                       }
-                       else
                        {
-                               nDiffCode |= DIFFCODE::INCLUDED;
-                               StoreDiffResult(subdir, 0, &rightFiles[j], nDiffCode, pCtxt);
+                               AddToList(subdir, 0, &rightFiles[j], nDiffCode, pList);
                        }
                        // Advance right pointer over right-only entry, and then retest with new pointers
                        ++j;
@@ -235,53 +201,9 @@ int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive,
                        ASSERT(j<rightFiles.GetSize());
                        CString newsubfile = subprefix + leftFiles[i].name;
                        int nDiffCode = DIFFCODE::BOTH | DIFFCODE::FILE;
-                       if (!pCtxt->m_piFilterGlobal->includeFile(newsubfile))
-                       {
-                               nDiffCode |= DIFFCODE::SKIPPED;
-                               StoreDiffResult(subdir, &leftFiles[i], &rightFiles[j], nDiffCode, pCtxt);
-                               ++i;
-                               ++j;
-                               continue;
-                       }
-                       else
-                               nDiffCode |= DIFFCODE::INCLUDED;
 
-                       LPCTSTR leftname = leftFiles[i].name;
-                       LPCTSTR rightname = rightFiles[j].name;
+                       AddToList(subdir, &leftFiles[i], &rightFiles[j], nDiffCode, pList);
 
-                       gLog.Write(_T("Comparing: n0=%s, n1=%s, d0=%s, d1=%s"), 
-                         leftname, rightname, (LPCTSTR)sLeftDir, (LPCTSTR)sRightDir);
-
-                       if (pCtxt->m_nCompMethod == CMP_DATE)
-                       {
-                               // Compare by modified date
-                               __int64 nTimeDiff = leftFiles[i].mtime - rightFiles[j].mtime;
-                               // Compare absolute time difference (lose sign)
-                               nTimeDiff = (nTimeDiff > 0 ? nTimeDiff : -nTimeDiff);
-                               if (pCtxt->m_bIgnoreSmallTimeDiff)
-                               {
-                                       // If option to ignore small timediffs (couple of seconds)
-                                       // is set, decrease absolute difference by allowed diff
-                                       nTimeDiff -= SmallTimeDiff;
-                               }
-                               if (nTimeDiff <= 0)
-                                       nDiffCode |= DIFFCODE::TEXT | DIFFCODE::SAME;
-                               else
-                                       nDiffCode |= DIFFCODE::TEXT | DIFFCODE::DIFF;
-                               // report result back to caller
-                               StoreDiffResult(subdir, &leftFiles[i], &rightFiles[j], nDiffCode, pCtxt);
-                               ++i;
-                               ++j;
-                               continue;
-                       }
-                       // Files to compare
-                       CString filepath1 = sLeftDir + backslash + leftname;
-                       CString filepath2 = sRightDir + backslash + rightname;
-                                       // Really compare
-                       DiffFileData diffdata;
-                       nDiffCode |= diffdata.prepAndCompareTwoFiles(pCtxt, filepath1, filepath2);
-                               // report result back to caller
-                       StoreDiffResult(subdir, &leftFiles[i], &rightFiles[j], nDiffCode, pCtxt, &diffdata);
                        ++i;
                        ++j;
                        continue;
@@ -292,6 +214,144 @@ int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive,
 }
 
 /**
+ * @brief Compare DiffItems in list and add results to compare context.
+ *
+ * @param list [in] List of items to compare
+ * @param pCtxt [in,out] Compare context: contains list where results are added.
+ * @param piAbortable [in] Interface allowing to abort compare
+ * @return 1 if compare finished, -1 if compare was aborted
+ */
+int DirScan_CompareItems(DiffItemList & list, CDiffContext * pCtxt, IAbortable * piAbortable)
+{
+       POSITION pos = list.GetFirstDiffPosition();
+       
+       while (pos != NULL)
+       {
+               if (piAbortable && piAbortable->ShouldAbort())
+                       return -1;
+
+               DIFFITEM di = list.GetNextDiffPosition(pos);
+               CompareDiffItem(di, pCtxt);
+       }
+       return 1;
+}
+
+/**
+ * @brief Compare two diffitems and add results to difflist in context.
+ *
+ * @param [in] di DiffItem to compare
+ * @param [in,out] pCtxt Compare context: contains difflist, encoding info etc.
+ */
+void CompareDiffItem(DIFFITEM di, CDiffContext * pCtxt)
+{
+       CString sLeftDir = pCtxt->GetNormalizedLeft();
+       CString sRightDir = pCtxt->GetNormalizedRight();
+       static const TCHAR backslash[] = _T("\\");
+
+       if (!di.sSubdir.IsEmpty())
+       {
+               sLeftDir += backslash + di.sSubdir;
+               sRightDir += backslash + di.sSubdir;
+       }
+
+       // 1. Test against filters
+       if (di.isDirectory())
+       {
+               if (!pCtxt->m_piFilterGlobal->includeDir(di.sfilename))
+                       di.diffcode |= DIFFCODE::SKIPPED;
+               else
+                       di.diffcode |= DIFFCODE::INCLUDED;
+
+               // Done for directories now
+               StoreDiffResult(di, pCtxt, NULL);
+               return;
+       }
+       else
+       {
+               if (!pCtxt->m_piFilterGlobal->includeFile(di.sfilename))
+                       di.diffcode |= DIFFCODE::SKIPPED;
+               else
+                       di.diffcode |= DIFFCODE::INCLUDED;
+       }
+
+       // Add unique files
+       if (di.isSideLeft())
+       {
+               if (pCtxt->m_nCompMethod != CMP_DATE)
+               {
+                       // Compare file to itself to detect encoding
+                       CString filepath = sRightDir + backslash + di.sfilename;
+                       DiffFileData diffdata;
+                       diffdata.prepAndCompareTwoFiles(pCtxt, filepath, filepath);
+                       StoreDiffResult(di, pCtxt, &diffdata);
+               }
+               else
+               {
+                       StoreDiffResult(di, pCtxt, NULL);
+               }
+               return;
+       }
+       else if (di.isSideRight())
+       {
+               if (pCtxt->m_nCompMethod != CMP_DATE)
+               {
+                       // Compare file to itself to detect encoding
+                       CString filepath = sLeftDir + backslash + di.sfilename;
+                       DiffFileData diffdata;
+                       diffdata.prepAndCompareTwoFiles(pCtxt, filepath, filepath);
+                       StoreDiffResult(di, pCtxt, &diffdata);
+
+               }
+               else
+               {
+                       StoreDiffResult(di, pCtxt, NULL);
+               }
+               return;
+       }
+       // Compare two files
+       else
+       {
+               /*LPCTSTR leftname = leftFiles[i].name;
+               LPCTSTR rightname = rightFiles[j].name;
+
+               gLog.Write(_T("Comparing: n0=%s, n1=%s, d0=%s, d1=%s"), 
+               leftname, rightname, (LPCTSTR)sLeftDir, (LPCTSTR)sRightDir);
+               */
+
+               if (pCtxt->m_nCompMethod == CMP_DATE)
+               {
+                       // Compare by modified date
+                       __int64 nTimeDiff = di.left.mtime - di.right.mtime;
+                       // Remove sign
+                       nTimeDiff = (nTimeDiff > 0 ? nTimeDiff : -nTimeDiff);
+                       if (pCtxt->m_bIgnoreSmallTimeDiff)
+                       {
+                               // If option to ignore small timediffs (couple of seconds)
+                               // is set, decrease absolute difference by allowed diff
+                               nTimeDiff -= SmallTimeDiff;
+                       }
+                       if (nTimeDiff <= 0)
+                               di.diffcode |= DIFFCODE::TEXT | DIFFCODE::SAME;
+                       else
+                               di.diffcode |= DIFFCODE::TEXT | DIFFCODE::DIFF;
+                       // report result back to caller
+                       StoreDiffResult(di, pCtxt, NULL);
+                       return;
+               }
+               // Files to compare
+               CString filepath1 = sLeftDir + backslash + di.sfilename;
+               CString filepath2 = sRightDir + backslash + di.sfilename;
+                               // Really compare
+               DiffFileData diffdata;
+               di.diffcode |= diffdata.prepAndCompareTwoFiles(pCtxt, filepath1, filepath2);
+                       // report result back to caller
+               StoreDiffResult(di, pCtxt, &diffdata);
+       }
+                               
+       return;
+}
+
+/**
  * @brief Load arrays with all directories & files in specified dir
  */
 void LoadAndSortFiles(const CString & sDir, fentryArray * dirs, fentryArray * files, bool casesensitive)
@@ -380,55 +440,71 @@ static int collstr(const CString & s1, const CString & s2, bool casesensitive)
 /**
  * @brief Send one file or directory result back through the diff context
  */
-static void StoreDiffResult(const CString & sDir, const fentry * lent, const fentry * rent,
-       int code, CDiffContext * pCtxt, const DiffFileData * pDiffFileData)
+static void StoreDiffResult(DIFFITEM &di, CDiffContext * pCtxt,
+               const DiffFileData * pDiffFileData)
+{
+       if (pDiffFileData)
+       {
+               di.nsdiffs = pDiffFileData->m_ndiffs - pDiffFileData->m_ntrivialdiffs;
+               di.ndiffs = pDiffFileData->m_ndiffs;
+
+               if (!di.isSideLeft())
+               {
+                       di.right.unicoding = pDiffFileData->m_sFilepath[1].unicoding;
+                       di.right.codepage = pDiffFileData->m_sFilepath[1].codepage;
+               }
+               
+               if (!di.isSideRight())
+               {
+                       di.left.unicoding = pDiffFileData->m_sFilepath[0].unicoding;
+                       di.left.codepage = pDiffFileData->m_sFilepath[0].codepage;
+               }
+       }
+
+       gLog.Write
+       (
+               LOGLEVEL::LCOMPAREDATA, _T("name=<%s>, leftdir=<%s>, rightdir=<%s>, code=%d"),
+               (LPCTSTR)di.sfilename, (LPCTSTR)_T("di.left.spath"), (LPCTSTR)_T("di.right.spath"), di.diffcode
+       );
+       pCtxt->AddDiff(di);
+}
+
+/**
+ * @brief Add one compare item to list.
+ */
+static void AddToList(CString sDir, const fentry * lent, const fentry * rent,
+       int code, DiffItemList * pList)
 {
        // We must store both paths - we cannot get paths later
        // and we need unique item paths for example when items
        // change to identical
 
        DIFFITEM di;
-       di.sSubdir = sDir;
+       di.left.unicoding = 0;
+       di.left.codepage = 0;
+       di.right.unicoding = 0;
+       di.right.codepage = 0;
 
-       if (pDiffFileData)
-       {
-               di.nsdiffs = pDiffFileData->m_ndiffs - pDiffFileData->m_ntrivialdiffs;
-               di.ndiffs = pDiffFileData->m_ndiffs;
-               di.left.unicoding = pDiffFileData->m_sFilepath[0].unicoding;
-               di.left.codepage = pDiffFileData->m_sFilepath[0].codepage;
-               di.right.unicoding = pDiffFileData->m_sFilepath[1].unicoding;
-               di.right.codepage = pDiffFileData->m_sFilepath[1].codepage;
-       }
+       if (!sDir.IsEmpty())
+               di.sSubdir = sDir;
 
        if (lent)
        {
                di.sfilename = lent->name;
-               //di.left.spath = pCtxt->m_strNormalizedLeft; //paths_ConcatPath(pCtxt->m_strNormalizedLeft, sDir);
                di.left.mtime = lent->mtime;
                di.left.ctime = lent->ctime;
                di.left.size = lent->size;
                di.left.flags.attributes = lent->attrs;
        }
-       else
-       {
-               di.left.unicoding = 0;
-               di.left.codepage = 0;
-       }
 
        if (rent)
        {
                di.sfilename = rent->name;
-               //di.right.spath = pCtxt->m_strNormalizedRight; //paths_ConcatPath(pCtxt->m_strNormalizedRight, sDir);
                di.right.mtime = rent->mtime;
                di.right.ctime = rent->ctime;
                di.right.size = rent->size;
                di.right.flags.attributes = rent->attrs;
        }
-       else
-       {
-               di.right.unicoding = 0;
-               di.right.codepage = 0;
-       }
 
        di.diffcode = code;
 
@@ -437,10 +513,9 @@ static void StoreDiffResult(const CString & sDir, const fentry * lent, const fen
                LOGLEVEL::LCOMPAREDATA, _T("name=<%s>, leftdir=<%s>, rightdir=<%s>, code=%d"),
                (LPCTSTR)di.sfilename, (LPCTSTR)_T("di.left.spath"), (LPCTSTR)_T("di.right.spath"), code
        );
-       pCtxt->AddDiff(di);
+       pList->AddDiff(di);
 }
 
-
 void // static
 DirScan_InitializeDefaultCodepage()
 {
index aa288aa..a9294ae 100644 (file)
@@ -10,6 +10,8 @@
 #define DirScan_h_included
 
 class CDiffContext;
+class DiffItemList;
+class PathContext;
 
 /** @brief callback to check if dirscan needs to abort */
 class IAbortable
@@ -18,8 +20,10 @@ public:
        virtual bool ShouldAbort() = 0;
 };
 
-int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive,
-       int depth, IAbortable * piAbortable);
+int DirScan_GetItems(const PathContext &paths, const CString & subdir, DiffItemList * pLst,
+               bool casesensitive, int depth, IAbortable * piAbortable);
+
+int DirScan_CompareItems(DiffItemList & list, CDiffContext * pCtxt, IAbortable * piAbortable);
 
 void DirScan_InitializeDefaultCodepage();
 
index 27b88cb..0ef80a8 100644 (file)
@@ -835,6 +835,7 @@ void CDirView::OpenParentDirectory()
 void CDirView::OpenSelection(PackingInfo * infoUnpacker /*= NULL*/)
 {
        int sel = -1;
+       CDirDoc * pDoc = GetDocument();
 
        while ((sel = m_pList->GetNextItem(sel, LVNI_SELECTED)) != -1)
        {
@@ -848,11 +849,10 @@ void CDirView::OpenSelection(PackingInfo * infoUnpacker /*= NULL*/)
                        break;
                }
 
-               const DIFFITEM & di = GetDocument()->GetDiffByKey((POSITION)diffpos);
+               DIFFITEM di = pDoc->GetDiffByKey((POSITION)diffpos);
 
                if (di.isDirectory() && (di.isSideLeft() == di.isSideRight()))
                {
-                       CDirDoc * pDoc = GetDocument();
                        if (pDoc->GetRecursive())
                                AfxMessageBox(IDS_FILEISDIR, MB_ICONINFORMATION);
                        else
@@ -860,8 +860,9 @@ void CDirView::OpenSelection(PackingInfo * infoUnpacker /*= NULL*/)
                                // Open subfolders if non-recursive compare
                                // Don't add folders to MRU
                                CString left, right;
-                               GetItemFileNames(sel, left, right);
-                               mf->DoFileOpen(left, right, FFILEOPEN_NOMRU, FFILEOPEN_NOMRU, FALSE, pDoc);
+                               PathContext paths;
+                               GetItemFileNames(sel, &paths);
+                               mf->DoFileOpen(paths.GetLeft(), paths.GetRight(), FFILEOPEN_NOMRU, FFILEOPEN_NOMRU, FALSE, pDoc);
                        }
                        break;
                }
@@ -874,17 +875,17 @@ void CDirView::OpenSelection(PackingInfo * infoUnpacker /*= NULL*/)
                        // Close open documents first (ask to save unsaved data)
                        if (!mf->m_options.GetBool(OPT_MULTIDOC_MERGEDOCS))
                        {
-                               if (!GetDocument()->CloseMergeDocs())
+                               if (!pDoc->CloseMergeDocs())
                                        return;
                        }
-                       
+
                        // Open identical and different files
-                       CString left, right;
-                       BOOL bLeftRO = GetDocument()->GetReadOnly(TRUE);
-                       BOOL bRightRO = GetDocument()->GetReadOnly(FALSE);
+                       BOOL bLeftRO = pDoc->GetReadOnly(TRUE);
+                       BOOL bRightRO = pDoc->GetReadOnly(FALSE);
 
-                       GetItemFileNames(sel, left, right);
-                       mf->ShowMergeDoc(GetDocument(), left, right,
+                       PathContext paths;
+                       GetItemFileNames(sel, &paths);
+                       mf->ShowMergeDoc(pDoc, paths.GetLeft(), paths.GetRight(),
                                bLeftRO, bRightRO,
                                di.left.codepage, di.right.codepage,
                                infoUnpacker);
@@ -1145,7 +1146,7 @@ void CDirView::SetItemKey(int idx, POSITION diffpos)
 /**
  * Given index in list control, get its associated DIFFITEM data
  */
-const DIFFITEM &CDirView::GetDiffItem(int sel)
+DIFFITEM CDirView::GetDiffItem(int sel)
 {
        POSITION diffpos = GetItemKey(sel);
        
@@ -1334,7 +1335,7 @@ int CDirView::GetFirstSelectedInd()
        return di;
 }*/
 
-const DIFFITEM &CDirView::GetItemAt(int ind)
+DIFFITEM CDirView::GetItemAt(int ind)
 {
        if (ind != -1)
        {       
@@ -1342,7 +1343,7 @@ const DIFFITEM &CDirView::GetItemAt(int ind)
        }
        // 26.01.2004 jtuc: seems to be nerver reached...
        ASSERT(FALSE);
-       static const DIFFITEM di;
+       DIFFITEM di;
        return di;
 }
 
index 1b627e0..6317f40 100644 (file)
@@ -44,6 +44,7 @@ class CDirDoc;
 class CDirFrame;
 
 class PackingInfo;
+class PathContext;
 
 namespace varprop { struct VariantValue; }
 
@@ -85,7 +86,7 @@ public:
        UINT GetSelectedCount() const;
        int GetFirstSelectedInd();
        //DIFFITEM GetNextSelectedInd(int &ind);
-       const DIFFITEM &GetItemAt(int ind);
+       DIFFITEM GetItemAt(int ind);
        int AddSpecialItems();
        BOOL AllowUpwardDirectory(CString leftPath, CString rightPath);
        void AddParentFolderItem(BOOL bEnable);
@@ -122,6 +123,7 @@ private:
        BOOL GetSelectedFileNames(CString& strLeft, CString& strRight) const;
        CString GetSelectedFileName(SIDE_TYPE stype) const;
        void GetItemFileNames(int sel, CString& strLeft, CString& strRight) const;
+       void GetItemFileNames(int sel, PathContext * paths) const;
        BOOL IsItemLeftOnly(int code);
        BOOL IsItemRightOnly(int code);
        BOOL IsItemCopyableToLeft(const DIFFITEM & di);
@@ -331,7 +333,7 @@ private:
        void DoUpdateCtxtDirMoveLeftTo(CCmdUI* pCmdUI);
        void DoUpdateCtxtDirMoveRightTo(CCmdUI* pCmdUI);
        POSITION GetItemKeyFromData(DWORD dw) const;
-       const DIFFITEM &GetDiffItem(int sel);
+       DIFFITEM GetDiffItem(int sel);
        int GetSingleSelectedItem() const;
        bool IsItemNavigableDiff(const DIFFITEM & di) const;
        void MoveSelection(int currentInd, int i, int selCount);
index 3b2c444..2c8590b 100644 (file)
@@ -137,8 +137,8 @@ int CALLBACK CDirView::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParam
        
        POSITION diffposl = pView->GetItemKeyFromData(lParam1);
        POSITION diffposr = pView->GetItemKeyFromData(lParam2);
-       const DIFFITEM &ldi = ctxt.GetDiffAt(diffposl);
-       const DIFFITEM &rdi = ctxt.GetDiffAt(diffposr);
+       const DIFFITEM ldi = ctxt.GetDiffAt(diffposl);
+       const DIFFITEM rdi = ctxt.GetDiffAt(diffposr);
 
        // compare 'left' and 'right' parameters as appropriate
        int sortCol = mf->m_options.GetInt(OPT_DIRVIEW_SORT_COLUMN);
index c1da360..d9d3972 100644 (file)
@@ -245,6 +245,14 @@ SOURCE=.\DiffFileInfo.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\DiffItem.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\DiffItemList.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\DiffList.cpp
 # End Source File
 # Begin Source File
@@ -913,6 +921,14 @@ SOURCE=.\DiffFileInfo.h
 # End Source File
 # Begin Source File
 
+SOURCE=.\DiffItem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\DiffItemList.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\DiffList.h
 # End Source File
 # Begin Source File
index c90cad4..2c5552b 100644 (file)
@@ -1,6 +1,11 @@
 2005-06-08 Kimmo
  PATCH: [ 1213649 ] Add copyconstructor to (Diff)FileInfo
   Src: DiffFileInfo.cpp DiffFileInfo.h FileInfo.cpp FileInfo.h
+ PATCH: [ 1205724 ] Two-phase directory compare
+  Src: 7zCommon.cpp 7zCommon.h DiffContext.cpp DiffContext.h DiffThread.cpp
+   DirActions.cpp DirDoc.h DirScan.cpp DirScan.h DirView.cpp DirView.h
+   DirViewColHandler.cpp Merge.dsp 
+  Src new files: DiffItem.cpp DiffItem.h DiffItemList.cpp DiffItemList.h
 
 2005-06-08 Perry
  PATCH: [ 1213238 ] noninteractive switch