aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/CellBuffer.cxx
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2024-02-27 15:34:01 +1100
committerNeil <nyamatongwe@gmail.com>2024-02-27 15:34:01 +1100
commitc596111b25cc19cc31945b28dbc00a57f9172689 (patch)
tree6bb71b91dd3bf3574affddd7dee71c458af1bbdc /src/CellBuffer.cxx
parent6c1c08e08029f3daeba6822dec4487e1cddae445 (diff)
downloadscintilla-mirror-c596111b25cc19cc31945b28dbc00a57f9172689.tar.gz
Restore change history to the extent possible when restoring undo history.
Diffstat (limited to 'src/CellBuffer.cxx')
-rw-r--r--src/CellBuffer.cxx133
1 files changed, 74 insertions, 59 deletions
diff --git a/src/CellBuffer.cxx b/src/CellBuffer.cxx
index 320a61639..1ffc749bf 100644
--- a/src/CellBuffer.cxx
+++ b/src/CellBuffer.cxx
@@ -483,7 +483,7 @@ const char *CellBuffer::DeleteChars(Sci::Position position, Sci::Position delete
if (changeHistory) {
changeHistory->DeleteRangeSavingHistory(position, deleteLength,
- uh->BeforeReachableSavePoint(), uh->AfterDetachPoint());
+ uh->BeforeReachableSavePoint(), uh->AfterOrAtDetachPoint());
}
BasicDeleteChars(position, deleteLength);
@@ -1092,24 +1092,26 @@ Action CellBuffer::GetUndoStep() const noexcept {
}
void CellBuffer::PerformUndoStep() {
- const Action actionStep = uh->GetUndoStep();
- if (changeHistory && uh->BeforeOrAtSavePoint()) {
+ const Action previousStep = uh->GetUndoStep();
+ // PreviousBeforeSavePoint and AfterDetachPoint are called since acting on the previous action,
+ // that is currentAction-1
+ if (changeHistory && uh->PreviousBeforeSavePoint()) {
changeHistory->StartReversion();
}
- if (actionStep.at == ActionType::insert) {
- if (substance.Length() < actionStep.lenData) {
+ if (previousStep.at == ActionType::insert) {
+ if (substance.Length() < previousStep.lenData) {
throw std::runtime_error(
"CellBuffer::PerformUndoStep: deletion must be less than document length.");
}
if (changeHistory) {
- changeHistory->DeleteRange(actionStep.position, actionStep.lenData,
- uh->BeforeOrAtSavePoint() && !uh->AfterDetachPoint());
+ changeHistory->DeleteRange(previousStep.position, previousStep.lenData,
+ uh->PreviousBeforeSavePoint() && !uh->AfterDetachPoint());
}
- BasicDeleteChars(actionStep.position, actionStep.lenData);
- } else if (actionStep.at == ActionType::remove) {
- BasicInsertString(actionStep.position, actionStep.data, actionStep.lenData);
+ BasicDeleteChars(previousStep.position, previousStep.lenData);
+ } else if (previousStep.at == ActionType::remove) {
+ BasicInsertString(previousStep.position, previousStep.data, previousStep.lenData);
if (changeHistory) {
- changeHistory->UndoDeleteStep(actionStep.position, actionStep.lenData, uh->AfterDetachPoint());
+ changeHistory->UndoDeleteStep(previousStep.position, previousStep.lenData, uh->AfterDetachPoint());
}
}
uh->CompletedUndoStep();
@@ -1138,7 +1140,7 @@ void CellBuffer::PerformRedoStep() {
} else if (actionStep.at == ActionType::remove) {
if (changeHistory) {
changeHistory->DeleteRangeSavingHistory(actionStep.position, actionStep.lenData,
- uh->BeforeReachableSavePoint(), uh->AfterDetachPoint());
+ uh->BeforeReachableSavePoint(), uh->AfterOrAtDetachPoint());
}
BasicDeleteChars(actionStep.position, actionStep.lenData);
}
@@ -1176,60 +1178,73 @@ int CellBuffer::UndoTentative() const noexcept {
return uh->TentativePoint();
}
+namespace {
+
+void RestoreChangeHistory(const UndoHistory *uh, ChangeHistory *changeHistory) {
+ // Replay all undo actions into changeHistory
+ const int savePoint = uh->SavePoint();
+ const int detachPoint = uh->DetachPoint();
+ const int currentPoint = uh->Current();
+ for (int act = 0; act < uh->Actions(); act++) {
+ const ActionType type = static_cast<ActionType>(uh->Type(act) & ~coalesceFlag);
+ const Sci::Position position = uh->Position(act);
+ const Sci::Position length = uh->Length(act);
+ const bool beforeSave = act < savePoint || ((detachPoint >= 0) && (detachPoint > act));
+ const bool afterDetach = (detachPoint >= 0) && (detachPoint < act);
+ switch (type) {
+ case ActionType::insert:
+ changeHistory->Insert(position, length, true, beforeSave);
+ break;
+ case ActionType::remove:
+ changeHistory->DeleteRangeSavingHistory(position, length, beforeSave, afterDetach);
+ break;
+ default:
+ // Only insertions and deletions go into change history
+ break;
+ }
+ changeHistory->Check();
+ }
+ // Undo back to currentPoint, updating change history
+ for (int act = uh->Actions() - 1; act >= currentPoint; act--) {
+ const ActionType type = static_cast<ActionType>(uh->Type(act) & ~coalesceFlag);
+ const Sci::Position position = uh->Position(act);
+ const Sci::Position length = uh->Length(act);
+ const bool beforeSave = act < savePoint;
+ const bool afterDetach = (detachPoint >= 0) && (detachPoint < act);
+ if (beforeSave) {
+ changeHistory->StartReversion();
+ }
+ switch (type) {
+ case ActionType::insert:
+ changeHistory->DeleteRange(position, length, beforeSave && !afterDetach);
+ break;
+ case ActionType::remove:
+ changeHistory->UndoDeleteStep(position, length, afterDetach);
+ break;
+ default:
+ // Only insertions and deletions go into change history
+ break;
+ }
+ changeHistory->Check();
+ }
+}
+
+}
+
void CellBuffer::SetUndoCurrent(int action) {
uh->SetCurrent(action, Length());
if (changeHistory) {
+ if ((uh->DetachPoint() >= 0) && (uh->SavePoint() >= 0)) {
+ // Can't have a valid save point and a valid detach point at same time
+ uh->DeleteUndoHistory();
+ changeHistory.reset();
+ throw std::runtime_error("UndoHistory::SetCurrent: invalid undo history.");
+ }
const intptr_t sizeChange = uh->Delta(action);
const intptr_t lengthOriginal = Length() - sizeChange;
// Recreate empty change history
changeHistory = std::make_unique<ChangeHistory>(lengthOriginal);
-
- // Replay all undo undo actions into changeHistory
- const int savePoint = uh->SavePoint();
- const int detachPoint = uh->DetachPoint();
- const int currentPoint = uh->Current();
- for (int act = 0; act < uh->Actions(); act++) {
- const ActionType type = static_cast<ActionType>(uh->Type(act) & ~coalesceFlag);
- const Sci::Position position = uh->Position(act);
- const Sci::Position length = uh->Length(act);
- const bool beforeSave = act < savePoint;
- const bool afterDetach = (detachPoint >= 0) && (detachPoint < act);
- switch (type) {
- case ActionType::insert:
- changeHistory->Insert(position, length, true, beforeSave);
- break;
- case ActionType::remove:
- changeHistory->DeleteRangeSavingHistory(position, length, beforeSave, afterDetach);
- break;
- default:
- // Only insertions and deletions go into change history
- break;
- }
- changeHistory->Check();
- }
- // Undo back to currentPoint, updating change history
- for (int act = uh->Actions()-1; act >= currentPoint; act--) {
- const ActionType type = static_cast<ActionType>(uh->Type(act) & ~coalesceFlag);
- const Sci::Position position = uh->Position(act);
- const Sci::Position length = uh->Length(act);
- const bool beforeOrAtSavePoint = (savePoint < 0) || (savePoint >= act);
- const bool afterDetach = (detachPoint >= 0) && (detachPoint < act);
- if (beforeOrAtSavePoint) {
- changeHistory->StartReversion();
- }
- switch (type) {
- case ActionType::insert:
- changeHistory->DeleteRange(position, length, beforeOrAtSavePoint && !afterDetach);
- break;
- case ActionType::remove:
- changeHistory->UndoDeleteStep(position, length, afterDetach);
- break;
- default:
- // Only insertions and deletions go into change history
- break;
- }
- changeHistory->Check();
- }
+ RestoreChangeHistory(uh.get(), changeHistory.get());
if (Length() != changeHistory->Length()) {
uh->DeleteUndoHistory();
changeHistory.reset();