From fc5004a9e14cfd5c462abca0c8af3cab614aa48d Mon Sep 17 00:00:00 2001 From: Neil Date: Thu, 23 Apr 2026 10:42:27 +1000 Subject: Add error status SC_STATUS_OUTSIDE_DOCUMENT that is set when operations are attempted on a position outside the document. Positions are checked earlier to prevent actions partly succeeding. This is implemented with a new exception type Failure which should be caught by platform layer's API handling code to produce a more granular error status. --- cocoa/ScintillaCocoa.mm | 2 ++ doc/ScintillaDoc.html | 10 ++++++++++ doc/ScintillaHistory.html | 7 +++++++ gtk/ScintillaGTK.cxx | 2 ++ include/Scintilla.h | 1 + include/Scintilla.iface | 1 + include/ScintillaTypes.h | 1 + qt/ScintillaEditBase/ScintillaQt.cpp | 2 ++ src/CellBuffer.h | 5 +++++ src/Document.cxx | 9 ++++++++- src/Document.h | 1 + src/Editor.cxx | 3 +++ win32/ScintillaWin.cxx | 2 ++ 13 files changed, 45 insertions(+), 1 deletion(-) diff --git a/cocoa/ScintillaCocoa.mm b/cocoa/ScintillaCocoa.mm index 8a9af4058..cc4e01c34 100644 --- a/cocoa/ScintillaCocoa.mm +++ b/cocoa/ScintillaCocoa.mm @@ -963,6 +963,8 @@ sptr_t ScintillaCocoa::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { } } catch (std::bad_alloc &) { errorStatus = Status::BadAlloc; + } catch (Failure &failure) { + errorStatus = failure.status; } catch (...) { errorStatus = Status::Failure; } diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html index 3189a001a..c21bd2e29 100644 --- a/doc/ScintillaDoc.html +++ b/doc/ScintillaDoc.html @@ -958,6 +958,12 @@ struct Sci_TextRangeFull { Memory is exhausted + + SC_STATUS_OUTSIDE_DOCUMENT + 3 + An operation was attempted on a position that is outside the document + + SC_STATUS_WARN_REGEX 1001 @@ -967,6 +973,10 @@ struct Sci_TextRangeFull { +

To more easily check the status of APIs, applications should call the direct status function using + SCI_GETDIRECTSTATUSFUNCTION. +

+

Selection

