diff options
-rw-r--r-- | call/ScintillaCall.cxx | 14 | ||||
-rw-r--r-- | doc/ScintillaDoc.html | 67 | ||||
-rw-r--r-- | doc/ScintillaHistory.html | 7 | ||||
-rw-r--r-- | include/ILoader.h | 13 | ||||
-rw-r--r-- | include/ScintillaCall.h | 12 | ||||
-rw-r--r-- | scripts/ScintillaAPIFacer.py | 18 | ||||
-rw-r--r-- | src/Document.cxx | 12 | ||||
-rw-r--r-- | src/Document.h | 6 | ||||
-rw-r--r-- | src/Editor.cxx | 14 |
9 files changed, 124 insertions, 39 deletions
diff --git a/call/ScintillaCall.cxx b/call/ScintillaCall.cxx index 99e400e28..98e1dbd3e 100644 --- a/call/ScintillaCall.cxx +++ b/call/ScintillaCall.cxx @@ -2071,11 +2071,11 @@ void ScintillaCall::SetViewEOL(bool visible) { Call(Message::SetViewEOL, visible); } -void *ScintillaCall::DocPointer() { - return reinterpret_cast<void *>(Call(Message::GetDocPointer)); +IDocumentEditable *ScintillaCall::DocPointer() { + return reinterpret_cast<IDocumentEditable *>(Call(Message::GetDocPointer)); } -void ScintillaCall::SetDocPointer(void *doc) { +void ScintillaCall::SetDocPointer(IDocumentEditable *doc) { CallPointer(Message::SetDocPointer, 0, doc); } @@ -2151,15 +2151,15 @@ int ScintillaCall::Zoom() { return static_cast<int>(Call(Message::GetZoom)); } -void *ScintillaCall::CreateDocument(Position bytes, Scintilla::DocumentOption documentOptions) { - return reinterpret_cast<void *>(Call(Message::CreateDocument, bytes, static_cast<intptr_t>(documentOptions))); +IDocumentEditable *ScintillaCall::CreateDocument(Position bytes, Scintilla::DocumentOption documentOptions) { + return reinterpret_cast<IDocumentEditable *>(Call(Message::CreateDocument, bytes, static_cast<intptr_t>(documentOptions))); } -void ScintillaCall::AddRefDocument(void *doc) { +void ScintillaCall::AddRefDocument(IDocumentEditable *doc) { CallPointer(Message::AddRefDocument, 0, doc); } -void ScintillaCall::ReleaseDocument(void *doc) { +void ScintillaCall::ReleaseDocument(IDocumentEditable *doc) { CallPointer(Message::ReleaseDocument, 0, doc); } diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html index 27a542e90..3035d2210 100644 --- a/doc/ScintillaDoc.html +++ b/doc/ScintillaDoc.html @@ -129,7 +129,7 @@ <h1>Scintilla Documentation</h1> - <p>Last edited 5 November 2023 NH</p> + <p>Last edited 19 December 2023 NH</p> <p style="background:#90F0C0">Scintilla 5 has moved the lexers from Scintilla into a new <a href="Lexilla.html">Lexilla</a> project.<br /> @@ -402,34 +402,35 @@ <tr> <td>○ <a class="toc" href="#MultipleViews">Multiple views</a></td> <td>○ <a class="toc" href="#BackgroundLoadSave">Background loading and saving</a></td> - <td>○ <a class="toc" href="#Folding">Folding</a></td> + <td>○ <a class="toc" href="#DocumentInterface">Document interface</a></td> </tr> <tr> + <td>○ <a class="toc" href="#Folding">Folding</a></td> <td>○ <a class="toc" href="#LineWrapping">Line wrapping</a></td> <td>○ <a class="toc" href="#Zooming">Zooming</a></td> - <td>○ <a class="toc" href="#LongLines">Long lines</a></td> </tr> <tr> + <td>○ <a class="toc" href="#LongLines">Long lines</a></td> <td>○ <a class="toc" href="#Accessibility">Accessibility</a></td> <td>○ <a class="toc" href="#Lexer">Lexer</a></td> - <td>○ <a class="toc" href="#LexerObjects">Lexer objects</a></td> </tr> <tr> + <td>○ <a class="toc" href="#LexerObjects">Lexer objects</a></td> <td>○ <a class="toc" href="#Notifications">Notifications</a></td> <td>○ <a class="toc" href="#Images">Images</a></td> - <td>○ <a class="toc" href="#GTK">GTK</a></td> </tr> <tr> + <td>○ <a class="toc" href="#GTK">GTK</a></td> <td>○ <a class="toc" href="#ProvisionalMessages"><span class="provisional">Provisional messages</span></a></td> <td>○ <a class="toc" href="#DeprecatedMessages">Deprecated messages</a></td> - <td>○ <a class="toc" href="#EditMessagesNeverSupportedByScintilla">Edit messages never supported by Scintilla</a></td> </tr> <tr> + <td>○ <a class="toc" href="#EditMessagesNeverSupportedByScintilla">Edit messages never supported by Scintilla</a></td> <td>○ <a class="toc" href="#RemovedFeatures">Removed features</a></td> <td>○ <a class="toc" href="#BuildingScintilla">Building Scintilla</a></td> </tr> @@ -7203,9 +7204,11 @@ sptr_t CallScintilla(unsigned int iMessage, uptr_t wParam, sptr_t lParam){ windows (for use with splitter windows).</p> <p>These messages use <code>pointer</code> returns and arguments to refer to documents. - They point to internal objects inside Scintilla and should be treated as an opaque <code>void*</code>. That - is, you can use and store the pointer as described in this section but you should not - dereference it.</p> + They point to <a class="seealso" href="#IDocumentEditable" style="background:#FFB000">IDocumentEditable</a> objects inside + Scintilla. + The <code>IDocumentEditable</code> interface is provisional and may change. + Client code can call <code>IDocumentEditable</code> methods. + Clients may just treat these as opaque <code>void*</code> values that are received from and passed to Scintilla without dereferencing.</p> <code><a class="message" href="#SCI_GETDOCPOINTER">SCI_GETDOCPOINTER → pointer</a><br /> <a class="message" href="#SCI_SETDOCPOINTER">SCI_SETDOCPOINTER(<unused>, pointer doc)</a><br /> <a class="message" href="#SCI_CREATEDOCUMENT">SCI_CREATEDOCUMENT(position bytes, int documentOptions) → pointer</a><br /> @@ -7339,7 +7342,7 @@ sptr_t CallScintilla(unsigned int iMessage, uptr_t wParam, sptr_t lParam){ <p>The <code class="parameter">documentOptions</code> argument is described in the <a class="seealso" href="#documentOptions"><code>SCI_CREATEDOCUMENT</code></a> section.</p> -<h4>ILoader</h4> +<h4 id="ILoader">ILoader</h4> <div class="highlighted"> <span class="S5">class</span><span class="S0"> </span>ILoader<span class="S0"> </span><span class="S10">{</span><br /> @@ -7356,7 +7359,9 @@ sptr_t CallScintilla(unsigned int iMessage, uptr_t wParam, sptr_t lParam){ If a failure occurs in <code>AddData</code> or in a file reading call then loading can be abandoned and the loader released with the <code>Release</code> call. When the whole file has been read, <code>ConvertToDocument</code> should be called to produce a Scintilla - document pointer. The newly created document will have a reference count of 1 in the same way as a document pointer + document pointer. This pointer can be treated as a <code>void*</code> cookie to pass to other APIs or cast to a + <a class="seealso" href="#IDocumentEditable" style="background:#FFB000">IDocumentEditable*</a> pointer. + The newly created document will have a reference count of 1 in the same way as a document pointer returned from <a class="seealso" href="#SCI_CREATEDOCUMENT">SCI_CREATEDOCUMENT</a>. There is no need to call <code>Release</code> after <code>ConvertToDocument</code>.</p> @@ -7373,6 +7378,46 @@ sptr_t CallScintilla(unsigned int iMessage, uptr_t wParam, sptr_t lParam){ The application may then decide to ignore the modification or to terminate the background saving thread and reenable modification before returning from the notification.</p> + <h2 id="DocumentInterface" class="provisional">Document interface</h2> + + <p>Applications may want to manipulate documents that are not visible and the provisional <code>IDocumentEditable</code> + interface can be used for this.</p> + + <p><code>IDocumentEditable</code> allows more direct access to functionality and is faster than calling Scintilla APIs.</p> + + <p><code>IDocumentEditable</code> pointers are returned by + <a class="seealso" href="#SCI_CREATEDOCUMENT">SCI_CREATEDOCUMENT</a>, + <a class="seealso" href="#SCI_GETDOCPOINTER">SCI_GETDOCPOINTER</a>, and + <a class="seealso" href="#ILoader">ILoader::ConvertToDocument</a>.</p> + + <p>They may be passed to + <a class="seealso" href="#SCI_ADDREFDOCUMENT">SCI_ADDREFDOCUMENT</a>, + <a class="seealso" href="#SCI_RELEASEDOCUMENT">SCI_RELEASEDOCUMENT</a>, and + <a class="seealso" href="#SCI_SETDOCPOINTER">SCI_SETDOCPOINTER</a>, + .</p> + +<h4 id="IDocumentEditable">IDocumentEditable</h4> + +<div class="highlighted" style="background:#FFD270;border: 1px solid #FFBB00"> +<span><span class="S5">class</span><span class="S0"> </span>IDocumentEditable<span class="S0"> </span><span class="S10">{</span><br /> +<span class="S5">public</span><span class="S10">:</span><br /> +<span class="S0"> </span><span class="S2">// Allow this interface to add methods over time and discover whether new methods available.</span><br /> +<span class="S0"> </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>DEVersion<span class="S10">()</span><span class="S0"> </span><span class="S5">const</span><span class="S0"> </span><span class="S5">noexcept</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br /> +<br /> +<span class="S0"> </span><span class="S2">// Lifetime control</span><br /> +<span class="S0"> </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>AddRef<span class="S10">()</span><span class="S0"> </span><span class="S5">noexcept</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br /> +<span class="S0"> </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>Release<span class="S10">()</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br /> +<span class="S10">};</span><br /> +<span class="S0"></span></span> +</div> + + <p>The <code>IDocumentEditable</code> interface is being developed and more methods will be added in the future. + Its also possible that methods will change signatures or be removed. + Thus the feature is provisional and users should be aware that they may have to modify client code in response to these changes.</p> + + <p><code>DEVersion</code> will return 0 while <code>IDocumentEditable</code> is provisional and will return 1 + for the first stable release. After that, it will be incremented when new methods are added.</p> + <h2 id="Folding">Folding</h2> <p>The fundamental operation in folding is making lines invisible or visible. Line visibility diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index 00023b102..a3d44d4ae 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -591,6 +591,13 @@ Released 18 November 2023. </li> <li> + Add IDocumentEditable interface to allow efficient interaction with document objects which may not be visible in + a Scintilla instance. This feature is provisonal and may change before being declared stable. + For better type-safety, the ScintillaCall C++ API uses IDocumentEditable* where void* was used before which may require + changes to client code that uses document pointer APIs + DocPointer, SetDocPointer, CreateDocument, AddRefDocument, and ReleaseDocument. + </li> + <li> Ctrl-click on a selection deselects it in multiple selection mode. </li> <li> diff --git a/include/ILoader.h b/include/ILoader.h index 2fa69f527..5d2eb2571 100644 --- a/include/ILoader.h +++ b/include/ILoader.h @@ -1,6 +1,7 @@ // Scintilla source code edit control /** @file ILoader.h ** Interface for loading into a Scintilla document from a background thread. + ** Interface for manipulating a document without a view. **/ // Copyright 1998-2017 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. @@ -20,6 +21,18 @@ public: virtual void * SCI_METHOD ConvertToDocument() = 0; }; +static constexpr int deRelease0 = 0; + +class IDocumentEditable { +public: + // Allow this interface to add methods over time and discover whether new methods available. + virtual int SCI_METHOD DEVersion() const noexcept = 0; + + // Lifetime control + virtual int SCI_METHOD AddRef() noexcept = 0; + virtual int SCI_METHOD Release() = 0; +}; + } #endif diff --git a/include/ScintillaCall.h b/include/ScintillaCall.h index 1a1a1e0f2..0ce4366d7 100644 --- a/include/ScintillaCall.h +++ b/include/ScintillaCall.h @@ -20,6 +20,8 @@ struct TextRangeFull; struct TextToFindFull; struct RangeToFormatFull; +class IDocumentEditable; + using FunctionDirect = intptr_t(*)(intptr_t ptr, unsigned int iMessage, uintptr_t wParam, intptr_t lParam, int *pStatus); struct Failure { @@ -561,8 +563,8 @@ public: Position BraceMatchNext(Position pos, Position startPos); bool ViewEOL(); void SetViewEOL(bool visible); - void *DocPointer(); - void SetDocPointer(void *doc); + IDocumentEditable *DocPointer(); + void SetDocPointer(IDocumentEditable *doc); void SetModEventMask(Scintilla::ModificationFlags eventMask); Position EdgeColumn(); void SetEdgeColumn(Position column); @@ -581,9 +583,9 @@ public: bool SelectionIsRectangle(); void SetZoom(int zoomInPoints); int Zoom(); - void *CreateDocument(Position bytes, Scintilla::DocumentOption documentOptions); - void AddRefDocument(void *doc); - void ReleaseDocument(void *doc); + IDocumentEditable *CreateDocument(Position bytes, Scintilla::DocumentOption documentOptions); + void AddRefDocument(IDocumentEditable *doc); + void ReleaseDocument(IDocumentEditable *doc); Scintilla::DocumentOption DocumentOptions(); Scintilla::ModificationFlags ModEventMask(); void SetCommandEvents(bool commandEvents); diff --git a/scripts/ScintillaAPIFacer.py b/scripts/ScintillaAPIFacer.py index f26389abb..9caa1ea7f 100644 --- a/scripts/ScintillaAPIFacer.py +++ b/scripts/ScintillaAPIFacer.py @@ -55,7 +55,9 @@ deadValues = [ ] def ActualTypeName(type, identifier=None): - if type in typeAliases: + if type == "pointer" and identifier in ["doc", "DocPointer", "CreateDocument"]: + return "IDocumentEditable *" + elif type in typeAliases: return typeAliases[type] else: return type @@ -63,6 +65,8 @@ def ActualTypeName(type, identifier=None): def IsEnumeration(s): if s in ["Position", "Line", "Colour", "ColourAlpha"]: return False + if s.endswith("*"): + return False return s[:1].isupper() def JoinTypeAndIdentifier(type, identifier): @@ -219,7 +223,7 @@ def HMethods(f): if v["FeatureType"] in ["fun", "get", "set"]: if v["FeatureType"] == "get" and name.startswith("Get"): name = name[len("Get"):] - retType = ActualTypeName(v["ReturnType"]) + retType = ActualTypeName(v["ReturnType"], name) if IsEnumeration(retType): retType = namespace + retType parameters, args, callName = ParametersArgsCallname(v) @@ -241,21 +245,21 @@ def CXXMethods(f): msgName = "Message::" + name if v["FeatureType"] == "get" and name.startswith("Get"): name = name[len("Get"):] - retType = ActualTypeName(v["ReturnType"]) + retType = ActualTypeName(v["ReturnType"], name) parameters, args, callName = ParametersArgsCallname(v) returnIfNeeded = "return " if retType != "void" else "" out.append(JoinTypeAndIdentifier(retType, "ScintillaCall::" + name) + "(" + parameters + ")" + " {") retCast = "" retCastEnd = "" - if retType not in basicTypes or retType in ["int", "Colour", "ColourAlpha"]: + if retType.endswith("*"): + retCast = "reinterpret_cast<" + retType + ">(" + retCastEnd = ")" + elif retType not in basicTypes or retType in ["int", "Colour", "ColourAlpha"]: if IsEnumeration(retType): retType = namespace + retType retCast = "static_cast<" + retType + ">(" retCastEnd = ")" - elif retType in ["void *"]: - retCast = "reinterpret_cast<" + retType + ">(" - retCastEnd = ")" out.append("\t" + returnIfNeeded + retCast + callName + "(" + msgName + args + ")" + retCastEnd + ";") out.append("}") out.append("") diff --git a/src/Document.cxx b/src/Document.cxx index dcb087930..d67cac25e 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -184,7 +184,7 @@ Document::~Document() { } // Increase reference count and return its previous value. -int Document::AddRef() { +int SCI_METHOD Document::AddRef() noexcept { return refCount++; } @@ -461,6 +461,10 @@ Sci_Position SCI_METHOD Document::LineEnd(Sci_Position line) const { return cb.LineEnd(line); } +int SCI_METHOD Document::DEVersion() const noexcept { + return deRelease0; +} + void SCI_METHOD Document::SetErrorStatus(int status) { // Tell the watchers an error has occurred. for (const WatcherWithUserData &watcher : watchers) { @@ -1341,8 +1345,12 @@ int SCI_METHOD Document::AddData(const char *data, Sci_Position length) { return static_cast<int>(Status::Ok); } +IDocumentEditable *Document::AsDocumentEditable() noexcept { + return static_cast<IDocumentEditable *>(this); +} + void * SCI_METHOD Document::ConvertToDocument() { - return this; + return AsDocumentEditable(); } Sci::Position Document::Undo() { diff --git a/src/Document.h b/src/Document.h index f7f4eeedd..9f51fc719 100644 --- a/src/Document.h +++ b/src/Document.h @@ -259,7 +259,7 @@ struct CharacterExtracted { /** */ -class Document : PerLine, public Scintilla::IDocument, public Scintilla::ILoader { +class Document : PerLine, public Scintilla::IDocument, public Scintilla::ILoader, public Scintilla::IDocumentEditable { public: /** Used to pair watcher pointer with user data. */ @@ -329,7 +329,7 @@ public: Document &operator=(Document &&) = delete; ~Document() override; - int AddRef(); + int SCI_METHOD AddRef() noexcept override; int SCI_METHOD Release() override; // From PerLine @@ -347,6 +347,7 @@ public: int SCI_METHOD Version() const override { return Scintilla::dvRelease4; } + int SCI_METHOD DEVersion() const noexcept override; void SCI_METHOD SetErrorStatus(int status) override; @@ -383,6 +384,7 @@ public: Sci::Position InsertString(Sci::Position position, std::string_view sv); void ChangeInsertion(const char *s, Sci::Position length); int SCI_METHOD AddData(const char *data, Sci_Position length) override; + IDocumentEditable *AsDocumentEditable() noexcept; void * SCI_METHOD ConvertToDocument() override; Sci::Position Undo(); Sci::Position Redo(); diff --git a/src/Editor.cxx b/src/Editor.cxx index 28d680d7a..8f29d3a8f 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -6079,6 +6079,10 @@ constexpr Selection::SelTypes SelTypeFromMode(SelectionMode mode) { } } +sptr_t SPtrFromPtr(void *ptr) noexcept { + return reinterpret_cast<sptr_t>(ptr); +} + } void Editor::SetSelectionMode(uptr_t wParam, bool setMoveExtends) { @@ -8216,11 +8220,11 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { break; case Message::GetDocPointer: - return reinterpret_cast<sptr_t>(pdoc); + return SPtrFromPtr(pdoc->AsDocumentEditable()); case Message::SetDocPointer: CancelModes(); - SetDocPointer(static_cast<Document *>(PtrFromSPtr(lParam))); + SetDocPointer(static_cast<Document *>(static_cast<IDocumentEditable *>(PtrFromSPtr(lParam)))); return 0; case Message::CreateDocument: { @@ -8228,15 +8232,15 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { doc->AddRef(); doc->Allocate(PositionFromUPtr(wParam)); pcs = ContractionStateCreate(pdoc->IsLarge()); - return reinterpret_cast<sptr_t>(doc); + return SPtrFromPtr(doc->AsDocumentEditable()); } case Message::AddRefDocument: - (static_cast<Document *>(PtrFromSPtr(lParam)))->AddRef(); + (static_cast<IDocumentEditable *>(PtrFromSPtr(lParam)))->AddRef(); break; case Message::ReleaseDocument: - (static_cast<Document *>(PtrFromSPtr(lParam)))->Release(); + (static_cast<IDocumentEditable *>(PtrFromSPtr(lParam)))->Release(); break; case Message::GetDocumentOptions: |