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
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)
#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
{
: m_pOptions(NULL)
, m_pFilterList(NULL)
, m_inf(NULL)
+ , m_FilterCommentsManager(new ::FilterCommentsManager)
+ , m_pDiffWrapper(new ::CDiffWrapper)
{
}
*/
DiffUtils::~DiffUtils()
{
+ delete m_FilterCommentsManager;
ClearCompareOptions();
ClearFilterList();
}
if (m_pOptions != NULL)
ClearCompareOptions();
- m_pOptions = new DiffutilsOptions(options);
+ m_pOptions = new DiffutilsOptions((DiffutilsOptions&)options);
if (m_pOptions == NULL)
return false;
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. */
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. */
class DiffutilsOptions;
struct file_data;
struct FileTextStats;
+class FilterCommentsManager;
+class CDiffWrapper;
namespace CompareEngines
{
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;
};
}\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
public:
DiffutilsOptions();
DiffutilsOptions(const CompareOptions& options);
+ DiffutilsOptions(const DiffutilsOptions& options);
void SetToDiffUtils();
void GetAsDiffOptions(DIFFOPTIONS &options);
virtual void SetFromDiffOptions(const DIFFOPTIONS & options);
else
return FALSE;
+ delete m_pCompareOptions;
+ m_pCompareOptions = NULL;
+
m_pCompareOptions = GetCompareOptions(m_nCompMethod);
if (m_pCompareOptions == NULL)
{
#include "StdAfx.h"
#include <sys/types.h>
#include <sys/stat.h>
+#include <algorithm>
#include <string>
#include <map>
#include <shlwapi.h>
* @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);
* @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,
}
/**
+ * @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
@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.
@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)
{
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;
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,