From a14f5340b58421aa8a107deca0eefabe5de5d3fd 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
@@ -726,13 +731,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 1668675a8..8d3addbe8 100644
--- a/doc/ScintillaHistory.html
+++ b/doc/ScintillaHistory.html
@@ -561,6 +561,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 8ed9ea1ce..42a15acd5 100755
--- a/gtk/ScintillaGTK.cxx
+++ b/gtk/ScintillaGTK.cxx
@@ -756,16 +756,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());
@@ -773,7 +773,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 693e8e460..db25b4f17 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 2aec8d092..cb55648ef 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 f11009d36..f8dd2ccad 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;
@@ -752,7 +751,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.
@@ -1598,17 +1597,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) != ' ';
@@ -1628,13 +1627,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++) {
@@ -1648,11 +1647,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());
}
}
}
@@ -4153,12 +4152,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 &) {
@@ -5245,8 +5244,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;
@@ -5581,11 +5579,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;
}
@@ -5978,41 +5985,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 54c50363d..52d422850 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 d9b906c1f..d375c7ca8 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -774,14 +774,14 @@ std::wstring StringMapCase(const std::wstring &ws, 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 = ::WideCharToMultiByte(CP_UTF8, 0, characters.c_str(), static_cast(characters.length()), NULL, 0, 0, 0);
if (text) {
--
cgit v1.2.3