OSDN Git Service

crystaledit: Use GetProfile*()/WriteProfile*() to read and write the registry wheneve...
[winmerge-jp/winmerge-jp.git] / Src / DiffWrapper.cpp
index bcf7c84..300bdbf 100644 (file)
 #include "parsers/crystallineparser.h"
 #include "SyntaxColors.h"
 #include "MergeApp.h"
-#include "OptionsMgr.h"
-#include "OptionsDef.h"
-#include "TokenPairList.h"
-#include "stringdiffs.h"
-using namespace strdiff;
-
+#include "SubstitutionList.h"
 
 using Poco::Debugger;
 using Poco::format;
@@ -79,7 +74,7 @@ CDiffWrapper::CDiffWrapper()
 , m_pDiffList(nullptr)
 , m_bPathsAreTemp(false)
 , m_pFilterList(nullptr)
-, m_pIgnoredSubstitutionsList{nullptr}
+, m_pSubstitutionList{nullptr}
 , m_bPluginsEnabled(false)
 , m_status()
 {
@@ -225,13 +220,28 @@ void CDiffWrapper::SetDetectMovedBlocks(bool bDetectMovedBlocks)
        }
 }
 
+static String convertToTString(const char* start, const char* end)
+{
+       if (!ucr::CheckForInvalidUtf8(start, end - start))
+       {
+               return ucr::toTString(std::string(start, end));
+       }
+       else
+       {
+               bool lossy = false;
+               String text;
+               ucr::maketstring(text, start, end - start, -1, &lossy);
+               return text;
+       }
+}
+
 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)
        {
-               String text = ucr::toTString(std::string{ linbuf[i], linbuf[i + 1] });
+               String text = convertToTString(linbuf[i], linbuf[i + 1]);
                int nActualItems = 0;
                std::vector<CrystalLineParser::TEXTBLOCK> blocks(text.length());
                dwCookie = enuType->ParseLineX(dwCookie, text.c_str(), static_cast<int>(text.length()), blocks.data(), nActualItems);
@@ -239,15 +249,16 @@ static unsigned GetLastLineCookie(unsigned dwCookie, int startLine, int endLine,
        return dwCookie;
 }
 
-static unsigned GetCommentsFilteredText(unsigned dwCookie, int startLine, int endLine, const char **linbuf, String& filtered, CrystalLineParser::TextDefinition* enuType)
+static unsigned GetCommentsFilteredText(unsigned dwCookie, int startLine, int endLine, const char **linbuf, std::string& filtered, CrystalLineParser::TextDefinition* enuType)
 {
+       String filteredT;
        for (int i = startLine; i <= endLine; ++i)
        {
-               String text = ucr::toTString(std::string{ linbuf[i], linbuf[i + 1] });
+               String text = convertToTString(linbuf[i], linbuf[i + 1]);
                unsigned textlen = static_cast<unsigned>(text.size());
                if (!enuType)
                {
-                       filtered += text;
+                       filteredT += text;
                }
                else
                {
@@ -257,7 +268,7 @@ static unsigned GetCommentsFilteredText(unsigned dwCookie, int startLine, int en
 
                        if (nActualItems == 0)
                        {
-                               filtered += text;
+                               filteredT += text;
                        }
                        else
                        {
@@ -267,13 +278,15 @@ static unsigned GetCommentsFilteredText(unsigned dwCookie, int startLine, int en
                                        if (block.m_nColorIndex != COLORINDEX_COMMENT)
                                        {
                                                unsigned blocklen = (j < nActualItems - 1) ? (blocks[j + 1].m_nCharPos - block.m_nCharPos) : textlen - block.m_nCharPos;
-                                               filtered.append(text.c_str() + block.m_nCharPos, blocklen);
+                                               filteredT.append(text.c_str() + block.m_nCharPos, blocklen);
                                        }
                                }
                        }
                }
        }
 
+       filtered = ucr::toUTF8(filteredT);
+
        return dwCookie;
 }
 
@@ -282,13 +295,13 @@ static unsigned GetCommentsFilteredText(unsigned dwCookie, int startLine, int en
  * @param [in] str - String to search
  * @param [in] rep - String to replace
  */
-static void ReplaceSpaces(String & str, const TCHAR *rep)
+static void ReplaceSpaces(std::string & str, const char *rep)
 {
-       String::size_type pos = 0;
-       size_t replen = _tcslen(rep);
-       while ((pos = str.find_first_of(_T(" \t"), pos)) != String::npos)
+       std::string::size_type pos = 0;
+       size_t replen = strlen(rep);
+       while ((pos = str.find_first_of(" \t", pos)) != std::string::npos)
        {
-               String::size_type posend = str.find_first_not_of(_T(" \t"), pos);
+               std::string::size_type posend = str.find_first_not_of(" \t", pos);
                if (posend != String::npos)
                        str.replace(pos, posend - pos, rep);
                else
@@ -310,42 +323,61 @@ void CDiffWrapper::PostFilter(PostFilterContext& ctxt, int LineNumberLeft, int Q
        if (Op == OP_TRIVIAL)
                return;
 
-       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);
+       std::string LineDataLeft, LineDataRight;
 
-       ctxt.nParsedLineEndLeft = LineNumberLeft + QtyLinesLeft - 1;
-       ctxt.nParsedLineEndRight = LineNumberRight + QtyLinesRight - 1;;
+       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
+       {
+               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]);
+       }
 
-       String LineDataLeft, LineDataRight;
-       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);
+       if (m_pSubstitutionList)
+       {
+               LineDataLeft = m_pSubstitutionList->Subst(LineDataLeft);
+               LineDataRight = m_pSubstitutionList->Subst(LineDataRight);
+       }
 
        if (m_options.m_ignoreWhitespace == WHITESPACE_IGNORE_ALL)
        {
                //Ignore character case
-               ReplaceSpaces(LineDataLeft, _T(""));
-               ReplaceSpaces(LineDataRight, _T(""));
+               ReplaceSpaces(LineDataLeft, "");
+               ReplaceSpaces(LineDataRight, "");
        }
        else if (m_options.m_ignoreWhitespace == WHITESPACE_IGNORE_CHANGE)
        {
                //Ignore change in whitespace char count
-               ReplaceSpaces(LineDataLeft, _T(" "));
-               ReplaceSpaces(LineDataRight, _T(" "));
+               ReplaceSpaces(LineDataLeft, " ");
+               ReplaceSpaces(LineDataRight, " ");
        }
 
        if (m_options.m_bIgnoreCase)
        {
                //ignore case
                // std::transform(LineDataLeft.begin(),  LineDataLeft.end(),  LineDataLeft.begin(),  ::toupper);
-               for (String::iterator pb = LineDataLeft.begin(), pe = LineDataLeft.end(); pb != pe; ++pb) 
-                       *pb = static_cast<TCHAR>(::toupper(*pb));
+               for (std::string::iterator pb = LineDataLeft.begin(), pe = LineDataLeft.end(); pb != pe; ++pb) 
+                       *pb = static_cast<char>(::toupper(*pb));
                // std::transform(LineDataRight.begin(), LineDataRight.end(), LineDataRight.begin(), ::toupper);
-               for (String::iterator pb = LineDataRight.begin(), pe = LineDataRight.end(); pb != pe; ++pb) 
-                       *pb = static_cast<TCHAR>(::toupper(*pb));
+               for (std::string::iterator pb = LineDataRight.begin(), pe = LineDataRight.end(); pb != pe; ++pb) 
+                       *pb = static_cast<char>(::toupper(*pb));
        }
        if (LineDataLeft != LineDataRight)
                return;
@@ -855,99 +887,6 @@ bool CDiffWrapper::RegExpFilter(int StartPos, int EndPos, const file_data *pinf)
        return linesMatch;
 }
 
-bool MatchDiffVsIngoredSubstitutions
-(
-       const std::string &fullLine0,
-       const std::string &fullLine1,
-       const strdiff::wdiff &diff,
-       const IgnoredSubstitutionsFilterList &ignoredSubstitutionsList,
-       const bool optUseRegexpsForIgnoredSubstitutions,
-       const bool optMatchBothWays
-)
-{
-       int changeStartPos[2] = { diff.begin[0], diff.begin[1] };
-       int changeEndPos[2] = { diff.end[0], diff.end[1] };
-       int changeLen0 = changeEndPos[0] - changeStartPos[0] + 1;
-       int changeLen1 = changeEndPos[1] - changeStartPos[1] + 1;
-       std::string change0 = std::string(fullLine0.c_str() + changeStartPos[0], changeLen0);
-       std::string change1 = std::string(fullLine1.c_str() + changeStartPos[1], changeLen1);
-
-       size_t numIgnoredSubstitutions = ignoredSubstitutionsList.GetCount();
-
-       for (int f = 0; f < numIgnoredSubstitutions; f++)
-       {
-               const IgnoredSusbstitutionItem& filter = ignoredSubstitutionsList[f];
-               // Check if the common prefix and suffix fit into the line around the change
-               if
-               (
-                          changeStartPos[0] < filter.CommonPrefixLength
-                       || changeStartPos[1] < filter.CommonPrefixLength
-                       || changeEndPos[0] >= fullLine0.length() - filter.CommonSuffixLength
-                       || changeEndPos[1] >= fullLine1.length() - filter.CommonSuffixLength
-               )
-                       continue; /// This filter does not fit into the line with its suffix and prefix
-
-               // Check if the common prefix and suffix match
-               bool continueWithNextFilter = false;
-               for (int p = 1; p <= filter.CommonPrefixLength; p++)
-               {
-                       char char0 = fullLine0[changeStartPos[0] - p];
-                       char char1 = fullLine1[changeStartPos[1] - p];
-                       if (char0 != char1)
-                       {
-                               continueWithNextFilter = true;
-                               break;
-                       }
-               }
-
-               for (int s = 1; s <= filter.CommonSuffixLength; s++)
-               {
-                       char char0 = fullLine0[changeEndPos[0] + s];
-                       char char1 = fullLine1[changeEndPos[1] + s];
-                       if (char0 != char1)
-                       {
-                               continueWithNextFilter = true;
-                               break;
-                       }
-               }
-
-               if (continueWithNextFilter)
-                       continue;
-
-               if(optUseRegexpsForIgnoredSubstitutions)
-               {
-
-                       if
-                       (
-                                       ignoredSubstitutionsList.MatchBoth(f, change0, change1)
-                               ||
-                                       optMatchBothWays
-                               && ignoredSubstitutionsList.MatchBoth(f, change1, change0)
-                       )
-                       {
-                               return true; /// a match found
-                       }
-               }
-               else
-               {
-                       if
-                       (
-                                  filter.ChangedPart[0].compare(change0) == 0
-                               && filter.ChangedPart[1].compare(change1) == 0
-                               ||
-                                  optMatchBothWays
-                               && filter.ChangedPart[0].compare(change1) == 0
-                               && filter.ChangedPart[1].compare(change0) == 0
-                       )
-                       {
-                               return true; /// a match found
-                       }
-               }
-       }
-
-       return false; /// n0 match found
-}
-
 /**
  * @brief Walk the diff utils change script, building the WinMerge list of diff blocks
  */
@@ -959,10 +898,6 @@ CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript(struct change * script, const
 
        struct change *next = script;
        
-       const bool optCompletelyBlankOutIgnoredSubstitutions = GetOptionsMgr()->GetBool(OPT_COMPLETELY_BLANK_OUT_IGNORED_SUBSTITUTIONS);
-       const bool optMatchBothWays = GetOptionsMgr()->GetBool(OPT_IGNORED_SUBSTITUTIONS_WORK_BOTH_WAYS);
-       const bool optUseRegexpsForIgnoredSubstitutions = GetOptionsMgr()->GetBool(OPT_USE_REGEXPS_FOR_IGNORED_SUBSTITUTIONS);
-
        while (next != nullptr)
        {
                /* Find a set of changes that belong together.  */
@@ -1025,7 +960,8 @@ CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript(struct change * script, const
                                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)
+                               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 != nullptr && m_pFilterList->HasRegExps())
@@ -1041,66 +977,10 @@ CDiffWrapper::LoadWinMergeDiffsFromDiffUtilsScript(struct change * script, const
                                                op = OP_TRIVIAL;
                                }
 
-                               /// Handling Ignored Substitutions
-                               if
-                               (
-                                          op == OP_DIFF
-                                       //&& next != nullptr
-                                       && QtyLinesLeft > 0
-                                       && QtyLinesRight > 0
-                                       && m_files.GetSize() == 2
-                                       && m_pIgnoredSubstitutionsList
-                                       && m_pIgnoredSubstitutionsList->GetCount()
-                               )
-                               {
-                                       size_t len = file_data_ary[0].linbuf[thisob->line0 + 1] - file_data_ary[0].linbuf[thisob->line0];
-                                       const char* string = file_data_ary[0].linbuf[thisob->line0];
-                                       size_t stringlen = linelen(string, len);
-                                       std::string fullLine0 = std::string(string, stringlen);
-
-                                       len = file_data_ary[1].linbuf[thisob->line1 + 1] - file_data_ary[1].linbuf[thisob->line1];
-                                       string = file_data_ary[1].linbuf[thisob->line1];
-                                       stringlen = linelen(string, len);
-                                       std::string fullLine1 = std::string(string, stringlen);
-
-                                       bool case_sensitive = false;
-                                       bool eol_sensitive = false;
-                                       int whitespace = WHITESPACE_IGNORE_CHANGE;
-                                       int breakType = 1;// breakType==1 means break also on punctuation
-                                       bool byte_level = true;
-                                       std::vector<wdiff> worddiffs = ComputeWordDiffs(
-                                               ucr::toTString(fullLine0.c_str()), ucr::toTString(fullLine1.c_str()),
-                                               case_sensitive, eol_sensitive, whitespace, breakType, byte_level
-                                       );
-
-                                       if (!worddiffs.empty())
-                                       {
-                                               bool lineShouldBeIgnored = true; /// If all changes are ignored the line is ignored
-                                               for (std::vector<strdiff::wdiff>::const_iterator diffIt = worddiffs.begin(); diffIt != worddiffs.end(); ++diffIt)
-                                               {
-                                                       if(!MatchDiffVsIngoredSubstitutions
-                                                       (
-                                                               fullLine0, fullLine1,
-                                                               *diffIt,
-                                                               *m_pIgnoredSubstitutionsList, optUseRegexpsForIgnoredSubstitutions,
-                                                               optMatchBothWays
-                                                       ))
-                                                       {
-                                                               lineShouldBeIgnored = false;
-                                                       }
-                                               }
-
-                                               if (lineShouldBeIgnored)
-                                               {
-                                                       if(optCompletelyBlankOutIgnoredSubstitutions)
-                                                               op = OP_NONE;
-                                                       else
-                                                               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);
                        }
                }
                
@@ -1242,7 +1122,8 @@ 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)
+                                       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())
@@ -1515,51 +1396,14 @@ void CDiffWrapper::SetFilterList(const FilterList* pFilterList)
        }
 }
 
