diff options
-rw-r--r-- | src/Selection.cxx | 23 | ||||
-rw-r--r-- | src/Selection.h | 9 | ||||
-rw-r--r-- | test/unit/testSelection.cxx | 32 |
3 files changed, 50 insertions, 14 deletions
diff --git a/src/Selection.cxx b/src/Selection.cxx index 7b517cc4a..20fb1efca 100644 --- a/src/Selection.cxx +++ b/src/Selection.cxx @@ -170,20 +170,15 @@ bool SelectionRange::ContainsCharacter(SelectionPosition spCharacter) const noex } SelectionSegment SelectionRange::Intersect(SelectionSegment check) const noexcept { - const SelectionSegment inOrder(caret, anchor); - if ((inOrder.start <= check.end) || (inOrder.end >= check.start)) { - SelectionSegment portion = check; - if (portion.start < inOrder.start) - portion.start = inOrder.start; - if (portion.end > inOrder.end) - portion.end = inOrder.end; - if (portion.start > portion.end) - return SelectionSegment(); - else - return portion; - } else { - return SelectionSegment(); - } + const SelectionSegment inOrder = AsSegment(); + if ((inOrder.start > check.end) || (inOrder.end < check.start)) { + // Nothing in common, not even touching so return empty *invalid* segment + return {}; + } + return { + std::max(check.start, inOrder.start), + std::min(check.end, inOrder.end) + }; } void SelectionRange::Swap() noexcept { diff --git a/src/Selection.h b/src/Selection.h index 57de92a57..8ffcbb0bb 100644 --- a/src/Selection.h +++ b/src/Selection.h @@ -81,6 +81,12 @@ struct SelectionSegment { end = a; } } + constexpr SelectionSegment(Sci::Position a, Sci::Position b) : + SelectionSegment(SelectionPosition(a), SelectionPosition(b)) { + } + [[nodiscard]] constexpr bool operator ==(const SelectionSegment &other) const noexcept { + return (start == other.start) && (end == other.end); + } bool Empty() const noexcept { return start == end; } @@ -115,6 +121,9 @@ struct SelectionRange { constexpr SelectionRange(Sci::Position caret_, Sci::Position anchor_) noexcept : caret(caret_), anchor(anchor_) { } explicit SelectionRange(std::string_view sv); + SelectionSegment AsSegment() const noexcept { + return {caret, anchor}; + } bool Empty() const noexcept { return anchor == caret; } diff --git a/test/unit/testSelection.cxx b/test/unit/testSelection.cxx index 64148bf61..d708607d2 100644 --- a/test/unit/testSelection.cxx +++ b/test/unit/testSelection.cxx @@ -162,6 +162,38 @@ TEST_CASE("SelectionRange") { REQUIRE(range123Returned == range123); } + SECTION("Intersect") { + constexpr SelectionSegment segmentEmpty; + + // Range from 1 to 2 with 3 virtual spaces + const SelectionRange range123(SelectionPosition(2, 3), SelectionPosition(1)); + const SelectionSegment segment12(1, 2); + const SelectionSegment inside = range123.Intersect(segment12); + REQUIRE(inside == segment12); + + const SelectionSegment segment121(SelectionPosition(1), SelectionPosition(2, 1)); + const SelectionSegment withVirtual = range123.Intersect(segment121); + REQUIRE(withVirtual == segment121); + + const SelectionSegment segment052(SelectionPosition(0), SelectionPosition(5, 2)); + const SelectionSegment internal = range123.Intersect(segment052); // All inside + REQUIRE(internal == range123.AsSegment()); + + const SelectionSegment wayOut(SelectionPosition(100), SelectionPosition(105, 2)); + const SelectionSegment nothing = range123.Intersect(wayOut); + REQUIRE(nothing == segmentEmpty); + + const SelectionSegment edge(1, 1); + const SelectionSegment nowt = range123.Intersect(edge); + REQUIRE(nowt == edge); + + // (0, 1) and (1, 2v3) touch so intersection is a single position. + const SelectionSegment front(0, 1); + const SelectionSegment single(1, 1); + const SelectionSegment thin = range123.Intersect(front); + REQUIRE(thin == single); + } + } TEST_CASE("Selection") { |