OSDN Git Service

PATCH: #3046938 Improvement in Folder comparison
authorKimmo Varis <kimmov@gmail.com>
Tue, 31 Aug 2010 18:03:24 +0000 (18:03 +0000)
committerKimmo Varis <kimmov@gmail.com>
Tue, 31 Aug 2010 18:03:24 +0000 (18:03 +0000)
 Submitted by Saitaman

Docs/Users/ChangeLog.txt
Src/CompareEngines/DiffUtils.cpp
Src/CompareEngines/DiffUtils.h
Src/CompareOptions.cpp
Src/CompareOptions.h
Src/DiffContext.cpp
Src/DiffWrapper.cpp
Src/DiffWrapper.h

index 25f354f..c4b445d 100644 (file)
@@ -7,6 +7,7 @@ WinMerge 2.13.14
   Update to PCRE 8.10 (r7210)
   Update SCEW to 1.1.2 (r7212)
   In-line difference highlighting improvement (#3022014)
+  Make comment filtering work for folder compare (#3046938)
   Recognize .ascx files as ASP files (#3042393)
   Comment filtering improvement (#3034083)
   Bugfix: Untranslated string ("Merge.rc:nnnn") was displayed 
@@ -14,6 +15,7 @@ WinMerge 2.13.14
   Bugfix: Options dialog didn't update when importing settings
     from .ini file. (#2794137)
   Bugfix: New fix for the bug #2210403 (#2929005)
+  Bugfix: Take changed compareoptions into use in folder compare (#3046938)
   Translation updates:
   - French (#3025202)
 
index e14790d..9711ea7 100644 (file)
@@ -8,12 +8,16 @@
 
 
 #include "StdAfx.h"
+#include <map>
 #include "CompareOptions.h"
 #include "FilterList.h"
 #include "DiffContext.h"
 #include "DIFF.H"
 #include "DiffUtils.h"
 #include "coretools.h"
+#include "DiffList.h"
+#include "DiffWrapper.h"
+#include "FilterCommentsManager.h"
 
 namespace CompareEngines
 {
@@ -26,6 +30,8 @@ DiffUtils::DiffUtils()
                : m_pOptions(NULL)
                , m_pFilterList(NULL)
                , m_inf(NULL)
+               , m_FilterCommentsManager(new ::FilterCommentsManager)
+               , m_pDiffWrapper(new ::CDiffWrapper)
 {
 }
 
@@ -34,6 +40,7 @@ DiffUtils::DiffUtils()
  */
 DiffUtils::~DiffUtils()
 {
+       delete m_FilterCommentsManager;
        ClearCompareOptions();
        ClearFilterList();
 }
@@ -48,7 +55,7 @@ bool DiffUtils::SetCompareOptions(const CompareOptions & options)
        if (m_pOptions != NULL)
                ClearCompareOptions();
 
-       m_pOptions = new DiffutilsOptions(options);
+       m_pOptions = new DiffutilsOptions((DiffutilsOptions&)options);
        if (m_pOptions == NULL)
                return false;
 
@@ -118,11 +125,21 @@ int DiffUtils::diffutils_compare_files()
        m_ndiffs = 0;
        m_ntrivialdiffs = 0;
 
-       if (script && m_pFilterList && m_pFilterList->HasRegExps())
+       if (script)
        {
                struct change *next = script;
                struct change *thisob = 0, *end = 0;
 
+               String asLwrCaseExt;
+               String LowerCaseExt = CA2T(m_inf[0].name);
+               int PosOfDot = LowerCaseExt.rfind('.');
+               if (PosOfDot != -1)
+               {
+                       LowerCaseExt.erase(0, PosOfDot + 1);
+                       CharLower(&*LowerCaseExt.begin());
+                       asLwrCaseExt = LowerCaseExt;
+               }
+
                while (next)
                {
                        /* Find a set of changes that belong together.  */
@@ -152,15 +169,41 @@ int DiffUtils::diffutils_compare_files()
                                        int QtyLinesLeft = (trans_b0 - trans_a0);
                                        int QtyLinesRight = (trans_b1 - trans_a1);
 
+
+                                       if(m_pOptions->m_filterCommentsLines || m_pOptions->m_bIgnoreBlankLines || m_pOptions->m_bIgnoreCase)
+                                       {
+                                               OP_TYPE op = OP_NONE;
+                                               if (!deletes && !inserts)
+                                                       op = OP_TRIVIAL;
+                                               else
+                                                       op = OP_DIFF;
+
+                                               DIFFOPTIONS options = {0};
+                                               options.nIgnoreWhitespace = m_pOptions->m_ignoreWhitespace;
+                                               options.bIgnoreBlankLines = m_pOptions->m_bIgnoreBlankLines;
+                                               options.bFilterCommentsLines = m_pOptions->m_filterCommentsLines;
+                                               options.bIgnoreCase = m_pOptions->m_bIgnoreCase;
+                                               options.bIgnoreEol = m_pOptions->m_bIgnoreEOLDifference;
+                                               m_pDiffWrapper->SetOptions(&options);
+                                               m_pDiffWrapper->PostFilter(thisob->line0, QtyLinesLeft+1, thisob->line1, QtyLinesRight+1, op, *m_FilterCommentsManager, asLwrCaseExt.c_str());
+                                               if(op == OP_TRIVIAL)
+                                               {
+                                                       thisob->trivial = 1;
+                                               }
+                                       }
+
                                        // Match lines against regular expression filters
                                        // Our strategy is that every line in both sides must
                                        // match regexp before we mark difference as ignored.
-                                       bool match2 = false;
-                                       bool match1 = RegExpFilter(thisob->line0, thisob->line0 + QtyLinesLeft, 0);
-                                       if (match1)
-                                               match2 = RegExpFilter(thisob->line1, thisob->line1 + QtyLinesRight, 1);
-                                       if (match1 && match2)
-                                               thisob->trivial = 1;
+                                       if(m_pFilterList && m_pFilterList->HasRegExps())
+                                       {
+                                               bool match2 = false;
+                                               bool match1 = RegExpFilter(thisob->line0, thisob->line0 + QtyLinesLeft, 0);
+                                               if (match1)
+                                                       match2 = RegExpFilter(thisob->line1, thisob->line1 + QtyLinesRight, 1);
+                                               if (match1 && match2)
+                                                       thisob->trivial = 1;
+                                       }
 
                                }
                                /* Reconnect the script so it will all be freed properly.  */
index 6f5f096..4783e01 100644 (file)
@@ -15,6 +15,8 @@ class FilterList;
 class DiffutilsOptions;
 struct file_data;
 struct FileTextStats;
+class FilterCommentsManager;
+class CDiffWrapper;
 
 namespace CompareEngines
 {
@@ -54,6 +56,8 @@ private:
        int m_ndiffs; /**< Real diffs found. */
        int m_ntrivialdiffs; /**< Ignored diffs found. */
        int m_codepage; /**< Codepage used in line filter */
+       FilterCommentsManager * m_FilterCommentsManager; /**< Comments filtering manager */
+       CDiffWrapper *m_pDiffWrapper;
 };
 
 
index 8cd466e..46696d8 100644 (file)
@@ -37,6 +37,23 @@ CompareOptions::CompareOptions(const CompareOptions & options)
 }\r
 \r
 /**\r
+ * @brief Sets options from DiffutilsOptions structure.\r
+ * @param [in] options Diffutils options.\r
+ */\r
+DiffutilsOptions::DiffutilsOptions(const DiffutilsOptions& options)\r
+: CompareOptions(options)\r
+{\r
+       m_bIgnoreBlankLines = options.m_bIgnoreBlankLines;\r
+       m_bIgnoreCase = options.m_bIgnoreCase;\r
+       m_bIgnoreEOLDifference = options.m_bIgnoreEOLDifference;\r
+       m_contextLines = options.m_contextLines;\r
+       m_filterCommentsLines = options.m_filterCommentsLines;\r
+       m_ignoreWhitespace = options.m_ignoreWhitespace;\r
+       m_outputStyle = options.m_outputStyle;\r
+       m_bIgnoreEOLDifference = options.m_bIgnoreEOLDifference;\r
+}\r
+\r
+/**\r
  * @brief Sets options from DIFFOPTIONS structure.\r
  * @param [in] options Diffutils options.\r
  */\r
index 43ade36..35b4fdd 100644 (file)
@@ -104,6 +104,7 @@ class DiffutilsOptions : public CompareOptions
 public:
        DiffutilsOptions();
        DiffutilsOptions(const CompareOptions& options);
+       DiffutilsOptions(const DiffutilsOptions& options);
        void SetToDiffUtils();
        void GetAsDiffOptions(DIFFOPTIONS &options);
        virtual void SetFromDiffOptions(const DIFFOPTIONS & options);
index 4713916..00d561a 100644 (file)
@@ -230,6 +230,9 @@ BOOL CDiffContext::CreateCompareOptions(const DIFFOPTIONS & options)
        else
                return FALSE;
 
+       delete m_pCompareOptions;
+       m_pCompareOptions = NULL;
+
        m_pCompareOptions = GetCompareOptions(m_nCompMethod);
        if (m_pCompareOptions == NULL)
        {
index 2bae550..1de74df 100644 (file)
@@ -27,6 +27,7 @@
 #include "StdAfx.h"
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <algorithm>
 #include <string>
 #include <map>
 #include <shlwapi.h>
@@ -266,7 +267,7 @@ void CDiffWrapper::SetDetectMovedBlocks(bool bDetectMovedBlocks)
  * @param [in] filtercommentsset       - For future use to determine trivial bytes
  * @return Returns true if all characters are trivial
  */
-static bool IsTrivialBytes(const char* Start, const char* End,
+bool CDiffWrapper::IsTrivialBytes(const char* Start, const char* End,
        const FilterCommentsSet& filtercommentsset)
 {
        std::string testdata(Start, End);
@@ -284,7 +285,7 @@ static bool IsTrivialBytes(const char* Start, const char* End,
  * @param [in] filtercommentsset       - Comment marker set used to indicate comment blocks.
  * @return Returns true if entire line is trivial
  */
-static bool IsTrivialLine(const std::string &Line, 
+bool CDiffWrapper::IsTrivialLine(const std::string &Line, 
                                   const char * StartOfComment, 
                                   const char * EndOfComment,   
                                   const char * InLineComment,  
@@ -351,6 +352,26 @@ static const char *FindCommentMarker(const char *target, const char *marker)
 }
 
 /**
+ * @brief Replace spaces in a string
+ * @param [in] str - String to search
+ * @param [in] rep - String to replace
+ */
+static void ReplaceSpaces(std::string & str, const char *rep)
+{
+       std::string::size_type pos = 0;
+       size_t replen = strlen(rep);
+       while ((pos = str.find_first_of(" \t", pos)) != std::string::npos)
+       {
+               std::string::size_type posend = str.find_first_not_of(" \t", pos);
+               if (posend != std::string::npos)
+                       str.replace(pos, posend - pos, rep);
+               else
+                       str.replace(pos, 1, rep);
+               pos += replen;
+       }
+}
+
+/**
        @brief Performs post-filtering, by setting comment blocks to trivial
        @param [in]  StartPos                   - First line number to read
        @param [in]  EndPos                             - The line number PASS the last line number to read
@@ -362,9 +383,8 @@ static const char *FindCommentMarker(const char *target, const char *marker)
        @return         Always returns true in reverse direction.
                                In forward direction, returns false if none trivial data is found within QtyLinesInBlock
 */
-static bool PostFilter(int StartPos, int EndPos, int Direction,
-       int QtyLinesInBlock, OP_TYPE &Op, int FileNo,
-       const FilterCommentsSet& filtercommentsset)
+bool CDiffWrapper::PostFilter(int StartPos, int EndPos, int Direction,
+                                                         int QtyLinesInBlock, OP_TYPE &Op, int FileNo, const FilterCommentsSet& filtercommentsset)
 {
        const char* EolIndicators = "\r\n"; //List of characters used as EOL
        if (Op == OP_TRIVIAL) //If already set to trivial, then exit.
@@ -488,7 +508,7 @@ static bool PostFilter(int StartPos, int EndPos, int Direction,
 @param [in]  filtercommentsset - Comment marker set used to indicate comment blocks.
 @param [in]  FileNameExt                       - The file name extension.  Needs to be lower case string ("cpp", "java", "c")
 */
-static void PostFilter(int LineNumberLeft, int QtyLinesLeft, int LineNumberRight,
+void CDiffWrapper::PostFilter(int LineNumberLeft, int QtyLinesLeft, int LineNumberRight,
        int QtyLinesRight, OP_TYPE &Op, const FilterCommentsManager &filtercommentsmanager,
        const TCHAR *FileNameExt)
 {
@@ -600,6 +620,26 @@ static void PostFilter(int LineNumberLeft, int QtyLinesLeft, int LineNumberRight
                                        LineDataRight.erase(CommentStrRight - LineDataRight.c_str());
                        }
 
+                       if (m_options.m_ignoreWhitespace == WHITESPACE_IGNORE_ALL)
+                       {
+                               //Ignore character case
+                               ReplaceSpaces(LineDataLeft, "");
+                               ReplaceSpaces(LineDataRight, "");
+                       }
+                       else if (m_options.m_ignoreWhitespace == WHITESPACE_IGNORE_CHANGE)
+                       {
+                               //Ignore change in whitespace char count
+                               ReplaceSpaces(LineDataLeft, " ");
+                               ReplaceSpaces(LineDataRight, " ");
+                       }
+
+                       if (m_options.m_bIgnoreCase)
+                       {
+                               //ignore case
+                               std::transform(LineDataLeft.begin(),  LineDataLeft.end(),  LineDataLeft.begin(),  ::toupper);
+                               std::transform(LineDataRight.begin(), LineDataRight.end(), LineDataRight.begin(), ::toupper);
+                       }
+
                        if (LineDataLeft != LineDataRight)
                        {       
                                return;
index 6804a78..f897492 100644 (file)
@@ -170,7 +170,17 @@ public:
        void SetCompareFiles(const String &OriginalFile1, const String &OriginalFile2);
        void SetFilterList(LPCTSTR filterStr);
        void EnablePlugins(bool enable);
-
+       bool IsTrivialBytes(const char* Start, const char* End,
+               const FilterCommentsSet& filtercommentsset);
+       bool IsTrivialLine(const std::string &Line, const char * StartOfComment,
+          const char * EndOfComment, const char * InLineComment,
+          const FilterCommentsSet& filtercommentsset);
+       bool PostFilter(int StartPos, int EndPos, int Direction,
+               int QtyLinesInBlock, OP_TYPE &Op, int FileNo,
+               const FilterCommentsSet& filtercommentsset);
+       void PostFilter(int LineNumberLeft, int QtyLinesLeft, int LineNumberRight,
+               int QtyLinesRight, OP_TYPE &Op, const FilterCommentsManager &filtercommentsmanager,
+               const TCHAR *FileNameExt);
 protected:
        String FormatSwitchString();
        BOOL Diff2Files(struct change ** diffs, DiffFileData *diffData,