From cdad8d8b9e4830a5b97631557c10135d7b12a541 Mon Sep 17 00:00:00 2001
From: Neil SCI_SEARCHINTARGET such as SCFIND_MATCHCASE,
SCFIND_WHOLEWORD, SCFIND_WORDSTART, and SCFIND_REGEXP
can be set with SCI_SETSEARCHFLAGS.
SCI_SETTARGETSTART(position start)
+
+ SCI_SETTARGETSTART(position start)
SCI_GETTARGETSTART → position
+ SCI_SETTARGETSTARTVIRTUALSPACE(position space)
+ SCI_GETTARGETSTARTVIRTUALSPACE → position
SCI_SETTARGETEND(position end)
SCI_GETTARGETEND → position
+ SCI_SETTARGETENDVIRTUALSPACE(position space)
+ SCI_GETTARGETENDVIRTUALSPACE → position
SCI_SETTARGETRANGE(position start, position end)
SCI_TARGETFROMSELECTION
SCI_TARGETWHOLEDOCUMENT
@@ -729,13 +734,22 @@ struct Sci_TextRange {
SCI_SETTARGETSTART(position start)
SCI_GETTARGETSTART → position
+ SCI_SETTARGETSTARTVIRTUALSPACE(position space)
+ SCI_GETTARGETSTARTVIRTUALSPACE → position
SCI_SETTARGETEND(position end)
SCI_GETTARGETEND → position
+ SCI_SETTARGETENDVIRTUALSPACE(position space)
+ SCI_GETTARGETENDVIRTUALSPACE → position
SCI_SETTARGETRANGE(position start, position end)
These functions set and return the start and end of the target. When searching
you can set start greater than end to find the last matching text in the
- target rather than the first matching text. The target is also set by a successful
+ target rather than the first matching text.
+ Setting a target position with SCI_SETTARGETSTART, SCI_SETTARGETEND, or SCI_SETTARGETRANGE
+ sets the virtual space to 0.
+ The target is also set by a successful
SCI_SEARCHINTARGET.
+ The virtual space of the target range can be set and retrieved with the corresponding ...VIRTUALSPACE
+ methods. This allows text to be inserted in virtual space more easily.
SCI_TARGETFROMSELECTION
Set the target start and end to the start and end positions of the selection.
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html
index 42bbd68f3..a5c815628 100644
--- a/doc/ScintillaHistory.html
+++ b/doc/ScintillaHistory.html
@@ -567,6 +567,7 @@
Released 24 October 2019.
+ Allow target to have virtual space.
Add methods for finding the virtual space at start and end of multiple selections.
Feature #1316.
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx
index 9162010c4..03213c500 100755
--- a/gtk/ScintillaGTK.cxx
+++ b/gtk/ScintillaGTK.cxx
@@ -757,16 +757,16 @@ std::string ConvertText(const char *s, size_t len, const char *charSetDest,
// Returns the target converted to UTF8.
// Return the length in bytes.
Sci::Position ScintillaGTK::TargetAsUTF8(char *text) const {
- const Sci::Position targetLength = targetEnd - targetStart;
+ const Sci::Position targetLength = targetRange.Length();
if (IsUnicodeMode()) {
if (text) {
- pdoc->GetCharRange(text, targetStart, targetLength);
+ pdoc->GetCharRange(text, targetRange.start.Position(), targetLength);
}
} else {
// Need to convert
const char *charSetBuffer = CharacterSetID();
if (*charSetBuffer) {
- std::string s = RangeText(targetStart, targetEnd);
+ std::string s = RangeText(targetRange.start.Position(), targetRange.end.Position());
std::string tmputf = ConvertText(&s[0], targetLength, "UTF-8", charSetBuffer, false);
if (text) {
memcpy(text, tmputf.c_str(), tmputf.length());
@@ -774,7 +774,7 @@ Sci::Position ScintillaGTK::TargetAsUTF8(char *text) const {
return tmputf.length();
} else {
if (text) {
- pdoc->GetCharRange(text, targetStart, targetLength);
+ pdoc->GetCharRange(text, targetRange.start.Position(), targetLength);
}
}
}
diff --git a/include/Scintilla.h b/include/Scintilla.h
index 59ab2ff7a..b5fc17eb6 100644
--- a/include/Scintilla.h
+++ b/include/Scintilla.h
@@ -451,8 +451,12 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_GETCARETWIDTH 2189
#define SCI_SETTARGETSTART 2190
#define SCI_GETTARGETSTART 2191
+#define SCI_SETTARGETSTARTVIRTUALSPACE 2728
+#define SCI_GETTARGETSTARTVIRTUALSPACE 2729
#define SCI_SETTARGETEND 2192
#define SCI_GETTARGETEND 2193
+#define SCI_SETTARGETENDVIRTUALSPACE 2730
+#define SCI_GETTARGETENDVIRTUALSPACE 2731
#define SCI_SETTARGETRANGE 2686
#define SCI_GETTARGETTEXT 2687
#define SCI_TARGETFROMSELECTION 2287
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index 9fa952f95..dde113847 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -1208,6 +1208,12 @@ set void SetTargetStart=2190(position start,)
# Get the position that starts the target.
get position GetTargetStart=2191(,)
+# Sets the virtual space of the target start
+set void SetTargetStartVirtualSpace=2728(position space,)
+
+# Get the virtual space of the target start
+get position GetTargetStartVirtualSpace=2729(,)
+
# Sets the position that ends the target which is used for updating the
# document without affecting the scroll position.
set void SetTargetEnd=2192(position end,)
@@ -1215,6 +1221,12 @@ set void SetTargetEnd=2192(position end,)
# Get the position that ends the target.
get position GetTargetEnd=2193(,)
+# Sets the virtual space of the target end
+set void SetTargetEndVirtualSpace=2730(position space,)
+
+# Get the virtual space of the target end
+get position GetTargetEndVirtualSpace=2731(,)
+
# Sets both the start and end of the target in one call.
fun void SetTargetRange=2686(position start, position end)
diff --git a/src/Editor.cxx b/src/Editor.cxx
index 826824cbd..016ef3383 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -167,8 +167,7 @@ Editor::Editor() : durationWrapOneLine(0.00001, 0.000001, 0.0001) {
multiPasteMode = SC_MULTIPASTE_ONCE;
virtualSpaceOptions = SCVS_NONE;
- targetStart = 0;
- targetEnd = 0;
+ targetRange = SelectionSegment();
searchFlags = 0;
topLine = 0;
@@ -755,7 +754,7 @@ void Editor::MultipleSelectAdd(AddNumber addNumber) {
const Range rangeMainSelection(sel.RangeMain().Start().Position(), sel.RangeMain().End().Position());
const std::string selectedText = RangeText(rangeMainSelection.start, rangeMainSelection.end);
- const Range rangeTarget(targetStart, targetEnd);
+ const Range rangeTarget(targetRange.start.Position(), targetRange.end.Position());
std::vector searchRanges;
// Search should be over the target range excluding the current selection so
// may need to search 2 ranges, after the selection then before the selection.
@@ -1601,17 +1600,17 @@ bool Editor::WrapLines(WrapScope ws) {
}
void Editor::LinesJoin() {
- if (!RangeContainsProtected(targetStart, targetEnd)) {
+ if (!RangeContainsProtected(targetRange.start.Position(), targetRange.end.Position())) {
UndoGroup ug(pdoc);
bool prevNonWS = true;
- for (Sci::Position pos = targetStart; pos < targetEnd; pos++) {
+ for (Sci::Position pos = targetRange.start.Position(); pos < targetRange.end.Position(); pos++) {
if (pdoc->IsPositionInLineEnd(pos)) {
- targetEnd -= pdoc->LenChar(pos);
+ targetRange.end.Add(-pdoc->LenChar(pos));
pdoc->DelChar(pos);
if (prevNonWS) {
// Ensure at least one space separating previous lines
const Sci::Position lengthInserted = pdoc->InsertString(pos, " ", 1);
- targetEnd += lengthInserted;
+ targetRange.end.Add(lengthInserted);
}
} else {
prevNonWS = pdoc->CharAt(pos) != ' ';
@@ -1631,13 +1630,13 @@ const char *Editor::StringFromEOLMode(int eolMode) noexcept {
}
void Editor::LinesSplit(int pixelWidth) {
- if (!RangeContainsProtected(targetStart, targetEnd)) {
+ if (!RangeContainsProtected(targetRange.start.Position(), targetRange.end.Position())) {
if (pixelWidth == 0) {
const PRectangle rcText = GetTextRectangle();
pixelWidth = static_cast(rcText.Width());
}
- const Sci::Line lineStart = pdoc->SciLineFromPosition(targetStart);
- Sci::Line lineEnd = pdoc->SciLineFromPosition(targetEnd);
+ const Sci::Line lineStart = pdoc->SciLineFromPosition(targetRange.start.Position());
+ Sci::Line lineEnd = pdoc->SciLineFromPosition(targetRange.end.Position());
const char *eol = StringFromEOLMode(pdoc->eolMode);
UndoGroup ug(pdoc);
for (Sci::Line line = lineStart; line <= lineEnd; line++) {
@@ -1651,11 +1650,11 @@ void Editor::LinesSplit(int pixelWidth) {
const Sci::Position lengthInserted = pdoc->InsertString(
posLineStart + lengthInsertedTotal + ll->LineStart(subLine),
eol, strlen(eol));
- targetEnd += lengthInserted;
+ targetRange.end.Add(lengthInserted);
lengthInsertedTotal += lengthInserted;
}
}
- lineEnd = pdoc->SciLineFromPosition(targetEnd);
+ lineEnd = pdoc->SciLineFromPosition(targetRange.end.Position());
}
}
}
@@ -4156,12 +4155,12 @@ Sci::Position Editor::SearchInTarget(const char *text, Sci::Position length) {
if (!pdoc->HasCaseFolder())
pdoc->SetCaseFolder(CaseFolderForEncoding());
try {
- const Sci::Position pos = pdoc->FindText(targetStart, targetEnd, text,
+ const Sci::Position pos = pdoc->FindText(targetRange.start.Position(), targetRange.end.Position(), text,
searchFlags,
&lengthFound);
if (pos != -1) {
- targetStart = pos;
- targetEnd = pos + lengthFound;
+ targetRange.start.SetPosition(pos);
+ targetRange.end.SetPosition(pos + lengthFound);
}
return pos;
} catch (RegexError &) {
@@ -5249,8 +5248,7 @@ void Editor::SetDocPointer(Document *document) {
// Ensure all positions within document
sel.Clear();
- targetStart = 0;
- targetEnd = 0;
+ targetRange = SelectionSegment();
braces[0] = Sci::invalidPosition;
braces[1] = Sci::invalidPosition;
@@ -5585,11 +5583,20 @@ Sci::Position Editor::ReplaceTarget(bool replacePatterns, const char *text, Sci:
return 0;
}
}
- if (targetStart != targetEnd)
- pdoc->DeleteChars(targetStart, targetEnd - targetStart);
- targetEnd = targetStart;
- const Sci::Position lengthInserted = pdoc->InsertString(targetStart, text, length);
- targetEnd = targetStart + lengthInserted;
+
+ // Remove the text inside the range
+ if (targetRange.Length() > 0)
+ pdoc->DeleteChars(targetRange.start.Position(), targetRange.Length());
+ targetRange.end = targetRange.start;
+
+ // Realize virtual space of target start
+ Sci::Position startAfterSpaceInsertion = RealizeVirtualSpace(targetRange.start.Position(), targetRange.start.VirtualSpace());
+ targetRange.start.SetPosition(startAfterSpaceInsertion);
+ targetRange.end = targetRange.start;
+
+ // Insert the new text
+ const Sci::Position lengthInserted = pdoc->InsertString(targetRange.start.Position(), text, length);
+ targetRange.end.SetPosition(targetRange.start.Position() + lengthInserted);
return length;
}
@@ -5982,41 +5989,50 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
break;
case SCI_SETTARGETSTART:
- targetStart = static_cast(wParam);
+ targetRange.start.SetPosition(static_cast(wParam));
break;
case SCI_GETTARGETSTART:
- return targetStart;
+ return targetRange.start.Position();
+
+ case SCI_SETTARGETSTARTVIRTUALSPACE:
+ targetRange.start.SetVirtualSpace(static_cast(wParam));
+ break;
+
+ case SCI_GETTARGETSTARTVIRTUALSPACE:
+ return targetRange.start.VirtualSpace();
case SCI_SETTARGETEND:
- targetEnd = static_cast(wParam);
+ targetRange.end.SetPosition(static_cast(wParam));
break;
case SCI_GETTARGETEND:
- return targetEnd;
+ return targetRange.end.Position();
+
+ case SCI_SETTARGETENDVIRTUALSPACE:
+ targetRange.end.SetVirtualSpace(static_cast(wParam));
+ break;
+
+ case SCI_GETTARGETENDVIRTUALSPACE:
+ return targetRange.end.VirtualSpace();
case SCI_SETTARGETRANGE:
- targetStart = static_cast(wParam);
- targetEnd = lParam;
+ targetRange.start.SetPosition(static_cast(wParam));
+ targetRange.end.SetPosition(lParam);
break;
case SCI_TARGETWHOLEDOCUMENT:
- targetStart = 0;
- targetEnd = pdoc->Length();
+ targetRange.start.SetPosition(0);
+ targetRange.end.SetPosition(pdoc->Length());
break;
case SCI_TARGETFROMSELECTION:
- if (sel.MainCaret() < sel.MainAnchor()) {
- targetStart = sel.MainCaret();
- targetEnd = sel.MainAnchor();
- } else {
- targetStart = sel.MainAnchor();
- targetEnd = sel.MainCaret();
- }
+ targetRange.start = sel.RangeMain().Start();
+ targetRange.end = sel.RangeMain().End();
break;
case SCI_GETTARGETTEXT: {
- std::string text = RangeText(targetStart, targetEnd);
+ std::string text = RangeText(targetRange.start.Position(), targetRange.end.Position());
return BytesResult(lParam, reinterpret_cast(text.c_str()), text.length());
}
diff --git a/src/Editor.h b/src/Editor.h
index 13e201169..69f8ef4ca 100644
--- a/src/Editor.h
+++ b/src/Editor.h
@@ -210,8 +210,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
Sci::Position wordSelectAnchorStartPos;
Sci::Position wordSelectAnchorEndPos;
Sci::Position wordSelectInitialCaretPos;
- Sci::Position targetStart;
- Sci::Position targetEnd;
+ SelectionSegment targetRange;
int searchFlags;
Sci::Line topLine;
Sci::Position posTopLine;
diff --git a/src/Selection.h b/src/Selection.h
index d078c043e..11a6f097a 100644
--- a/src/Selection.h
+++ b/src/Selection.h
@@ -72,6 +72,9 @@ struct SelectionSegment {
bool Empty() const noexcept {
return start == end;
}
+ Sci::Position Length() const noexcept {
+ return end.Position() - start.Position();
+ }
void Extend(SelectionPosition p) noexcept {
if (start > p)
start = p;
diff --git a/test/simpleTests.py b/test/simpleTests.py
index a4730980f..a68668f74 100644
--- a/test/simpleTests.py
+++ b/test/simpleTests.py
@@ -609,6 +609,26 @@ class TestSimple(unittest.TestCase):
self.ed.ReplaceTargetRE(len(rep), rep)
self.assertEquals(self.ed.Contents(), b"a\\nd")
+ def testTargetVirtualSpace(self):
+ self.ed.SetContents(b"a\nbcd")
+ self.assertEquals(self.ed.TargetStart, 0)
+ self.assertEquals(self.ed.TargetStartVirtualSpace, 0)
+ self.assertEquals(self.ed.TargetEnd, 5)
+ self.assertEquals(self.ed.TargetEndVirtualSpace, 0)
+ self.ed.TargetStart = 1
+ self.ed.TargetStartVirtualSpace = 2
+ self.ed.TargetEnd = 3
+ self.ed.TargetEndVirtualSpace = 4
+ # Adds 2 spaces to first line due to virtual space, and replace 2 characters with 3
+ rep = b"12\n"
+ self.ed.ReplaceTarget(len(rep), rep)
+ self.assertEquals(self.ed.Contents(), b"a 12\ncd")
+ # 1+2v realized to 3
+ self.assertEquals(self.ed.TargetStart, 3)
+ self.assertEquals(self.ed.TargetStartVirtualSpace, 0)
+ self.assertEquals(self.ed.TargetEnd, 6)
+ self.assertEquals(self.ed.TargetEndVirtualSpace, 0)
+
def testPointsAndPositions(self):
self.ed.AddText(1, b"x")
# Start of text
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
index ff20740f8..b5ff31bae 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -791,14 +791,14 @@ std::wstring StringMapCase(std::wstring_view wsv, DWORD mapFlags) {
// Returns the target converted to UTF8.
// Return the length in bytes.
Sci::Position ScintillaWin::TargetAsUTF8(char *text) const {
- const Sci::Position targetLength = targetEnd - targetStart;
+ const Sci::Position targetLength = targetRange.Length();
if (IsUnicodeMode()) {
if (text) {
- pdoc->GetCharRange(text, targetStart, targetLength);
+ pdoc->GetCharRange(text, targetRange.start.Position(), targetLength);
}
} else {
// Need to convert
- const std::string s = RangeText(targetStart, targetEnd);
+ const std::string s = RangeText(targetRange.start.Position(), targetRange.end.Position());
const std::wstring characters = StringDecode(s, CodePageOfDocument());
const int utf8Len = MultiByteLenFromWideChar(CP_UTF8, characters);
if (text) {
--
cgit v1.2.3