aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2025-02-01 09:39:53 +1100
committerNeil <nyamatongwe@gmail.com>2025-02-01 09:39:53 +1100
commitdb6332fa9933244c45c44063afbdcccb462cfc03 (patch)
treeb09bb8f87572f084ad0e701745059351ed6e86d0
parentbd03d24f8bd44813db8ed1c73c5a46400d94a7cf (diff)
downloadscintilla-mirror-db6332fa9933244c45c44063afbdcccb462cfc03.tar.gz
Use string form for selection undo history as it saves significant space.
On average takes around 20% of SelectionSimple.
-rw-r--r--src/EditModel.cxx26
-rw-r--r--src/EditModel.h23
-rw-r--r--src/Editor.cxx17
-rw-r--r--src/Editor.h2
4 files changed, 21 insertions, 47 deletions
diff --git a/src/EditModel.cxx b/src/EditModel.cxx
index 1f9c2d064..033d79bd2 100644
--- a/src/EditModel.cxx
+++ b/src/EditModel.cxx
@@ -58,21 +58,9 @@ using namespace Scintilla::Internal;
Caret::Caret() noexcept :
active(false), on(false), period(500) {}
-SelectionSimple::SelectionSimple(const Selection &sel) {
- selType = sel.selType;
- if (sel.IsRectangular()) {
- // rectangular or thin
- // Could be large so don't remember each range, just the rectangular bounds then reconstitute when undone
- rangeRectangular = sel.RectangularCopy();
- } else {
- ranges = sel.RangesCopy();
- }
- mainRange = sel.Main();
-}
-
void ModelState::RememberSelectionForUndo(int index, const Selection &sel) {
historyForUndo.indexCurrent = index;
- historyForUndo.ssCurrent = SelectionSimple(sel);
+ historyForUndo.ssCurrent = sel.ToString();
}
void ModelState::ForgetSelectionForUndo() noexcept {
@@ -87,22 +75,22 @@ void ModelState::RememberSelectionOntoStack(int index) {
}
void ModelState::RememberSelectionForRedoOntoStack(int index, const Selection &sel) {
- historyForRedo.stack[index] = SelectionSimple(sel);
+ historyForRedo.stack[index] = sel.ToString();
}
-const SelectionSimple *ModelState::SelectionFromStack(int index, UndoRedo history) const {
+std::string_view ModelState::SelectionFromStack(int index, UndoRedo history) const {
const SelectionHistory &sh = history == UndoRedo::undo ? historyForUndo : historyForRedo;
- std::map<int, SelectionSimple>::const_iterator it = sh.stack.find(index);
+ const SelectionStack::const_iterator it = sh.stack.find(index);
if (it != sh.stack.end()) {
- return &it->second;
+ return it->second;
}
return {};
}
void ModelState::TruncateUndo(int index) {
- std::map<int, SelectionSimple>::iterator itUndo = historyForUndo.stack.find(index);
+ const SelectionStack::const_iterator itUndo = historyForUndo.stack.find(index);
historyForUndo.stack.erase(itUndo, historyForUndo.stack.end());
- std::map<int, SelectionSimple>::iterator itRedo = historyForRedo.stack.find(index);
+ const SelectionStack::const_iterator itRedo = historyForRedo.stack.find(index);
historyForRedo.stack.erase(itRedo, historyForRedo.stack.end());
}
diff --git a/src/EditModel.h b/src/EditModel.h
index f75cece44..b9c331573 100644
--- a/src/EditModel.h
+++ b/src/EditModel.h
@@ -21,26 +21,15 @@ public:
Caret() noexcept;
};
-// Simplified version of selection which won't contain rectangular selection realized
-// into ranges as too much data.
-// Just a type and single range for now.
-
-struct SelectionSimple {
- std::vector<SelectionRange> ranges;
- SelectionRange rangeRectangular;
- size_t mainRange = 0;
- Selection::SelTypes selType = Selection::SelTypes::stream;
-
- SelectionSimple() = default;
- explicit SelectionSimple(const Selection &sel);
-};
-
enum class UndoRedo { undo, redo };
+// Selection stack is sparse so use a map
+using SelectionStack = std::map<int, std::string>;
+
struct SelectionHistory {
int indexCurrent = 0;
- SelectionSimple ssCurrent;
- std::map<int, SelectionSimple> stack;
+ std::string ssCurrent;
+ SelectionStack stack;
};
struct ModelState : ViewState {
@@ -50,7 +39,7 @@ struct ModelState : ViewState {
void ForgetSelectionForUndo() noexcept;
void RememberSelectionOntoStack(int index);
void RememberSelectionForRedoOntoStack(int index, const Selection &sel);
- const SelectionSimple *SelectionFromStack(int index, UndoRedo history) const;
+ std::string_view SelectionFromStack(int index, UndoRedo history) const;
virtual void TruncateUndo(int index) final;
};
diff --git a/src/Editor.cxx b/src/Editor.cxx
index 0d1a221cd..10c694990 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -2403,19 +2403,18 @@ void Editor::RestoreSelection(Sci::Position newPos, UndoRedo history) {
if ((undoSelectionHistoryOption == UndoSelectionHistoryOption::Enabled) && modelState) {
// Undo wants the element after the current as it just undid it
const int index = pdoc->UndoCurrent() + (history == UndoRedo::undo ? 1 : 0);
- const SelectionSimple *pss = modelState->SelectionFromStack(index, history);
- if (pss) {
- sel.selType = pss->selType;
+ const std::string_view ss = modelState->SelectionFromStack(index, history);
+ if (!ss.empty()) {
+ sel = Selection(ss);
if (sel.IsRectangular()) {
- sel.Rectangular() = pss->rangeRectangular;
+ const size_t mainForRectangular = sel.Main();
// Reconstitute ranges from rectangular range
SetRectangularRange();
- } else {
- sel.SetRanges(pss->ranges);
+ // Restore main if possible.
+ if (mainForRectangular < sel.Count()) {
+ sel.SetMain(mainForRectangular);
+ }
}
- // Unsure if this is safe with SetMain potentially failing if document doesn't appear the same.
- // Maybe this can occur if the user changes font or wrap mode?
- sel.SetMain(pss->mainRange);
newPos = -1; // Used selection from stack so don't use position returned from undo/redo.
}
}
diff --git a/src/Editor.h b/src/Editor.h
index 655184a31..a6a484ede 100644
--- a/src/Editor.h
+++ b/src/Editor.h
@@ -178,8 +178,6 @@ constexpr XYScrollOptions operator|(XYScrollOptions a, XYScrollOptions b) noexce
return static_cast<XYScrollOptions>(static_cast<int>(a) | static_cast<int>(b));
}
-struct SelectionStack;
-
/**
*/
class Editor : public EditModel, public DocWatcher {