aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--call/ScintillaCall.cxx14
-rw-r--r--doc/ScintillaDoc.html67
-rw-r--r--doc/ScintillaHistory.html7
-rw-r--r--include/ILoader.h13
-rw-r--r--include/ScintillaCall.h12
-rw-r--r--scripts/ScintillaAPIFacer.py18
-rw-r--r--src/Document.cxx12
-rw-r--r--src/Document.h6
-rw-r--r--src/Editor.cxx14
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>&cir; <a class="toc" href="#MultipleViews">Multiple views</a></td>
<td>&cir; <a class="toc" href="#BackgroundLoadSave">Background loading and saving</a></td>
- <td>&cir; <a class="toc" href="#Folding">Folding</a></td>
+ <td>&cir; <a class="toc" href="#DocumentInterface">Document interface</a></td>
</tr>
<tr>
+ <td>&cir; <a class="toc" href="#Folding">Folding</a></td>
<td>&cir; <a class="toc" href="#LineWrapping">Line wrapping</a></td>
<td>&cir; <a class="toc" href="#Zooming">Zooming</a></td>
- <td>&cir; <a class="toc" href="#LongLines">Long lines</a></td>
</tr>
<tr>
+ <td>&cir; <a class="toc" href="#LongLines">Long lines</a></td>
<td>&cir; <a class="toc" href="#Accessibility">Accessibility</a></td>
<td>&cir; <a class="toc" href="#Lexer">Lexer</a></td>
- <td>&cir; <a class="toc" href="#LexerObjects">Lexer objects</a></td>
</tr>
<tr>
+ <td>&cir; <a class="toc" href="#LexerObjects">Lexer objects</a></td>
<td>&cir; <a class="toc" href="#Notifications">Notifications</a></td>
<td>&cir; <a class="toc" href="#Images">Images</a></td>
- <td>&cir; <a class="toc" href="#GTK">GTK</a></td>
</tr>
<tr>
+ <td>&cir; <a class="toc" href="#GTK">GTK</a></td>
<td>&cir; <a class="toc" href="#ProvisionalMessages"><span class="provisional">Provisional messages</span></a></td>
<td>&cir; <a class="toc" href="#DeprecatedMessages">Deprecated messages</a></td>
- <td>&cir; <a class="toc" href="#EditMessagesNeverSupportedByScintilla">Edit messages never supported by Scintilla</a></td>
</tr>
<tr>
+ <td>&cir; <a class="toc" href="#EditMessagesNeverSupportedByScintilla">Edit messages never supported by Scintilla</a></td>
<td>&cir; <a class="toc" href="#RemovedFeatures">Removed features</a></td>
<td>&cir; <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 &rarr; pointer</a><br />
<a class="message" href="#SCI_SETDOCPOINTER">SCI_SETDOCPOINTER(&lt;unused&gt;, pointer doc)</a><br />
<a class="message" href="#SCI_CREATEDOCUMENT">SCI_CREATEDOCUMENT(position bytes, int documentOptions) &rarr; 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">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S2">// Allow this interface to add methods over time and discover whether new methods available.</span><br />
+<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </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">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S2">// Lifetime control</span><br />
+<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </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">&nbsp; &nbsp; &nbsp; &nbsp; </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: