diff options
| -rw-r--r-- | cocoa/ScintillaCocoa.mm | 6 | ||||
| -rw-r--r-- | doc/ScintillaDoc.html | 18 | ||||
| -rw-r--r-- | doc/ScintillaHistory.html | 1 | ||||
| -rwxr-xr-x | gtk/ScintillaGTK.cxx | 8 | ||||
| -rw-r--r-- | include/Scintilla.h | 4 | ||||
| -rw-r--r-- | include/Scintilla.iface | 12 | ||||
| -rw-r--r-- | src/Editor.cxx | 92 | ||||
| -rw-r--r-- | src/Editor.h | 3 | ||||
| -rw-r--r-- | src/Selection.h | 3 | ||||
| -rw-r--r-- | test/simpleTests.py | 20 | ||||
| -rw-r--r-- | win32/ScintillaWin.cxx | 6 | 
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 → position</a><br /> +     <a class="message" href="#SCI_SETTARGETSTARTVIRTUALSPACE">SCI_SETTARGETSTARTVIRTUALSPACE(position space)</a><br /> +     <a class="message" href="#SCI_GETTARGETSTARTVIRTUALSPACE">SCI_GETTARGETSTARTVIRTUALSPACE → position</a><br />       <a class="message" href="#SCI_SETTARGETEND">SCI_SETTARGETEND(position end)</a><br />       <a class="message" href="#SCI_GETTARGETEND">SCI_GETTARGETEND → position</a><br /> +     <a class="message" href="#SCI_SETTARGETENDVIRTUALSPACE">SCI_SETTARGETENDVIRTUALSPACE(position space)</a><br /> +     <a class="message" href="#SCI_GETTARGETENDVIRTUALSPACE">SCI_GETTARGETENDVIRTUALSPACE → 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 → position</b><br /> +     <b id="SCI_SETTARGETSTARTVIRTUALSPACE">SCI_SETTARGETSTARTVIRTUALSPACE(position space)</b><br /> +     <b id="SCI_GETTARGETSTARTVIRTUALSPACE">SCI_GETTARGETSTARTVIRTUALSPACE → position</b><br />       <b id="SCI_SETTARGETEND">SCI_SETTARGETEND(position end)</b><br />       <b id="SCI_GETTARGETEND">SCI_GETTARGETEND → position</b><br /> +     <b id="SCI_SETTARGETENDVIRTUALSPACE">SCI_SETTARGETENDVIRTUALSPACE(position space)</b><br /> +     <b id="SCI_GETTARGETENDVIRTUALSPACE">SCI_GETTARGETENDVIRTUALSPACE → 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) { | 