Scintilla maintains a selection that stretches between two points, the anchor and the diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index ea660ae37..fdcde25f9 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -606,6 +606,13 @@ Released 26 March 2026.

  • + Add error status SC_STATUS_OUTSIDE_DOCUMENT that is set when operations are attempted on a position + outside the document. + Positions are checked earlier to prevent actions partly succeeding. + Incomplete actions could lead to features that are out of synchronization + like change history referring to text that has been deleted. +
  • +
  • On Win32 with DirectWrite in a GDI scaled application, draw sharper text in autocompletion lists. Bug #2505.
  • diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index 686a8c13f..b8a7c354a 100755 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -947,6 +947,8 @@ sptr_t ScintillaGTK::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { } } catch (std::bad_alloc &) { errorStatus = Status::BadAlloc; + } catch (Failure &failure) { + errorStatus = failure.status; } catch (...) { errorStatus = Status::Failure; } diff --git a/include/Scintilla.h b/include/Scintilla.h index 94a66d4f8..7f12703d3 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -863,6 +863,7 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP #define SC_STATUS_OK 0 #define SC_STATUS_FAILURE 1 #define SC_STATUS_BADALLOC 2 +#define SC_STATUS_OUTSIDE_DOCUMENT 3 #define SC_STATUS_WARN_START 1000 #define SC_STATUS_WARN_REGEX 1001 #define SCI_SETSTATUS 2382 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index d98ac8358..ddb025c50 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -2291,6 +2291,7 @@ enu Status=SC_STATUS_ val SC_STATUS_OK=0 val SC_STATUS_FAILURE=1 val SC_STATUS_BADALLOC=2 +val SC_STATUS_OUTSIDE_DOCUMENT=3 val SC_STATUS_WARN_START=1000 val SC_STATUS_WARN_REGEX=1001 diff --git a/include/ScintillaTypes.h b/include/ScintillaTypes.h index a1e55c203..cc5f03815 100644 --- a/include/ScintillaTypes.h +++ b/include/ScintillaTypes.h @@ -432,6 +432,7 @@ enum class Status { Ok = 0, Failure = 1, BadAlloc = 2, + OutsideDocument = 3, WarnStart = 1000, RegEx = 1001, }; diff --git a/qt/ScintillaEditBase/ScintillaQt.cpp b/qt/ScintillaEditBase/ScintillaQt.cpp index d5e6eb7b0..5e9d262a4 100644 --- a/qt/ScintillaEditBase/ScintillaQt.cpp +++ b/qt/ScintillaEditBase/ScintillaQt.cpp @@ -768,6 +768,8 @@ sptr_t ScintillaQt::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) } } catch (std::bad_alloc &) { errorStatus = Status::BadAlloc; + } catch (Failure &failure) { + errorStatus = failure.status; } catch (...) { errorStatus = Status::Failure; } diff --git a/src/CellBuffer.h b/src/CellBuffer.h index d54d2be8d..11479f14a 100644 --- a/src/CellBuffer.h +++ b/src/CellBuffer.h @@ -10,6 +10,11 @@ namespace Scintilla::Internal { +struct Failure : public std::runtime_error { + Status status; + Failure(Status status_) : std::runtime_error("failure with status"), status(status_) {} +}; + // Interface to per-line data that wants to see each line insertion and deletion class PerLine { public: diff --git a/src/Document.cxx b/src/Document.cxx index f3dac9aaa..289fb6731 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -530,6 +530,13 @@ void SCI_METHOD Document::SetErrorStatus(int status) { } } +void Document::CheckPosition(Sci::Position pos) const { + PLATFORM_ASSERT((pos >= 0) && (pos <= LengthNoExcept())); + if ((pos < 0) || (pos > LengthNoExcept())) { + throw Failure(Status::OutsideDocument); + } +} + Sci_Position SCI_METHOD Document::LineFromPosition(Sci_Position pos) const { return cb.LineFromPosition(pos); } @@ -1485,7 +1492,7 @@ Sci::Position Document::InsertString(Sci::Position position, const char *s, Sci: if (insertLength <= 0) { return 0; } - PLATFORM_ASSERT((position >= 0) && (position <= Length())); + CheckPosition(position); CheckReadOnly(); // Application may change read only state here if (cb.IsReadOnly()) { return 0; diff --git a/src/Document.h b/src/Document.h index 7fd150f37..dfb0a7ff5 100644 --- a/src/Document.h +++ b/src/Document.h @@ -369,6 +369,7 @@ public: int SCI_METHOD DEVersion() const noexcept override; void SCI_METHOD SetErrorStatus(int status) override; + void CheckPosition(Sci::Position pos) const; Sci_Position SCI_METHOD LineFromPosition(Sci_Position pos) const override; Sci::Line SciLineFromPosition(Sci::Position pos) const noexcept; // Avoids casting LineFromPosition diff --git a/src/Editor.cxx b/src/Editor.cxx index d946c7bd2..1dfa8fd6b 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -5899,6 +5899,8 @@ Sci::Position Editor::GetTag(char *tagValue, int tagNumber) { } Sci::Position Editor::ReplaceTarget(ReplaceType replaceType, std::string_view text) { + pdoc->CheckPosition(targetRange.start.Position()); + UndoGroup ug(pdoc); std::string substituted; // Copy in case of re-entrance @@ -6697,6 +6699,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { Sci::Position insertPos = PositionFromUPtr(wParam); if (insertPos == -1) insertPos = CurrentPosition(); + pdoc->CheckPosition(insertPos); Sci::Position newCurrent = CurrentPosition(); const char *sz = ConstCharPtrFromSPtr(lParam); const Sci::Position lengthInserted = pdoc->InsertString(insertPos, sz, strlen(sz)); diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 81101a261..856c66ca9 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -2500,6 +2500,8 @@ sptr_t ScintillaWin::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { } } catch (std::bad_alloc &) { errorStatus = Status::BadAlloc; + } catch (Failure &failure) { + errorStatus = failure.status; } catch (...) { errorStatus = Status::Failure; } -- cgit v1.2.3