From 6658e397e2d0447bef4c5dd1db1c38d5d7917ac9 Mon Sep 17 00:00:00 2001 From: Zufu Liu Date: Sun, 15 Oct 2023 08:46:43 +1100 Subject: Bug [#2405]. Fix incorrect substitution when searching for a regular expression backwards. --- doc/ScintillaHistory.html | 4 ++++ src/Document.cxx | 8 ++++++++ test/unit/testDocument.cxx | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index 5a54725a2..7d1d9f48f 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -595,6 +595,10 @@ Notepad++ Issue #13442.
  • + Fix incorrect substitution when searching for a regular expression backwards. + Bug #2405. +
  • +
  • For Cocoa, fix invisible text on macOS 14 Sonoma. Bug #2402.
  • diff --git a/src/Document.cxx b/src/Document.cxx index 0365b24db..a45479e4b 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -3294,7 +3294,11 @@ Sci::Position BuiltinRegex::FindText(Document *doc, Sci::Position minPos, Sci::P if ((resr.increment == -1) && !searchforLineStart) { // Check for the last match on this line. int repetitions = 1000; // Break out of infinite loop + RESearch::MatchPositions bopat{}; + RESearch::MatchPositions eopat{}; while (success && (search.eopat[0] <= endOfLine) && (repetitions--)) { + bopat = search.bopat; + eopat = search.eopat; success = search.Execute(di, pos+1, endOfLine); if (success) { if (search.eopat[0] <= minPos) { @@ -3305,6 +3309,10 @@ Sci::Position BuiltinRegex::FindText(Document *doc, Sci::Position minPos, Sci::P } } } + if (!success) { + search.bopat = bopat; + search.eopat = eopat; + } } break; } diff --git a/test/unit/testDocument.cxx b/test/unit/testDocument.cxx index 3cfb54db4..4ed1dbbbd 100644 --- a/test/unit/testDocument.cxx +++ b/test/unit/testDocument.cxx @@ -453,6 +453,52 @@ TEST_CASE("Document") { REQUIRE(doc.NextPosition(15, -1) == 14); } + SECTION("RegexSearchAndSubstitution") { + DocPlus doc("\n\r\r\n 1a\xCE\x93z \n\r\r\n 2b\xCE\x93y \n\r\r\n", CpUtf8);// 1a gamma z 2b gamma y + const std::string finding = R"(\d+(\w+))"; + Sci::Position lengthFinding = finding.length(); + Sci::Position location = doc.FindNeedle(finding, FindOption::RegExp | FindOption::Posix, &lengthFinding); + REQUIRE(location == 5); + REQUIRE(lengthFinding == 5); + + const std::string_view substituteText = R"(\t\1\n)"; + Sci::Position lengthsubstitute = substituteText.length(); + std::string substituted = doc.document.SubstituteByPosition(substituteText.data(), &lengthsubstitute); + REQUIRE(lengthsubstitute == 6); + REQUIRE(substituted == "\ta\xCE\x93z\n"); + + lengthFinding = finding.length(); + location = doc.FindNeedleReverse(finding, FindOption::RegExp | FindOption::Posix, &lengthFinding); + REQUIRE(location == 16); + REQUIRE(lengthFinding == 5); + + lengthsubstitute = substituteText.length(); + substituted = doc.document.SubstituteByPosition(substituteText.data(), &lengthsubstitute); + REQUIRE(lengthsubstitute == 6); + REQUIRE(substituted == "\tb\xCE\x93y\n"); + + #ifndef NO_CXX11_REGEX + lengthFinding = finding.length(); + location = doc.FindNeedle(finding, FindOption::RegExp | FindOption::Cxx11RegEx, &lengthFinding); + REQUIRE(location == 5); + REQUIRE(lengthFinding == 5); + + lengthsubstitute = substituteText.length(); + substituted = doc.document.SubstituteByPosition(substituteText.data(), &lengthsubstitute); + REQUIRE(lengthsubstitute == 6); + REQUIRE(substituted == "\ta\xCE\x93z\n"); + + lengthFinding = finding.length(); + location = doc.FindNeedleReverse(finding, FindOption::RegExp | FindOption::Cxx11RegEx, &lengthFinding); + REQUIRE(location == 16); + REQUIRE(lengthFinding == 5); + + lengthsubstitute = substituteText.length(); + substituted = doc.document.SubstituteByPosition(substituteText.data(), &lengthsubstitute); + REQUIRE(lengthsubstitute == 6); + REQUIRE(substituted == "\tb\xCE\x93y\n"); + #endif + } } TEST_CASE("Words") { -- cgit v1.2.3