aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/ChangeHistory.cxx42
-rw-r--r--src/ChangeHistory.h8
-rw-r--r--test/unit/testCellBuffer.cxx49
3 files changed, 83 insertions, 16 deletions
diff --git a/src/ChangeHistory.cxx b/src/ChangeHistory.cxx
index 7295f89af..704f3f1c9 100644
--- a/src/ChangeHistory.cxx
+++ b/src/ChangeHistory.cxx
@@ -30,7 +30,7 @@ namespace Scintilla::Internal {
void ChangeStack::Clear() noexcept {
steps.clear();
- insertions.clear();
+ changes.clear();
}
void ChangeStack::AddStep() {
@@ -39,12 +39,12 @@ void ChangeStack::AddStep() {
void ChangeStack::PushDeletion(Sci::Position positionDeletion, int edition) {
steps.back()++;
- insertions.push_back({ positionDeletion, 0, edition, InsertionSpan::Direction::deletion });
+ changes.push_back({ positionDeletion, 0, edition, ChangeSpan::Direction::deletion });
}
void ChangeStack::PushInsertion(Sci::Position positionInsertion, Sci::Position length, int edition) {
steps.back()++;
- insertions.push_back({ positionInsertion, length, edition, InsertionSpan::Direction::insertion });
+ changes.push_back({ positionInsertion, length, edition, ChangeSpan::Direction::insertion });
}
size_t ChangeStack::PopStep() noexcept {
@@ -53,21 +53,33 @@ size_t ChangeStack::PopStep() noexcept {
return spans;
}
-InsertionSpan ChangeStack::PopSpan() noexcept {
- const InsertionSpan span = insertions.back();
- insertions.pop_back();
+ChangeSpan ChangeStack::PopSpan() noexcept {
+ const ChangeSpan span = changes.back();
+ changes.pop_back();
return span;
}
void ChangeStack::SetSavePoint() noexcept {
// Switch changeUnsaved to changeSaved
- for (InsertionSpan &x : insertions) {
+ for (ChangeSpan &x : changes) {
if (x.edition == changeModified) {
x.edition = changeSaved;
}
}
}
+void ChangeStack::Check() const noexcept {
+#ifdef _DEBUG
+ // Ensure count in steps same as insertions;
+ size_t sizeSteps = 0;
+ for (const size_t c : steps) {
+ sizeSteps += c;
+ }
+ const size_t sizeInsertions = changes.size();
+ assert(sizeSteps == sizeInsertions);
+#endif
+}
+
void ChangeLog::Clear(Sci::Position length) {
changeStack.Clear();
insertEdition.DeleteAll();
@@ -167,13 +179,16 @@ void ChangeLog::PopDeletion(Sci::Position position, Sci::Position deleteLength)
editions->pop_back();
const size_t inserts = changeStack.PopStep();
for (size_t i = 0; i < inserts; i++) {
- const InsertionSpan span = changeStack.PopSpan();
- if (span.direction == InsertionSpan::Direction::insertion) {
+ const ChangeSpan span = changeStack.PopSpan();
+ if (span.direction == ChangeSpan::Direction::insertion) {
insertEdition.FillRange(span.start, span.edition, span.length);
} else {
assert(editions);
assert(editions->back() == span.edition);
editions->pop_back();
+ // Iterating backwards (pop) through changeStack, reverse order of insertion
+ // and original deletion list.
+ // Therefore need to insert at front to recreate original order.
InsertFrontDeletionAt(span.start, span.edition);
}
}
@@ -242,6 +257,7 @@ size_t ChangeLog::DeletionCount(Sci::Position start, Sci::Position length) const
void ChangeLog::Check() const noexcept {
assert(insertEdition.Length() == deleteEdition.Length());
+ changeStack.Check();
}
ChangeHistory::ChangeHistory(Sci::Position length) {
@@ -270,7 +286,7 @@ void ChangeHistory::DeleteRange(Sci::Position position, Sci::Position deleteLeng
if (changeLogReversions) {
changeLogReversions->DeleteRangeSavingHistory(position, deleteLength);
if (reverting) {
- changeLogReversions->PushDeletionAt(position, 1);
+ changeLogReversions->PushDeletionAt(position, changeRevertedOriginal);
}
}
Check();
@@ -349,9 +365,9 @@ int ChangeHistory::EditionAt(Sci::Position pos) const noexcept {
if (changeLogReversions) {
const int editionReversion = changeLogReversions->insertEdition.ValueAt(pos);
if (editionReversion) {
- if (edition < 0)
- return 1;
- return edition ? 4 : 1;
+ if (edition < 0) // Historical revision
+ return changeRevertedOriginal;
+ return edition ? changeRevertedToChange : changeRevertedOriginal;
}
}
return edition;
diff --git a/src/ChangeHistory.h b/src/ChangeHistory.h
index 8a6e745dc..0475a3a6e 100644
--- a/src/ChangeHistory.h
+++ b/src/ChangeHistory.h
@@ -22,27 +22,29 @@ constexpr unsigned int bitSaved = 2;
constexpr unsigned int bitModified = 4;
constexpr unsigned int bitRevertedToModified = 8;
-struct InsertionSpan {
+struct ChangeSpan {
Sci::Position start;
Sci::Position length;
int edition;
enum class Direction { insertion, deletion } direction;
};
+// EditionSet is ordered from oldest to newest, its not really a set
using EditionSet = std::vector<int>;
using EditionSetOwned = std::unique_ptr<EditionSet>;
class ChangeStack {
std::vector<size_t> steps;
- std::vector<InsertionSpan> insertions;
+ std::vector<ChangeSpan> changes;
public:
void Clear() noexcept;
void AddStep();
void PushDeletion(Sci::Position positionDeletion, int edition);
void PushInsertion(Sci::Position positionInsertion, Sci::Position length, int edition);
[[nodiscard]] size_t PopStep() noexcept;
- [[nodiscard]] InsertionSpan PopSpan() noexcept;
+ [[nodiscard]] ChangeSpan PopSpan() noexcept;
void SetSavePoint() noexcept;
+ void Check() const noexcept;
};
struct ChangeLog {
diff --git a/test/unit/testCellBuffer.cxx b/test/unit/testCellBuffer.cxx
index cb69e7756..f7795c9e7 100644
--- a/test/unit/testCellBuffer.cxx
+++ b/test/unit/testCellBuffer.cxx
@@ -633,6 +633,55 @@ TEST_CASE("ChangeHistory") {
}
REQUIRE(il.DeletionCount(0, 10) == 0);
REQUIRE(il.Length() == 10);
+
+ }
+
+ SECTION("Delete Contiguous Backward") {
+ // Deletes that touch
+ constexpr size_t length = 20;
+ constexpr size_t rounds = 8;
+ il.Insert(0, length, false, true);
+ REQUIRE(il.Length() == length);
+ il.SetSavePoint();
+ for (size_t i = 0; i < rounds; i++) {
+ il.DeleteRangeSavingHistory(9-i, 1, false, false);
+ }
+
+ constexpr size_t lengthAfterDeletions = length - rounds;
+ REQUIRE(il.Length() == lengthAfterDeletions);
+ REQUIRE(il.DeletionCount(0, lengthAfterDeletions) == rounds);
+
+ for (size_t j = 0; j < rounds; j++) {
+ il.UndoDeleteStep(2+j, 1, false);
+ }
+
+ // Restored to original
+ REQUIRE(il.DeletionCount(0, length) == 0);
+ REQUIRE(il.Length() == length);
+ }
+
+ SECTION("Delete Contiguous Forward") {
+ // Deletes that touch
+ constexpr size_t length = 20;
+ constexpr size_t rounds = 8;
+ il.Insert(0, length, false, true);
+ REQUIRE(il.Length() == length);
+ il.SetSavePoint();
+ for (size_t i = 0; i < rounds; i++) {
+ il.DeleteRangeSavingHistory(2,1, false, false);
+ }
+
+ constexpr size_t lengthAfterDeletions = length - rounds;
+ REQUIRE(il.Length() == lengthAfterDeletions);
+ REQUIRE(il.DeletionCount(0, lengthAfterDeletions) == rounds);
+
+ for (size_t j = 0; j < rounds; j++) {
+ il.UndoDeleteStep(2, 1, false);
+ }
+
+ // Restored to original
+ REQUIRE(il.Length() == length);
+ REQUIRE(il.DeletionCount(0, length) == 0);
}
}