aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2022-11-22 09:24:07 +1100
committerNeil <nyamatongwe@gmail.com>2022-11-22 09:24:07 +1100
commitcb8cd73d839a96f98bb1ce887c694271f9c24788 (patch)
tree1920fae848da38e7942ea9a36c21f87272254e23 /src
parentb3e46461ce564d295b629a1d16dc4cee60722e66 (diff)
downloadscintilla-mirror-cb8cd73d839a96f98bb1ce887c694271f9c24788.tar.gz
Add SCI_REPLACETARGETMINIMAL to change text without causing unchanged prefix and
suffix to be marked as modified in change history.
Diffstat (limited to 'src')
-rw-r--r--src/Document.cxx11
-rw-r--r--src/Document.h5
-rw-r--r--src/Editor.cxx36
-rw-r--r--src/Editor.h9
4 files changed, 50 insertions, 11 deletions
diff --git a/src/Document.cxx b/src/Document.cxx
index 0237cef78..6a638471d 100644
--- a/src/Document.cxx
+++ b/src/Document.cxx
@@ -1242,6 +1242,17 @@ void Document::CheckReadOnly() {
}
}
+void Document::TrimReplacement(std::string_view &text, Range &range) const noexcept {
+ while (!text.empty() && !range.Empty() && (text.front() == CharAt(range.start))) {
+ text.remove_prefix(1);
+ range.start++;
+ }
+ while (!text.empty() && !range.Empty() && (text.back() == CharAt(range.end-1))) {
+ text.remove_suffix(1);
+ range.end--;
+ }
+}
+
// Document only modified by gateways DeleteChars, InsertString, Undo, Redo, and SetStyleAt.
// SetStyleAt does not change the persistent state of a document
diff --git a/src/Document.h b/src/Document.h
index ae784180a..ac9c6670c 100644
--- a/src/Document.h
+++ b/src/Document.h
@@ -46,6 +46,10 @@ public:
return (start != Sci::invalidPosition) && (end != Sci::invalidPosition);
}
+ [[nodiscard]] bool Empty() const noexcept {
+ return start == end;
+ }
+
Sci::Position First() const noexcept {
return (start <= end) ? start : end;
}
@@ -369,6 +373,7 @@ public:
// Gateways to modifying document
void ModifiedAt(Sci::Position pos) noexcept;
void CheckReadOnly();
+ void TrimReplacement(std::string_view &text, Range &range) const noexcept;
bool DeleteChars(Sci::Position pos, Sci::Position len);
Sci::Position InsertString(Sci::Position position, const char *s, Sci::Position insertLength);
Sci::Position InsertString(Sci::Position position, std::string_view sv);
diff --git a/src/Editor.cxx b/src/Editor.cxx
index 2e1467e32..1fb6d960d 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -5696,15 +5696,27 @@ Sci::Position Editor::GetTag(char *tagValue, int tagNumber) {
return length;
}
-Sci::Position Editor::ReplaceTarget(bool replacePatterns, const char *text, Sci::Position length) {
+Sci::Position Editor::ReplaceTarget(ReplaceType replaceType, std::string_view text) {
UndoGroup ug(pdoc);
- if (length == -1)
- length = strlen(text);
- if (replacePatterns) {
- text = pdoc->SubstituteByPosition(text, &length);
- if (!text) {
+ if (replaceType == ReplaceType::patterns) {
+ Sci::Position length = text.length();
+ const char *p = pdoc->SubstituteByPosition(text.data(), &length);
+ if (!p) {
return 0;
}
+ text = std::string_view(p, length);
+ }
+
+ if (replaceType == ReplaceType::minimal) {
+ // Check for prefix and suffix and reduce text and target to match.
+ // This is performed with Range which doesn't support virtual space.
+ Range range(targetRange.start.Position(), targetRange.end.Position());
+ pdoc->TrimReplacement(text, range);
+ // Re-apply virtual space to start if start position didn't change.
+ // Don't bother with end as its virtual space is not used
+ const SelectionPosition start(range.start == targetRange.start.Position() ?
+ targetRange.start : SelectionPosition(range.start));
+ targetRange = SelectionSegment(start, SelectionPosition(range.end));
}
// Remove the text inside the range
@@ -5718,9 +5730,9 @@ Sci::Position Editor::ReplaceTarget(bool replacePatterns, const char *text, Sci:
targetRange.end = targetRange.start;
// Insert the new text
- const Sci::Position lengthInserted = pdoc->InsertString(targetRange.start.Position(), text, length);
+ const Sci::Position lengthInserted = pdoc->InsertString(targetRange.start.Position(), text);
targetRange.end.SetPosition(targetRange.start.Position() + lengthInserted);
- return length;
+ return text.length();
}
bool Editor::IsUnicodeMode() const noexcept {
@@ -6240,11 +6252,15 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
case Message::ReplaceTarget:
PLATFORM_ASSERT(lParam);
- return ReplaceTarget(false, ConstCharPtrFromSPtr(lParam), PositionFromUPtr(wParam));
+ return ReplaceTarget(ReplaceType::basic, ViewFromParams(lParam, wParam));
case Message::ReplaceTargetRE:
PLATFORM_ASSERT(lParam);
- return ReplaceTarget(true, ConstCharPtrFromSPtr(lParam), PositionFromUPtr(wParam));
+ return ReplaceTarget(ReplaceType::patterns, ViewFromParams(lParam, wParam));
+
+ case Message::ReplaceTargetMinimal:
+ PLATFORM_ASSERT(lParam);
+ return ReplaceTarget(ReplaceType::minimal, ViewFromParams(lParam, wParam));
case Message::SearchInTarget:
PLATFORM_ASSERT(lParam);
diff --git a/src/Editor.h b/src/Editor.h
index 128abf234..85d95e21d 100644
--- a/src/Editor.h
+++ b/src/Editor.h
@@ -581,7 +581,8 @@ protected: // ScintillaBase subclass needs access to much of Editor
void FoldAll(Scintilla::FoldAction action);
Sci::Position GetTag(char *tagValue, int tagNumber);
- Sci::Position ReplaceTarget(bool replacePatterns, const char *text, Sci::Position length=-1);
+ enum class ReplaceType {basic, patterns, minimal};
+ Sci::Position ReplaceTarget(ReplaceType replaceType, std::string_view text);
bool PositionIsHotspot(Sci::Position position) const noexcept;
bool PointIsHotspot(Point pt);
@@ -625,6 +626,12 @@ protected: // ScintillaBase subclass needs access to much of Editor
static unsigned char *UCharPtrFromSPtr(Scintilla::sptr_t lParam) noexcept {
return static_cast<unsigned char *>(PtrFromSPtr(lParam));
}
+ static std::string_view ViewFromParams(Scintilla::sptr_t lParam, Scintilla::uptr_t wParam) noexcept {
+ if (SPtrFromUPtr(wParam) == -1) {
+ return std::string_view(CharPtrFromSPtr(lParam));
+ }
+ return std::string_view(CharPtrFromSPtr(lParam), wParam);
+ }
static void *PtrFromUPtr(Scintilla::uptr_t wParam) noexcept {
return reinterpret_cast<void *>(wParam);
}