aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--cocoa/ScintillaCocoa.mm6
-rw-r--r--doc/ScintillaDoc.html18
-rw-r--r--doc/ScintillaHistory.html1
-rwxr-xr-xgtk/ScintillaGTK.cxx8
-rw-r--r--include/Scintilla.h4
-rw-r--r--include/Scintilla.iface12
-rw-r--r--src/Editor.cxx92
-rw-r--r--src/Editor.h3
-rw-r--r--src/Selection.h3
-rw-r--r--test/simpleTests.py20
-rw-r--r--win32/ScintillaWin.cxx6
11 files changed, 121 insertions, 52 deletions
diff --git a/cocoa/ScintillaCocoa.mm b/cocoa/ScintillaCocoa.mm
index bc6bb3698..e9284888f 100644
--- a/cocoa/ScintillaCocoa.mm
+++ b/cocoa/ScintillaCocoa.mm
@@ -1598,15 +1598,15 @@ bool ScintillaCocoa::GetPasteboardData(NSPasteboard *board, SelectionText *selec
// Returns the target converted to UTF8.
// Return the length in bytes.
Sci::Position ScintillaCocoa::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 CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(),
vs.styles[STYLE_DEFAULT].characterSet);
- const std::string s = RangeText(targetStart, targetEnd);
+ const std::string s = RangeText(targetRange.start.Position(), targetRange.end.Position());
CFStringRef cfsVal = CFStringFromString(s.c_str(), s.length(), encoding);
if (!cfsVal) {
return 0;
diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html
index 9fa7f94c1..d77536e5b 100644
--- a/doc/ScintillaDoc.html
+++ b/doc/ScintillaDoc.html
@@ -711,10 +711,15 @@ struct Sci_TextRange {
<code>SCI_SEARCHINTARGET</code> such as <code>SCFIND_MATCHCASE</code>,
<code>SCFIND_WHOLEWORD</code>, <code>SCFIND_WORDSTART</code>, and <code>SCFIND_REGEXP</code>
can be set with <code>SCI_SETSEARCHFLAGS</code>.</p>
- <code><a class="message" href="#SCI_SETTARGETSTART">SCI_SETTARGETSTART(position start)</a><br />
+ <code>
+ <a class="message" href="#SCI_SETTARGETSTART">SCI_SETTARGETSTART(position start)</a><br />
<a class="message" href="#SCI_GETTARGETSTART">SCI_GETTARGETSTART &rarr; position</a><br />
+ <a class="message" href="#SCI_SETTARGETSTARTVIRTUALSPACE">SCI_SETTARGETSTARTVIRTUALSPACE(position space)</a><br />
+ <a class="message" href="#SCI_GETTARGETSTARTVIRTUALSPACE">SCI_GETTARGETSTARTVIRTUALSPACE &rarr; position</a><br />
<a class="message" href="#SCI_SETTARGETEND">SCI_SETTARGETEND(position end)</a><br />
<a class="message" href="#SCI_GETTARGETEND">SCI_GETTARGETEND &rarr; position</a><br />
+ <a class="message" href="#SCI_SETTARGETENDVIRTUALSPACE">SCI_SETTARGETENDVIRTUALSPACE(position space)</a><br />
+ <a class="message" href="#SCI_GETTARGETENDVIRTUALSPACE">SCI_GETTARGETENDVIRTUALSPACE &rarr; position</a><br />
<a class="message" href="#SCI_SETTARGETRANGE">SCI_SETTARGETRANGE(position start, position end)</a><br />
<a class="message" href="#SCI_TARGETFROMSELECTION">SCI_TARGETFROMSELECTION</a><br />
<a class="message" href="#SCI_TARGETWHOLEDOCUMENT">SCI_TARGETWHOLEDOCUMENT</a><br />
@@ -729,13 +734,22 @@ struct Sci_TextRange {
<p><b id="SCI_SETTARGETSTART">SCI_SETTARGETSTART(position start)</b><br />
<b id="SCI_GETTARGETSTART">SCI_GETTARGETSTART &rarr; position</b><br />
+ <b id="SCI_SETTARGETSTARTVIRTUALSPACE">SCI_SETTARGETSTARTVIRTUALSPACE(position space)</b><br />
+ <b id="SCI_GETTARGETSTARTVIRTUALSPACE">SCI_GETTARGETSTARTVIRTUALSPACE &rarr; position</b><br />
<b id="SCI_SETTARGETEND">SCI_SETTARGETEND(position end)</b><br />
<b id="SCI_GETTARGETEND">SCI_GETTARGETEND &rarr; position</b><br />
+ <b id="SCI_SETTARGETENDVIRTUALSPACE">SCI_SETTARGETENDVIRTUALSPACE(position space)</b><br />
+ <b id="SCI_GETTARGETENDVIRTUALSPACE">SCI_GETTARGETENDVIRTUALSPACE &rarr; position</b><br />
<b id="SCI_SETTARGETRANGE">SCI_SETTARGETRANGE(position start, position end)</b><br />
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 <code>SCI_SETTARGETSTART</code>, <code>SCI_SETTARGETEND</code>, or <code>SCI_SETTARGETRANGE</code>
+ sets the virtual space to 0.
+ The target is also set by a successful
<code>SCI_SEARCHINTARGET</code>.</p>
+ <p>The virtual space of the target range can be set and retrieved with the corresponding <code>...VIRTUALSPACE</code>
+ methods. This allows text to be inserted in virtual space more easily.</p>
<p><b id="SCI_TARGETFROMSELECTION">SCI_TARGETFROMSELECTION</b><br />
Set the target start and end to the start and end positions of the selection.</p>
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.
</li>
<li>
+ Allow target to have virtual space.
Add methods for finding the virtual space at start and end of multiple selections.
<a href="https://sourceforge.net/p/scintilla/feature-requests/1316/">Feature #1316</a>.
</li>
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<Range> 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<int>(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<Sci::Position>(wParam);
+ targetRange.start.SetPosition(static_cast<Sci::Position>(wParam));
break;
case SCI_GETTARGETSTART:
- return targetStart;
+ return targetRange.start.Position();
+
+ case SCI_SETTARGETSTARTVIRTUALSPACE:
+ targetRange.start.SetVirtualSpace(static_cast<Sci::Position>(wParam));
+ break;
+
+ case SCI_GETTARGETSTARTVIRTUALSPACE:
+ return targetRange.start.VirtualSpace();
case SCI_SETTARGETEND:
- targetEnd = static_cast<Sci::Position>(wParam);
+ targetRange.end.SetPosition(static_cast<Sci::Position>(wParam));
break;
case SCI_GETTARGETEND:
- return targetEnd;
+ return targetRange.end.Position();
+
+ case SCI_SETTARGETENDVIRTUALSPACE:
+ targetRange.end.SetVirtualSpace(static_cast<Sci::Position>(wParam));
+ break;
+
+ case SCI_GETTARGETENDVIRTUALSPACE:
+ return targetRange.end.VirtualSpace();
case SCI_SETTARGETRANGE:
- targetStart = static_cast<Sci::Position>(wParam);
- targetEnd = lParam;
+ targetRange.start.SetPosition(static_cast<Sci::Position>(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<const unsigned char *>(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) {