X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=Src%2FDiffWrapper.cpp;h=300bdbfb8392d2f597d8b3dbe521dcb522937437;hb=5a478c4115f3ffeb35fb51df893912409c793bb0;hp=48e9b8f59733177e15e483f17cde3c3bafed1912;hpb=107108eb9323f116147f2490c898b6d15837a4ee;p=winmerge-jp%2Fwinmerge-jp.git diff --git a/Src/DiffWrapper.cpp b/Src/DiffWrapper.cpp index 48e9b8f59..300bdbfb8 100644 --- a/Src/DiffWrapper.cpp +++ b/Src/DiffWrapper.cpp @@ -1,19 +1,4 @@ -///////////////////////////////////////////////////////////////////////////// -// License (GPLv2+): -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or (at -// your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -///////////////////////////////////////////////////////////////////////////// +// SPDX-License-Identifier: GPL-2.0-or-later /** * @file DiffWrapper.cpp * @@ -22,6 +7,7 @@ * @date Created: 2003-08-22 */ +#include "pch.h" #define NOMINMAX #include "DiffWrapper.h" #include @@ -46,19 +32,22 @@ #include "FilterList.h" #include "diff.h" #include "Diff3.h" +#include "xdiff_gnudiff_compat.h" #include "FileTransform.h" #include "paths.h" #include "CompareOptions.h" #include "FileTextStats.h" #include "FolderCmp.h" -#include "FilterCommentsManager.h" #include "Environment.h" #include "PatchHTML.h" #include "UnicodeString.h" #include "unicoder.h" #include "TFile.h" #include "Exceptions.h" +#include "parsers/crystallineparser.h" +#include "SyntaxColors.h" #include "MergeApp.h" +#include "SubstitutionList.h" using Poco::Debugger; using Poco::format; @@ -72,20 +61,20 @@ static void CopyDiffutilTextStats(file_data *inf, DiffFileData * diffData); /** * @brief Default constructor. - * Initializes members and creates new FilterCommentsManager. + * Initializes members. */ CDiffWrapper::CDiffWrapper() -: m_pFilterCommentsManager(nullptr) +: m_pFilterCommentsDef(nullptr) , m_bCreatePatchFile(false) , m_bUseDiffList(false) , m_bAddCmdLine(true) , m_bAppendFiles(false) , m_nDiffs(0) -, m_codepage(GetACP()) , m_infoPrediffer(nullptr) , m_pDiffList(nullptr) , m_bPathsAreTemp(false) , m_pFilterList(nullptr) +, m_pSubstitutionList{nullptr} , m_bPluginsEnabled(false) , m_status() { @@ -101,15 +90,6 @@ CDiffWrapper::~CDiffWrapper() } /** - * @brief Set plugins enabled/disabled. - * @param [in] enable if true plugins are enabled. - */ -void CDiffWrapper::EnablePlugins(bool enable) -{ - m_bPluginsEnabled = enable; -} - -/** * @brief Enables/disables patch-file creation and sets filename. * This function enables or disables patch file creation. When * @p filename is empty, patch files are disabled. @@ -133,16 +113,16 @@ void CDiffWrapper::SetCreatePatchFile(const String &filename) /** * @brief Enables/disabled DiffList creation ands sets DiffList. * This function enables or disables DiffList creation. When - * @p diffList is NULL difflist is not created. When valid DiffList - * pointer is given, compare results are stored into it. + * @p diffList is `nullptr`, a difflist was not created. When valid + * DiffList pointer is given, compare results are stored into it. * @param [in] diffList Pointer to DiffList getting compare results. */ void CDiffWrapper::SetCreateDiffList(DiffList *diffList) { - if (diffList == NULL) + if (diffList == nullptr) { m_bUseDiffList = false; - m_pDiffList = NULL; + m_pDiffList = nullptr; } else { @@ -177,26 +157,14 @@ void CDiffWrapper::SetOptions(const DIFFOPTIONS *options) m_options.SetFromDiffOptions(*options); } -/** - * @brief Set text tested to find the prediffer automatically. - * Most probably a concatenated string of both filenames. - */ -void CDiffWrapper::SetTextForAutomaticPrediff(const String &text) -{ - m_sToFindPrediffer = text; -} -void CDiffWrapper::SetPrediffer(const PrediffingInfo * prediffer /*=NULL*/) +void CDiffWrapper::SetPrediffer(const PrediffingInfo * prediffer /*= nullptr*/) { // all flags are set correctly during the construction m_infoPrediffer.reset(new PrediffingInfo); - if (prediffer) + if (prediffer != nullptr) *m_infoPrediffer = *prediffer; } -void CDiffWrapper::GetPrediffer(PrediffingInfo * prediffer) const -{ - *prediffer = *m_infoPrediffer; -} /** * @brief Set options used for patch-file creation. @@ -237,7 +205,7 @@ void CDiffWrapper::SetDetectMovedBlocks(bool bDetectMovedBlocks) { if (bDetectMovedBlocks) { - if (m_pMovedLines[0] == NULL) + if (m_pMovedLines[0] == nullptr) { m_pMovedLines[0].reset(new MovedLines); m_pMovedLines[1].reset(new MovedLines); @@ -252,95 +220,74 @@ void CDiffWrapper::SetDetectMovedBlocks(bool bDetectMovedBlocks) } } -/** - * @brief Test for trivial only characters in string - * @param [in] Start - Start position in string - * @param [in] End - One character pass the end position of the string - * @param [in] filtercommentsset - For future use to determine trivial bytes - * @return Returns true if all characters are trivial - */ -bool CDiffWrapper::IsTrivialBytes(const char* Start, const char* End, - const FilterCommentsSet& filtercommentsset) const -{ - std::string testdata(Start, End); - //@TODO: Need to replace the following trivial string with a user specified string - size_t pos = testdata.find_first_not_of(" \t\r\n"); - return (pos == std::string::npos); -} - -/** - * @brief Test for a line of trivial data - * @param [in] Line - String to test for - * @param [in] StartOfComment - - * @param [in] EndOfComment - - * @param [in] InLineComment - - * @param [in] filtercommentsset - Comment marker set used to indicate comment blocks. - * @return Returns true if entire line is trivial - */ -bool CDiffWrapper::IsTrivialLine(const std::string &Line, - const char * StartOfComment, - const char * EndOfComment, - const char * InLineComment, - const FilterCommentsSet& filtercommentsset) const +static String convertToTString(const char* start, const char* end) { - //Do easy test first - if ((!StartOfComment || !EndOfComment) && !InLineComment) - return false;//In no Start and End pair, and no single in-line set, then it's not trivial - - if (StartOfComment == Line.c_str() && - static_cast((EndOfComment + filtercommentsset.EndMarker.size()) - StartOfComment) == Line.size()) - {//If entire line is blocked by End and Start markers, then entire line is trivial - return true; + if (!ucr::CheckForInvalidUtf8(start, end - start)) + { + return ucr::toTString(std::string(start, end)); } - - if (InLineComment && InLineComment < StartOfComment) + else { - if (InLineComment == Line.c_str()) - return true;//If line starts with InLineComment marker, then entire line is trivial - - //Other wise, check if data before InLineComment marker is trivial - return IsTrivialBytes(Line.c_str(), InLineComment, filtercommentsset); + bool lossy = false; + String text; + ucr::maketstring(text, start, end - start, -1, &lossy); + return text; } +} - //Done with easy test, so now do more complex test - if (StartOfComment && - EndOfComment && - StartOfComment < EndOfComment && - IsTrivialBytes(Line.c_str(), StartOfComment, filtercommentsset) && - IsTrivialBytes(EndOfComment + filtercommentsset.EndMarker.size(), - Line.c_str()+Line.size(), filtercommentsset)) +static unsigned GetLastLineCookie(unsigned dwCookie, int startLine, int endLine, const char **linbuf, CrystalLineParser::TextDefinition* enuType) +{ + if (!enuType) + return dwCookie; + for (int i = startLine; i <= endLine; ++i) { - return true; + String text = convertToTString(linbuf[i], linbuf[i + 1]); + int nActualItems = 0; + std::vector blocks(text.length()); + dwCookie = enuType->ParseLineX(dwCookie, text.c_str(), static_cast(text.length()), blocks.data(), nActualItems); } - - return false; + return dwCookie; } -/** - * @brief Find comment marker in string, excluding portions enclosed in quotation marks or apostrophes - * @param [in] target - string to search - * @param [in] marker - marker to search for - * @return Returns position of marker, or NULL if none is present - */ -static const char *FindCommentMarker(const char *target, const char *marker) +static unsigned GetCommentsFilteredText(unsigned dwCookie, int startLine, int endLine, const char **linbuf, std::string& filtered, CrystalLineParser::TextDefinition* enuType) { - char prev = '\0'; - char quote = '\0'; - size_t marker_len = strlen(marker); - while (char c = *target) - { - if (quote == '\0' && strncmp(target, marker, marker_len) == 0) - return target; - if ((prev != '\\') && - (c == '"' || c == '\'') && - (quote == '\0' || quote == c)) + String filteredT; + for (int i = startLine; i <= endLine; ++i) + { + String text = convertToTString(linbuf[i], linbuf[i + 1]); + unsigned textlen = static_cast(text.size()); + if (!enuType) + { + filteredT += text; + } + else { - quote ^= c; + int nActualItems = 0; + std::vector blocks(textlen); + dwCookie = enuType->ParseLineX(dwCookie, text.c_str(), textlen, blocks.data(), nActualItems); + + if (nActualItems == 0) + { + filteredT += text; + } + else + { + for (int j = 0; j < nActualItems; ++j) + { + CrystalLineParser::TEXTBLOCK& block = blocks[j]; + if (block.m_nColorIndex != COLORINDEX_COMMENT) + { + unsigned blocklen = (j < nActualItems - 1) ? (blocks[j + 1].m_nCharPos - block.m_nCharPos) : textlen - block.m_nCharPos; + filteredT.append(text.c_str() + block.m_nCharPos, blocklen); + } + } + } } - prev = c; - ++target; } - return NULL; + + filtered = ucr::toUTF8(filteredT); + + return dwCookie; } /** @@ -355,138 +302,13 @@ static void ReplaceSpaces(std::string & str, const char *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) + if (posend != 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 - @param [in] QtyLinesInBlock - Number of lines in diff block. Not needed in backward direction. - @param [in] Direction - This should be 1 or -1, to indicate which direction to read (backward or forward) - @param [in,out] Op - This variable is set to trivial if block should be ignored. - @param [in] FileNo - Should be 0 or 1, to indicate left or right file. - @param [in] filtercommentsset - Comment marker set used to indicate comment blocks. - @return Always returns true in reverse direction. - In forward direction, returns false if none trivial data is found within QtyLinesInBlock -*/ -bool CDiffWrapper::PostFilter(int StartPos, int EndPos, int Direction, - int QtyLinesInBlock, OP_TYPE &Op, int FileNo, - FilterCommentsSet& filtercommentsset) const -{ - if (Op == OP_TRIVIAL) //If already set to trivial, then exit. - return true; - bool OpShouldBeTrivial = false; - int QtyTrivialLines = 0; - for(int i = StartPos + ((Direction == -1)?-1:0); i != EndPos;i += Direction) - { - if ((i - StartPos) == QtyLinesInBlock && - QtyLinesInBlock == QtyTrivialLines) - { - OpShouldBeTrivial = true; - break; - } - size_t len = files[FileNo].linbuf[i + 1] - files[FileNo].linbuf[i]; - const char *LineStr = files[FileNo].linbuf[i]; - std::string LineData(LineStr, linelen(LineStr, len)); - - const char * StartOfComment = FindCommentMarker(LineData.c_str(), filtercommentsset.StartMarker.c_str()); - const char * EndOfComment = FindCommentMarker(LineData.c_str(), filtercommentsset.EndMarker.c_str()); - const char * InLineComment = FindCommentMarker(LineData.c_str(), filtercommentsset.InlineMarker.c_str()); - //The following logic determines if the entire block is a comment block, and only marks it as trivial - //if all the changes are within a comment block. - if (Direction == -1) - { - if (!StartOfComment && EndOfComment) - break; - - if (StartOfComment && (!EndOfComment || EndOfComment < StartOfComment) && (!InLineComment || InLineComment > StartOfComment)) - { - OpShouldBeTrivial = true; - break; - } - } - else if (Direction == 1) - { - if (IsTrivialBytes(LineData.c_str(), LineData.c_str()+LineData.size(), filtercommentsset) || - IsTrivialLine(LineData, StartOfComment, EndOfComment, InLineComment, filtercommentsset)) - { - ++QtyTrivialLines; - } - - if (!EndOfComment && StartOfComment) - { - if (i == (StartPos + QtyTrivialLines) ) - { - if (StartOfComment == LineData.c_str()) - {//If this is at the beginning of the first line, then lets continue - continue; - } - if (IsTrivialBytes(LineData.c_str(), StartOfComment, filtercommentsset)) - {//If only trivial bytes before comment marker, then continue - continue; - } - break; - } - //If this is not the first line, then assume - //previous lines are non-trivial, and return true. - return false; - } - - if (EndOfComment && - (!StartOfComment || StartOfComment > EndOfComment) && - (!InLineComment || InLineComment > EndOfComment) ) - { - if (!IsTrivialBytes(EndOfComment+filtercommentsset.EndMarker.size(), LineData.c_str()+LineData.size(), filtercommentsset)) - { - return false; - } - - if ((i - StartPos) >= (QtyLinesInBlock-1)) - { - OpShouldBeTrivial = true; - break; - } - - //Lets check if the remaining lines only contain trivial data - bool AllRemainingLinesContainTrivialData = true; - int TrivLinePos = i+1; - for(; TrivLinePos != (StartPos + QtyLinesInBlock);++TrivLinePos) - { - size_t len1 = files[FileNo].linbuf[TrivLinePos + 1] - files[FileNo].linbuf[TrivLinePos]; - const char *LineStrTrvCk = files[FileNo].linbuf[TrivLinePos]; - std::string LineDataTrvCk(LineStrTrvCk, linelen(LineStrTrvCk, len1)); - if (LineDataTrvCk.size() && - !IsTrivialBytes(LineDataTrvCk.c_str(), LineDataTrvCk.c_str() + LineDataTrvCk.size(), filtercommentsset)) - { - AllRemainingLinesContainTrivialData = false; - break; - } - } - if (AllRemainingLinesContainTrivialData) - { - OpShouldBeTrivial = true; - break; - } - if (TrivLinePos != (StartPos + QtyLinesInBlock) ) - { - return PostFilter(TrivLinePos, EndPos, Direction, QtyLinesInBlock - (TrivLinePos - StartPos), Op, FileNo, filtercommentsset); - } - } - } - } - if (OpShouldBeTrivial) - { - Op = OP_TRIVIAL; - } - return true; -} - /** @brief The main entry for post filtering. Performs post-filtering, by setting comment blocks to trivial @param [in] LineNumberLeft - First line number to read from left file @@ -494,151 +316,70 @@ bool CDiffWrapper::PostFilter(int StartPos, int EndPos, int Direction, @param [in] LineNumberRight - First line number to read from right file @param [in] QtyLinesRight - Number of lines in the block for right file @param [in,out] Op - This variable is set to trivial if block should be ignored. -@param [in] FileNameExt - The file name extension. Needs to be lower case string ("cpp", "java", "c") */ -void CDiffWrapper::PostFilter(int LineNumberLeft, int QtyLinesLeft, int LineNumberRight, - int QtyLinesRight, OP_TYPE &Op, const String& FileNameExt) const +void CDiffWrapper::PostFilter(PostFilterContext& ctxt, int LineNumberLeft, int QtyLinesLeft, int LineNumberRight, + int QtyLinesRight, OP_TYPE &Op, const file_data *file_data_ary) const { - if (Op == OP_TRIVIAL || !m_pFilterCommentsManager) - return; - - //First we need to get lowercase file name extension - FilterCommentsSet filtercommentsset = m_pFilterCommentsManager->GetSetForFileType(FileNameExt); - if (filtercommentsset.StartMarker.empty() && - filtercommentsset.EndMarker.empty() && - filtercommentsset.InlineMarker.empty()) - { + if (Op == OP_TRIVIAL) return; - } - OP_TYPE LeftOp = OP_NONE; - OP_TYPE RightOp = OP_NONE; + std::string LineDataLeft, LineDataRight; - if (QtyLinesRight == 0) - { //Only check left side - if (PostFilter(LineNumberLeft, files[0].valid_lines, 1, QtyLinesLeft, LeftOp, 0, filtercommentsset)) - PostFilter(LineNumberLeft, -1, -1, QtyLinesLeft, LeftOp, 0, filtercommentsset); - } - else if (QtyLinesLeft == 0) - { //Only check right side - if (PostFilter(LineNumberRight, files[1].valid_lines, 1, QtyLinesRight, RightOp, 1, filtercommentsset)) - PostFilter(LineNumberRight, -1, -1, QtyLinesRight, RightOp, 1, filtercommentsset); + if (m_options.m_filterCommentsLines) + { + ctxt.dwCookieLeft = GetLastLineCookie(ctxt.dwCookieLeft, + ctxt.nParsedLineEndLeft + 1, LineNumberLeft - 1, file_data_ary[0].linbuf + file_data_ary[0].linbuf_base, m_pFilterCommentsDef); + ctxt.dwCookieRight = GetLastLineCookie(ctxt.dwCookieRight, + ctxt.nParsedLineEndRight + 1, LineNumberRight - 1, file_data_ary[1].linbuf + file_data_ary[1].linbuf_base, m_pFilterCommentsDef); + + ctxt.nParsedLineEndLeft = LineNumberLeft + QtyLinesLeft - 1; + ctxt.nParsedLineEndRight = LineNumberRight + QtyLinesRight - 1;; + + ctxt.dwCookieLeft = GetCommentsFilteredText(ctxt.dwCookieLeft, + LineNumberLeft, ctxt.nParsedLineEndLeft, file_data_ary[0].linbuf + file_data_ary[0].linbuf_base, LineDataLeft, m_pFilterCommentsDef); + ctxt.dwCookieRight = GetCommentsFilteredText(ctxt.dwCookieRight, + LineNumberRight, ctxt.nParsedLineEndRight, file_data_ary[1].linbuf + file_data_ary[1].linbuf_base, LineDataRight, m_pFilterCommentsDef); } else { - if (PostFilter(LineNumberLeft, files[0].valid_lines, 1, QtyLinesLeft, LeftOp, 0, filtercommentsset)) - PostFilter(LineNumberLeft, -1, -1, QtyLinesLeft, LeftOp, 0, filtercommentsset); - - if (PostFilter(LineNumberRight, files[1].valid_lines, 1, QtyLinesRight, RightOp, 1, filtercommentsset)) - PostFilter(LineNumberRight, -1, -1, QtyLinesRight, RightOp, 1, filtercommentsset); + LineDataLeft.assign(file_data_ary[0].linbuf[LineNumberLeft + file_data_ary[0].linbuf_base], + file_data_ary[0].linbuf[LineNumberLeft + QtyLinesLeft + file_data_ary[0].linbuf_base] + - file_data_ary[0].linbuf[LineNumberLeft + file_data_ary[0].linbuf_base]); + LineDataRight.assign(file_data_ary[1].linbuf[LineNumberRight + file_data_ary[1].linbuf_base], + file_data_ary[1].linbuf[LineNumberRight + QtyLinesRight + file_data_ary[1].linbuf_base] + - file_data_ary[1].linbuf[LineNumberRight + file_data_ary[1].linbuf_base]); } - std::list LeftLines, RightLines; - for (int i = 0; (i < QtyLinesLeft) || (i < QtyLinesRight); i++) + if (m_pSubstitutionList) { - //Lets test all lines if only a comment is different. - const char * LineStrLeft = ""; - const char * EndLineLeft = LineStrLeft; - const char * LineStrRight = ""; - const char * EndLineRight = LineStrRight; - if(i < QtyLinesLeft) - { - LineStrLeft = files[0].linbuf[LineNumberLeft + i]; - EndLineLeft = files[0].linbuf[LineNumberLeft + i + 1]; - } - if(i < QtyLinesRight) - { - LineStrRight = files[1].linbuf[LineNumberRight + i]; - EndLineRight = files[1].linbuf[LineNumberRight + i + 1]; - } - - if (EndLineLeft && EndLineRight) - { - std::string LineDataLeft(LineStrLeft, EndLineLeft); - std::string LineDataRight(LineStrRight, EndLineRight); - - if (!filtercommentsset.StartMarker.empty() && !filtercommentsset.EndMarker.empty()) - { - const char * CommentStrLeftStart; - const char * CommentStrLeftEnd; - const char * CommentStrRightStart; - const char * CommentStrRightEnd; - - bool bFirstLoop = true; - do { - //Lets remove block comments, and see if lines are equal - CommentStrLeftStart = FindCommentMarker(LineDataLeft.c_str(), filtercommentsset.StartMarker.c_str()); - CommentStrLeftEnd = FindCommentMarker(LineDataLeft.c_str(), filtercommentsset.EndMarker.c_str()); - CommentStrRightStart = FindCommentMarker(LineDataRight.c_str(), filtercommentsset.StartMarker.c_str()); - CommentStrRightEnd = FindCommentMarker(LineDataRight.c_str(), filtercommentsset.EndMarker.c_str()); - - if (CommentStrLeftStart != NULL && CommentStrLeftEnd != NULL && CommentStrLeftStart < CommentStrLeftEnd) - LineDataLeft.erase(CommentStrLeftStart - LineDataLeft.c_str(), CommentStrLeftEnd + filtercommentsset.EndMarker.size() - CommentStrLeftStart); - else if (CommentStrLeftEnd != NULL) - LineDataLeft.erase(0, CommentStrLeftEnd + filtercommentsset.EndMarker.size() - LineDataLeft.c_str()); - else if (CommentStrLeftStart != NULL) - LineDataLeft.erase(CommentStrLeftStart - LineDataLeft.c_str()); - else if(LeftOp == OP_TRIVIAL && bFirstLoop) - LineDataLeft.erase(0); //This line is all in block comments - - if (CommentStrRightStart != NULL && CommentStrRightEnd != NULL && CommentStrRightStart < CommentStrRightEnd) - LineDataRight.erase(CommentStrRightStart - LineDataRight.c_str(), CommentStrRightEnd + filtercommentsset.EndMarker.size() - CommentStrRightStart); - else if (CommentStrRightEnd != NULL) - LineDataRight.erase(0, CommentStrRightEnd + filtercommentsset.EndMarker.size() - LineDataRight.c_str()); - else if (CommentStrRightStart != NULL) - LineDataRight.erase(CommentStrRightStart - LineDataRight.c_str()); - else if(RightOp == OP_TRIVIAL && bFirstLoop) - LineDataRight.erase(0); //This line is all in block comments - - bFirstLoop = false; - - } while (CommentStrLeftStart != NULL || CommentStrLeftEnd != NULL - || CommentStrRightStart != NULL || CommentStrRightEnd != NULL); //Loops until all blockcomments are lost - } - - if (!filtercommentsset.InlineMarker.empty()) - { - //Lets remove line comments - const char * CommentStrLeft = FindCommentMarker(LineDataLeft.c_str(), filtercommentsset.InlineMarker.c_str()); - const char * CommentStrRight = FindCommentMarker(LineDataRight.c_str(), filtercommentsset.InlineMarker.c_str()); - - if (CommentStrLeft != NULL) - LineDataLeft.erase(CommentStrLeft - LineDataLeft.c_str()); - if (CommentStrRight != NULL) - 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, " "); - } + LineDataLeft = m_pSubstitutionList->Subst(LineDataLeft); + LineDataRight = m_pSubstitutionList->Subst(LineDataRight); + } - if (m_options.m_bIgnoreCase) - { - //ignore case - // std::transform(LineDataLeft.begin(), LineDataLeft.end(), LineDataLeft.begin(), ::toupper); - for (std::basic_string::iterator pb = LineDataLeft.begin(), pe = LineDataLeft.end(); pb != pe; ++pb) - *pb = static_cast(::toupper(*pb)); - // std::transform(LineDataRight.begin(), LineDataRight.end(), LineDataRight.begin(), ::toupper); - for (std::basic_string::iterator pb = LineDataRight.begin(), pe = LineDataRight.end(); pb != pe; ++pb) - *pb = static_cast(::toupper(*pb)); - } + 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 (!LineDataLeft.empty()) - LeftLines.push_back(LineDataLeft); - if (!LineDataRight.empty()) - RightLines.push_back(LineDataRight); - } + if (m_options.m_bIgnoreCase) + { + //ignore case + // std::transform(LineDataLeft.begin(), LineDataLeft.end(), LineDataLeft.begin(), ::toupper); + for (std::string::iterator pb = LineDataLeft.begin(), pe = LineDataLeft.end(); pb != pe; ++pb) + *pb = static_cast(::toupper(*pb)); + // std::transform(LineDataRight.begin(), LineDataRight.end(), LineDataRight.begin(), ::toupper); + for (std::string::iterator pb = LineDataRight.begin(), pe = LineDataRight.end(); pb != pe; ++pb) + *pb = static_cast(::toupper(*pb)); } - if (LeftLines != RightLines) + if (LineDataLeft != LineDataRight) return; //only difference is trival Op = OP_TRIVIAL; @@ -660,29 +401,6 @@ void CDiffWrapper::SetPaths(const PathContext &tFiles, } /** - * @brief Set source paths for original (NON-TEMP) diffing two files. - * Sets full paths to two (NON-TEMP) files we are diffing. - * @param [in] OriginalFile1 First file to compare "(NON-TEMP) file". - * @param [in] OriginalFile2 Second file to compare "(NON-TEMP) file". - */ -void CDiffWrapper::SetCompareFiles(const PathContext &originalFile) -{ - m_originalFile = originalFile; -} - -/** - * @brief Set alternative paths for compared files. - * Sets alternative paths for diff'ed files. These alternative paths might not - * be real paths. For example when creating a patch file from folder compare - * we want to use relative paths. - * @param [in] altPaths Alternative file paths. - */ -void CDiffWrapper::SetAlternativePaths(const PathContext &altPaths) -{ - m_alternativePaths = altPaths; -} - -/** * @brief Runs diff-engine. */ bool CDiffWrapper::RunFileDiff() @@ -718,22 +436,22 @@ bool CDiffWrapper::RunFileDiff() String sError = strutils::format( _T("An error occurred while prediffing the file '%s' with the plugin '%s'. The prediffing is not applied any more."), strFileTemp[file].c_str(), - m_infoPrediffer->pluginName.c_str()); + m_infoPrediffer->m_PluginName.c_str()); AppErrorMessageBox(sError); // don't use any more this prediffer - m_infoPrediffer->bToBeScanned = false; - m_infoPrediffer->pluginName.erase(); + m_infoPrediffer->m_PluginOrPredifferMode = PLUGIN_MODE::PLUGIN_MANUAL; + m_infoPrediffer->m_PluginName.erase(); } // We use the same plugin for both files, so it must be defined before // second file - assert(!m_infoPrediffer->bToBeScanned); + assert(m_infoPrediffer->m_PluginOrPredifferMode == PLUGIN_MODE::PLUGIN_MANUAL); } } - struct change *script = NULL; - struct change *script10 = NULL; - struct change *script12 = NULL; + struct change *script = nullptr; + struct change *script10 = nullptr; + struct change *script12 = nullptr; DiffFileData diffdata, diffdata10, diffdata12; int bin_flag = 0, bin_flag10 = 0, bin_flag12 = 0; @@ -747,9 +465,9 @@ bool CDiffWrapper::RunFileDiff() } // Compare the files, if no error was found. - // Last param (bin_file) is NULL since we don't + // Last param (bin_file) is `nullptr` since we don't // (yet) need info about binary sides. - bRet = Diff2Files(&script, &diffdata, &bin_flag, NULL); + bRet = Diff2Files(&script, &diffdata, &bin_flag, nullptr); // We don't anymore create diff-files for every rescan. // User can create patch-file whenever one wants to. @@ -779,14 +497,14 @@ bool CDiffWrapper::RunFileDiff() return false; } - bRet = Diff2Files(&script10, &diffdata10, &bin_flag10, NULL); + bRet = Diff2Files(&script10, &diffdata10, &bin_flag10, nullptr); if (!diffdata12.OpenFiles(strFileTemp[1], strFileTemp[2])) { return false; } - bRet = Diff2Files(&script12, &diffdata12, &bin_flag12, NULL); + bRet = Diff2Files(&script12, &diffdata12, &bin_flag12, nullptr); } // First determine what happened during comparison @@ -806,13 +524,13 @@ bool CDiffWrapper::RunFileDiff() { m_status.bBinaries = true; if (bin_flag != -1) - m_status.Identical = IDENTLEVEL_ALL; + m_status.Identical = IDENTLEVEL::ALL; else - m_status.Identical = IDENTLEVEL_NONE; + m_status.Identical = IDENTLEVEL::NONE; } else { // text files according to diffutils, so change script exists - m_status.Identical = (script == 0) ? IDENTLEVEL_ALL : IDENTLEVEL_NONE; + m_status.Identical = (script == 0) ? IDENTLEVEL::ALL : IDENTLEVEL::NONE; m_status.bBinaries = false; } m_status.bMissingNL[0] = !!inf[0].missing_newline; @@ -820,30 +538,30 @@ bool CDiffWrapper::RunFileDiff() } else { - m_status.Identical = IDENTLEVEL_NONE; + m_status.Identical = IDENTLEVEL::NONE; if (bin_flag10 != 0 || bin_flag12 != 0) { m_status.bBinaries = true; if (bin_flag10 != -1 && bin_flag12 != -1) - m_status.Identical = IDENTLEVEL_ALL; + m_status.Identical = IDENTLEVEL::ALL; else if (bin_flag10 != -1) - m_status.Identical = IDENTLEVEL_EXCEPTRIGHT; + m_status.Identical = IDENTLEVEL::EXCEPTRIGHT; else if (bin_flag12 != -1) - m_status.Identical = IDENTLEVEL_EXCEPTLEFT; + m_status.Identical = IDENTLEVEL::EXCEPTLEFT; else - m_status.Identical = IDENTLEVEL_EXCEPTMIDDLE; + m_status.Identical = IDENTLEVEL::EXCEPTMIDDLE; } else { // text files according to diffutils, so change script exists m_status.bBinaries = false; - if (script10 == 0 && script12 == 0) - m_status.Identical = IDENTLEVEL_ALL; - else if (script10 == 0) - m_status.Identical = IDENTLEVEL_EXCEPTRIGHT; - else if (script12 == 0) - m_status.Identical = IDENTLEVEL_EXCEPTLEFT; + if (script10 == nullptr && script12 == nullptr) + m_status.Identical = IDENTLEVEL::ALL; + else if (script10 == nullptr) + m_status.Identical = IDENTLEVEL::EXCEPTRIGHT; + else if (script12 == nullptr) + m_status.Identical = IDENTLEVEL::EXCEPTLEFT; else - m_status.Identical = IDENTLEVEL_EXCEPTMIDDLE; + m_status.Identical = IDENTLEVEL::EXCEPTMIDDLE; } m_status.bMissingNL[0] = !!inf10[1].missing_newline; m_status.bMissingNL[1] = !!inf12[0].missing_newline; @@ -958,7 +676,7 @@ void CDiffWrapper::FixLastDiffRange(int nFiles, int bufferLines[], bool bMissing { DIFFRANGE dr; const int count = m_pDiffList->GetSize(); - if (count > 0 && !bIgnoreBlankLines) + if (count > 0) { m_pDiffList->GetDiff(count - 1, dr); @@ -1011,10 +729,10 @@ String CDiffWrapper::FormatSwitchString() const switches = _T(" "); break; case DIFF_OUTPUT_CONTEXT: - switches = _T(" C"); + switches = (m_options.m_contextLines > 0) ? _T(" -C ") : _T(" -c"); break; case DIFF_OUTPUT_UNIFIED: - switches = _T(" U"); + switches = (m_options.m_contextLines > 0) ? _T(" -U ") : _T(" -u"); break; #if 0 case DIFF_OUTPUT_ED: @@ -1035,7 +753,8 @@ String CDiffWrapper::FormatSwitchString() const #endif } - if (m_options.m_contextLines > 0) + if ((m_options.m_outputStyle == DIFF_OUTPUT_CONTEXT || m_options.m_outputStyle == DIFF_OUTPUT_UNIFIED) && + m_options.m_contextLines > 0) { TCHAR tmpNum[5] = {0}; _itot_s(m_options.m_contextLines, tmpNum, 10); @@ -1043,16 +762,16 @@ String CDiffWrapper::FormatSwitchString() const } if (ignore_all_space_flag > 0) - switches += _T("w"); + switches += _T(" -w"); if (ignore_blank_lines_flag > 0) - switches += _T("B"); + switches += _T(" -B"); if (ignore_case_flag > 0) - switches += _T("i"); + switches += _T(" -i"); if (ignore_space_change_flag > 0) - switches += _T("b"); + switches += _T(" -b"); return switches; } @@ -1078,7 +797,7 @@ void CDiffWrapper::SetAppendFiles(bool bAppendFiles) * @param [in] diffData files to compare. * @param [out] bin_status used to return binary status from compare. * @param [out] bin_file Returns which file was binary file as bitmap. - So if first file is binary, first bit is set etc. Can be NULL if binary file + So if first file is binary, first bit is set etc. Can be `nullptr` if binary file info is not needed (faster compare since diffutils don't bother checking second file if first is binary). * @return true when compare succeeds, false if error happened during compare. @@ -1092,14 +811,24 @@ bool CDiffWrapper::Diff2Files(struct change ** diffs, DiffFileData *diffData, SE_Handler seh; try { - // Diff files. depth is zero because we are not comparing dirs - *diffs = diff_2_files (diffData->m_inf, 0, bin_status, - (m_pMovedLines[0] != NULL), bin_file); + if (m_options.m_diffAlgorithm != DIFF_ALGORITHM_DEFAULT) + { + unsigned xdl_flags = make_xdl_flags(m_options); + *diffs = diff_2_files_xdiff(diffData->m_inf, (m_pMovedLines[0] != nullptr), xdl_flags); + files[0] = diffData->m_inf[0]; + files[1] = diffData->m_inf[1]; + } + else + { + // Diff files. depth is zero because we are not comparing dirs + *diffs = diff_2_files(diffData->m_inf, 0, bin_status, + (m_pMovedLines[0] != nullptr), bin_file); + } CopyDiffutilTextStats(diffData->m_inf, diffData); } catch (SE_Exception&) { - *diffs = NULL; + *diffs = nullptr; bRet = false; } return bRet; @@ -1111,15 +840,15 @@ bool CDiffWrapper::Diff2Files(struct change ** diffs, DiffFileData *diffData, void CDiffWrapper::FreeDiffUtilsScript(struct change * & script) { - if (!script) return; - struct change *e=0, *p=0; + if (script == nullptr) return; + struct change *e=nullptr, *p=nullptr; // cleanup the script - for (e = script; e; e = p) + for (e = script; e != nullptr; e = p) { p = e->link; free(e); } - script = 0; + script = nullptr; } /** @@ -1132,12 +861,12 @@ CDiffWrapper::FreeDiffUtilsScript(struct change * & script) * @param [in] FileNo File to match. * return true if any of the expressions matches. */ -bool CDiffWrapper::RegExpFilter(int StartPos, int EndPos, int FileNo) const +bool CDiffWrapper::RegExpFilter(int StartPos, int EndPos, const file_data *pinf) const { - if (m_pFilterList == NULL) + if (m_pFilterList == nullptr) { throw "CDiffWrapper::RegExpFilter() called when " - "filterlist doesn't exist (=NULL)"; + "filterlist doesn't exist (=nullptr)"; } bool linesMatch = true; // set to false when non-matching line is found. @@ -1145,10 +874,10 @@ bool CDiffWrapper::RegExpFilter(int StartPos, int EndPos, int FileNo) const while (line <= EndPos && linesMatch) { - size_t len = files[FileNo].linbuf[line + 1] - files[FileNo].linbuf[line]; - const char *string = files[FileNo].linbuf[line]; + size_t len = pinf->linbuf[line + 1] - pinf->linbuf[line]; + const char *string = pinf->linbuf[line]; size_t stringlen = linelen(string, len); - if (!m_pFilterList->Match(std::string(string, stringlen), m_codepage)) + if (!m_pFilterList->Match(std::string(string, stringlen))) { linesMatch = false; @@ -1162,27 +891,14 @@ bool CDiffWrapper::RegExpFilter(int StartPos, int EndPos, int FileNo) const * @brief Walk the diff utils change script, building the WinMerge list of diff blocks */ void -CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript(struct change * script, const file_data * inf) +CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript(struct change * script, const file_data * file_data_ary) { //Logic needed for Ignore comment option - DIFFOPTIONS options; - GetOptions(&options); - String asLwrCaseExt; - if (options.bFilterCommentsLines) - { - String LowerCaseExt = m_originalFile.GetLeft(); - String::size_type PosOfDot = LowerCaseExt.rfind('.'); - if (PosOfDot != String::npos) - { - LowerCaseExt.erase(0, PosOfDot + 1); - std::transform(LowerCaseExt.begin(), LowerCaseExt.end(), LowerCaseExt.begin(), ::towlower); - asLwrCaseExt = LowerCaseExt; - } - } + PostFilterContext ctxt; struct change *next = script; - while (next) + while (next != nullptr) { /* Find a set of changes that belong together. */ struct change *thisob = next; @@ -1191,7 +907,7 @@ CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript(struct change * script, const /* Disconnect them from the rest of the changes, making them a hunk, and remember the rest for next iteration. */ next = end->link; - end->link = 0; + end->link = nullptr; #ifdef DEBUG debug_script(thisob); #endif @@ -1201,7 +917,7 @@ CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript(struct change * script, const { /* Determine range of line numbers involved in each file. */ int first0=0, last0=0, first1=0, last1=0, deletes=0, inserts=0; - analyze_hunk (thisob, &first0, &last0, &first1, &last1, &deletes, &inserts, inf); + analyze_hunk (thisob, &first0, &last0, &first1, &last1, &deletes, &inserts, file_data_ary); if (deletes || inserts || thisob->trivial) { OP_TYPE op = OP_NONE; @@ -1214,8 +930,8 @@ CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript(struct change * script, const /* Print the lines that the first file has. */ int trans_a0=0, trans_b0=0, trans_a1=0, trans_b1=0; - translate_range(&inf[0], first0, last0, &trans_a0, &trans_b0); - translate_range(&inf[1], first1, last1, &trans_a1, &trans_b1); + translate_range(&file_data_ary[0], first0, last0, &trans_a0, &trans_b0); + translate_range(&file_data_ary[1], first1, last1, &trans_a1, &trans_b1); // Store information about these blocks in moved line info if (GetDetectMovedBlocks()) @@ -1227,7 +943,7 @@ CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript(struct change * script, const { int line0 = i+thisob->match0 + (trans_a0-first0-1); int line1 = i+thisob->line1 + (trans_a1-first1-1); - GetMovedLines(1)->Add(MovedLines::SIDE_LEFT, line1, line0); + GetMovedLines(1)->Add(MovedLines::SIDE::LEFT, line1, line0); } } if (thisob->match1>=0) @@ -1237,36 +953,34 @@ CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript(struct change * script, const { int line0 = i+thisob->line0 + (trans_a0-first0-1); int line1 = i+thisob->match1 + (trans_a1-first1-1); - GetMovedLines(0)->Add(MovedLines::SIDE_RIGHT, line0, line1); + GetMovedLines(0)->Add(MovedLines::SIDE::RIGHT, line0, line1); } } } + int QtyLinesLeft = (trans_b0 - trans_a0) + 1; //Determine quantity of lines in this block for left side + int QtyLinesRight = (trans_b1 - trans_a1) + 1;//Determine quantity of lines in this block for right side - if (options.bFilterCommentsLines) - { - int QtyLinesLeft = (trans_b0 - trans_a0) + 1; //Determine quantity of lines in this block for left side - int QtyLinesRight = (trans_b1 - trans_a1) + 1;//Determine quantity of lines in this block for right side - PostFilter(thisob->line0, QtyLinesLeft, thisob->line1, QtyLinesRight, op, asLwrCaseExt); - } + if (m_options.m_filterCommentsLines || + (m_pSubstitutionList && m_pSubstitutionList->HasRegExps())) + PostFilter(ctxt, trans_a0 - 1, QtyLinesLeft, trans_a1 - 1, QtyLinesRight, op, file_data_ary); - if (m_pFilterList && m_pFilterList->HasRegExps()) + if (m_pFilterList != nullptr && m_pFilterList->HasRegExps()) { - //Determine quantity of lines in this block for both sides - int QtyLinesLeft = (trans_b0 - trans_a0); - int QtyLinesRight = (trans_b1 - trans_a1); - // 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); + bool match1 = RegExpFilter(thisob->line0, thisob->line0 + QtyLinesLeft - 1, &file_data_ary[0]); if (match1) - match2 = RegExpFilter(thisob->line1, thisob->line1 + QtyLinesRight, 1); + match2 = RegExpFilter(thisob->line1, thisob->line1 + QtyLinesRight - 1, &file_data_ary[1]); if (match1 && match2) op = OP_TRIVIAL; } - AddDiffRange(m_pDiffList, trans_a0-1, trans_b0-1, trans_a1-1, trans_b1-1, op); + if (op == OP_TRIVIAL && m_options.m_bCompletelyBlankOutIgnoredDiffereneces) + op = OP_NONE; + if (op != OP_NONE) + AddDiffRange(m_pDiffList, trans_a0-1, trans_b0-1, trans_a1-1, trans_b1-1, op); } } @@ -1326,6 +1040,7 @@ CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript3( OP_TYPE op; const file_data *pinf = nullptr; DiffList *pdiff = nullptr; + PostFilterContext ctxt; switch (file) { @@ -1333,7 +1048,7 @@ CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript3( case 1: next = script12; pdiff = &diff12; pinf = inf12; break; } - while (next) + while (next != nullptr) { /* Find a set of changes that belong together. */ struct change *thisob = next; @@ -1342,7 +1057,7 @@ CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript3( /* Disconnect them from the rest of the changes, making them a hunk, and remember the rest for next iteration. */ next = end->link; - end->link = 0; + end->link = nullptr; #ifdef DEBUG debug_script(thisob); #endif @@ -1370,14 +1085,14 @@ CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript3( { int index1 = 0; // defaults for (file == 0 /* diff10 */) int index2 = 1; - MovedLines::ML_SIDE side1 = MovedLines::SIDE_RIGHT; - MovedLines::ML_SIDE side2 = MovedLines::SIDE_LEFT; + MovedLines::SIDE side1 = MovedLines::SIDE::RIGHT; + MovedLines::SIDE side2 = MovedLines::SIDE::LEFT; if (file == 1 /* diff12 */) { index1 = 2; index2 = 1; - side1 = MovedLines::SIDE_LEFT; - side2 = MovedLines::SIDE_RIGHT; + side1 = MovedLines::SIDE::LEFT; + side2 = MovedLines::SIDE::RIGHT; } if (index1 != -1 && index2 != -1) { @@ -1404,6 +1119,26 @@ CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript3( } } + int QtyLinesLeft = (trans_b0 - trans_a0) + 1; //Determine quantity of lines in this block for left side + int QtyLinesRight = (trans_b1 - trans_a1) + 1;//Determine quantity of lines in this block for right side + + if (m_options.m_filterCommentsLines || + (m_pSubstitutionList && m_pSubstitutionList->HasRegExps())) + PostFilter(ctxt, trans_a0 - 1, QtyLinesLeft, trans_a1 - 1, QtyLinesRight, op, pinf); + + if (m_pFilterList != nullptr && m_pFilterList->HasRegExps()) + { + // 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 - 1, &pinf[0]); + if (match1) + match2 = RegExpFilter(thisob->line1, thisob->line1 + QtyLinesRight - 1, &pinf[1]); + if (match1 && match2) + op = OP_TRIVIAL; + } + AddDiffRange(pdiff, trans_a0-1, trans_b0-1, trans_a1-1, trans_b1-1, op); } } @@ -1414,7 +1149,8 @@ CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript3( } Make3wayDiff(m_pDiffList->GetDiffRangeInfoVector(), diff10.GetDiffRangeInfoVector(), diff12.GetDiffRangeInfoVector(), - Comp02Functor(inf10, inf12), (m_pFilterList && m_pFilterList->HasRegExps())); + Comp02Functor(inf10, inf12), + (m_pFilterList != nullptr && m_pFilterList->HasRegExps()) || m_options.m_bIgnoreBlankLines || m_options.m_filterCommentsLines); } void CDiffWrapper::WritePatchFileHeader(enum output_style tOutput_style, bool bAppendFiles) @@ -1503,9 +1239,8 @@ void CDiffWrapper::WritePatchFileTerminator(enum output_style tOutput_style) */ void CDiffWrapper::WritePatchFile(struct change * script, file_data * inf) { - file_data inf_patch[2] = {0}; - std::memcpy(&inf_patch, inf, sizeof(file_data) * 2); - + file_data inf_patch[2] = { inf[0], inf[1] }; + // Get paths, primarily use alternative paths, only if they are empty // use full filepaths String path1(m_alternativePaths[0]); @@ -1516,8 +1251,17 @@ void CDiffWrapper::WritePatchFile(struct change * script, file_data * inf) path2 = m_files[1]; path1 = paths::ToUnixPath(path1); path2 = paths::ToUnixPath(path2); - inf_patch[0].name = _strdup(ucr::toSystemCP(path1).c_str()); - inf_patch[1].name = _strdup(ucr::toSystemCP(path2).c_str()); + if ((inf_patch[0].linbuf && ucr::CheckForInvalidUtf8(inf_patch[0].buffer, inf_patch[0].buffered_chars)) || + (inf_patch[1].linbuf && ucr::CheckForInvalidUtf8(inf_patch[1].buffer, inf_patch[1].buffered_chars))) + { + inf_patch[0].name = _strdup(ucr::toThreadCP(path1).c_str()); + inf_patch[1].name = _strdup(ucr::toThreadCP(path2).c_str()); + } + else + { + inf_patch[0].name = _strdup(ucr::toUTF8(path1).c_str()); + inf_patch[1].name = _strdup(ucr::toUTF8(path2).c_str()); + } // If paths in m_s1File and m_s2File point to original files, then we can use // them to fix potentially meaningless stats from potentially temporary files, @@ -1559,13 +1303,13 @@ void CDiffWrapper::WritePatchFile(struct change * script, file_data * inf) if (strcmp(inf[0].name, "NUL") == 0) { - free((void *)inf[0].name); - inf[0].name = _strdup("/dev/null"); + free((void *)inf_patch[0].name); + inf_patch[0].name = _strdup("/dev/null"); } if (strcmp(inf[1].name, "NUL") == 0) { - free((void *)inf[1].name); - inf[1].name = _strdup("/dev/null"); + free((void *)inf_patch[1].name); + inf_patch[1].name = _strdup("/dev/null"); } // Output patchfile @@ -1626,7 +1370,7 @@ void CDiffWrapper::SetFilterList(const String& filterStr) } // Adding new filter without previous filter - if (m_pFilterList == NULL) + if (m_pFilterList == nullptr) { m_pFilterList.reset(new FilterList); } @@ -1641,6 +1385,32 @@ void CDiffWrapper::SetFilterList(const String& filterStr) m_pFilterList->AddRegExp(*it); } +void CDiffWrapper::SetFilterList(const FilterList* pFilterList) +{ + if (!pFilterList) + m_pFilterList.reset(); + else + { + m_pFilterList.reset(new FilterList()); + *m_pFilterList = *pFilterList; + } +} + +const SubstitutionList* CDiffWrapper::GetSubstitutionList() const +{ + return m_pSubstitutionList.get(); +} + +void CDiffWrapper::SetSubstitutionList(std::shared_ptr pSubstitutionList) +{ + m_pSubstitutionList = pSubstitutionList; +} + +void CDiffWrapper::SetFilterCommentsSourceDef(const String& ext) +{ + m_pFilterCommentsDef = CrystalLineParser::GetTextType(ext.c_str()); +} + /** * @brief Copy text stat results from diffutils back into the FileTextStats structure */