From bd53ffcbefe4e7a22fc493b1916939bae5f9dc1d Mon Sep 17 00:00:00 2001
From: Neil
○ Undo and Redo
+ ○ Undo save and restore
○ Change history
- ○ Scrolling and automatic scrolling
+
○ Scrolling and automatic scrolling
○ White space
○ Cursor
- ○ Mouse capture
+
○ Mouse capture
○ Line endings
○ Words
- ○ Styling
+
○ Styling
○ Style definition
○ Element colours
- ○ Selection, caret, and hotspot styles
+
○ Selection, caret, and hotspot styles
○ Character representations
○ Margins
- ○ Annotations
+
○ Annotations
○ End of Line Annotations
○ Other settings
- ○ Brace highlighting
+
○ Brace highlighting
○ Tabs and Indentation Guides
○ Markers
- ○ Indicators
+
○ Indicators
○ Autocompletion
○ User lists
- ○ Call tips
+
○ Call tips
○ Keyboard commands
○ Key bindings
- ○ Popup edit menu
+
○ Popup edit menu
○ Macro recording
○ Printing
- ○ Direct access
+
○ Direct access
○ Multiple views
○ Background loading and saving
- ○ Document interface
+
○ Document interface
○ Folding
○ Line wrapping
- ○ Zooming
+
○ Zooming
○ Long lines
○ Accessibility
- ○ Lexer
+
○ Lexer
○ Lexer objects
○ Notifications
- ○ Images
+
○ Images
○ GTK
○ Provisional messages
- ○ Deprecated messages
+
+
+ ○ Deprecated messages
○ Edit messages never supported by Scintilla
○ Removed features
+
@@ -1988,6 +1992,90 @@ struct Sci_TextToFindFull {
look like typing or deletions that look like multiple uses of the Backspace or Delete keys.
○ Building Scintilla
This feature is unfinished and has limitations. + Restoring undo state is not compatible with change history so turn change history off before restoral. + The operation sequences discussed here are a 'golden path' that has been tested to some extent and calling + the APIs in other circumstances or with out-of-bounds values may cause failures. + The behaviour of tentative actions in save and restore is uncertain as these are meant to be short-term states in language input + and which need to synchronize with a language IME (input method editor).
+ +It is possible to retrieve the undo stack from Scintilla and subsequently restore the state of the stack.
+ +An application may save both the document and its save stack between sessions to enable the user to return + to the same state the next time they edit. + For this to work, the loaded file must be exactly the same as when the undo stack was saved. + If the file was changed, even in minor ways like converting line ends from Windows to Unix style then + the undo actions will not line up so undo may fail completely and will produce unexpected results.
+ +SCI_GETUNDOACTIONS → int
+ SCI_SETUNDOSAVEPOINT(int action)
+ SCI_GETUNDOSAVEPOINT → int
+ SCI_SETUNDOCURRENT(int action)
+ SCI_GETUNDOCURRENT → int
+ SCI_SETUNDOTENTATIVE(int action)
+ SCI_GETUNDOTENTATIVE → int
+ SCI_PUSHUNDOACTIONTYPE(int type, position pos)
+ SCI_CHANGELASTUNDOACTIONTEXT(position length, const char *text)
+ SCI_GETUNDOACTIONTYPE(int action) → int
+ SCI_GETUNDOACTIONPOSITION(int action) → position
+ SCI_GETUNDOACTIONTEXT(int action, char *text) → int
+
+
+ The retrieval APIs are the 'GET*' ones:
+ SCI_GETUNDOACTIONS,
+ SCI_GETUNDOSAVEPOINT,
+ SCI_GETUNDOCURRENT,
+ SCI_GETUNDOTENTATIVE,
+ SCI_GETUNDOACTIONTYPE,
+ SCI_GETUNDOACTIONPOSITION, and
+ SCI_GETUNDOACTIONTEXT.
+
The SCI_GETUNDOACTIONS,
+ SCI_GETUNDOSAVEPOINT, SCI_GETUNDOCURRENT, and
+ SCI_GETUNDOTENTATIVE APIs each return a single value and may be called in any order.
+
The SCI_GETUNDOACTIONTYPE,
+ SCI_GETUNDOACTIONPOSITION, and SCI_GETUNDOACTIONTEXT
+ APIs take an action index and should be called with indices from 0 to one less than the result of
+ SCI_GETUNDOACTIONS.
+ The actions should only be iterated in the positive direction and should start from 0.
+ That is because undo stack data is not all randomly accessible and iterating in other orders may take O(n^2) time.
+ Data may also be inaccurate if a cursor is not initialised first with 0 index calls.
+
Restoration is only possible when the undo state is empty so SCI_EMPTYUNDOBUFFER
+ should be called first if there may already be some undo actions.
The restore APIs are the 'SET*' and others:
+ SCI_SETUNDOSAVEPOINT,
+ SCI_SETUNDOCURRENT,
+ SCI_SETUNDOTENTATIVE,
+ SCI_PUSHUNDOACTIONTYPE, and
+ SCI_CHANGELASTUNDOACTIONTEXT.
+
The history should first be set up with SCI_PUSHUNDOACTIONTYPE, and
+ SCI_CHANGELASTUNDOACTIONTEXT then the save, current, and tentativ points set
+ with SCI_SETUNDOSAVEPOINT, SCI_SETUNDOCURRENT, and
+ SCI_SETUNDOTENTATIVE.
+
SCI_PUSHUNDOACTIONTYPE(int type, position pos) appends an action to the undo stack
+ with a particular type and position then the text and length of that action are set with
+ SCI_CHANGELASTUNDOACTIONTEXT(position length, const char *text).
+
The current implementation may only work when the current and save point are the same and there is no tentative point. +
+Scintilla can display document changes (modified, saved, ...) in the margin or in the text.
diff --git a/include/Scintilla.h b/include/Scintilla.h index 8c555352c..be537abad 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -339,6 +339,18 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP #define SCI_GETCHARACTERCATEGORYOPTIMIZATION 2721 #define SCI_BEGINUNDOACTION 2078 #define SCI_ENDUNDOACTION 2079 +#define SCI_GETUNDOACTIONS 2790 +#define SCI_SETUNDOSAVEPOINT 2791 +#define SCI_GETUNDOSAVEPOINT 2792 +#define SCI_SETUNDOCURRENT 2793 +#define SCI_GETUNDOCURRENT 2794 +#define SCI_SETUNDOTENTATIVE 2795 +#define SCI_GETUNDOTENTATIVE 2796 +#define SCI_PUSHUNDOACTIONTYPE 2797 +#define SCI_CHANGELASTUNDOACTIONTEXT 2798 +#define SCI_GETUNDOACTIONTYPE 2799 +#define SCI_GETUNDOACTIONPOSITION 2800 +#define SCI_GETUNDOACTIONTEXT 2801 #define INDIC_PLAIN 0 #define INDIC_SQUIGGLE 1 #define INDIC_TT 2 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index 918121596..dd7495a6f 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -833,6 +833,42 @@ fun void BeginUndoAction=2078(,) # End a sequence of actions that is undone and redone as a unit. fun void EndUndoAction=2079(,) +# How many undo actions are in the history? +get int GetUndoActions=2790(,) + +# Set action as the save point +set void SetUndoSavePoint=2791(int action,) + +# Which action is the save point? +get int GetUndoSavePoint=2792(,) + +# Set action as the current point +set void SetUndoCurrent=2793(int action,) + +# Which action is the current point? +get int GetUndoCurrent=2794(,) + +# Set action as the tentative point +set void SetUndoTentative=2795(int action,) + +# Which action is the tentative point? +get int GetUndoTentative=2796(,) + +# Push one action onto undo history with no text +fun void PushUndoActionType=2797(int type, position pos) + +# Set the text and length of the most recently pushed action +fun void ChangeLastUndoActionText=2798(position length, string text) + +# What is the type of an action? +get int GetUndoActionType=2799(int action,) + +# What is the position of an action? +get position GetUndoActionPosition=2800(int action,) + +# What is the text of an action? +get int GetUndoActionText=2801(int action, stringresult text) + # Indicator style enumeration and some constants enu IndicatorStyle=INDIC_ val INDIC_PLAIN=0 diff --git a/include/ScintillaCall.h b/include/ScintillaCall.h index 0ce4366d7..47122fcfe 100644 --- a/include/ScintillaCall.h +++ b/include/ScintillaCall.h @@ -245,6 +245,19 @@ public: int CharacterCategoryOptimization(); void BeginUndoAction(); void EndUndoAction(); + int UndoActions(); + void SetUndoSavePoint(int action); + int UndoSavePoint(); + void SetUndoCurrent(int action); + int UndoCurrent(); + void SetUndoTentative(int action); + int UndoTentative(); + void PushUndoActionType(int type, Position pos); + void ChangeLastUndoActionText(Position length, const char *text); + int UndoActionType(int action); + Position UndoActionPosition(int action); + int UndoActionText(int action, char *text); + std::string UndoActionText(int action); void IndicSetStyle(int indicator, Scintilla::IndicatorStyle indicatorStyle); Scintilla::IndicatorStyle IndicGetStyle(int indicator); void IndicSetFore(int indicator, Colour fore); diff --git a/include/ScintillaMessages.h b/include/ScintillaMessages.h index 4b9421242..5cff5ed26 100644 --- a/include/ScintillaMessages.h +++ b/include/ScintillaMessages.h @@ -171,6 +171,18 @@ enum class Message { GetCharacterCategoryOptimization = 2721, BeginUndoAction = 2078, EndUndoAction = 2079, + GetUndoActions = 2790, + SetUndoSavePoint = 2791, + GetUndoSavePoint = 2792, + SetUndoCurrent = 2793, + GetUndoCurrent = 2794, + SetUndoTentative = 2795, + GetUndoTentative = 2796, + PushUndoActionType = 2797, + ChangeLastUndoActionText = 2798, + GetUndoActionType = 2799, + GetUndoActionPosition = 2800, + GetUndoActionText = 2801, IndicSetStyle = 2080, IndicGetStyle = 2081, IndicSetFore = 2082, diff --git a/src/CellBuffer.cxx b/src/CellBuffer.cxx index bfef83da5..b3111914e 100644 --- a/src/CellBuffer.cxx +++ b/src/CellBuffer.cxx @@ -1148,6 +1148,54 @@ void CellBuffer::PerformRedoStep() { uh->CompletedRedoStep(); } +int CellBuffer::UndoActions() const noexcept { + return uh->Actions(); +} + +void CellBuffer::SetUndoSavePoint(int action) noexcept { + uh->SetSavePoint(action); +} + +int CellBuffer::UndoSavePoint() const noexcept { + return uh->SavePoint(); +} + +void CellBuffer::SetUndoCurrent(int action) noexcept { + uh->SetCurrent(action); +} + +int CellBuffer::UndoCurrent() const noexcept { + return uh->Current(); +} + +void CellBuffer::SetUndoTentative(int action) noexcept { + uh->SetTentative(action); +} + +int CellBuffer::UndoTentative() const noexcept { + return uh->TentativePoint(); +} + +int CellBuffer::UndoActionType(int action) const noexcept { + return uh->Type(action); +} + +Sci::Position CellBuffer::UndoActionPosition(int action) const noexcept { + return uh->Position(action); +} + +std::string_view CellBuffer::UndoActionText(int action) const noexcept { + return uh->Text(action); +} + +void CellBuffer::PushUndoActionType(int type, Sci::Position position) { + uh->PushUndoActionType(type, position); +} + +void CellBuffer::ChangeLastUndoActionText(size_t length, const char *text) { + uh->ChangeLastUndoActionText(length, text); +} + void CellBuffer::ChangeHistorySet(bool set) { if (set) { if (!changeHistory && !uh->CanUndo()) { diff --git a/src/CellBuffer.h b/src/CellBuffer.h index 16ed14d6c..5422e92aa 100644 --- a/src/CellBuffer.h +++ b/src/CellBuffer.h @@ -180,6 +180,19 @@ public: Action GetRedoStep() const noexcept; void PerformRedoStep(); + int UndoActions() const noexcept; + void SetUndoSavePoint(int action) noexcept; + int UndoSavePoint() const noexcept; + void SetUndoCurrent(int action) noexcept; + int UndoCurrent() const noexcept; + void SetUndoTentative(int action) noexcept; + int UndoTentative() const noexcept; + int UndoActionType(int action) const noexcept; + Sci::Position UndoActionPosition(int action) const noexcept; + std::string_view UndoActionText(int action) const noexcept; + void PushUndoActionType(int type, Sci::Position position); + void ChangeLastUndoActionText(size_t length, const char *text); + void ChangeHistorySet(bool set); [[nodiscard]] int EditionAt(Sci::Position pos) const noexcept; [[nodiscard]] Sci::Position EditionEndRun(Sci::Position pos) const noexcept; diff --git a/src/Document.cxx b/src/Document.cxx index 306cdb725..52081e1cd 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -351,6 +351,54 @@ void Document::TentativeUndo() { } } +int Document::UndoActions() const noexcept { + return cb.UndoActions(); +} + +void Document::SetUndoSavePoint(int action) noexcept { + cb.SetUndoSavePoint(action); +} + +int Document::UndoSavePoint() const noexcept { + return cb.UndoSavePoint(); +} + +void Document::SetUndoCurrent(int action) noexcept { + cb.SetUndoCurrent(action); +} + +int Document::UndoCurrent() const noexcept { + return cb.UndoCurrent(); +} + +void Document::SetUndoTentative(int action) noexcept { + cb.SetUndoTentative(action); +} + +int Document::UndoTentative() const noexcept { + return cb.UndoTentative(); +} + +int Document::UndoActionType(int action) const noexcept { + return cb.UndoActionType(action); +} + +Sci::Position Document::UndoActionPosition(int action) const noexcept { + return cb.UndoActionPosition(action); +} + +std::string_view Document::UndoActionText(int action) const noexcept { + return cb.UndoActionText(action); +} + +void Document::PushUndoActionType(int type, Sci::Position position) { + cb.PushUndoActionType(type, position); +} + +void Document::ChangeLastUndoActionText(size_t length, const char *text) { + cb.ChangeLastUndoActionText(length, text); +} + int Document::GetMark(Sci::Line line, bool includeChangeHistory) const { int marksHistory = 0; if (includeChangeHistory && (line < LinesTotal())) { diff --git a/src/Document.h b/src/Document.h index af6bb98fd..185066a6c 100644 --- a/src/Document.h +++ b/src/Document.h @@ -406,6 +406,19 @@ public: void TentativeUndo(); bool TentativeActive() const noexcept { return cb.TentativeActive(); } + int UndoActions() const noexcept; + void SetUndoSavePoint(int action) noexcept; + int UndoSavePoint() const noexcept; + void SetUndoCurrent(int action) noexcept; + int UndoCurrent() const noexcept; + void SetUndoTentative(int action) noexcept; + int UndoTentative() const noexcept; + int UndoActionType(int action) const noexcept; + Sci::Position UndoActionPosition(int action) const noexcept; + std::string_view UndoActionText(int action) const noexcept; + void PushUndoActionType(int type, Sci::Position position); + void ChangeLastUndoActionText(size_t length, const char *text); + void ChangeHistorySet(bool set) { cb.ChangeHistorySet(set); } [[nodiscard]] int EditionAt(Sci::Position pos) const noexcept { return cb.EditionAt(pos); } [[nodiscard]] Sci::Position EditionEndRun(Sci::Position pos) const noexcept { return cb.EditionEndRun(pos); } diff --git a/src/Editor.cxx b/src/Editor.cxx index 2d7d07e22..b8ed636d3 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -6586,6 +6586,49 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { pdoc->EndUndoAction(); return 0; + case Message::GetUndoActions: + return pdoc->UndoActions(); + + case Message::SetUndoSavePoint: + pdoc->SetUndoSavePoint(static_cast