-IgnoredSubstitutionsFilterList* CDiffWrapper::GetIgnoredSubstitutionsList()
+const SubstitutionList* CDiffWrapper::GetSubstitutionList() const
 {
-       return m_pIgnoredSubstitutionsList.get();
+       return m_pSubstitutionList.get();
 }
 
-void CDiffWrapper::SetIgnoredSubstitutionsList(const FilterList* pIgnoredSubstitutionsList0, const FilterList* pIgnoredSubstitutionsList1)
+void CDiffWrapper::SetSubstitutionList(std::shared_ptr<SubstitutionList> pSubstitutionList)
 {
-       m_pIgnoredSubstitutionsList.reset(new IgnoredSubstitutionsFilterList());
-
-       if (!pIgnoredSubstitutionsList0 || pIgnoredSubstitutionsList0->GetCount() == 0)
-       {
-               m_pIgnoredSubstitutionsList.reset();
-               return;
-       }
-
-       const bool optUseRegexpsForIgnoredSubstitutions = GetOptionsMgr()->GetBool(OPT_USE_REGEXPS_FOR_IGNORED_SUBSTITUTIONS);
-
-       for (int f = 0; f < pIgnoredSubstitutionsList0->GetCount(); f++)
-       {
-               std::string s0 = (*pIgnoredSubstitutionsList0)[f].filterAsString;
-               std::string s1 = (*pIgnoredSubstitutionsList1)[f].filterAsString;
-               m_pIgnoredSubstitutionsList->Add(s0, s1, !optUseRegexpsForIgnoredSubstitutions);
-       }
-}
-
-void CDiffWrapper::SetIgnoredSubstitutionsList(const TokenPairList *ignoredSubstitutionsList)
-{
-       m_pIgnoredSubstitutionsList.reset(new IgnoredSubstitutionsFilterList());
-
-       // Remove filterlist if new filter is empty
-       if (!ignoredSubstitutionsList || ignoredSubstitutionsList->GetCount() == 0)
-       {
-               m_pIgnoredSubstitutionsList.reset();
-               return;
-       }
-
-       const bool optUseRegexpsForIgnoredSubstitutions = GetOptionsMgr()->GetBool(OPT_USE_REGEXPS_FOR_IGNORED_SUBSTITUTIONS);
-
-       for (int f = 0; f < ignoredSubstitutionsList->GetCount(); f++)
-       {
-               std::string s0 = ucr::toUTF8(ignoredSubstitutionsList->GetAt(f).filterStr0.c_str());
-               std::string s1 = ucr::toUTF8(ignoredSubstitutionsList->GetAt(f).filterStr1.c_str());
-               if(s0 != s1)
-                       m_pIgnoredSubstitutionsList->Add(s0, s1, !optUseRegexpsForIgnoredSubstitutions);
-       }
+       m_pSubstitutionList = pSubstitutionList;
 }
 
 void CDiffWrapper::SetFilterCommentsSourceDef(const String& ext)