xref: /MusicPlayer2/scintilla/src/Editor.cxx (revision 8af74909132ed5e696cb05b6689ae4baf14c1c96)
1*8af74909SZhong Yang // Scintilla source code edit control
2*8af74909SZhong Yang /** @file Editor.cxx
3*8af74909SZhong Yang  ** Main code for the edit control.
4*8af74909SZhong Yang  **/
5*8af74909SZhong Yang // Copyright 1998-2011 by Neil Hodgson <[email protected]>
6*8af74909SZhong Yang // The License.txt file describes the conditions under which this software may be distributed.
7*8af74909SZhong Yang 
8*8af74909SZhong Yang #include <cstddef>
9*8af74909SZhong Yang #include <cstdlib>
10*8af74909SZhong Yang #include <cassert>
11*8af74909SZhong Yang #include <cstring>
12*8af74909SZhong Yang #include <cstdio>
13*8af74909SZhong Yang #include <cmath>
14*8af74909SZhong Yang 
15*8af74909SZhong Yang #include <stdexcept>
16*8af74909SZhong Yang #include <string>
17*8af74909SZhong Yang #include <string_view>
18*8af74909SZhong Yang #include <vector>
19*8af74909SZhong Yang #include <map>
20*8af74909SZhong Yang #include <forward_list>
21*8af74909SZhong Yang #include <algorithm>
22*8af74909SZhong Yang #include <iterator>
23*8af74909SZhong Yang #include <memory>
24*8af74909SZhong Yang #include <chrono>
25*8af74909SZhong Yang 
26*8af74909SZhong Yang #include "Platform.h"
27*8af74909SZhong Yang 
28*8af74909SZhong Yang #include "ILoader.h"
29*8af74909SZhong Yang #include "ILexer.h"
30*8af74909SZhong Yang #include "Scintilla.h"
31*8af74909SZhong Yang 
32*8af74909SZhong Yang #include "CharacterSet.h"
33*8af74909SZhong Yang #include "CharacterCategory.h"
34*8af74909SZhong Yang #include "Position.h"
35*8af74909SZhong Yang #include "UniqueString.h"
36*8af74909SZhong Yang #include "SplitVector.h"
37*8af74909SZhong Yang #include "Partitioning.h"
38*8af74909SZhong Yang #include "RunStyles.h"
39*8af74909SZhong Yang #include "ContractionState.h"
40*8af74909SZhong Yang #include "CellBuffer.h"
41*8af74909SZhong Yang #include "PerLine.h"
42*8af74909SZhong Yang #include "KeyMap.h"
43*8af74909SZhong Yang #include "Indicator.h"
44*8af74909SZhong Yang #include "LineMarker.h"
45*8af74909SZhong Yang #include "Style.h"
46*8af74909SZhong Yang #include "ViewStyle.h"
47*8af74909SZhong Yang #include "CharClassify.h"
48*8af74909SZhong Yang #include "Decoration.h"
49*8af74909SZhong Yang #include "CaseFolder.h"
50*8af74909SZhong Yang #include "Document.h"
51*8af74909SZhong Yang #include "UniConversion.h"
52*8af74909SZhong Yang #include "Selection.h"
53*8af74909SZhong Yang #include "PositionCache.h"
54*8af74909SZhong Yang #include "EditModel.h"
55*8af74909SZhong Yang #include "MarginView.h"
56*8af74909SZhong Yang #include "EditView.h"
57*8af74909SZhong Yang #include "Editor.h"
58*8af74909SZhong Yang #include "ElapsedPeriod.h"
59*8af74909SZhong Yang 
60*8af74909SZhong Yang using namespace Scintilla;
61*8af74909SZhong Yang 
62*8af74909SZhong Yang namespace {
63*8af74909SZhong Yang 
64*8af74909SZhong Yang /*
65*8af74909SZhong Yang 	return whether this modification represents an operation that
66*8af74909SZhong Yang 	may reasonably be deferred (not done now OR [possibly] at all)
67*8af74909SZhong Yang */
CanDeferToLastStep(const DocModification & mh)68*8af74909SZhong Yang constexpr bool CanDeferToLastStep(const DocModification &mh) noexcept {
69*8af74909SZhong Yang 	if (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE))
70*8af74909SZhong Yang 		return true;	// CAN skip
71*8af74909SZhong Yang 	if (!(mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO)))
72*8af74909SZhong Yang 		return false;	// MUST do
73*8af74909SZhong Yang 	if (mh.modificationType & SC_MULTISTEPUNDOREDO)
74*8af74909SZhong Yang 		return true;	// CAN skip
75*8af74909SZhong Yang 	return false;		// PRESUMABLY must do
76*8af74909SZhong Yang }
77*8af74909SZhong Yang 
CanEliminate(const DocModification & mh)78*8af74909SZhong Yang constexpr bool CanEliminate(const DocModification &mh) noexcept {
79*8af74909SZhong Yang 	return
80*8af74909SZhong Yang 	    (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) != 0;
81*8af74909SZhong Yang }
82*8af74909SZhong Yang 
83*8af74909SZhong Yang /*
84*8af74909SZhong Yang 	return whether this modification represents the FINAL step
85*8af74909SZhong Yang 	in a [possibly lengthy] multi-step Undo/Redo sequence
86*8af74909SZhong Yang */
IsLastStep(const DocModification & mh)87*8af74909SZhong Yang constexpr bool IsLastStep(const DocModification &mh) noexcept {
88*8af74909SZhong Yang 	return
89*8af74909SZhong Yang 	    (mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO)) != 0
90*8af74909SZhong Yang 	    && (mh.modificationType & SC_MULTISTEPUNDOREDO) != 0
91*8af74909SZhong Yang 	    && (mh.modificationType & SC_LASTSTEPINUNDOREDO) != 0
92*8af74909SZhong Yang 	    && (mh.modificationType & SC_MULTILINEUNDOREDO) != 0;
93*8af74909SZhong Yang }
94*8af74909SZhong Yang 
95*8af74909SZhong Yang }
96*8af74909SZhong Yang 
Timer()97*8af74909SZhong Yang Timer::Timer() noexcept :
98*8af74909SZhong Yang 		ticking(false), ticksToWait(0), tickerID{} {}
99*8af74909SZhong Yang 
Idler()100*8af74909SZhong Yang Idler::Idler() noexcept :
101*8af74909SZhong Yang 		state(false), idlerID(0) {}
102*8af74909SZhong Yang 
IsAllSpacesOrTabs(std::string_view sv)103*8af74909SZhong Yang static constexpr bool IsAllSpacesOrTabs(std::string_view sv) noexcept {
104*8af74909SZhong Yang 	for (const char ch : sv) {
105*8af74909SZhong Yang 		// This is safe because IsSpaceOrTab() will return false for null terminators
106*8af74909SZhong Yang 		if (!IsSpaceOrTab(ch))
107*8af74909SZhong Yang 			return false;
108*8af74909SZhong Yang 	}
109*8af74909SZhong Yang 	return true;
110*8af74909SZhong Yang }
111*8af74909SZhong Yang 
Editor()112*8af74909SZhong Yang Editor::Editor() : durationWrapOneLine(0.00001, 0.000001, 0.0001) {
113*8af74909SZhong Yang 	ctrlID = 0;
114*8af74909SZhong Yang 
115*8af74909SZhong Yang 	stylesValid = false;
116*8af74909SZhong Yang 	technology = SC_TECHNOLOGY_DEFAULT;
117*8af74909SZhong Yang 	scaleRGBAImage = 100.0f;
118*8af74909SZhong Yang 
119*8af74909SZhong Yang 	cursorMode = SC_CURSORNORMAL;
120*8af74909SZhong Yang 
121*8af74909SZhong Yang 	hasFocus = false;
122*8af74909SZhong Yang 	errorStatus = 0;
123*8af74909SZhong Yang 	mouseDownCaptures = true;
124*8af74909SZhong Yang 	mouseWheelCaptures = true;
125*8af74909SZhong Yang 
126*8af74909SZhong Yang 	lastClickTime = 0;
127*8af74909SZhong Yang 	doubleClickCloseThreshold = Point(3, 3);
128*8af74909SZhong Yang 	dwellDelay = SC_TIME_FOREVER;
129*8af74909SZhong Yang 	ticksToDwell = SC_TIME_FOREVER;
130*8af74909SZhong Yang 	dwelling = false;
131*8af74909SZhong Yang 	ptMouseLast.x = 0;
132*8af74909SZhong Yang 	ptMouseLast.y = 0;
133*8af74909SZhong Yang 	inDragDrop = ddNone;
134*8af74909SZhong Yang 	dropWentOutside = false;
135*8af74909SZhong Yang 	posDrop = SelectionPosition(Sci::invalidPosition);
136*8af74909SZhong Yang 	hotSpotClickPos = INVALID_POSITION;
137*8af74909SZhong Yang 	selectionUnit = TextUnit::character;
138*8af74909SZhong Yang 
139*8af74909SZhong Yang 	lastXChosen = 0;
140*8af74909SZhong Yang 	lineAnchorPos = 0;
141*8af74909SZhong Yang 	originalAnchorPos = 0;
142*8af74909SZhong Yang 	wordSelectAnchorStartPos = 0;
143*8af74909SZhong Yang 	wordSelectAnchorEndPos = 0;
144*8af74909SZhong Yang 	wordSelectInitialCaretPos = -1;
145*8af74909SZhong Yang 
146*8af74909SZhong Yang 	caretPolicies.x = { CARET_SLOP | CARET_EVEN, 50 };
147*8af74909SZhong Yang 	caretPolicies.y = { CARET_EVEN, 0 };
148*8af74909SZhong Yang 
149*8af74909SZhong Yang 	visiblePolicy = { 0, 0 };
150*8af74909SZhong Yang 
151*8af74909SZhong Yang 	searchAnchor = 0;
152*8af74909SZhong Yang 
153*8af74909SZhong Yang 	xCaretMargin = 50;
154*8af74909SZhong Yang 	horizontalScrollBarVisible = true;
155*8af74909SZhong Yang 	scrollWidth = 2000;
156*8af74909SZhong Yang 	verticalScrollBarVisible = true;
157*8af74909SZhong Yang 	endAtLastLine = true;
158*8af74909SZhong Yang 	caretSticky = SC_CARETSTICKY_OFF;
159*8af74909SZhong Yang 	marginOptions = SC_MARGINOPTION_NONE;
160*8af74909SZhong Yang 	mouseSelectionRectangularSwitch = false;
161*8af74909SZhong Yang 	multipleSelection = false;
162*8af74909SZhong Yang 	additionalSelectionTyping = false;
163*8af74909SZhong Yang 	multiPasteMode = SC_MULTIPASTE_ONCE;
164*8af74909SZhong Yang 	virtualSpaceOptions = SCVS_NONE;
165*8af74909SZhong Yang 
166*8af74909SZhong Yang 	targetRange = SelectionSegment();
167*8af74909SZhong Yang 	searchFlags = 0;
168*8af74909SZhong Yang 
169*8af74909SZhong Yang 	topLine = 0;
170*8af74909SZhong Yang 	posTopLine = 0;
171*8af74909SZhong Yang 
172*8af74909SZhong Yang 	lengthForEncode = -1;
173*8af74909SZhong Yang 
174*8af74909SZhong Yang 	needUpdateUI = 0;
175*8af74909SZhong Yang 	ContainerNeedsUpdate(SC_UPDATE_CONTENT);
176*8af74909SZhong Yang 
177*8af74909SZhong Yang 	paintState = notPainting;
178*8af74909SZhong Yang 	paintAbandonedByStyling = false;
179*8af74909SZhong Yang 	paintingAllText = false;
180*8af74909SZhong Yang 	willRedrawAll = false;
181*8af74909SZhong Yang 	idleStyling = SC_IDLESTYLING_NONE;
182*8af74909SZhong Yang 	needIdleStyling = false;
183*8af74909SZhong Yang 
184*8af74909SZhong Yang 	modEventMask = SC_MODEVENTMASKALL;
185*8af74909SZhong Yang 	commandEvents = true;
186*8af74909SZhong Yang 
187*8af74909SZhong Yang 	pdoc->AddWatcher(this, 0);
188*8af74909SZhong Yang 
189*8af74909SZhong Yang 	recordingMacro = false;
190*8af74909SZhong Yang 	foldAutomatic = 0;
191*8af74909SZhong Yang 
192*8af74909SZhong Yang 	convertPastes = true;
193*8af74909SZhong Yang 
194*8af74909SZhong Yang 	SetRepresentations();
195*8af74909SZhong Yang }
196*8af74909SZhong Yang 
~Editor()197*8af74909SZhong Yang Editor::~Editor() {
198*8af74909SZhong Yang 	pdoc->RemoveWatcher(this, 0);
199*8af74909SZhong Yang 	DropGraphics(true);
200*8af74909SZhong Yang }
201*8af74909SZhong Yang 
Finalise()202*8af74909SZhong Yang void Editor::Finalise() {
203*8af74909SZhong Yang 	SetIdle(false);
204*8af74909SZhong Yang 	CancelModes();
205*8af74909SZhong Yang }
206*8af74909SZhong Yang 
SetRepresentations()207*8af74909SZhong Yang void Editor::SetRepresentations() {
208*8af74909SZhong Yang 	reprs.Clear();
209*8af74909SZhong Yang 
210*8af74909SZhong Yang 	// C0 control set
211*8af74909SZhong Yang 	const char *const reps[] = {
212*8af74909SZhong Yang 		"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
213*8af74909SZhong Yang 		"BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
214*8af74909SZhong Yang 		"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
215*8af74909SZhong Yang 		"CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
216*8af74909SZhong Yang 	};
217*8af74909SZhong Yang 	for (size_t j=0; j < std::size(reps); j++) {
218*8af74909SZhong Yang 		const char c[2] = { static_cast<char>(j), 0 };
219*8af74909SZhong Yang 		reprs.SetRepresentation(c, reps[j]);
220*8af74909SZhong Yang 	}
221*8af74909SZhong Yang 	reprs.SetRepresentation("\x7f", "DEL");
222*8af74909SZhong Yang 
223*8af74909SZhong Yang 	// C1 control set
224*8af74909SZhong Yang 	// As well as Unicode mode, ISO-8859-1 should use these
225*8af74909SZhong Yang 	if (IsUnicodeMode()) {
226*8af74909SZhong Yang 		const char *const repsC1[] = {
227*8af74909SZhong Yang 			"PAD", "HOP", "BPH", "NBH", "IND", "NEL", "SSA", "ESA",
228*8af74909SZhong Yang 			"HTS", "HTJ", "VTS", "PLD", "PLU", "RI", "SS2", "SS3",
229*8af74909SZhong Yang 			"DCS", "PU1", "PU2", "STS", "CCH", "MW", "SPA", "EPA",
230*8af74909SZhong Yang 			"SOS", "SGCI", "SCI", "CSI", "ST", "OSC", "PM", "APC"
231*8af74909SZhong Yang 		};
232*8af74909SZhong Yang 		for (size_t j=0; j < std::size(repsC1); j++) {
233*8af74909SZhong Yang 			const char c1[3] = { '\xc2',  static_cast<char>(0x80+j), 0 };
234*8af74909SZhong Yang 			reprs.SetRepresentation(c1, repsC1[j]);
235*8af74909SZhong Yang 		}
236*8af74909SZhong Yang 		reprs.SetRepresentation("\xe2\x80\xa8", "LS");
237*8af74909SZhong Yang 		reprs.SetRepresentation("\xe2\x80\xa9", "PS");
238*8af74909SZhong Yang 	}
239*8af74909SZhong Yang 
240*8af74909SZhong Yang 	// UTF-8 invalid bytes
241*8af74909SZhong Yang 	if (IsUnicodeMode()) {
242*8af74909SZhong Yang 		for (int k=0x80; k < 0x100; k++) {
243*8af74909SZhong Yang 			const char hiByte[2] = {  static_cast<char>(k), 0 };
244*8af74909SZhong Yang 			char hexits[5];	// Really only needs 4 but that causes warning from gcc 7.1
245*8af74909SZhong Yang 			sprintf(hexits, "x%2X", k);
246*8af74909SZhong Yang 			reprs.SetRepresentation(hiByte, hexits);
247*8af74909SZhong Yang 		}
248*8af74909SZhong Yang 	} else if (pdoc->dbcsCodePage) {
249*8af74909SZhong Yang 		// DBCS invalid single lead bytes
250*8af74909SZhong Yang 		for (int k = 0x80; k < 0x100; k++) {
251*8af74909SZhong Yang 			const char ch = static_cast<char>(k);
252*8af74909SZhong Yang 			if (pdoc->IsDBCSLeadByteNoExcept(ch)  || pdoc->IsDBCSLeadByteInvalid(ch)) {
253*8af74909SZhong Yang 				const char hiByte[2] = { ch, 0 };
254*8af74909SZhong Yang 				char hexits[5];	// Really only needs 4 but that causes warning from gcc 7.1
255*8af74909SZhong Yang 				sprintf(hexits, "x%2X", k);
256*8af74909SZhong Yang 				reprs.SetRepresentation(hiByte, hexits);
257*8af74909SZhong Yang 			}
258*8af74909SZhong Yang 		}
259*8af74909SZhong Yang 	}
260*8af74909SZhong Yang }
261*8af74909SZhong Yang 
DropGraphics(bool freeObjects)262*8af74909SZhong Yang void Editor::DropGraphics(bool freeObjects) {
263*8af74909SZhong Yang 	marginView.DropGraphics(freeObjects);
264*8af74909SZhong Yang 	view.DropGraphics(freeObjects);
265*8af74909SZhong Yang }
266*8af74909SZhong Yang 
AllocateGraphics()267*8af74909SZhong Yang void Editor::AllocateGraphics() {
268*8af74909SZhong Yang 	marginView.AllocateGraphics(vs);
269*8af74909SZhong Yang 	view.AllocateGraphics(vs);
270*8af74909SZhong Yang }
271*8af74909SZhong Yang 
InvalidateStyleData()272*8af74909SZhong Yang void Editor::InvalidateStyleData() {
273*8af74909SZhong Yang 	stylesValid = false;
274*8af74909SZhong Yang 	vs.technology = technology;
275*8af74909SZhong Yang 	DropGraphics(false);
276*8af74909SZhong Yang 	AllocateGraphics();
277*8af74909SZhong Yang 	view.llc.Invalidate(LineLayout::ValidLevel::invalid);
278*8af74909SZhong Yang 	view.posCache.Clear();
279*8af74909SZhong Yang }
280*8af74909SZhong Yang 
InvalidateStyleRedraw()281*8af74909SZhong Yang void Editor::InvalidateStyleRedraw() {
282*8af74909SZhong Yang 	NeedWrapping();
283*8af74909SZhong Yang 	InvalidateStyleData();
284*8af74909SZhong Yang 	Redraw();
285*8af74909SZhong Yang }
286*8af74909SZhong Yang 
RefreshStyleData()287*8af74909SZhong Yang void Editor::RefreshStyleData() {
288*8af74909SZhong Yang 	if (!stylesValid) {
289*8af74909SZhong Yang 		stylesValid = true;
290*8af74909SZhong Yang 		AutoSurface surface(this);
291*8af74909SZhong Yang 		if (surface) {
292*8af74909SZhong Yang 			vs.Refresh(*surface, pdoc->tabInChars);
293*8af74909SZhong Yang 		}
294*8af74909SZhong Yang 		SetScrollBars();
295*8af74909SZhong Yang 		SetRectangularRange();
296*8af74909SZhong Yang 	}
297*8af74909SZhong Yang }
298*8af74909SZhong Yang 
GetVisibleOriginInMain() const299*8af74909SZhong Yang Point Editor::GetVisibleOriginInMain() const {
300*8af74909SZhong Yang 	return Point(0, 0);
301*8af74909SZhong Yang }
302*8af74909SZhong Yang 
DocumentPointFromView(Point ptView) const303*8af74909SZhong Yang PointDocument Editor::DocumentPointFromView(Point ptView) const {
304*8af74909SZhong Yang 	PointDocument ptDocument(ptView);
305*8af74909SZhong Yang 	if (wMargin.GetID()) {
306*8af74909SZhong Yang 		const Point ptOrigin = GetVisibleOriginInMain();
307*8af74909SZhong Yang 		ptDocument.x += ptOrigin.x;
308*8af74909SZhong Yang 		ptDocument.y += ptOrigin.y;
309*8af74909SZhong Yang 	} else {
310*8af74909SZhong Yang 		ptDocument.x += xOffset;
311*8af74909SZhong Yang 		ptDocument.y += topLine * vs.lineHeight;
312*8af74909SZhong Yang 	}
313*8af74909SZhong Yang 	return ptDocument;
314*8af74909SZhong Yang }
315*8af74909SZhong Yang 
TopLineOfMain() const316*8af74909SZhong Yang Sci::Line Editor::TopLineOfMain() const {
317*8af74909SZhong Yang 	if (wMargin.GetID())
318*8af74909SZhong Yang 		return 0;
319*8af74909SZhong Yang 	else
320*8af74909SZhong Yang 		return topLine;
321*8af74909SZhong Yang }
322*8af74909SZhong Yang 
GetClientRectangle() const323*8af74909SZhong Yang PRectangle Editor::GetClientRectangle() const {
324*8af74909SZhong Yang 	return wMain.GetClientPosition();
325*8af74909SZhong Yang }
326*8af74909SZhong Yang 
GetClientDrawingRectangle()327*8af74909SZhong Yang PRectangle Editor::GetClientDrawingRectangle() {
328*8af74909SZhong Yang 	return GetClientRectangle();
329*8af74909SZhong Yang }
330*8af74909SZhong Yang 
GetTextRectangle() const331*8af74909SZhong Yang PRectangle Editor::GetTextRectangle() const {
332*8af74909SZhong Yang 	PRectangle rc = GetClientRectangle();
333*8af74909SZhong Yang 	rc.left += vs.textStart;
334*8af74909SZhong Yang 	rc.right -= vs.rightMarginWidth;
335*8af74909SZhong Yang 	return rc;
336*8af74909SZhong Yang }
337*8af74909SZhong Yang 
LinesOnScreen() const338*8af74909SZhong Yang Sci::Line Editor::LinesOnScreen() const {
339*8af74909SZhong Yang 	const PRectangle rcClient = GetClientRectangle();
340*8af74909SZhong Yang 	const int htClient = static_cast<int>(rcClient.bottom - rcClient.top);
341*8af74909SZhong Yang 	//Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1);
342*8af74909SZhong Yang 	return htClient / vs.lineHeight;
343*8af74909SZhong Yang }
344*8af74909SZhong Yang 
LinesToScroll() const345*8af74909SZhong Yang Sci::Line Editor::LinesToScroll() const {
346*8af74909SZhong Yang 	const Sci::Line retVal = LinesOnScreen() - 1;
347*8af74909SZhong Yang 	if (retVal < 1)
348*8af74909SZhong Yang 		return 1;
349*8af74909SZhong Yang 	else
350*8af74909SZhong Yang 		return retVal;
351*8af74909SZhong Yang }
352*8af74909SZhong Yang 
MaxScrollPos() const353*8af74909SZhong Yang Sci::Line Editor::MaxScrollPos() const {
354*8af74909SZhong Yang 	//Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n",
355*8af74909SZhong Yang 	//LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1);
356*8af74909SZhong Yang 	Sci::Line retVal = pcs->LinesDisplayed();
357*8af74909SZhong Yang 	if (endAtLastLine) {
358*8af74909SZhong Yang 		retVal -= LinesOnScreen();
359*8af74909SZhong Yang 	} else {
360*8af74909SZhong Yang 		retVal--;
361*8af74909SZhong Yang 	}
362*8af74909SZhong Yang 	if (retVal < 0) {
363*8af74909SZhong Yang 		return 0;
364*8af74909SZhong Yang 	} else {
365*8af74909SZhong Yang 		return retVal;
366*8af74909SZhong Yang 	}
367*8af74909SZhong Yang }
368*8af74909SZhong Yang 
ClampPositionIntoDocument(SelectionPosition sp) const369*8af74909SZhong Yang SelectionPosition Editor::ClampPositionIntoDocument(SelectionPosition sp) const {
370*8af74909SZhong Yang 	if (sp.Position() < 0) {
371*8af74909SZhong Yang 		return SelectionPosition(0);
372*8af74909SZhong Yang 	} else if (sp.Position() > pdoc->Length()) {
373*8af74909SZhong Yang 		return SelectionPosition(pdoc->Length());
374*8af74909SZhong Yang 	} else {
375*8af74909SZhong Yang 		// If not at end of line then set offset to 0
376*8af74909SZhong Yang 		if (!pdoc->IsLineEndPosition(sp.Position()))
377*8af74909SZhong Yang 			sp.SetVirtualSpace(0);
378*8af74909SZhong Yang 		return sp;
379*8af74909SZhong Yang 	}
380*8af74909SZhong Yang }
381*8af74909SZhong Yang 
LocationFromPosition(SelectionPosition pos,PointEnd pe)382*8af74909SZhong Yang Point Editor::LocationFromPosition(SelectionPosition pos, PointEnd pe) {
383*8af74909SZhong Yang 	const PRectangle rcClient = GetTextRectangle();
384*8af74909SZhong Yang 	RefreshStyleData();
385*8af74909SZhong Yang 	AutoSurface surface(this);
386*8af74909SZhong Yang 	return view.LocationFromPosition(surface, *this, pos, topLine, vs, pe, rcClient);
387*8af74909SZhong Yang }
388*8af74909SZhong Yang 
LocationFromPosition(Sci::Position pos,PointEnd pe)389*8af74909SZhong Yang Point Editor::LocationFromPosition(Sci::Position pos, PointEnd pe) {
390*8af74909SZhong Yang 	return LocationFromPosition(SelectionPosition(pos), pe);
391*8af74909SZhong Yang }
392*8af74909SZhong Yang 
XFromPosition(SelectionPosition sp)393*8af74909SZhong Yang int Editor::XFromPosition(SelectionPosition sp) {
394*8af74909SZhong Yang 	const Point pt = LocationFromPosition(sp);
395*8af74909SZhong Yang 	return static_cast<int>(pt.x) - vs.textStart + xOffset;
396*8af74909SZhong Yang }
397*8af74909SZhong Yang 
SPositionFromLocation(Point pt,bool canReturnInvalid,bool charPosition,bool virtualSpace)398*8af74909SZhong Yang SelectionPosition Editor::SPositionFromLocation(Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace) {
399*8af74909SZhong Yang 	RefreshStyleData();
400*8af74909SZhong Yang 	AutoSurface surface(this);
401*8af74909SZhong Yang 
402*8af74909SZhong Yang 	PRectangle rcClient = GetTextRectangle();
403*8af74909SZhong Yang 	// May be in scroll view coordinates so translate back to main view
404*8af74909SZhong Yang 	const Point ptOrigin = GetVisibleOriginInMain();
405*8af74909SZhong Yang 	rcClient.Move(-ptOrigin.x, -ptOrigin.y);
406*8af74909SZhong Yang 
407*8af74909SZhong Yang 	if (canReturnInvalid) {
408*8af74909SZhong Yang 		if (!rcClient.Contains(pt))
409*8af74909SZhong Yang 			return SelectionPosition(INVALID_POSITION);
410*8af74909SZhong Yang 		if (pt.x < vs.textStart)
411*8af74909SZhong Yang 			return SelectionPosition(INVALID_POSITION);
412*8af74909SZhong Yang 		if (pt.y < 0)
413*8af74909SZhong Yang 			return SelectionPosition(INVALID_POSITION);
414*8af74909SZhong Yang 	}
415*8af74909SZhong Yang 	const PointDocument ptdoc = DocumentPointFromView(pt);
416*8af74909SZhong Yang 	return view.SPositionFromLocation(surface, *this, ptdoc, canReturnInvalid,
417*8af74909SZhong Yang 		charPosition, virtualSpace, vs, rcClient);
418*8af74909SZhong Yang }
419*8af74909SZhong Yang 
PositionFromLocation(Point pt,bool canReturnInvalid,bool charPosition)420*8af74909SZhong Yang Sci::Position Editor::PositionFromLocation(Point pt, bool canReturnInvalid, bool charPosition) {
421*8af74909SZhong Yang 	return SPositionFromLocation(pt, canReturnInvalid, charPosition, false).Position();
422*8af74909SZhong Yang }
423*8af74909SZhong Yang 
424*8af74909SZhong Yang /**
425*8af74909SZhong Yang * Find the document position corresponding to an x coordinate on a particular document line.
426*8af74909SZhong Yang * Ensure is between whole characters when document is in multi-byte or UTF-8 mode.
427*8af74909SZhong Yang * This method is used for rectangular selections and does not work on wrapped lines.
428*8af74909SZhong Yang */
SPositionFromLineX(Sci::Line lineDoc,int x)429*8af74909SZhong Yang SelectionPosition Editor::SPositionFromLineX(Sci::Line lineDoc, int x) {
430*8af74909SZhong Yang 	RefreshStyleData();
431*8af74909SZhong Yang 	if (lineDoc >= pdoc->LinesTotal())
432*8af74909SZhong Yang 		return SelectionPosition(pdoc->Length());
433*8af74909SZhong Yang 	//Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
434*8af74909SZhong Yang 	AutoSurface surface(this);
435*8af74909SZhong Yang 	return view.SPositionFromLineX(surface, *this, lineDoc, x, vs);
436*8af74909SZhong Yang }
437*8af74909SZhong Yang 
PositionFromLineX(Sci::Line lineDoc,int x)438*8af74909SZhong Yang Sci::Position Editor::PositionFromLineX(Sci::Line lineDoc, int x) {
439*8af74909SZhong Yang 	return SPositionFromLineX(lineDoc, x).Position();
440*8af74909SZhong Yang }
441*8af74909SZhong Yang 
LineFromLocation(Point pt) const442*8af74909SZhong Yang Sci::Line Editor::LineFromLocation(Point pt) const {
443*8af74909SZhong Yang 	return pcs->DocFromDisplay(static_cast<int>(pt.y) / vs.lineHeight + topLine);
444*8af74909SZhong Yang }
445*8af74909SZhong Yang 
SetTopLine(Sci::Line topLineNew)446*8af74909SZhong Yang void Editor::SetTopLine(Sci::Line topLineNew) {
447*8af74909SZhong Yang 	if ((topLine != topLineNew) && (topLineNew >= 0)) {
448*8af74909SZhong Yang 		topLine = topLineNew;
449*8af74909SZhong Yang 		ContainerNeedsUpdate(SC_UPDATE_V_SCROLL);
450*8af74909SZhong Yang 	}
451*8af74909SZhong Yang 	posTopLine = pdoc->LineStart(pcs->DocFromDisplay(topLine));
452*8af74909SZhong Yang }
453*8af74909SZhong Yang 
454*8af74909SZhong Yang /**
455*8af74909SZhong Yang  * If painting then abandon the painting because a wider redraw is needed.
456*8af74909SZhong Yang  * @return true if calling code should stop drawing.
457*8af74909SZhong Yang  */
AbandonPaint()458*8af74909SZhong Yang bool Editor::AbandonPaint() {
459*8af74909SZhong Yang 	if ((paintState == painting) && !paintingAllText) {
460*8af74909SZhong Yang 		paintState = paintAbandoned;
461*8af74909SZhong Yang 	}
462*8af74909SZhong Yang 	return paintState == paintAbandoned;
463*8af74909SZhong Yang }
464*8af74909SZhong Yang 
RedrawRect(PRectangle rc)465*8af74909SZhong Yang void Editor::RedrawRect(PRectangle rc) {
466*8af74909SZhong Yang 	//Platform::DebugPrintf("Redraw %0d,%0d - %0d,%0d\n", rc.left, rc.top, rc.right, rc.bottom);
467*8af74909SZhong Yang 
468*8af74909SZhong Yang 	// Clip the redraw rectangle into the client area
469*8af74909SZhong Yang 	const PRectangle rcClient = GetClientRectangle();
470*8af74909SZhong Yang 	if (rc.top < rcClient.top)
471*8af74909SZhong Yang 		rc.top = rcClient.top;
472*8af74909SZhong Yang 	if (rc.bottom > rcClient.bottom)
473*8af74909SZhong Yang 		rc.bottom = rcClient.bottom;
474*8af74909SZhong Yang 	if (rc.left < rcClient.left)
475*8af74909SZhong Yang 		rc.left = rcClient.left;
476*8af74909SZhong Yang 	if (rc.right > rcClient.right)
477*8af74909SZhong Yang 		rc.right = rcClient.right;
478*8af74909SZhong Yang 
479*8af74909SZhong Yang 	if ((rc.bottom > rc.top) && (rc.right > rc.left)) {
480*8af74909SZhong Yang 		wMain.InvalidateRectangle(rc);
481*8af74909SZhong Yang 	}
482*8af74909SZhong Yang }
483*8af74909SZhong Yang 
DiscardOverdraw()484*8af74909SZhong Yang void Editor::DiscardOverdraw() {
485*8af74909SZhong Yang 	// Overridden on platforms that may draw outside visible area.
486*8af74909SZhong Yang }
487*8af74909SZhong Yang 
Redraw()488*8af74909SZhong Yang void Editor::Redraw() {
489*8af74909SZhong Yang 	//Platform::DebugPrintf("Redraw all\n");
490*8af74909SZhong Yang 	const PRectangle rcClient = GetClientRectangle();
491*8af74909SZhong Yang 	wMain.InvalidateRectangle(rcClient);
492*8af74909SZhong Yang 	if (wMargin.GetID())
493*8af74909SZhong Yang 		wMargin.InvalidateAll();
494*8af74909SZhong Yang 	//wMain.InvalidateAll();
495*8af74909SZhong Yang }
496*8af74909SZhong Yang 
RedrawSelMargin(Sci::Line line,bool allAfter)497*8af74909SZhong Yang void Editor::RedrawSelMargin(Sci::Line line, bool allAfter) {
498*8af74909SZhong Yang 	const bool markersInText = vs.maskInLine || vs.maskDrawInText;
499*8af74909SZhong Yang 	if (!wMargin.GetID() || markersInText) {	// May affect text area so may need to abandon and retry
500*8af74909SZhong Yang 		if (AbandonPaint()) {
501*8af74909SZhong Yang 			return;
502*8af74909SZhong Yang 		}
503*8af74909SZhong Yang 	}
504*8af74909SZhong Yang 	if (wMargin.GetID() && markersInText) {
505*8af74909SZhong Yang 		Redraw();
506*8af74909SZhong Yang 		return;
507*8af74909SZhong Yang 	}
508*8af74909SZhong Yang 	PRectangle rcMarkers = GetClientRectangle();
509*8af74909SZhong Yang 	if (!markersInText) {
510*8af74909SZhong Yang 		// Normal case: just draw the margin
511*8af74909SZhong Yang 		rcMarkers.right = rcMarkers.left + vs.fixedColumnWidth;
512*8af74909SZhong Yang 	}
513*8af74909SZhong Yang 	if (line != -1) {
514*8af74909SZhong Yang 		PRectangle rcLine = RectangleFromRange(Range(pdoc->LineStart(line)), 0);
515*8af74909SZhong Yang 
516*8af74909SZhong Yang 		// Inflate line rectangle if there are image markers with height larger than line height
517*8af74909SZhong Yang 		if (vs.largestMarkerHeight > vs.lineHeight) {
518*8af74909SZhong Yang 			const int delta = (vs.largestMarkerHeight - vs.lineHeight + 1) / 2;
519*8af74909SZhong Yang 			rcLine.top -= delta;
520*8af74909SZhong Yang 			rcLine.bottom += delta;
521*8af74909SZhong Yang 			if (rcLine.top < rcMarkers.top)
522*8af74909SZhong Yang 				rcLine.top = rcMarkers.top;
523*8af74909SZhong Yang 			if (rcLine.bottom > rcMarkers.bottom)
524*8af74909SZhong Yang 				rcLine.bottom = rcMarkers.bottom;
525*8af74909SZhong Yang 		}
526*8af74909SZhong Yang 
527*8af74909SZhong Yang 		rcMarkers.top = rcLine.top;
528*8af74909SZhong Yang 		if (!allAfter)
529*8af74909SZhong Yang 			rcMarkers.bottom = rcLine.bottom;
530*8af74909SZhong Yang 		if (rcMarkers.Empty())
531*8af74909SZhong Yang 			return;
532*8af74909SZhong Yang 	}
533*8af74909SZhong Yang 	if (wMargin.GetID()) {
534*8af74909SZhong Yang 		const Point ptOrigin = GetVisibleOriginInMain();
535*8af74909SZhong Yang 		rcMarkers.Move(-ptOrigin.x, -ptOrigin.y);
536*8af74909SZhong Yang 		wMargin.InvalidateRectangle(rcMarkers);
537*8af74909SZhong Yang 	} else {
538*8af74909SZhong Yang 		wMain.InvalidateRectangle(rcMarkers);
539*8af74909SZhong Yang 	}
540*8af74909SZhong Yang }
541*8af74909SZhong Yang 
RectangleFromRange(Range r,int overlap)542*8af74909SZhong Yang PRectangle Editor::RectangleFromRange(Range r, int overlap) {
543*8af74909SZhong Yang 	const Sci::Line minLine = pcs->DisplayFromDoc(
544*8af74909SZhong Yang 		pdoc->SciLineFromPosition(r.First()));
545*8af74909SZhong Yang 	const Sci::Line maxLine = pcs->DisplayLastFromDoc(
546*8af74909SZhong Yang 		pdoc->SciLineFromPosition(r.Last()));
547*8af74909SZhong Yang 	const PRectangle rcClientDrawing = GetClientDrawingRectangle();
548*8af74909SZhong Yang 	PRectangle rc;
549*8af74909SZhong Yang 	const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0;
550*8af74909SZhong Yang 	rc.left = static_cast<XYPOSITION>(vs.textStart - leftTextOverlap);
551*8af74909SZhong Yang 	rc.top = static_cast<XYPOSITION>((minLine - TopLineOfMain()) * vs.lineHeight - overlap);
552*8af74909SZhong Yang 	if (rc.top < rcClientDrawing.top)
553*8af74909SZhong Yang 		rc.top = rcClientDrawing.top;
554*8af74909SZhong Yang 	// Extend to right of prepared area if any to prevent artifacts from caret line highlight
555*8af74909SZhong Yang 	rc.right = rcClientDrawing.right;
556*8af74909SZhong Yang 	rc.bottom = static_cast<XYPOSITION>((maxLine - TopLineOfMain() + 1) * vs.lineHeight + overlap);
557*8af74909SZhong Yang 
558*8af74909SZhong Yang 	return rc;
559*8af74909SZhong Yang }
560*8af74909SZhong Yang 
InvalidateRange(Sci::Position start,Sci::Position end)561*8af74909SZhong Yang void Editor::InvalidateRange(Sci::Position start, Sci::Position end) {
562*8af74909SZhong Yang 	RedrawRect(RectangleFromRange(Range(start, end), view.LinesOverlap() ? vs.lineOverlap : 0));
563*8af74909SZhong Yang }
564*8af74909SZhong Yang 
CurrentPosition() const565*8af74909SZhong Yang Sci::Position Editor::CurrentPosition() const {
566*8af74909SZhong Yang 	return sel.MainCaret();
567*8af74909SZhong Yang }
568*8af74909SZhong Yang 
SelectionEmpty() const569*8af74909SZhong Yang bool Editor::SelectionEmpty() const noexcept {
570*8af74909SZhong Yang 	return sel.Empty();
571*8af74909SZhong Yang }
572*8af74909SZhong Yang 
SelectionStart()573*8af74909SZhong Yang SelectionPosition Editor::SelectionStart() {
574*8af74909SZhong Yang 	return sel.RangeMain().Start();
575*8af74909SZhong Yang }
576*8af74909SZhong Yang 
SelectionEnd()577*8af74909SZhong Yang SelectionPosition Editor::SelectionEnd() {
578*8af74909SZhong Yang 	return sel.RangeMain().End();
579*8af74909SZhong Yang }
580*8af74909SZhong Yang 
SetRectangularRange()581*8af74909SZhong Yang void Editor::SetRectangularRange() {
582*8af74909SZhong Yang 	if (sel.IsRectangular()) {
583*8af74909SZhong Yang 		const int xAnchor = XFromPosition(sel.Rectangular().anchor);
584*8af74909SZhong Yang 		int xCaret = XFromPosition(sel.Rectangular().caret);
585*8af74909SZhong Yang 		if (sel.selType == Selection::selThin) {
586*8af74909SZhong Yang 			xCaret = xAnchor;
587*8af74909SZhong Yang 		}
588*8af74909SZhong Yang 		const Sci::Line lineAnchorRect =
589*8af74909SZhong Yang 			pdoc->SciLineFromPosition(sel.Rectangular().anchor.Position());
590*8af74909SZhong Yang 		const Sci::Line lineCaret =
591*8af74909SZhong Yang 			pdoc->SciLineFromPosition(sel.Rectangular().caret.Position());
592*8af74909SZhong Yang 		const int increment = (lineCaret > lineAnchorRect) ? 1 : -1;
593*8af74909SZhong Yang 		AutoSurface surface(this);
594*8af74909SZhong Yang 		for (Sci::Line line=lineAnchorRect; line != lineCaret+increment; line += increment) {
595*8af74909SZhong Yang 			SelectionRange range(
596*8af74909SZhong Yang 				view.SPositionFromLineX(surface, *this, line, xCaret, vs),
597*8af74909SZhong Yang 				view.SPositionFromLineX(surface, *this, line, xAnchor, vs));
598*8af74909SZhong Yang 			if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) == 0)
599*8af74909SZhong Yang 				range.ClearVirtualSpace();
600*8af74909SZhong Yang 			if (line == lineAnchorRect)
601*8af74909SZhong Yang 				sel.SetSelection(range);
602*8af74909SZhong Yang 			else
603*8af74909SZhong Yang 				sel.AddSelectionWithoutTrim(range);
604*8af74909SZhong Yang 		}
605*8af74909SZhong Yang 	}
606*8af74909SZhong Yang }
607*8af74909SZhong Yang 
ThinRectangularRange()608*8af74909SZhong Yang void Editor::ThinRectangularRange() {
609*8af74909SZhong Yang 	if (sel.IsRectangular()) {
610*8af74909SZhong Yang 		sel.selType = Selection::selThin;
611*8af74909SZhong Yang 		if (sel.Rectangular().caret < sel.Rectangular().anchor) {
612*8af74909SZhong Yang 			sel.Rectangular() = SelectionRange(sel.Range(sel.Count()-1).caret, sel.Range(0).anchor);
613*8af74909SZhong Yang 		} else {
614*8af74909SZhong Yang 			sel.Rectangular() = SelectionRange(sel.Range(sel.Count()-1).anchor, sel.Range(0).caret);
615*8af74909SZhong Yang 		}
616*8af74909SZhong Yang 		SetRectangularRange();
617*8af74909SZhong Yang 	}
618*8af74909SZhong Yang }
619*8af74909SZhong Yang 
InvalidateSelection(SelectionRange newMain,bool invalidateWholeSelection)620*8af74909SZhong Yang void Editor::InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection) {
621*8af74909SZhong Yang 	if (sel.Count() > 1 || !(sel.RangeMain().anchor == newMain.anchor) || sel.IsRectangular()) {
622*8af74909SZhong Yang 		invalidateWholeSelection = true;
623*8af74909SZhong Yang 	}
624*8af74909SZhong Yang 	Sci::Position firstAffected = std::min(sel.RangeMain().Start().Position(), newMain.Start().Position());
625*8af74909SZhong Yang 	// +1 for lastAffected ensures caret repainted
626*8af74909SZhong Yang 	Sci::Position lastAffected = std::max(newMain.caret.Position()+1, newMain.anchor.Position());
627*8af74909SZhong Yang 	lastAffected = std::max(lastAffected, sel.RangeMain().End().Position());
628*8af74909SZhong Yang 	if (invalidateWholeSelection) {
629*8af74909SZhong Yang 		for (size_t r=0; r<sel.Count(); r++) {
630*8af74909SZhong Yang 			firstAffected = std::min(firstAffected, sel.Range(r).caret.Position());
631*8af74909SZhong Yang 			firstAffected = std::min(firstAffected, sel.Range(r).anchor.Position());
632*8af74909SZhong Yang 			lastAffected = std::max(lastAffected, sel.Range(r).caret.Position()+1);
633*8af74909SZhong Yang 			lastAffected = std::max(lastAffected, sel.Range(r).anchor.Position());
634*8af74909SZhong Yang 		}
635*8af74909SZhong Yang 	}
636*8af74909SZhong Yang 	ContainerNeedsUpdate(SC_UPDATE_SELECTION);
637*8af74909SZhong Yang 	InvalidateRange(firstAffected, lastAffected);
638*8af74909SZhong Yang }
639*8af74909SZhong Yang 
InvalidateWholeSelection()640*8af74909SZhong Yang void Editor::InvalidateWholeSelection() {
641*8af74909SZhong Yang 	InvalidateSelection(sel.RangeMain(), true);
642*8af74909SZhong Yang }
643*8af74909SZhong Yang 
644*8af74909SZhong Yang /* For Line selection - the anchor and caret are always
645*8af74909SZhong Yang    at the beginning and end of the region lines. */
LineSelectionRange(SelectionPosition currentPos_,SelectionPosition anchor_) const646*8af74909SZhong Yang SelectionRange Editor::LineSelectionRange(SelectionPosition currentPos_, SelectionPosition anchor_) const {
647*8af74909SZhong Yang 	if (currentPos_ > anchor_) {
648*8af74909SZhong Yang 		anchor_ = SelectionPosition(
649*8af74909SZhong Yang 			pdoc->LineStart(pdoc->LineFromPosition(anchor_.Position())));
650*8af74909SZhong Yang 		currentPos_ = SelectionPosition(
651*8af74909SZhong Yang 			pdoc->LineEnd(pdoc->LineFromPosition(currentPos_.Position())));
652*8af74909SZhong Yang 	} else {
653*8af74909SZhong Yang 		currentPos_ = SelectionPosition(
654*8af74909SZhong Yang 			pdoc->LineStart(pdoc->LineFromPosition(currentPos_.Position())));
655*8af74909SZhong Yang 		anchor_ = SelectionPosition(
656*8af74909SZhong Yang 			pdoc->LineEnd(pdoc->LineFromPosition(anchor_.Position())));
657*8af74909SZhong Yang 	}
658*8af74909SZhong Yang 	return SelectionRange(currentPos_, anchor_);
659*8af74909SZhong Yang }
660*8af74909SZhong Yang 
SetSelection(SelectionPosition currentPos_,SelectionPosition anchor_)661*8af74909SZhong Yang void Editor::SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_) {
662*8af74909SZhong Yang 	currentPos_ = ClampPositionIntoDocument(currentPos_);
663*8af74909SZhong Yang 	anchor_ = ClampPositionIntoDocument(anchor_);
664*8af74909SZhong Yang 	const Sci::Line currentLine = pdoc->SciLineFromPosition(currentPos_.Position());
665*8af74909SZhong Yang 	SelectionRange rangeNew(currentPos_, anchor_);
666*8af74909SZhong Yang 	if (sel.selType == Selection::selLines) {
667*8af74909SZhong Yang 		rangeNew = LineSelectionRange(currentPos_, anchor_);
668*8af74909SZhong Yang 	}
669*8af74909SZhong Yang 	if (sel.Count() > 1 || !(sel.RangeMain() == rangeNew)) {
670*8af74909SZhong Yang 		InvalidateSelection(rangeNew);
671*8af74909SZhong Yang 	}
672*8af74909SZhong Yang 	sel.RangeMain() = rangeNew;
673*8af74909SZhong Yang 	SetRectangularRange();
674*8af74909SZhong Yang 	ClaimSelection();
675*8af74909SZhong Yang 	SetHoverIndicatorPosition(sel.MainCaret());
676*8af74909SZhong Yang 
677*8af74909SZhong Yang 	if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) {
678*8af74909SZhong Yang 		RedrawSelMargin();
679*8af74909SZhong Yang 	}
680*8af74909SZhong Yang 	QueueIdleWork(WorkNeeded::workUpdateUI);
681*8af74909SZhong Yang }
682*8af74909SZhong Yang 
SetSelection(Sci::Position currentPos_,Sci::Position anchor_)683*8af74909SZhong Yang void Editor::SetSelection(Sci::Position currentPos_, Sci::Position anchor_) {
684*8af74909SZhong Yang 	SetSelection(SelectionPosition(currentPos_), SelectionPosition(anchor_));
685*8af74909SZhong Yang }
686*8af74909SZhong Yang 
687*8af74909SZhong Yang // Just move the caret on the main selection
SetSelection(SelectionPosition currentPos_)688*8af74909SZhong Yang void Editor::SetSelection(SelectionPosition currentPos_) {
689*8af74909SZhong Yang 	currentPos_ = ClampPositionIntoDocument(currentPos_);
690*8af74909SZhong Yang 	const Sci::Line currentLine = pdoc->SciLineFromPosition(currentPos_.Position());
691*8af74909SZhong Yang 	if (sel.Count() > 1 || !(sel.RangeMain().caret == currentPos_)) {
692*8af74909SZhong Yang 		InvalidateSelection(SelectionRange(currentPos_));
693*8af74909SZhong Yang 	}
694*8af74909SZhong Yang 	if (sel.IsRectangular()) {
695*8af74909SZhong Yang 		sel.Rectangular() =
696*8af74909SZhong Yang 			SelectionRange(SelectionPosition(currentPos_), sel.Rectangular().anchor);
697*8af74909SZhong Yang 		SetRectangularRange();
698*8af74909SZhong Yang 	} else if (sel.selType == Selection::selLines) {
699*8af74909SZhong Yang 		sel.RangeMain() = LineSelectionRange(currentPos_, sel.RangeMain().anchor);
700*8af74909SZhong Yang 	} else {
701*8af74909SZhong Yang 		sel.RangeMain() =
702*8af74909SZhong Yang 			SelectionRange(SelectionPosition(currentPos_), sel.RangeMain().anchor);
703*8af74909SZhong Yang 	}
704*8af74909SZhong Yang 	ClaimSelection();
705*8af74909SZhong Yang 	SetHoverIndicatorPosition(sel.MainCaret());
706*8af74909SZhong Yang 
707*8af74909SZhong Yang 	if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) {
708*8af74909SZhong Yang 		RedrawSelMargin();
709*8af74909SZhong Yang 	}
710*8af74909SZhong Yang 	QueueIdleWork(WorkNeeded::workUpdateUI);
711*8af74909SZhong Yang }
712*8af74909SZhong Yang 
SetSelection(int currentPos_)713*8af74909SZhong Yang void Editor::SetSelection(int currentPos_) {
714*8af74909SZhong Yang 	SetSelection(SelectionPosition(currentPos_));
715*8af74909SZhong Yang }
716*8af74909SZhong Yang 
SetEmptySelection(SelectionPosition currentPos_)717*8af74909SZhong Yang void Editor::SetEmptySelection(SelectionPosition currentPos_) {
718*8af74909SZhong Yang 	const Sci::Line currentLine = pdoc->SciLineFromPosition(currentPos_.Position());
719*8af74909SZhong Yang 	SelectionRange rangeNew(ClampPositionIntoDocument(currentPos_));
720*8af74909SZhong Yang 	if (sel.Count() > 1 || !(sel.RangeMain() == rangeNew)) {
721*8af74909SZhong Yang 		InvalidateSelection(rangeNew);
722*8af74909SZhong Yang 	}
723*8af74909SZhong Yang 	sel.Clear();
724*8af74909SZhong Yang 	sel.RangeMain() = rangeNew;
725*8af74909SZhong Yang 	SetRectangularRange();
726*8af74909SZhong Yang 	ClaimSelection();
727*8af74909SZhong Yang 	SetHoverIndicatorPosition(sel.MainCaret());
728*8af74909SZhong Yang 
729*8af74909SZhong Yang 	if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) {
730*8af74909SZhong Yang 		RedrawSelMargin();
731*8af74909SZhong Yang 	}
732*8af74909SZhong Yang 	QueueIdleWork(WorkNeeded::workUpdateUI);
733*8af74909SZhong Yang }
734*8af74909SZhong Yang 
SetEmptySelection(Sci::Position currentPos_)735*8af74909SZhong Yang void Editor::SetEmptySelection(Sci::Position currentPos_) {
736*8af74909SZhong Yang 	SetEmptySelection(SelectionPosition(currentPos_));
737*8af74909SZhong Yang }
738*8af74909SZhong Yang 
MultipleSelectAdd(AddNumber addNumber)739*8af74909SZhong Yang void Editor::MultipleSelectAdd(AddNumber addNumber) {
740*8af74909SZhong Yang 	if (SelectionEmpty() || !multipleSelection) {
741*8af74909SZhong Yang 		// Select word at caret
742*8af74909SZhong Yang 		const Sci::Position startWord = pdoc->ExtendWordSelect(sel.MainCaret(), -1, true);
743*8af74909SZhong Yang 		const Sci::Position endWord = pdoc->ExtendWordSelect(startWord, 1, true);
744*8af74909SZhong Yang 		TrimAndSetSelection(endWord, startWord);
745*8af74909SZhong Yang 
746*8af74909SZhong Yang 	} else {
747*8af74909SZhong Yang 
748*8af74909SZhong Yang 		if (!pdoc->HasCaseFolder())
749*8af74909SZhong Yang 			pdoc->SetCaseFolder(CaseFolderForEncoding());
750*8af74909SZhong Yang 
751*8af74909SZhong Yang 		const Range rangeMainSelection(sel.RangeMain().Start().Position(), sel.RangeMain().End().Position());
752*8af74909SZhong Yang 		const std::string selectedText = RangeText(rangeMainSelection.start, rangeMainSelection.end);
753*8af74909SZhong Yang 
754*8af74909SZhong Yang 		const Range rangeTarget(targetRange.start.Position(), targetRange.end.Position());
755*8af74909SZhong Yang 		std::vector<Range> searchRanges;
756*8af74909SZhong Yang 		// Search should be over the target range excluding the current selection so
757*8af74909SZhong Yang 		// may need to search 2 ranges, after the selection then before the selection.
758*8af74909SZhong Yang 		if (rangeTarget.Overlaps(rangeMainSelection)) {
759*8af74909SZhong Yang 			// Common case is that the selection is completely within the target but
760*8af74909SZhong Yang 			// may also have overlap at start or end.
761*8af74909SZhong Yang 			if (rangeMainSelection.end < rangeTarget.end)
762*8af74909SZhong Yang 				searchRanges.push_back(Range(rangeMainSelection.end, rangeTarget.end));
763*8af74909SZhong Yang 			if (rangeTarget.start < rangeMainSelection.start)
764*8af74909SZhong Yang 				searchRanges.push_back(Range(rangeTarget.start, rangeMainSelection.start));
765*8af74909SZhong Yang 		} else {
766*8af74909SZhong Yang 			// No overlap
767*8af74909SZhong Yang 			searchRanges.push_back(rangeTarget);
768*8af74909SZhong Yang 		}
769*8af74909SZhong Yang 
770*8af74909SZhong Yang 		for (std::vector<Range>::const_iterator it = searchRanges.begin(); it != searchRanges.end(); ++it) {
771*8af74909SZhong Yang 			Sci::Position searchStart = it->start;
772*8af74909SZhong Yang 			const Sci::Position searchEnd = it->end;
773*8af74909SZhong Yang 			for (;;) {
774*8af74909SZhong Yang 				Sci::Position lengthFound = selectedText.length();
775*8af74909SZhong Yang 				const Sci::Position pos = pdoc->FindText(searchStart, searchEnd,
776*8af74909SZhong Yang 					selectedText.c_str(), searchFlags, &lengthFound);
777*8af74909SZhong Yang 				if (pos >= 0) {
778*8af74909SZhong Yang 					sel.AddSelection(SelectionRange(pos + lengthFound, pos));
779*8af74909SZhong Yang 					ContainerNeedsUpdate(SC_UPDATE_SELECTION);
780*8af74909SZhong Yang 					ScrollRange(sel.RangeMain());
781*8af74909SZhong Yang 					Redraw();
782*8af74909SZhong Yang 					if (addNumber == AddNumber::one)
783*8af74909SZhong Yang 						return;
784*8af74909SZhong Yang 					searchStart = pos + lengthFound;
785*8af74909SZhong Yang 				} else {
786*8af74909SZhong Yang 					break;
787*8af74909SZhong Yang 				}
788*8af74909SZhong Yang 			}
789*8af74909SZhong Yang 		}
790*8af74909SZhong Yang 	}
791*8af74909SZhong Yang }
792*8af74909SZhong Yang 
RangeContainsProtected(Sci::Position start,Sci::Position end) const793*8af74909SZhong Yang bool Editor::RangeContainsProtected(Sci::Position start, Sci::Position end) const noexcept {
794*8af74909SZhong Yang 	if (vs.ProtectionActive()) {
795*8af74909SZhong Yang 		if (start > end) {
796*8af74909SZhong Yang 			const Sci::Position t = start;
797*8af74909SZhong Yang 			start = end;
798*8af74909SZhong Yang 			end = t;
799*8af74909SZhong Yang 		}
800*8af74909SZhong Yang 		for (Sci::Position pos = start; pos < end; pos++) {
801*8af74909SZhong Yang 			if (vs.styles[pdoc->StyleIndexAt(pos)].IsProtected())
802*8af74909SZhong Yang 				return true;
803*8af74909SZhong Yang 		}
804*8af74909SZhong Yang 	}
805*8af74909SZhong Yang 	return false;
806*8af74909SZhong Yang }
807*8af74909SZhong Yang 
SelectionContainsProtected() const808*8af74909SZhong Yang bool Editor::SelectionContainsProtected() const {
809*8af74909SZhong Yang 	for (size_t r=0; r<sel.Count(); r++) {
810*8af74909SZhong Yang 		if (RangeContainsProtected(sel.Range(r).Start().Position(),
811*8af74909SZhong Yang 			sel.Range(r).End().Position())) {
812*8af74909SZhong Yang 			return true;
813*8af74909SZhong Yang 		}
814*8af74909SZhong Yang 	}
815*8af74909SZhong Yang 	return false;
816*8af74909SZhong Yang }
817*8af74909SZhong Yang 
818*8af74909SZhong Yang /**
819*8af74909SZhong Yang  * Asks document to find a good position and then moves out of any invisible positions.
820*8af74909SZhong Yang  */
MovePositionOutsideChar(Sci::Position pos,Sci::Position moveDir,bool checkLineEnd) const821*8af74909SZhong Yang Sci::Position Editor::MovePositionOutsideChar(Sci::Position pos, Sci::Position moveDir, bool checkLineEnd) const {
822*8af74909SZhong Yang 	return MovePositionOutsideChar(SelectionPosition(pos), moveDir, checkLineEnd).Position();
823*8af74909SZhong Yang }
824*8af74909SZhong Yang 
MovePositionOutsideChar(SelectionPosition pos,Sci::Position moveDir,bool checkLineEnd) const825*8af74909SZhong Yang SelectionPosition Editor::MovePositionOutsideChar(SelectionPosition pos, Sci::Position moveDir, bool checkLineEnd) const {
826*8af74909SZhong Yang 	const Sci::Position posMoved = pdoc->MovePositionOutsideChar(pos.Position(), moveDir, checkLineEnd);
827*8af74909SZhong Yang 	if (posMoved != pos.Position())
828*8af74909SZhong Yang 		pos.SetPosition(posMoved);
829*8af74909SZhong Yang 	if (vs.ProtectionActive()) {
830*8af74909SZhong Yang 		if (moveDir > 0) {
831*8af74909SZhong Yang 			if ((pos.Position() > 0) && vs.styles[pdoc->StyleIndexAt(pos.Position() - 1)].IsProtected()) {
832*8af74909SZhong Yang 				while ((pos.Position() < pdoc->Length()) &&
833*8af74909SZhong Yang 				        (vs.styles[pdoc->StyleIndexAt(pos.Position())].IsProtected()))
834*8af74909SZhong Yang 					pos.Add(1);
835*8af74909SZhong Yang 			}
836*8af74909SZhong Yang 		} else if (moveDir < 0) {
837*8af74909SZhong Yang 			if (vs.styles[pdoc->StyleIndexAt(pos.Position())].IsProtected()) {
838*8af74909SZhong Yang 				while ((pos.Position() > 0) &&
839*8af74909SZhong Yang 				        (vs.styles[pdoc->StyleIndexAt(pos.Position() - 1)].IsProtected()))
840*8af74909SZhong Yang 					pos.Add(-1);
841*8af74909SZhong Yang 			}
842*8af74909SZhong Yang 		}
843*8af74909SZhong Yang 	}
844*8af74909SZhong Yang 	return pos;
845*8af74909SZhong Yang }
846*8af74909SZhong Yang 
MovedCaret(SelectionPosition newPos,SelectionPosition previousPos,bool ensureVisible,CaretPolicies policies)847*8af74909SZhong Yang void Editor::MovedCaret(SelectionPosition newPos, SelectionPosition previousPos,
848*8af74909SZhong Yang 	bool ensureVisible, CaretPolicies policies) {
849*8af74909SZhong Yang 	const Sci::Line currentLine = pdoc->SciLineFromPosition(newPos.Position());
850*8af74909SZhong Yang 	if (ensureVisible) {
851*8af74909SZhong Yang 		// In case in need of wrapping to ensure DisplayFromDoc works.
852*8af74909SZhong Yang 		if (currentLine >= wrapPending.start) {
853*8af74909SZhong Yang 			if (WrapLines(WrapScope::wsAll)) {
854*8af74909SZhong Yang 				Redraw();
855*8af74909SZhong Yang 			}
856*8af74909SZhong Yang 		}
857*8af74909SZhong Yang 		const XYScrollPosition newXY = XYScrollToMakeVisible(
858*8af74909SZhong Yang 			SelectionRange(posDrag.IsValid() ? posDrag : newPos), xysDefault, policies);
859*8af74909SZhong Yang 		if (previousPos.IsValid() && (newXY.xOffset == xOffset)) {
860*8af74909SZhong Yang 			// simple vertical scroll then invalidate
861*8af74909SZhong Yang 			ScrollTo(newXY.topLine);
862*8af74909SZhong Yang 			InvalidateSelection(SelectionRange(previousPos), true);
863*8af74909SZhong Yang 		} else {
864*8af74909SZhong Yang 			SetXYScroll(newXY);
865*8af74909SZhong Yang 		}
866*8af74909SZhong Yang 	}
867*8af74909SZhong Yang 
868*8af74909SZhong Yang 	ShowCaretAtCurrentPosition();
869*8af74909SZhong Yang 	NotifyCaretMove();
870*8af74909SZhong Yang 
871*8af74909SZhong Yang 	ClaimSelection();
872*8af74909SZhong Yang 	SetHoverIndicatorPosition(sel.MainCaret());
873*8af74909SZhong Yang 	QueueIdleWork(WorkNeeded::workUpdateUI);
874*8af74909SZhong Yang 
875*8af74909SZhong Yang 	if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) {
876*8af74909SZhong Yang 		RedrawSelMargin();
877*8af74909SZhong Yang 	}
878*8af74909SZhong Yang }
879*8af74909SZhong Yang 
MovePositionTo(SelectionPosition newPos,Selection::selTypes selt,bool ensureVisible)880*8af74909SZhong Yang void Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt, bool ensureVisible) {
881*8af74909SZhong Yang 	const SelectionPosition spCaret = ((sel.Count() == 1) && sel.Empty()) ?
882*8af74909SZhong Yang 		sel.Last() : SelectionPosition(INVALID_POSITION);
883*8af74909SZhong Yang 
884*8af74909SZhong Yang 	const Sci::Position delta = newPos.Position() - sel.MainCaret();
885*8af74909SZhong Yang 	newPos = ClampPositionIntoDocument(newPos);
886*8af74909SZhong Yang 	newPos = MovePositionOutsideChar(newPos, delta);
887*8af74909SZhong Yang 	if (!multipleSelection && sel.IsRectangular() && (selt == Selection::selStream)) {
888*8af74909SZhong Yang 		// Can't turn into multiple selection so clear additional selections
889*8af74909SZhong Yang 		InvalidateSelection(SelectionRange(newPos), true);
890*8af74909SZhong Yang 		sel.DropAdditionalRanges();
891*8af74909SZhong Yang 	}
892*8af74909SZhong Yang 	if (!sel.IsRectangular() && (selt == Selection::selRectangle)) {
893*8af74909SZhong Yang 		// Switching to rectangular
894*8af74909SZhong Yang 		InvalidateSelection(sel.RangeMain(), false);
895*8af74909SZhong Yang 		SelectionRange rangeMain = sel.RangeMain();
896*8af74909SZhong Yang 		sel.Clear();
897*8af74909SZhong Yang 		sel.Rectangular() = rangeMain;
898*8af74909SZhong Yang 	}
899*8af74909SZhong Yang 	if (selt != Selection::noSel) {
900*8af74909SZhong Yang 		sel.selType = selt;
901*8af74909SZhong Yang 	}
902*8af74909SZhong Yang 	if (selt != Selection::noSel || sel.MoveExtends()) {
903*8af74909SZhong Yang 		SetSelection(newPos);
904*8af74909SZhong Yang 	} else {
905*8af74909SZhong Yang 		SetEmptySelection(newPos);
906*8af74909SZhong Yang 	}
907*8af74909SZhong Yang 
908*8af74909SZhong Yang 	MovedCaret(newPos, spCaret, ensureVisible, caretPolicies);
909*8af74909SZhong Yang }
910*8af74909SZhong Yang 
MovePositionTo(Sci::Position newPos,Selection::selTypes selt,bool ensureVisible)911*8af74909SZhong Yang void Editor::MovePositionTo(Sci::Position newPos, Selection::selTypes selt, bool ensureVisible) {
912*8af74909SZhong Yang 	MovePositionTo(SelectionPosition(newPos), selt, ensureVisible);
913*8af74909SZhong Yang }
914*8af74909SZhong Yang 
MovePositionSoVisible(SelectionPosition pos,int moveDir)915*8af74909SZhong Yang SelectionPosition Editor::MovePositionSoVisible(SelectionPosition pos, int moveDir) {
916*8af74909SZhong Yang 	pos = ClampPositionIntoDocument(pos);
917*8af74909SZhong Yang 	pos = MovePositionOutsideChar(pos, moveDir);
918*8af74909SZhong Yang 	const Sci::Line lineDoc = pdoc->SciLineFromPosition(pos.Position());
919*8af74909SZhong Yang 	if (pcs->GetVisible(lineDoc)) {
920*8af74909SZhong Yang 		return pos;
921*8af74909SZhong Yang 	} else {
922*8af74909SZhong Yang 		Sci::Line lineDisplay = pcs->DisplayFromDoc(lineDoc);
923*8af74909SZhong Yang 		if (moveDir > 0) {
924*8af74909SZhong Yang 			// lineDisplay is already line before fold as lines in fold use display line of line after fold
925*8af74909SZhong Yang 			lineDisplay = std::clamp<Sci::Line>(lineDisplay, 0, pcs->LinesDisplayed());
926*8af74909SZhong Yang 			return SelectionPosition(
927*8af74909SZhong Yang 				pdoc->LineStart(pcs->DocFromDisplay(lineDisplay)));
928*8af74909SZhong Yang 		} else {
929*8af74909SZhong Yang 			lineDisplay = std::clamp<Sci::Line>(lineDisplay - 1, 0, pcs->LinesDisplayed());
930*8af74909SZhong Yang 			return SelectionPosition(
931*8af74909SZhong Yang 				pdoc->LineEnd(pcs->DocFromDisplay(lineDisplay)));
932*8af74909SZhong Yang 		}
933*8af74909SZhong Yang 	}
934*8af74909SZhong Yang }
935*8af74909SZhong Yang 
MovePositionSoVisible(Sci::Position pos,int moveDir)936*8af74909SZhong Yang SelectionPosition Editor::MovePositionSoVisible(Sci::Position pos, int moveDir) {
937*8af74909SZhong Yang 	return MovePositionSoVisible(SelectionPosition(pos), moveDir);
938*8af74909SZhong Yang }
939*8af74909SZhong Yang 
PointMainCaret()940*8af74909SZhong Yang Point Editor::PointMainCaret() {
941*8af74909SZhong Yang 	return LocationFromPosition(sel.Range(sel.Main()).caret);
942*8af74909SZhong Yang }
943*8af74909SZhong Yang 
944*8af74909SZhong Yang /**
945*8af74909SZhong Yang  * Choose the x position that the caret will try to stick to
946*8af74909SZhong Yang  * as it moves up and down.
947*8af74909SZhong Yang  */
SetLastXChosen()948*8af74909SZhong Yang void Editor::SetLastXChosen() {
949*8af74909SZhong Yang 	const Point pt = PointMainCaret();
950*8af74909SZhong Yang 	lastXChosen = static_cast<int>(pt.x) + xOffset;
951*8af74909SZhong Yang }
952*8af74909SZhong Yang 
ScrollTo(Sci::Line line,bool moveThumb)953*8af74909SZhong Yang void Editor::ScrollTo(Sci::Line line, bool moveThumb) {
954*8af74909SZhong Yang 	const Sci::Line topLineNew = std::clamp<Sci::Line>(line, 0, MaxScrollPos());
955*8af74909SZhong Yang 	if (topLineNew != topLine) {
956*8af74909SZhong Yang 		// Try to optimise small scrolls
957*8af74909SZhong Yang #ifndef UNDER_CE
958*8af74909SZhong Yang 		const Sci::Line linesToMove = topLine - topLineNew;
959*8af74909SZhong Yang 		const bool performBlit = (std::abs(linesToMove) <= 10) && (paintState == notPainting);
960*8af74909SZhong Yang 		willRedrawAll = !performBlit;
961*8af74909SZhong Yang #endif
962*8af74909SZhong Yang 		SetTopLine(topLineNew);
963*8af74909SZhong Yang 		// Optimize by styling the view as this will invalidate any needed area
964*8af74909SZhong Yang 		// which could abort the initial paint if discovered later.
965*8af74909SZhong Yang 		StyleAreaBounded(GetClientRectangle(), true);
966*8af74909SZhong Yang #ifndef UNDER_CE
967*8af74909SZhong Yang 		// Perform redraw rather than scroll if many lines would be redrawn anyway.
968*8af74909SZhong Yang 		if (performBlit) {
969*8af74909SZhong Yang 			ScrollText(linesToMove);
970*8af74909SZhong Yang 		} else {
971*8af74909SZhong Yang 			Redraw();
972*8af74909SZhong Yang 		}
973*8af74909SZhong Yang 		willRedrawAll = false;
974*8af74909SZhong Yang #else
975*8af74909SZhong Yang 		Redraw();
976*8af74909SZhong Yang #endif
977*8af74909SZhong Yang 		if (moveThumb) {
978*8af74909SZhong Yang 			SetVerticalScrollPos();
979*8af74909SZhong Yang 		}
980*8af74909SZhong Yang 	}
981*8af74909SZhong Yang }
982*8af74909SZhong Yang 
ScrollText(Sci::Line)983*8af74909SZhong Yang void Editor::ScrollText(Sci::Line /* linesToMove */) {
984*8af74909SZhong Yang 	//Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove);
985*8af74909SZhong Yang 	Redraw();
986*8af74909SZhong Yang }
987*8af74909SZhong Yang 
HorizontalScrollTo(int xPos)988*8af74909SZhong Yang void Editor::HorizontalScrollTo(int xPos) {
989*8af74909SZhong Yang 	//Platform::DebugPrintf("HorizontalScroll %d\n", xPos);
990*8af74909SZhong Yang 	if (xPos < 0)
991*8af74909SZhong Yang 		xPos = 0;
992*8af74909SZhong Yang 	if (!Wrapping() && (xOffset != xPos)) {
993*8af74909SZhong Yang 		xOffset = xPos;
994*8af74909SZhong Yang 		ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
995*8af74909SZhong Yang 		SetHorizontalScrollPos();
996*8af74909SZhong Yang 		RedrawRect(GetClientRectangle());
997*8af74909SZhong Yang 	}
998*8af74909SZhong Yang }
999*8af74909SZhong Yang 
VerticalCentreCaret()1000*8af74909SZhong Yang void Editor::VerticalCentreCaret() {
1001*8af74909SZhong Yang 	const Sci::Line lineDoc =
1002*8af74909SZhong Yang 		pdoc->SciLineFromPosition(sel.IsRectangular() ? sel.Rectangular().caret.Position() : sel.MainCaret());
1003*8af74909SZhong Yang 	const Sci::Line lineDisplay = pcs->DisplayFromDoc(lineDoc);
1004*8af74909SZhong Yang 	const Sci::Line newTop = lineDisplay - (LinesOnScreen() / 2);
1005*8af74909SZhong Yang 	if (topLine != newTop) {
1006*8af74909SZhong Yang 		SetTopLine(newTop > 0 ? newTop : 0);
1007*8af74909SZhong Yang 		RedrawRect(GetClientRectangle());
1008*8af74909SZhong Yang 	}
1009*8af74909SZhong Yang }
1010*8af74909SZhong Yang 
MoveSelectedLines(int lineDelta)1011*8af74909SZhong Yang void Editor::MoveSelectedLines(int lineDelta) {
1012*8af74909SZhong Yang 
1013*8af74909SZhong Yang 	if (sel.IsRectangular()) {
1014*8af74909SZhong Yang 		return;
1015*8af74909SZhong Yang 	}
1016*8af74909SZhong Yang 
1017*8af74909SZhong Yang 	// if selection doesn't start at the beginning of the line, set the new start
1018*8af74909SZhong Yang 	Sci::Position selectionStart = SelectionStart().Position();
1019*8af74909SZhong Yang 	const Sci::Line startLine = pdoc->SciLineFromPosition(selectionStart);
1020*8af74909SZhong Yang 	const Sci::Position beginningOfStartLine = pdoc->LineStart(startLine);
1021*8af74909SZhong Yang 	selectionStart = beginningOfStartLine;
1022*8af74909SZhong Yang 
1023*8af74909SZhong Yang 	// if selection doesn't end at the beginning of a line greater than that of the start,
1024*8af74909SZhong Yang 	// then set it at the beginning of the next one
1025*8af74909SZhong Yang 	Sci::Position selectionEnd = SelectionEnd().Position();
1026*8af74909SZhong Yang 	const Sci::Line endLine = pdoc->SciLineFromPosition(selectionEnd);
1027*8af74909SZhong Yang 	const Sci::Position beginningOfEndLine = pdoc->LineStart(endLine);
1028*8af74909SZhong Yang 	bool appendEol = false;
1029*8af74909SZhong Yang 	if (selectionEnd > beginningOfEndLine
1030*8af74909SZhong Yang 		|| selectionStart == selectionEnd) {
1031*8af74909SZhong Yang 		selectionEnd = pdoc->LineStart(endLine + 1);
1032*8af74909SZhong Yang 		appendEol = (selectionEnd == pdoc->Length() && pdoc->SciLineFromPosition(selectionEnd) == endLine);
1033*8af74909SZhong Yang 	}
1034*8af74909SZhong Yang 
1035*8af74909SZhong Yang 	// if there's nowhere for the selection to move
1036*8af74909SZhong Yang 	// (i.e. at the beginning going up or at the end going down),
1037*8af74909SZhong Yang 	// stop it right there!
1038*8af74909SZhong Yang 	if ((selectionStart == 0 && lineDelta < 0)
1039*8af74909SZhong Yang 		|| (selectionEnd == pdoc->Length() && lineDelta > 0)
1040*8af74909SZhong Yang 	        || selectionStart == selectionEnd) {
1041*8af74909SZhong Yang 		return;
1042*8af74909SZhong Yang 	}
1043*8af74909SZhong Yang 
1044*8af74909SZhong Yang 	UndoGroup ug(pdoc);
1045*8af74909SZhong Yang 
1046*8af74909SZhong Yang 	if (lineDelta > 0 && selectionEnd == pdoc->LineStart(pdoc->LinesTotal() - 1)) {
1047*8af74909SZhong Yang 		SetSelection(pdoc->MovePositionOutsideChar(selectionEnd - 1, -1), selectionEnd);
1048*8af74909SZhong Yang 		ClearSelection();
1049*8af74909SZhong Yang 		selectionEnd = CurrentPosition();
1050*8af74909SZhong Yang 	}
1051*8af74909SZhong Yang 	SetSelection(selectionStart, selectionEnd);
1052*8af74909SZhong Yang 
1053*8af74909SZhong Yang 	SelectionText selectedText;
1054*8af74909SZhong Yang 	CopySelectionRange(&selectedText);
1055*8af74909SZhong Yang 
1056*8af74909SZhong Yang 	const Point currentLocation = LocationFromPosition(CurrentPosition());
1057*8af74909SZhong Yang 	const Sci::Line currentLine = LineFromLocation(currentLocation);
1058*8af74909SZhong Yang 
1059*8af74909SZhong Yang 	if (appendEol)
1060*8af74909SZhong Yang 		SetSelection(pdoc->MovePositionOutsideChar(selectionStart - 1, -1), selectionEnd);
1061*8af74909SZhong Yang 	ClearSelection();
1062*8af74909SZhong Yang 
1063*8af74909SZhong Yang 	const char *eol = StringFromEOLMode(pdoc->eolMode);
1064*8af74909SZhong Yang 	if (currentLine + lineDelta >= pdoc->LinesTotal())
1065*8af74909SZhong Yang 		pdoc->InsertString(pdoc->Length(), eol, strlen(eol));
1066*8af74909SZhong Yang 	GoToLine(currentLine + lineDelta);
1067*8af74909SZhong Yang 
1068*8af74909SZhong Yang 	Sci::Position selectionLength = pdoc->InsertString(CurrentPosition(), selectedText.Data(), selectedText.Length());
1069*8af74909SZhong Yang 	if (appendEol) {
1070*8af74909SZhong Yang 		const Sci::Position lengthInserted = pdoc->InsertString(CurrentPosition() + selectionLength, eol, strlen(eol));
1071*8af74909SZhong Yang 		selectionLength += lengthInserted;
1072*8af74909SZhong Yang 	}
1073*8af74909SZhong Yang 	SetSelection(CurrentPosition(), CurrentPosition() + selectionLength);
1074*8af74909SZhong Yang }
1075*8af74909SZhong Yang 
MoveSelectedLinesUp()1076*8af74909SZhong Yang void Editor::MoveSelectedLinesUp() {
1077*8af74909SZhong Yang 	MoveSelectedLines(-1);
1078*8af74909SZhong Yang }
1079*8af74909SZhong Yang 
MoveSelectedLinesDown()1080*8af74909SZhong Yang void Editor::MoveSelectedLinesDown() {
1081*8af74909SZhong Yang 	MoveSelectedLines(1);
1082*8af74909SZhong Yang }
1083*8af74909SZhong Yang 
MoveCaretInsideView(bool ensureVisible)1084*8af74909SZhong Yang void Editor::MoveCaretInsideView(bool ensureVisible) {
1085*8af74909SZhong Yang 	const PRectangle rcClient = GetTextRectangle();
1086*8af74909SZhong Yang 	const Point pt = PointMainCaret();
1087*8af74909SZhong Yang 	if (pt.y < rcClient.top) {
1088*8af74909SZhong Yang 		MovePositionTo(SPositionFromLocation(
1089*8af74909SZhong Yang 		            Point::FromInts(lastXChosen - xOffset, static_cast<int>(rcClient.top)),
1090*8af74909SZhong Yang 					false, false, UserVirtualSpace()),
1091*8af74909SZhong Yang 					Selection::noSel, ensureVisible);
1092*8af74909SZhong Yang 	} else if ((pt.y + vs.lineHeight - 1) > rcClient.bottom) {
1093*8af74909SZhong Yang 		const ptrdiff_t yOfLastLineFullyDisplayed = static_cast<ptrdiff_t>(rcClient.top) + (LinesOnScreen() - 1) * vs.lineHeight;
1094*8af74909SZhong Yang 		MovePositionTo(SPositionFromLocation(
1095*8af74909SZhong Yang 		            Point::FromInts(lastXChosen - xOffset, static_cast<int>(rcClient.top + yOfLastLineFullyDisplayed)),
1096*8af74909SZhong Yang 					false, false, UserVirtualSpace()),
1097*8af74909SZhong Yang 		        Selection::noSel, ensureVisible);
1098*8af74909SZhong Yang 	}
1099*8af74909SZhong Yang }
1100*8af74909SZhong Yang 
DisplayFromPosition(Sci::Position pos)1101*8af74909SZhong Yang Sci::Line Editor::DisplayFromPosition(Sci::Position pos) {
1102*8af74909SZhong Yang 	AutoSurface surface(this);
1103*8af74909SZhong Yang 	return view.DisplayFromPosition(surface, *this, pos, vs);
1104*8af74909SZhong Yang }
1105*8af74909SZhong Yang 
1106*8af74909SZhong Yang /**
1107*8af74909SZhong Yang  * Ensure the caret is reasonably visible in context.
1108*8af74909SZhong Yang  *
1109*8af74909SZhong Yang Caret policy in Scintilla
1110*8af74909SZhong Yang 
1111*8af74909SZhong Yang If slop is set, we can define a slop value.
1112*8af74909SZhong Yang This value defines an unwanted zone (UZ) where the caret is... unwanted.
1113*8af74909SZhong Yang This zone is defined as a number of pixels near the vertical margins,
1114*8af74909SZhong Yang and as a number of lines near the horizontal margins.
1115*8af74909SZhong Yang By keeping the caret away from the edges, it is seen within its context,
1116*8af74909SZhong Yang so it is likely that the identifier that the caret is on can be completely seen,
1117*8af74909SZhong Yang and that the current line is seen with some of the lines following it which are
1118*8af74909SZhong Yang often dependent on that line.
1119*8af74909SZhong Yang 
1120*8af74909SZhong Yang If strict is set, the policy is enforced... strictly.
1121*8af74909SZhong Yang The caret is centred on the display if slop is not set,
1122*8af74909SZhong Yang and cannot go in the UZ if slop is set.
1123*8af74909SZhong Yang 
1124*8af74909SZhong Yang If jumps is set, the display is moved more energetically
1125*8af74909SZhong Yang so the caret can move in the same direction longer before the policy is applied again.
1126*8af74909SZhong Yang '3UZ' notation is used to indicate three time the size of the UZ as a distance to the margin.
1127*8af74909SZhong Yang 
1128*8af74909SZhong Yang If even is not set, instead of having symmetrical UZs,
1129*8af74909SZhong Yang the left and bottom UZs are extended up to right and top UZs respectively.
1130*8af74909SZhong Yang This way, we favour the displaying of useful information: the beginning of lines,
1131*8af74909SZhong Yang where most code reside, and the lines after the caret, eg. the body of a function.
1132*8af74909SZhong Yang 
1133*8af74909SZhong Yang      |        |       |      |                                            |
1134*8af74909SZhong Yang slop | strict | jumps | even | Caret can go to the margin                 | When reaching limit (caret going out of
1135*8af74909SZhong Yang      |        |       |      |                                            | visibility or going into the UZ) display is...
1136*8af74909SZhong Yang -----+--------+-------+------+--------------------------------------------+--------------------------------------------------------------
1137*8af74909SZhong Yang   0  |   0    |   0   |   0  | Yes                                        | moved to put caret on top/on right
1138*8af74909SZhong Yang   0  |   0    |   0   |   1  | Yes                                        | moved by one position
1139*8af74909SZhong Yang   0  |   0    |   1   |   0  | Yes                                        | moved to put caret on top/on right
1140*8af74909SZhong Yang   0  |   0    |   1   |   1  | Yes                                        | centred on the caret
1141*8af74909SZhong Yang   0  |   1    |   -   |   0  | Caret is always on top/on right of display | -
1142*8af74909SZhong Yang   0  |   1    |   -   |   1  | No, caret is always centred                | -
1143*8af74909SZhong Yang   1  |   0    |   0   |   0  | Yes                                        | moved to put caret out of the asymmetrical UZ
1144*8af74909SZhong Yang   1  |   0    |   0   |   1  | Yes                                        | moved to put caret out of the UZ
1145*8af74909SZhong Yang   1  |   0    |   1   |   0  | Yes                                        | moved to put caret at 3UZ of the top or right margin
1146*8af74909SZhong Yang   1  |   0    |   1   |   1  | Yes                                        | moved to put caret at 3UZ of the margin
1147*8af74909SZhong Yang   1  |   1    |   -   |   0  | Caret is always at UZ of top/right margin  | -
1148*8af74909SZhong Yang   1  |   1    |   0   |   1  | No, kept out of UZ                         | moved by one position
1149*8af74909SZhong Yang   1  |   1    |   1   |   1  | No, kept out of UZ                         | moved to put caret at 3UZ of the margin
1150*8af74909SZhong Yang */
1151*8af74909SZhong Yang 
XYScrollToMakeVisible(const SelectionRange & range,const XYScrollOptions options,CaretPolicies policies)1152*8af74909SZhong Yang Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &range,
1153*8af74909SZhong Yang 	const XYScrollOptions options, CaretPolicies policies) {
1154*8af74909SZhong Yang 	const PRectangle rcClient = GetTextRectangle();
1155*8af74909SZhong Yang 	const Point ptOrigin = GetVisibleOriginInMain();
1156*8af74909SZhong Yang 	const Point pt = LocationFromPosition(range.caret) + ptOrigin;
1157*8af74909SZhong Yang 	const Point ptAnchor = LocationFromPosition(range.anchor) + ptOrigin;
1158*8af74909SZhong Yang 	const Point ptBottomCaret(pt.x, pt.y + vs.lineHeight - 1);
1159*8af74909SZhong Yang 
1160*8af74909SZhong Yang 	XYScrollPosition newXY(xOffset, topLine);
1161*8af74909SZhong Yang 	if (rcClient.Empty()) {
1162*8af74909SZhong Yang 		return newXY;
1163*8af74909SZhong Yang 	}
1164*8af74909SZhong Yang 
1165*8af74909SZhong Yang 	// Vertical positioning
1166*8af74909SZhong Yang 	if ((options & xysVertical) && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (policies.y.policy & CARET_STRICT) != 0)) {
1167*8af74909SZhong Yang 		const Sci::Line lineCaret = DisplayFromPosition(range.caret.Position());
1168*8af74909SZhong Yang 		const Sci::Line linesOnScreen = LinesOnScreen();
1169*8af74909SZhong Yang 		const Sci::Line halfScreen = std::max(linesOnScreen - 1, static_cast<Sci::Line>(2)) / 2;
1170*8af74909SZhong Yang 		const bool bSlop = (policies.y.policy & CARET_SLOP) != 0;
1171*8af74909SZhong Yang 		const bool bStrict = (policies.y.policy & CARET_STRICT) != 0;
1172*8af74909SZhong Yang 		const bool bJump = (policies.y.policy & CARET_JUMPS) != 0;
1173*8af74909SZhong Yang 		const bool bEven = (policies.y.policy & CARET_EVEN) != 0;
1174*8af74909SZhong Yang 
1175*8af74909SZhong Yang 		// It should be possible to scroll the window to show the caret,
1176*8af74909SZhong Yang 		// but this fails to remove the caret on GTK+
1177*8af74909SZhong Yang 		if (bSlop) {	// A margin is defined
1178*8af74909SZhong Yang 			Sci::Line yMoveT, yMoveB;
1179*8af74909SZhong Yang 			if (bStrict) {
1180*8af74909SZhong Yang 				Sci::Line yMarginT, yMarginB;
1181*8af74909SZhong Yang 				if (!(options & xysUseMargin)) {
1182*8af74909SZhong Yang 					// In drag mode, avoid moves
1183*8af74909SZhong Yang 					// otherwise, a double click will select several lines.
1184*8af74909SZhong Yang 					yMarginT = yMarginB = 0;
1185*8af74909SZhong Yang 				} else {
1186*8af74909SZhong Yang 					// yMarginT must equal to caretYSlop, with a minimum of 1 and
1187*8af74909SZhong Yang 					// a maximum of slightly less than half the height of the text area.
1188*8af74909SZhong Yang 					yMarginT = std::clamp<Sci::Line>(policies.y.slop, 1, halfScreen);
1189*8af74909SZhong Yang 					if (bEven) {
1190*8af74909SZhong Yang 						yMarginB = yMarginT;
1191*8af74909SZhong Yang 					} else {
1192*8af74909SZhong Yang 						yMarginB = linesOnScreen - yMarginT - 1;
1193*8af74909SZhong Yang 					}
1194*8af74909SZhong Yang 				}
1195*8af74909SZhong Yang 				yMoveT = yMarginT;
1196*8af74909SZhong Yang 				if (bEven) {
1197*8af74909SZhong Yang 					if (bJump) {
1198*8af74909SZhong Yang 						yMoveT = std::clamp<Sci::Line>(policies.y.slop * 3, 1, halfScreen);
1199*8af74909SZhong Yang 					}
1200*8af74909SZhong Yang 					yMoveB = yMoveT;
1201*8af74909SZhong Yang 				} else {
1202*8af74909SZhong Yang 					yMoveB = linesOnScreen - yMoveT - 1;
1203*8af74909SZhong Yang 				}
1204*8af74909SZhong Yang 				if (lineCaret < topLine + yMarginT) {
1205*8af74909SZhong Yang 					// Caret goes too high
1206*8af74909SZhong Yang 					newXY.topLine = lineCaret - yMoveT;
1207*8af74909SZhong Yang 				} else if (lineCaret > topLine + linesOnScreen - 1 - yMarginB) {
1208*8af74909SZhong Yang 					// Caret goes too low
1209*8af74909SZhong Yang 					newXY.topLine = lineCaret - linesOnScreen + 1 + yMoveB;
1210*8af74909SZhong Yang 				}
1211*8af74909SZhong Yang 			} else {	// Not strict
1212*8af74909SZhong Yang 				yMoveT = bJump ? policies.y.slop * 3 : policies.y.slop;
1213*8af74909SZhong Yang 				yMoveT = std::clamp<Sci::Line>(yMoveT, 1, halfScreen);
1214*8af74909SZhong Yang 				if (bEven) {
1215*8af74909SZhong Yang 					yMoveB = yMoveT;
1216*8af74909SZhong Yang 				} else {
1217*8af74909SZhong Yang 					yMoveB = linesOnScreen - yMoveT - 1;
1218*8af74909SZhong Yang 				}
1219*8af74909SZhong Yang 				if (lineCaret < topLine) {
1220*8af74909SZhong Yang 					// Caret goes too high
1221*8af74909SZhong Yang 					newXY.topLine = lineCaret - yMoveT;
1222*8af74909SZhong Yang 				} else if (lineCaret > topLine + linesOnScreen - 1) {
1223*8af74909SZhong Yang 					// Caret goes too low
1224*8af74909SZhong Yang 					newXY.topLine = lineCaret - linesOnScreen + 1 + yMoveB;
1225*8af74909SZhong Yang 				}
1226*8af74909SZhong Yang 			}
1227*8af74909SZhong Yang 		} else {	// No slop
1228*8af74909SZhong Yang 			if (!bStrict && !bJump) {
1229*8af74909SZhong Yang 				// Minimal move
1230*8af74909SZhong Yang 				if (lineCaret < topLine) {
1231*8af74909SZhong Yang 					// Caret goes too high
1232*8af74909SZhong Yang 					newXY.topLine = lineCaret;
1233*8af74909SZhong Yang 				} else if (lineCaret > topLine + linesOnScreen - 1) {
1234*8af74909SZhong Yang 					// Caret goes too low
1235*8af74909SZhong Yang 					if (bEven) {
1236*8af74909SZhong Yang 						newXY.topLine = lineCaret - linesOnScreen + 1;
1237*8af74909SZhong Yang 					} else {
1238*8af74909SZhong Yang 						newXY.topLine = lineCaret;
1239*8af74909SZhong Yang 					}
1240*8af74909SZhong Yang 				}
1241*8af74909SZhong Yang 			} else {	// Strict or going out of display
1242*8af74909SZhong Yang 				if (bEven) {
1243*8af74909SZhong Yang 					// Always centre caret
1244*8af74909SZhong Yang 					newXY.topLine = lineCaret - halfScreen;
1245*8af74909SZhong Yang 				} else {
1246*8af74909SZhong Yang 					// Always put caret on top of display
1247*8af74909SZhong Yang 					newXY.topLine = lineCaret;
1248*8af74909SZhong Yang 				}
1249*8af74909SZhong Yang 			}
1250*8af74909SZhong Yang 		}
1251*8af74909SZhong Yang 		if (!(range.caret == range.anchor)) {
1252*8af74909SZhong Yang 			const Sci::Line lineAnchor = DisplayFromPosition(range.anchor.Position());
1253*8af74909SZhong Yang 			if (lineAnchor < lineCaret) {
1254*8af74909SZhong Yang 				// Shift up to show anchor or as much of range as possible
1255*8af74909SZhong Yang 				newXY.topLine = std::min(newXY.topLine, lineAnchor);
1256*8af74909SZhong Yang 				newXY.topLine = std::max(newXY.topLine, lineCaret - LinesOnScreen());
1257*8af74909SZhong Yang 			} else {
1258*8af74909SZhong Yang 				// Shift down to show anchor or as much of range as possible
1259*8af74909SZhong Yang 				newXY.topLine = std::max(newXY.topLine, lineAnchor - LinesOnScreen());
1260*8af74909SZhong Yang 				newXY.topLine = std::min(newXY.topLine, lineCaret);
1261*8af74909SZhong Yang 			}
1262*8af74909SZhong Yang 		}
1263*8af74909SZhong Yang 		newXY.topLine = std::clamp<Sci::Line>(newXY.topLine, 0, MaxScrollPos());
1264*8af74909SZhong Yang 	}
1265*8af74909SZhong Yang 
1266*8af74909SZhong Yang 	// Horizontal positioning
1267*8af74909SZhong Yang 	if ((options & xysHorizontal) && !Wrapping()) {
1268*8af74909SZhong Yang 		const int halfScreen = std::max(static_cast<int>(rcClient.Width()) - 4, 4) / 2;
1269*8af74909SZhong Yang 		const bool bSlop = (policies.x.policy & CARET_SLOP) != 0;
1270*8af74909SZhong Yang 		const bool bStrict = (policies.x.policy & CARET_STRICT) != 0;
1271*8af74909SZhong Yang 		const bool bJump = (policies.x.policy & CARET_JUMPS) != 0;
1272*8af74909SZhong Yang 		const bool bEven = (policies.x.policy & CARET_EVEN) != 0;
1273*8af74909SZhong Yang 
1274*8af74909SZhong Yang 		if (bSlop) {	// A margin is defined
1275*8af74909SZhong Yang 			int xMoveL, xMoveR;
1276*8af74909SZhong Yang 			if (bStrict) {
1277*8af74909SZhong Yang 				int xMarginL, xMarginR;
1278*8af74909SZhong Yang 				if (!(options & xysUseMargin)) {
1279*8af74909SZhong Yang 					// In drag mode, avoid moves unless very near of the margin
1280*8af74909SZhong Yang 					// otherwise, a simple click will select text.
1281*8af74909SZhong Yang 					xMarginL = xMarginR = 2;
1282*8af74909SZhong Yang 				} else {
1283*8af74909SZhong Yang 					// xMargin must equal to caretXSlop, with a minimum of 2 and
1284*8af74909SZhong Yang 					// a maximum of slightly less than half the width of the text area.
1285*8af74909SZhong Yang 					xMarginR = std::clamp(policies.x.slop, 2, halfScreen);
1286*8af74909SZhong Yang 					if (bEven) {
1287*8af74909SZhong Yang 						xMarginL = xMarginR;
1288*8af74909SZhong Yang 					} else {
1289*8af74909SZhong Yang 						xMarginL = static_cast<int>(rcClient.Width()) - xMarginR - 4;
1290*8af74909SZhong Yang 					}
1291*8af74909SZhong Yang 				}
1292*8af74909SZhong Yang 				if (bJump && bEven) {
1293*8af74909SZhong Yang 					// Jump is used only in even mode
1294*8af74909SZhong Yang 					xMoveL = xMoveR = std::clamp(policies.x.slop * 3, 1, halfScreen);
1295*8af74909SZhong Yang 				} else {
1296*8af74909SZhong Yang 					xMoveL = xMoveR = 0;	// Not used, avoid a warning
1297*8af74909SZhong Yang 				}
1298*8af74909SZhong Yang 				if (pt.x < rcClient.left + xMarginL) {
1299*8af74909SZhong Yang 					// Caret is on the left of the display
1300*8af74909SZhong Yang 					if (bJump && bEven) {
1301*8af74909SZhong Yang 						newXY.xOffset -= xMoveL;
1302*8af74909SZhong Yang 					} else {
1303*8af74909SZhong Yang 						// Move just enough to allow to display the caret
1304*8af74909SZhong Yang 						newXY.xOffset -= static_cast<int>((rcClient.left + xMarginL) - pt.x);
1305*8af74909SZhong Yang 					}
1306*8af74909SZhong Yang 				} else if (pt.x >= rcClient.right - xMarginR) {
1307*8af74909SZhong Yang 					// Caret is on the right of the display
1308*8af74909SZhong Yang 					if (bJump && bEven) {
1309*8af74909SZhong Yang 						newXY.xOffset += xMoveR;
1310*8af74909SZhong Yang 					} else {
1311*8af74909SZhong Yang 						// Move just enough to allow to display the caret
1312*8af74909SZhong Yang 						newXY.xOffset += static_cast<int>(pt.x - (rcClient.right - xMarginR) + 1);
1313*8af74909SZhong Yang 					}
1314*8af74909SZhong Yang 				}
1315*8af74909SZhong Yang 			} else {	// Not strict
1316*8af74909SZhong Yang 				xMoveR = bJump ? policies.x.slop * 3 : policies.x.slop;
1317*8af74909SZhong Yang 				xMoveR = std::clamp(xMoveR, 1, halfScreen);
1318*8af74909SZhong Yang 				if (bEven) {
1319*8af74909SZhong Yang 					xMoveL = xMoveR;
1320*8af74909SZhong Yang 				} else {
1321*8af74909SZhong Yang 					xMoveL = static_cast<int>(rcClient.Width()) - xMoveR - 4;
1322*8af74909SZhong Yang 				}
1323*8af74909SZhong Yang 				if (pt.x < rcClient.left) {
1324*8af74909SZhong Yang 					// Caret is on the left of the display
1325*8af74909SZhong Yang 					newXY.xOffset -= xMoveL;
1326*8af74909SZhong Yang 				} else if (pt.x >= rcClient.right) {
1327*8af74909SZhong Yang 					// Caret is on the right of the display
1328*8af74909SZhong Yang 					newXY.xOffset += xMoveR;
1329*8af74909SZhong Yang 				}
1330*8af74909SZhong Yang 			}
1331*8af74909SZhong Yang 		} else {	// No slop
1332*8af74909SZhong Yang 			if (bStrict ||
1333*8af74909SZhong Yang 			        (bJump && (pt.x < rcClient.left || pt.x >= rcClient.right))) {
1334*8af74909SZhong Yang 				// Strict or going out of display
1335*8af74909SZhong Yang 				if (bEven) {
1336*8af74909SZhong Yang 					// Centre caret
1337*8af74909SZhong Yang 					newXY.xOffset += static_cast<int>(pt.x - rcClient.left - halfScreen);
1338*8af74909SZhong Yang 				} else {
1339*8af74909SZhong Yang 					// Put caret on right
1340*8af74909SZhong Yang 					newXY.xOffset += static_cast<int>(pt.x - rcClient.right + 1);
1341*8af74909SZhong Yang 				}
1342*8af74909SZhong Yang 			} else {
1343*8af74909SZhong Yang 				// Move just enough to allow to display the caret
1344*8af74909SZhong Yang 				if (pt.x < rcClient.left) {
1345*8af74909SZhong Yang 					// Caret is on the left of the display
1346*8af74909SZhong Yang 					if (bEven) {
1347*8af74909SZhong Yang 						newXY.xOffset -= static_cast<int>(rcClient.left - pt.x);
1348*8af74909SZhong Yang 					} else {
1349*8af74909SZhong Yang 						newXY.xOffset += static_cast<int>(pt.x - rcClient.right) + 1;
1350*8af74909SZhong Yang 					}
1351*8af74909SZhong Yang 				} else if (pt.x >= rcClient.right) {
1352*8af74909SZhong Yang 					// Caret is on the right of the display
1353*8af74909SZhong Yang 					newXY.xOffset += static_cast<int>(pt.x - rcClient.right) + 1;
1354*8af74909SZhong Yang 				}
1355*8af74909SZhong Yang 			}
1356*8af74909SZhong Yang 		}
1357*8af74909SZhong Yang 		// In case of a jump (find result) largely out of display, adjust the offset to display the caret
1358*8af74909SZhong Yang 		if (pt.x + xOffset < rcClient.left + newXY.xOffset) {
1359*8af74909SZhong Yang 			newXY.xOffset = static_cast<int>(pt.x + xOffset - rcClient.left) - 2;
1360*8af74909SZhong Yang 		} else if (pt.x + xOffset >= rcClient.right + newXY.xOffset) {
1361*8af74909SZhong Yang 			newXY.xOffset = static_cast<int>(pt.x + xOffset - rcClient.right) + 2;
1362*8af74909SZhong Yang 			if (vs.IsBlockCaretStyle() || view.imeCaretBlockOverride) {
1363*8af74909SZhong Yang 				// Ensure we can see a good portion of the block caret
1364*8af74909SZhong Yang 				newXY.xOffset += static_cast<int>(vs.aveCharWidth);
1365*8af74909SZhong Yang 			}
1366*8af74909SZhong Yang 		}
1367*8af74909SZhong Yang 		if (!(range.caret == range.anchor)) {
1368*8af74909SZhong Yang 			if (ptAnchor.x < pt.x) {
1369*8af74909SZhong Yang 				// Shift to left to show anchor or as much of range as possible
1370*8af74909SZhong Yang 				const int maxOffset = static_cast<int>(ptAnchor.x + xOffset - rcClient.left) - 1;
1371*8af74909SZhong Yang 				const int minOffset = static_cast<int>(pt.x + xOffset - rcClient.right) + 1;
1372*8af74909SZhong Yang 				newXY.xOffset = std::min(newXY.xOffset, maxOffset);
1373*8af74909SZhong Yang 				newXY.xOffset = std::max(newXY.xOffset, minOffset);
1374*8af74909SZhong Yang 			} else {
1375*8af74909SZhong Yang 				// Shift to right to show anchor or as much of range as possible
1376*8af74909SZhong Yang 				const int minOffset = static_cast<int>(ptAnchor.x + xOffset - rcClient.right) + 1;
1377*8af74909SZhong Yang 				const int maxOffset = static_cast<int>(pt.x + xOffset - rcClient.left) - 1;
1378*8af74909SZhong Yang 				newXY.xOffset = std::max(newXY.xOffset, minOffset);
1379*8af74909SZhong Yang 				newXY.xOffset = std::min(newXY.xOffset, maxOffset);
1380*8af74909SZhong Yang 			}
1381*8af74909SZhong Yang 		}
1382*8af74909SZhong Yang 		if (newXY.xOffset < 0) {
1383*8af74909SZhong Yang 			newXY.xOffset = 0;
1384*8af74909SZhong Yang 		}
1385*8af74909SZhong Yang 	}
1386*8af74909SZhong Yang 
1387*8af74909SZhong Yang 	return newXY;
1388*8af74909SZhong Yang }
1389*8af74909SZhong Yang 
SetXYScroll(XYScrollPosition newXY)1390*8af74909SZhong Yang void Editor::SetXYScroll(XYScrollPosition newXY) {
1391*8af74909SZhong Yang 	if ((newXY.topLine != topLine) || (newXY.xOffset != xOffset)) {
1392*8af74909SZhong Yang 		if (newXY.topLine != topLine) {
1393*8af74909SZhong Yang 			SetTopLine(newXY.topLine);
1394*8af74909SZhong Yang 			SetVerticalScrollPos();
1395*8af74909SZhong Yang 		}
1396*8af74909SZhong Yang 		if (newXY.xOffset != xOffset) {
1397*8af74909SZhong Yang 			xOffset = newXY.xOffset;
1398*8af74909SZhong Yang 			ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
1399*8af74909SZhong Yang 			if (newXY.xOffset > 0) {
1400*8af74909SZhong Yang 				const PRectangle rcText = GetTextRectangle();
1401*8af74909SZhong Yang 				if (horizontalScrollBarVisible &&
1402*8af74909SZhong Yang 					rcText.Width() + xOffset > scrollWidth) {
1403*8af74909SZhong Yang 					scrollWidth = xOffset + static_cast<int>(rcText.Width());
1404*8af74909SZhong Yang 					SetScrollBars();
1405*8af74909SZhong Yang 				}
1406*8af74909SZhong Yang 			}
1407*8af74909SZhong Yang 			SetHorizontalScrollPos();
1408*8af74909SZhong Yang 		}
1409*8af74909SZhong Yang 		Redraw();
1410*8af74909SZhong Yang 		UpdateSystemCaret();
1411*8af74909SZhong Yang 	}
1412*8af74909SZhong Yang }
1413*8af74909SZhong Yang 
ScrollRange(SelectionRange range)1414*8af74909SZhong Yang void Editor::ScrollRange(SelectionRange range) {
1415*8af74909SZhong Yang 	SetXYScroll(XYScrollToMakeVisible(range, xysDefault, caretPolicies));
1416*8af74909SZhong Yang }
1417*8af74909SZhong Yang 
EnsureCaretVisible(bool useMargin,bool vert,bool horiz)1418*8af74909SZhong Yang void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) {
1419*8af74909SZhong Yang 	SetXYScroll(XYScrollToMakeVisible(SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret),
1420*8af74909SZhong Yang 		static_cast<XYScrollOptions>((useMargin?xysUseMargin:0)|(vert?xysVertical:0)|(horiz?xysHorizontal:0)),
1421*8af74909SZhong Yang 		caretPolicies));
1422*8af74909SZhong Yang }
1423*8af74909SZhong Yang 
ShowCaretAtCurrentPosition()1424*8af74909SZhong Yang void Editor::ShowCaretAtCurrentPosition() {
1425*8af74909SZhong Yang 	if (hasFocus) {
1426*8af74909SZhong Yang 		caret.active = true;
1427*8af74909SZhong Yang 		caret.on = true;
1428*8af74909SZhong Yang 		FineTickerCancel(tickCaret);
1429*8af74909SZhong Yang 		if (caret.period > 0)
1430*8af74909SZhong Yang 			FineTickerStart(tickCaret, caret.period, caret.period/10);
1431*8af74909SZhong Yang 	} else {
1432*8af74909SZhong Yang 		caret.active = false;
1433*8af74909SZhong Yang 		caret.on = false;
1434*8af74909SZhong Yang 		FineTickerCancel(tickCaret);
1435*8af74909SZhong Yang 	}
1436*8af74909SZhong Yang 	InvalidateCaret();
1437*8af74909SZhong Yang }
1438*8af74909SZhong Yang 
DropCaret()1439*8af74909SZhong Yang void Editor::DropCaret() {
1440*8af74909SZhong Yang 	caret.active = false;
1441*8af74909SZhong Yang 	FineTickerCancel(tickCaret);
1442*8af74909SZhong Yang 	InvalidateCaret();
1443*8af74909SZhong Yang }
1444*8af74909SZhong Yang 
CaretSetPeriod(int period)1445*8af74909SZhong Yang void Editor::CaretSetPeriod(int period) {
1446*8af74909SZhong Yang 	if (caret.period != period) {
1447*8af74909SZhong Yang 		caret.period = period;
1448*8af74909SZhong Yang 		caret.on = true;
1449*8af74909SZhong Yang 		FineTickerCancel(tickCaret);
1450*8af74909SZhong Yang 		if ((caret.active) && (caret.period > 0))
1451*8af74909SZhong Yang 			FineTickerStart(tickCaret, caret.period, caret.period/10);
1452*8af74909SZhong Yang 		InvalidateCaret();
1453*8af74909SZhong Yang 	}
1454*8af74909SZhong Yang }
1455*8af74909SZhong Yang 
InvalidateCaret()1456*8af74909SZhong Yang void Editor::InvalidateCaret() {
1457*8af74909SZhong Yang 	if (posDrag.IsValid()) {
1458*8af74909SZhong Yang 		InvalidateRange(posDrag.Position(), posDrag.Position() + 1);
1459*8af74909SZhong Yang 	} else {
1460*8af74909SZhong Yang 		for (size_t r=0; r<sel.Count(); r++) {
1461*8af74909SZhong Yang 			InvalidateRange(sel.Range(r).caret.Position(), sel.Range(r).caret.Position() + 1);
1462*8af74909SZhong Yang 		}
1463*8af74909SZhong Yang 	}
1464*8af74909SZhong Yang 	UpdateSystemCaret();
1465*8af74909SZhong Yang }
1466*8af74909SZhong Yang 
NotifyCaretMove()1467*8af74909SZhong Yang void Editor::NotifyCaretMove() {
1468*8af74909SZhong Yang }
1469*8af74909SZhong Yang 
UpdateSystemCaret()1470*8af74909SZhong Yang void Editor::UpdateSystemCaret() {
1471*8af74909SZhong Yang }
1472*8af74909SZhong Yang 
Wrapping() const1473*8af74909SZhong Yang bool Editor::Wrapping() const noexcept {
1474*8af74909SZhong Yang 	return vs.wrapState != WrapMode::none;
1475*8af74909SZhong Yang }
1476*8af74909SZhong Yang 
NeedWrapping(Sci::Line docLineStart,Sci::Line docLineEnd)1477*8af74909SZhong Yang void Editor::NeedWrapping(Sci::Line docLineStart, Sci::Line docLineEnd) {
1478*8af74909SZhong Yang //Platform::DebugPrintf("\nNeedWrapping: %0d..%0d\n", docLineStart, docLineEnd);
1479*8af74909SZhong Yang 	if (wrapPending.AddRange(docLineStart, docLineEnd)) {
1480*8af74909SZhong Yang 		view.llc.Invalidate(LineLayout::ValidLevel::positions);
1481*8af74909SZhong Yang 	}
1482*8af74909SZhong Yang 	// Wrap lines during idle.
1483*8af74909SZhong Yang 	if (Wrapping() && wrapPending.NeedsWrap()) {
1484*8af74909SZhong Yang 		SetIdle(true);
1485*8af74909SZhong Yang 	}
1486*8af74909SZhong Yang }
1487*8af74909SZhong Yang 
WrapOneLine(Surface * surface,Sci::Line lineToWrap)1488*8af74909SZhong Yang bool Editor::WrapOneLine(Surface *surface, Sci::Line lineToWrap) {
1489*8af74909SZhong Yang 	AutoLineLayout ll(view.llc, view.RetrieveLineLayout(lineToWrap, *this));
1490*8af74909SZhong Yang 	int linesWrapped = 1;
1491*8af74909SZhong Yang 	if (ll) {
1492*8af74909SZhong Yang 		view.LayoutLine(*this, lineToWrap, surface, vs, ll, wrapWidth);
1493*8af74909SZhong Yang 		linesWrapped = ll->lines;
1494*8af74909SZhong Yang 	}
1495*8af74909SZhong Yang 	return pcs->SetHeight(lineToWrap, linesWrapped +
1496*8af74909SZhong Yang 		(vs.annotationVisible ? pdoc->AnnotationLines(lineToWrap) : 0));
1497*8af74909SZhong Yang }
1498*8af74909SZhong Yang 
1499*8af74909SZhong Yang // Perform  wrapping for a subset of the lines needing wrapping.
1500*8af74909SZhong Yang // wsAll: wrap all lines which need wrapping in this single call
1501*8af74909SZhong Yang // wsVisible: wrap currently visible lines
1502*8af74909SZhong Yang // wsIdle: wrap one page + 100 lines
1503*8af74909SZhong Yang // Return true if wrapping occurred.
WrapLines(WrapScope ws)1504*8af74909SZhong Yang bool Editor::WrapLines(WrapScope ws) {
1505*8af74909SZhong Yang 	Sci::Line goodTopLine = topLine;
1506*8af74909SZhong Yang 	bool wrapOccurred = false;
1507*8af74909SZhong Yang 	if (!Wrapping()) {
1508*8af74909SZhong Yang 		if (wrapWidth != LineLayout::wrapWidthInfinite) {
1509*8af74909SZhong Yang 			wrapWidth = LineLayout::wrapWidthInfinite;
1510*8af74909SZhong Yang 			for (Sci::Line lineDoc = 0; lineDoc < pdoc->LinesTotal(); lineDoc++) {
1511*8af74909SZhong Yang 				pcs->SetHeight(lineDoc, 1 +
1512*8af74909SZhong Yang 					(vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0));
1513*8af74909SZhong Yang 			}
1514*8af74909SZhong Yang 			wrapOccurred = true;
1515*8af74909SZhong Yang 		}
1516*8af74909SZhong Yang 		wrapPending.Reset();
1517*8af74909SZhong Yang 
1518*8af74909SZhong Yang 	} else if (wrapPending.NeedsWrap()) {
1519*8af74909SZhong Yang 		wrapPending.start = std::min(wrapPending.start, pdoc->LinesTotal());
1520*8af74909SZhong Yang 		if (!SetIdle(true)) {
1521*8af74909SZhong Yang 			// Idle processing not supported so full wrap required.
1522*8af74909SZhong Yang 			ws = WrapScope::wsAll;
1523*8af74909SZhong Yang 		}
1524*8af74909SZhong Yang 		// Decide where to start wrapping
1525*8af74909SZhong Yang 		Sci::Line lineToWrap = wrapPending.start;
1526*8af74909SZhong Yang 		Sci::Line lineToWrapEnd = std::min(wrapPending.end, pdoc->LinesTotal());
1527*8af74909SZhong Yang 		const Sci::Line lineDocTop = pcs->DocFromDisplay(topLine);
1528*8af74909SZhong Yang 		const Sci::Line subLineTop = topLine - pcs->DisplayFromDoc(lineDocTop);
1529*8af74909SZhong Yang 		if (ws == WrapScope::wsVisible) {
1530*8af74909SZhong Yang 			lineToWrap = std::clamp(lineDocTop-5, wrapPending.start, pdoc->LinesTotal());
1531*8af74909SZhong Yang 			// Priority wrap to just after visible area.
1532*8af74909SZhong Yang 			// Since wrapping could reduce display lines, treat each
1533*8af74909SZhong Yang 			// as taking only one display line.
1534*8af74909SZhong Yang 			lineToWrapEnd = lineDocTop;
1535*8af74909SZhong Yang 			Sci::Line lines = LinesOnScreen() + 1;
1536*8af74909SZhong Yang 			while ((lineToWrapEnd < pcs->LinesInDoc()) && (lines>0)) {
1537*8af74909SZhong Yang 				if (pcs->GetVisible(lineToWrapEnd))
1538*8af74909SZhong Yang 					lines--;
1539*8af74909SZhong Yang 				lineToWrapEnd++;
1540*8af74909SZhong Yang 			}
1541*8af74909SZhong Yang 			// .. and if the paint window is outside pending wraps
1542*8af74909SZhong Yang 			if ((lineToWrap > wrapPending.end) || (lineToWrapEnd < wrapPending.start)) {
1543*8af74909SZhong Yang 				// Currently visible text does not need wrapping
1544*8af74909SZhong Yang 				return false;
1545*8af74909SZhong Yang 			}
1546*8af74909SZhong Yang 		} else if (ws == WrapScope::wsIdle) {
1547*8af74909SZhong Yang 			// Try to keep time taken by wrapping reasonable so interaction remains smooth.
1548*8af74909SZhong Yang 			constexpr double secondsAllowed = 0.01;
1549*8af74909SZhong Yang 			const Sci::Line linesInAllowedTime = std::clamp<Sci::Line>(
1550*8af74909SZhong Yang 				static_cast<Sci::Line>(secondsAllowed / durationWrapOneLine.Duration()),
1551*8af74909SZhong Yang 				LinesOnScreen() + 50, 0x10000);
1552*8af74909SZhong Yang 			lineToWrapEnd = lineToWrap + linesInAllowedTime;
1553*8af74909SZhong Yang 		}
1554*8af74909SZhong Yang 		const Sci::Line lineEndNeedWrap = std::min(wrapPending.end, pdoc->LinesTotal());
1555*8af74909SZhong Yang 		lineToWrapEnd = std::min(lineToWrapEnd, lineEndNeedWrap);
1556*8af74909SZhong Yang 
1557*8af74909SZhong Yang 		// Ensure all lines being wrapped are styled.
1558*8af74909SZhong Yang 		pdoc->EnsureStyledTo(pdoc->LineStart(lineToWrapEnd));
1559*8af74909SZhong Yang 
1560*8af74909SZhong Yang 		if (lineToWrap < lineToWrapEnd) {
1561*8af74909SZhong Yang 
1562*8af74909SZhong Yang 			PRectangle rcTextArea = GetClientRectangle();
1563*8af74909SZhong Yang 			rcTextArea.left = static_cast<XYPOSITION>(vs.textStart);
1564*8af74909SZhong Yang 			rcTextArea.right -= vs.rightMarginWidth;
1565*8af74909SZhong Yang 			wrapWidth = static_cast<int>(rcTextArea.Width());
1566*8af74909SZhong Yang 			RefreshStyleData();
1567*8af74909SZhong Yang 			AutoSurface surface(this);
1568*8af74909SZhong Yang 			if (surface) {
1569*8af74909SZhong Yang //Platform::DebugPrintf("Wraplines: scope=%0d need=%0d..%0d perform=%0d..%0d\n", ws, wrapPending.start, wrapPending.end, lineToWrap, lineToWrapEnd);
1570*8af74909SZhong Yang 
1571*8af74909SZhong Yang 				const Sci::Line linesBeingWrapped = lineToWrapEnd - lineToWrap;
1572*8af74909SZhong Yang 				ElapsedPeriod epWrapping;
1573*8af74909SZhong Yang 				while (lineToWrap < lineToWrapEnd) {
1574*8af74909SZhong Yang 					if (WrapOneLine(surface, lineToWrap)) {
1575*8af74909SZhong Yang 						wrapOccurred = true;
1576*8af74909SZhong Yang 					}
1577*8af74909SZhong Yang 					wrapPending.Wrapped(lineToWrap);
1578*8af74909SZhong Yang 					lineToWrap++;
1579*8af74909SZhong Yang 				}
1580*8af74909SZhong Yang 				durationWrapOneLine.AddSample(linesBeingWrapped, epWrapping.Duration());
1581*8af74909SZhong Yang 
1582*8af74909SZhong Yang 				goodTopLine = pcs->DisplayFromDoc(lineDocTop) + std::min(
1583*8af74909SZhong Yang 					subLineTop, static_cast<Sci::Line>(pcs->GetHeight(lineDocTop)-1));
1584*8af74909SZhong Yang 			}
1585*8af74909SZhong Yang 		}
1586*8af74909SZhong Yang 
1587*8af74909SZhong Yang 		// If wrapping is done, bring it to resting position
1588*8af74909SZhong Yang 		if (wrapPending.start >= lineEndNeedWrap) {
1589*8af74909SZhong Yang 			wrapPending.Reset();
1590*8af74909SZhong Yang 		}
1591*8af74909SZhong Yang 	}
1592*8af74909SZhong Yang 
1593*8af74909SZhong Yang 	if (wrapOccurred) {
1594*8af74909SZhong Yang 		SetScrollBars();
1595*8af74909SZhong Yang 		SetTopLine(std::clamp<Sci::Line>(goodTopLine, 0, MaxScrollPos()));
1596*8af74909SZhong Yang 		SetVerticalScrollPos();
1597*8af74909SZhong Yang 	}
1598*8af74909SZhong Yang 
1599*8af74909SZhong Yang 	return wrapOccurred;
1600*8af74909SZhong Yang }
1601*8af74909SZhong Yang 
LinesJoin()1602*8af74909SZhong Yang void Editor::LinesJoin() {
1603*8af74909SZhong Yang 	if (!RangeContainsProtected(targetRange.start.Position(), targetRange.end.Position())) {
1604*8af74909SZhong Yang 		UndoGroup ug(pdoc);
1605*8af74909SZhong Yang 		bool prevNonWS = true;
1606*8af74909SZhong Yang 		for (Sci::Position pos = targetRange.start.Position(); pos < targetRange.end.Position(); pos++) {
1607*8af74909SZhong Yang 			if (pdoc->IsPositionInLineEnd(pos)) {
1608*8af74909SZhong Yang 				targetRange.end.Add(-pdoc->LenChar(pos));
1609*8af74909SZhong Yang 				pdoc->DelChar(pos);
1610*8af74909SZhong Yang 				if (prevNonWS) {
1611*8af74909SZhong Yang 					// Ensure at least one space separating previous lines
1612*8af74909SZhong Yang 					const Sci::Position lengthInserted = pdoc->InsertString(pos, " ", 1);
1613*8af74909SZhong Yang 					targetRange.end.Add(lengthInserted);
1614*8af74909SZhong Yang 				}
1615*8af74909SZhong Yang 			} else {
1616*8af74909SZhong Yang 				prevNonWS = pdoc->CharAt(pos) != ' ';
1617*8af74909SZhong Yang 			}
1618*8af74909SZhong Yang 		}
1619*8af74909SZhong Yang 	}
1620*8af74909SZhong Yang }
1621*8af74909SZhong Yang 
StringFromEOLMode(int eolMode)1622*8af74909SZhong Yang const char *Editor::StringFromEOLMode(int eolMode) noexcept {
1623*8af74909SZhong Yang 	if (eolMode == SC_EOL_CRLF) {
1624*8af74909SZhong Yang 		return "\r\n";
1625*8af74909SZhong Yang 	} else if (eolMode == SC_EOL_CR) {
1626*8af74909SZhong Yang 		return "\r";
1627*8af74909SZhong Yang 	} else {
1628*8af74909SZhong Yang 		return "\n";
1629*8af74909SZhong Yang 	}
1630*8af74909SZhong Yang }
1631*8af74909SZhong Yang 
LinesSplit(int pixelWidth)1632*8af74909SZhong Yang void Editor::LinesSplit(int pixelWidth) {
1633*8af74909SZhong Yang 	if (!RangeContainsProtected(targetRange.start.Position(), targetRange.end.Position())) {
1634*8af74909SZhong Yang 		if (pixelWidth == 0) {
1635*8af74909SZhong Yang 			const PRectangle rcText = GetTextRectangle();
1636*8af74909SZhong Yang 			pixelWidth = static_cast<int>(rcText.Width());
1637*8af74909SZhong Yang 		}
1638*8af74909SZhong Yang 		const Sci::Line lineStart = pdoc->SciLineFromPosition(targetRange.start.Position());
1639*8af74909SZhong Yang 		Sci::Line lineEnd = pdoc->SciLineFromPosition(targetRange.end.Position());
1640*8af74909SZhong Yang 		const char *eol = StringFromEOLMode(pdoc->eolMode);
1641*8af74909SZhong Yang 		UndoGroup ug(pdoc);
1642*8af74909SZhong Yang 		for (Sci::Line line = lineStart; line <= lineEnd; line++) {
1643*8af74909SZhong Yang 			AutoSurface surface(this);
1644*8af74909SZhong Yang 			AutoLineLayout ll(view.llc, view.RetrieveLineLayout(line, *this));
1645*8af74909SZhong Yang 			if (surface && ll) {
1646*8af74909SZhong Yang 				const Sci::Position posLineStart = pdoc->LineStart(line);
1647*8af74909SZhong Yang 				view.LayoutLine(*this, line, surface, vs, ll, pixelWidth);
1648*8af74909SZhong Yang 				Sci::Position lengthInsertedTotal = 0;
1649*8af74909SZhong Yang 				for (int subLine = 1; subLine < ll->lines; subLine++) {
1650*8af74909SZhong Yang 					const Sci::Position lengthInserted = pdoc->InsertString(
1651*8af74909SZhong Yang 						posLineStart + lengthInsertedTotal + ll->LineStart(subLine),
1652*8af74909SZhong Yang 						eol, strlen(eol));
1653*8af74909SZhong Yang 					targetRange.end.Add(lengthInserted);
1654*8af74909SZhong Yang 					lengthInsertedTotal += lengthInserted;
1655*8af74909SZhong Yang 				}
1656*8af74909SZhong Yang 			}
1657*8af74909SZhong Yang 			lineEnd = pdoc->SciLineFromPosition(targetRange.end.Position());
1658*8af74909SZhong Yang 		}
1659*8af74909SZhong Yang 	}
1660*8af74909SZhong Yang }
1661*8af74909SZhong Yang 
PaintSelMargin(Surface * surfaceWindow,const PRectangle & rc)1662*8af74909SZhong Yang void Editor::PaintSelMargin(Surface *surfaceWindow, const PRectangle &rc) {
1663*8af74909SZhong Yang 	if (vs.fixedColumnWidth == 0)
1664*8af74909SZhong Yang 		return;
1665*8af74909SZhong Yang 
1666*8af74909SZhong Yang 	AllocateGraphics();
1667*8af74909SZhong Yang 	RefreshStyleData();
1668*8af74909SZhong Yang 	RefreshPixMaps(surfaceWindow);
1669*8af74909SZhong Yang 
1670*8af74909SZhong Yang 	// On GTK+ with Ubuntu overlay scroll bars, the surface may have been finished
1671*8af74909SZhong Yang 	// at this point. The Initialised call checks for this case and sets the status
1672*8af74909SZhong Yang 	// to be bad which avoids crashes in following calls.
1673*8af74909SZhong Yang 	if (!surfaceWindow->Initialised()) {
1674*8af74909SZhong Yang 		return;
1675*8af74909SZhong Yang 	}
1676*8af74909SZhong Yang 
1677*8af74909SZhong Yang 	PRectangle rcMargin = GetClientRectangle();
1678*8af74909SZhong Yang 	const Point ptOrigin = GetVisibleOriginInMain();
1679*8af74909SZhong Yang 	rcMargin.Move(0, -ptOrigin.y);
1680*8af74909SZhong Yang 	rcMargin.left = 0;
1681*8af74909SZhong Yang 	rcMargin.right = static_cast<XYPOSITION>(vs.fixedColumnWidth);
1682*8af74909SZhong Yang 
1683*8af74909SZhong Yang 	if (!rc.Intersects(rcMargin))
1684*8af74909SZhong Yang 		return;
1685*8af74909SZhong Yang 
1686*8af74909SZhong Yang 	Surface *surface;
1687*8af74909SZhong Yang 	if (view.bufferedDraw) {
1688*8af74909SZhong Yang 		surface = marginView.pixmapSelMargin.get();
1689*8af74909SZhong Yang 	} else {
1690*8af74909SZhong Yang 		surface = surfaceWindow;
1691*8af74909SZhong Yang 	}
1692*8af74909SZhong Yang 
1693*8af74909SZhong Yang 	// Clip vertically to paint area to avoid drawing line numbers
1694*8af74909SZhong Yang 	if (rcMargin.bottom > rc.bottom)
1695*8af74909SZhong Yang 		rcMargin.bottom = rc.bottom;
1696*8af74909SZhong Yang 	if (rcMargin.top < rc.top)
1697*8af74909SZhong Yang 		rcMargin.top = rc.top;
1698*8af74909SZhong Yang 
1699*8af74909SZhong Yang 	marginView.PaintMargin(surface, topLine, rc, rcMargin, *this, vs);
1700*8af74909SZhong Yang 
1701*8af74909SZhong Yang 	if (view.bufferedDraw) {
1702*8af74909SZhong Yang 		surfaceWindow->Copy(rcMargin, Point(rcMargin.left, rcMargin.top), *marginView.pixmapSelMargin);
1703*8af74909SZhong Yang 	}
1704*8af74909SZhong Yang }
1705*8af74909SZhong Yang 
RefreshPixMaps(Surface * surfaceWindow)1706*8af74909SZhong Yang void Editor::RefreshPixMaps(Surface *surfaceWindow) {
1707*8af74909SZhong Yang 	view.RefreshPixMaps(surfaceWindow, wMain.GetID(), vs);
1708*8af74909SZhong Yang 	marginView.RefreshPixMaps(surfaceWindow, wMain.GetID(), vs);
1709*8af74909SZhong Yang 	if (view.bufferedDraw) {
1710*8af74909SZhong Yang 		const PRectangle rcClient = GetClientRectangle();
1711*8af74909SZhong Yang 		if (!view.pixmapLine->Initialised()) {
1712*8af74909SZhong Yang 
1713*8af74909SZhong Yang 			view.pixmapLine->InitPixMap(static_cast<int>(rcClient.Width()), vs.lineHeight,
1714*8af74909SZhong Yang 			        surfaceWindow, wMain.GetID());
1715*8af74909SZhong Yang 		}
1716*8af74909SZhong Yang 		if (!marginView.pixmapSelMargin->Initialised()) {
1717*8af74909SZhong Yang 			marginView.pixmapSelMargin->InitPixMap(vs.fixedColumnWidth,
1718*8af74909SZhong Yang 				static_cast<int>(rcClient.Height()), surfaceWindow, wMain.GetID());
1719*8af74909SZhong Yang 		}
1720*8af74909SZhong Yang 	}
1721*8af74909SZhong Yang }
1722*8af74909SZhong Yang 
Paint(Surface * surfaceWindow,PRectangle rcArea)1723*8af74909SZhong Yang void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
1724*8af74909SZhong Yang 	//Platform::DebugPrintf("Paint:%1d (%3d,%3d) ... (%3d,%3d)\n",
1725*8af74909SZhong Yang 	//	paintingAllText, rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
1726*8af74909SZhong Yang 	AllocateGraphics();
1727*8af74909SZhong Yang 
1728*8af74909SZhong Yang 	RefreshStyleData();
1729*8af74909SZhong Yang 	if (paintState == paintAbandoned)
1730*8af74909SZhong Yang 		return;	// Scroll bars may have changed so need redraw
1731*8af74909SZhong Yang 	RefreshPixMaps(surfaceWindow);
1732*8af74909SZhong Yang 
1733*8af74909SZhong Yang 	paintAbandonedByStyling = false;
1734*8af74909SZhong Yang 
1735*8af74909SZhong Yang 	StyleAreaBounded(rcArea, false);
1736*8af74909SZhong Yang 
1737*8af74909SZhong Yang 	const PRectangle rcClient = GetClientRectangle();
1738*8af74909SZhong Yang 	//Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d)   %d\n",
1739*8af74909SZhong Yang 	//	rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
1740*8af74909SZhong Yang 
1741*8af74909SZhong Yang 	if (NotifyUpdateUI()) {
1742*8af74909SZhong Yang 		RefreshStyleData();
1743*8af74909SZhong Yang 		RefreshPixMaps(surfaceWindow);
1744*8af74909SZhong Yang 	}
1745*8af74909SZhong Yang 
1746*8af74909SZhong Yang 	// Wrap the visible lines if needed.
1747*8af74909SZhong Yang 	if (WrapLines(WrapScope::wsVisible)) {
1748*8af74909SZhong Yang 		// The wrapping process has changed the height of some lines so
1749*8af74909SZhong Yang 		// abandon this paint for a complete repaint.
1750*8af74909SZhong Yang 		if (AbandonPaint()) {
1751*8af74909SZhong Yang 			return;
1752*8af74909SZhong Yang 		}
1753*8af74909SZhong Yang 		RefreshPixMaps(surfaceWindow);	// In case pixmaps invalidated by scrollbar change
1754*8af74909SZhong Yang 	}
1755*8af74909SZhong Yang 
1756*8af74909SZhong Yang 	if (!marginView.pixmapSelPattern->Initialised()) {
1757*8af74909SZhong Yang 		// When Direct2D is used, pixmap creation may fail with D2DERR_RECREATE_TARGET so
1758*8af74909SZhong Yang 		// abandon this paint to avoid further failures.
1759*8af74909SZhong Yang 		// Main drawing surface and pixmaps should be recreated by next paint.
1760*8af74909SZhong Yang 		return;
1761*8af74909SZhong Yang 	}
1762*8af74909SZhong Yang 
1763*8af74909SZhong Yang 	if (!view.bufferedDraw)
1764*8af74909SZhong Yang 		surfaceWindow->SetClip(rcArea);
1765*8af74909SZhong Yang 
1766*8af74909SZhong Yang 	if (paintState != paintAbandoned) {
1767*8af74909SZhong Yang 		if (vs.marginInside) {
1768*8af74909SZhong Yang 			PaintSelMargin(surfaceWindow, rcArea);
1769*8af74909SZhong Yang 			PRectangle rcRightMargin = rcClient;
1770*8af74909SZhong Yang 			rcRightMargin.left = rcRightMargin.right - vs.rightMarginWidth;
1771*8af74909SZhong Yang 			if (rcArea.Intersects(rcRightMargin)) {
1772*8af74909SZhong Yang 				surfaceWindow->FillRectangle(rcRightMargin, vs.styles[STYLE_DEFAULT].back);
1773*8af74909SZhong Yang 			}
1774*8af74909SZhong Yang 		} else { // Else separate view so separate paint event but leftMargin included to allow overlap
1775*8af74909SZhong Yang 			PRectangle rcLeftMargin = rcArea;
1776*8af74909SZhong Yang 			rcLeftMargin.left = 0;
1777*8af74909SZhong Yang 			rcLeftMargin.right = rcLeftMargin.left + vs.leftMarginWidth;
1778*8af74909SZhong Yang 			if (rcArea.Intersects(rcLeftMargin)) {
1779*8af74909SZhong Yang 				surfaceWindow->FillRectangle(rcLeftMargin, vs.styles[STYLE_DEFAULT].back);
1780*8af74909SZhong Yang 			}
1781*8af74909SZhong Yang 		}
1782*8af74909SZhong Yang 	}
1783*8af74909SZhong Yang 
1784*8af74909SZhong Yang 	if (paintState == paintAbandoned) {
1785*8af74909SZhong Yang 		// Either styling or NotifyUpdateUI noticed that painting is needed
1786*8af74909SZhong Yang 		// outside the current painting rectangle
1787*8af74909SZhong Yang 		//Platform::DebugPrintf("Abandoning paint\n");
1788*8af74909SZhong Yang 		if (Wrapping()) {
1789*8af74909SZhong Yang 			if (paintAbandonedByStyling) {
1790*8af74909SZhong Yang 				// Styling has spilled over a line end, such as occurs by starting a multiline
1791*8af74909SZhong Yang 				// comment. The width of subsequent text may have changed, so rewrap.
1792*8af74909SZhong Yang 				NeedWrapping(pcs->DocFromDisplay(topLine));
1793*8af74909SZhong Yang 			}
1794*8af74909SZhong Yang 		}
1795*8af74909SZhong Yang 		return;
1796*8af74909SZhong Yang 	}
1797*8af74909SZhong Yang 
1798*8af74909SZhong Yang 	view.PaintText(surfaceWindow, *this, rcArea, rcClient, vs);
1799*8af74909SZhong Yang 
1800*8af74909SZhong Yang 	if (horizontalScrollBarVisible && trackLineWidth && (view.lineWidthMaxSeen > scrollWidth)) {
1801*8af74909SZhong Yang 		scrollWidth = view.lineWidthMaxSeen;
1802*8af74909SZhong Yang 		if (!FineTickerRunning(tickWiden)) {
1803*8af74909SZhong Yang 			FineTickerStart(tickWiden, 50, 5);
1804*8af74909SZhong Yang 		}
1805*8af74909SZhong Yang 	}
1806*8af74909SZhong Yang 
1807*8af74909SZhong Yang 	NotifyPainted();
1808*8af74909SZhong Yang }
1809*8af74909SZhong Yang 
1810*8af74909SZhong Yang // This is mostly copied from the Paint method but with some things omitted
1811*8af74909SZhong Yang // such as the margin markers, line numbers, selection and caret
1812*8af74909SZhong Yang // Should be merged back into a combined Draw method.
FormatRange(bool draw,const Sci_RangeToFormat * pfr)1813*8af74909SZhong Yang Sci::Position Editor::FormatRange(bool draw, const Sci_RangeToFormat *pfr) {
1814*8af74909SZhong Yang 	if (!pfr)
1815*8af74909SZhong Yang 		return 0;
1816*8af74909SZhong Yang 
1817*8af74909SZhong Yang 	AutoSurface surface(pfr->hdc, this, SC_TECHNOLOGY_DEFAULT);
1818*8af74909SZhong Yang 	if (!surface)
1819*8af74909SZhong Yang 		return 0;
1820*8af74909SZhong Yang 	AutoSurface surfaceMeasure(pfr->hdcTarget, this, SC_TECHNOLOGY_DEFAULT);
1821*8af74909SZhong Yang 	if (!surfaceMeasure) {
1822*8af74909SZhong Yang 		return 0;
1823*8af74909SZhong Yang 	}
1824*8af74909SZhong Yang 	return view.FormatRange(draw, pfr, surface, surfaceMeasure, *this, vs);
1825*8af74909SZhong Yang }
1826*8af74909SZhong Yang 
TextWidth(uptr_t style,const char * text)1827*8af74909SZhong Yang long Editor::TextWidth(uptr_t style, const char *text) {
1828*8af74909SZhong Yang 	RefreshStyleData();
1829*8af74909SZhong Yang 	AutoSurface surface(this);
1830*8af74909SZhong Yang 	if (surface) {
1831*8af74909SZhong Yang 		return std::lround(surface->WidthText(vs.styles[style].font, text));
1832*8af74909SZhong Yang 	} else {
1833*8af74909SZhong Yang 		return 1;
1834*8af74909SZhong Yang 	}
1835*8af74909SZhong Yang }
1836*8af74909SZhong Yang 
1837*8af74909SZhong Yang // Empty method is overridden on GTK+ to show / hide scrollbars
ReconfigureScrollBars()1838*8af74909SZhong Yang void Editor::ReconfigureScrollBars() {}
1839*8af74909SZhong Yang 
SetScrollBars()1840*8af74909SZhong Yang void Editor::SetScrollBars() {
1841*8af74909SZhong Yang 	RefreshStyleData();
1842*8af74909SZhong Yang 
1843*8af74909SZhong Yang 	const Sci::Line nMax = MaxScrollPos();
1844*8af74909SZhong Yang 	const Sci::Line nPage = LinesOnScreen();
1845*8af74909SZhong Yang 	const bool modified = ModifyScrollBars(nMax + nPage - 1, nPage);
1846*8af74909SZhong Yang 	if (modified) {
1847*8af74909SZhong Yang 		DwellEnd(true);
1848*8af74909SZhong Yang 	}
1849*8af74909SZhong Yang 
1850*8af74909SZhong Yang 	// TODO: ensure always showing as many lines as possible
1851*8af74909SZhong Yang 	// May not be, if, for example, window made larger
1852*8af74909SZhong Yang 	if (topLine > MaxScrollPos()) {
1853*8af74909SZhong Yang 		SetTopLine(std::clamp<Sci::Line>(topLine, 0, MaxScrollPos()));
1854*8af74909SZhong Yang 		SetVerticalScrollPos();
1855*8af74909SZhong Yang 		Redraw();
1856*8af74909SZhong Yang 	}
1857*8af74909SZhong Yang 	if (modified) {
1858*8af74909SZhong Yang 		if (!AbandonPaint())
1859*8af74909SZhong Yang 			Redraw();
1860*8af74909SZhong Yang 	}
1861*8af74909SZhong Yang 	//Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage);
1862*8af74909SZhong Yang }
1863*8af74909SZhong Yang 
ChangeSize()1864*8af74909SZhong Yang void Editor::ChangeSize() {
1865*8af74909SZhong Yang 	DropGraphics(false);
1866*8af74909SZhong Yang 	SetScrollBars();
1867*8af74909SZhong Yang 	if (Wrapping()) {
1868*8af74909SZhong Yang 		PRectangle rcTextArea = GetClientRectangle();
1869*8af74909SZhong Yang 		rcTextArea.left = static_cast<XYPOSITION>(vs.textStart);
1870*8af74909SZhong Yang 		rcTextArea.right -= vs.rightMarginWidth;
1871*8af74909SZhong Yang 		if (wrapWidth != rcTextArea.Width()) {
1872*8af74909SZhong Yang 			NeedWrapping();
1873*8af74909SZhong Yang 			Redraw();
1874*8af74909SZhong Yang 		}
1875*8af74909SZhong Yang 	}
1876*8af74909SZhong Yang }
1877*8af74909SZhong Yang 
RealizeVirtualSpace(Sci::Position position,Sci::Position virtualSpace)1878*8af74909SZhong Yang Sci::Position Editor::RealizeVirtualSpace(Sci::Position position, Sci::Position virtualSpace) {
1879*8af74909SZhong Yang 	if (virtualSpace > 0) {
1880*8af74909SZhong Yang 		const Sci::Line line = pdoc->SciLineFromPosition(position);
1881*8af74909SZhong Yang 		const Sci::Position indent = pdoc->GetLineIndentPosition(line);
1882*8af74909SZhong Yang 		if (indent == position) {
1883*8af74909SZhong Yang 			return pdoc->SetLineIndentation(line, pdoc->GetLineIndentation(line) + virtualSpace);
1884*8af74909SZhong Yang 		} else {
1885*8af74909SZhong Yang 			std::string spaceText(virtualSpace, ' ');
1886*8af74909SZhong Yang 			const Sci::Position lengthInserted = pdoc->InsertString(position, spaceText.c_str(), virtualSpace);
1887*8af74909SZhong Yang 			position += lengthInserted;
1888*8af74909SZhong Yang 		}
1889*8af74909SZhong Yang 	}
1890*8af74909SZhong Yang 	return position;
1891*8af74909SZhong Yang }
1892*8af74909SZhong Yang 
RealizeVirtualSpace(const SelectionPosition & position)1893*8af74909SZhong Yang SelectionPosition Editor::RealizeVirtualSpace(const SelectionPosition &position) {
1894*8af74909SZhong Yang 	// Return the new position with no virtual space
1895*8af74909SZhong Yang 	return SelectionPosition(RealizeVirtualSpace(position.Position(), position.VirtualSpace()));
1896*8af74909SZhong Yang }
1897*8af74909SZhong Yang 
AddChar(char ch)1898*8af74909SZhong Yang void Editor::AddChar(char ch) {
1899*8af74909SZhong Yang 	char s[2];
1900*8af74909SZhong Yang 	s[0] = ch;
1901*8af74909SZhong Yang 	s[1] = '\0';
1902*8af74909SZhong Yang 	InsertCharacter(std::string_view(s, 1), CharacterSource::directInput);
1903*8af74909SZhong Yang }
1904*8af74909SZhong Yang 
FilterSelections()1905*8af74909SZhong Yang void Editor::FilterSelections() {
1906*8af74909SZhong Yang 	if (!additionalSelectionTyping && (sel.Count() > 1)) {
1907*8af74909SZhong Yang 		InvalidateWholeSelection();
1908*8af74909SZhong Yang 		sel.DropAdditionalRanges();
1909*8af74909SZhong Yang 	}
1910*8af74909SZhong Yang }
1911*8af74909SZhong Yang 
1912*8af74909SZhong Yang // InsertCharacter inserts a character encoded in document code page.
InsertCharacter(std::string_view sv,CharacterSource charSource)1913*8af74909SZhong Yang void Editor::InsertCharacter(std::string_view sv, CharacterSource charSource) {
1914*8af74909SZhong Yang 	if (sv.empty()) {
1915*8af74909SZhong Yang 		return;
1916*8af74909SZhong Yang 	}
1917*8af74909SZhong Yang 	FilterSelections();
1918*8af74909SZhong Yang 	{
1919*8af74909SZhong Yang 		UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty() || inOverstrike);
1920*8af74909SZhong Yang 
1921*8af74909SZhong Yang 		// Vector elements point into selection in order to change selection.
1922*8af74909SZhong Yang 		std::vector<SelectionRange *> selPtrs;
1923*8af74909SZhong Yang 		for (size_t r = 0; r < sel.Count(); r++) {
1924*8af74909SZhong Yang 			selPtrs.push_back(&sel.Range(r));
1925*8af74909SZhong Yang 		}
1926*8af74909SZhong Yang 		// Order selections by position in document.
1927*8af74909SZhong Yang 		std::sort(selPtrs.begin(), selPtrs.end(),
1928*8af74909SZhong Yang 			[](const SelectionRange *a, const SelectionRange *b) noexcept {return *a < *b;});
1929*8af74909SZhong Yang 
1930*8af74909SZhong Yang 		// Loop in reverse to avoid disturbing positions of selections yet to be processed.
1931*8af74909SZhong Yang 		for (std::vector<SelectionRange *>::reverse_iterator rit = selPtrs.rbegin();
1932*8af74909SZhong Yang 			rit != selPtrs.rend(); ++rit) {
1933*8af74909SZhong Yang 			SelectionRange *currentSel = *rit;
1934*8af74909SZhong Yang 			if (!RangeContainsProtected(currentSel->Start().Position(),
1935*8af74909SZhong Yang 				currentSel->End().Position())) {
1936*8af74909SZhong Yang 				Sci::Position positionInsert = currentSel->Start().Position();
1937*8af74909SZhong Yang 				if (!currentSel->Empty()) {
1938*8af74909SZhong Yang 					if (currentSel->Length()) {
1939*8af74909SZhong Yang 						pdoc->DeleteChars(positionInsert, currentSel->Length());
1940*8af74909SZhong Yang 						currentSel->ClearVirtualSpace();
1941*8af74909SZhong Yang 					} else {
1942*8af74909SZhong Yang 						// Range is all virtual so collapse to start of virtual space
1943*8af74909SZhong Yang 						currentSel->MinimizeVirtualSpace();
1944*8af74909SZhong Yang 					}
1945*8af74909SZhong Yang 				} else if (inOverstrike) {
1946*8af74909SZhong Yang 					if (positionInsert < pdoc->Length()) {
1947*8af74909SZhong Yang 						if (!pdoc->IsPositionInLineEnd(positionInsert)) {
1948*8af74909SZhong Yang 							pdoc->DelChar(positionInsert);
1949*8af74909SZhong Yang 							currentSel->ClearVirtualSpace();
1950*8af74909SZhong Yang 						}
1951*8af74909SZhong Yang 					}
1952*8af74909SZhong Yang 				}
1953*8af74909SZhong Yang 				positionInsert = RealizeVirtualSpace(positionInsert, currentSel->caret.VirtualSpace());
1954*8af74909SZhong Yang 				const Sci::Position lengthInserted = pdoc->InsertString(positionInsert, sv.data(), sv.length());
1955*8af74909SZhong Yang 				if (lengthInserted > 0) {
1956*8af74909SZhong Yang 					currentSel->caret.SetPosition(positionInsert + lengthInserted);
1957*8af74909SZhong Yang 					currentSel->anchor.SetPosition(positionInsert + lengthInserted);
1958*8af74909SZhong Yang 				}
1959*8af74909SZhong Yang 				currentSel->ClearVirtualSpace();
1960*8af74909SZhong Yang 				// If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
1961*8af74909SZhong Yang 				if (Wrapping()) {
1962*8af74909SZhong Yang 					AutoSurface surface(this);
1963*8af74909SZhong Yang 					if (surface) {
1964*8af74909SZhong Yang 						if (WrapOneLine(surface, pdoc->SciLineFromPosition(positionInsert))) {
1965*8af74909SZhong Yang 							SetScrollBars();
1966*8af74909SZhong Yang 							SetVerticalScrollPos();
1967*8af74909SZhong Yang 							Redraw();
1968*8af74909SZhong Yang 						}
1969*8af74909SZhong Yang 					}
1970*8af74909SZhong Yang 				}
1971*8af74909SZhong Yang 			}
1972*8af74909SZhong Yang 		}
1973*8af74909SZhong Yang 	}
1974*8af74909SZhong Yang 	if (Wrapping()) {
1975*8af74909SZhong Yang 		SetScrollBars();
1976*8af74909SZhong Yang 	}
1977*8af74909SZhong Yang 	ThinRectangularRange();
1978*8af74909SZhong Yang 	// If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
1979*8af74909SZhong Yang 	EnsureCaretVisible();
1980*8af74909SZhong Yang 	// Avoid blinking during rapid typing:
1981*8af74909SZhong Yang 	ShowCaretAtCurrentPosition();
1982*8af74909SZhong Yang 	if ((caretSticky == SC_CARETSTICKY_OFF) ||
1983*8af74909SZhong Yang 		((caretSticky == SC_CARETSTICKY_WHITESPACE) && !IsAllSpacesOrTabs(sv))) {
1984*8af74909SZhong Yang 		SetLastXChosen();
1985*8af74909SZhong Yang 	}
1986*8af74909SZhong Yang 
1987*8af74909SZhong Yang 	int ch = static_cast<unsigned char>(sv[0]);
1988*8af74909SZhong Yang 	if (pdoc->dbcsCodePage != SC_CP_UTF8) {
1989*8af74909SZhong Yang 		if (sv.length() > 1) {
1990*8af74909SZhong Yang 			// DBCS code page or DBCS font character set.
1991*8af74909SZhong Yang 			ch = (ch << 8) | static_cast<unsigned char>(sv[1]);
1992*8af74909SZhong Yang 		}
1993*8af74909SZhong Yang 	} else {
1994*8af74909SZhong Yang 		if ((ch < 0xC0) || (1 == sv.length())) {
1995*8af74909SZhong Yang 			// Handles UTF-8 characters between 0x01 and 0x7F and single byte
1996*8af74909SZhong Yang 			// characters when not in UTF-8 mode.
1997*8af74909SZhong Yang 			// Also treats \0 and naked trail bytes 0x80 to 0xBF as valid
1998*8af74909SZhong Yang 			// characters representing themselves.
1999*8af74909SZhong Yang 		} else {
2000*8af74909SZhong Yang 			unsigned int utf32[1] = { 0 };
2001*8af74909SZhong Yang 			UTF32FromUTF8(sv, utf32, std::size(utf32));
2002*8af74909SZhong Yang 			ch = utf32[0];
2003*8af74909SZhong Yang 		}
2004*8af74909SZhong Yang 	}
2005*8af74909SZhong Yang 	NotifyChar(ch, charSource);
2006*8af74909SZhong Yang 
2007*8af74909SZhong Yang 	if (recordingMacro && charSource != CharacterSource::tentativeInput) {
2008*8af74909SZhong Yang 		std::string copy(sv); // ensure NUL-terminated
2009*8af74909SZhong Yang 		NotifyMacroRecord(SCI_REPLACESEL, 0, reinterpret_cast<sptr_t>(copy.data()));
2010*8af74909SZhong Yang 	}
2011*8af74909SZhong Yang }
2012*8af74909SZhong Yang 
ClearBeforeTentativeStart()2013*8af74909SZhong Yang void Editor::ClearBeforeTentativeStart() {
2014*8af74909SZhong Yang 	// Make positions for the first composition string.
2015*8af74909SZhong Yang 	FilterSelections();
2016*8af74909SZhong Yang 	UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty() || inOverstrike);
2017*8af74909SZhong Yang 	for (size_t r = 0; r<sel.Count(); r++) {
2018*8af74909SZhong Yang 		if (!RangeContainsProtected(sel.Range(r).Start().Position(),
2019*8af74909SZhong Yang 			sel.Range(r).End().Position())) {
2020*8af74909SZhong Yang 			const Sci::Position positionInsert = sel.Range(r).Start().Position();
2021*8af74909SZhong Yang 			if (!sel.Range(r).Empty()) {
2022*8af74909SZhong Yang 				if (sel.Range(r).Length()) {
2023*8af74909SZhong Yang 					pdoc->DeleteChars(positionInsert, sel.Range(r).Length());
2024*8af74909SZhong Yang 					sel.Range(r).ClearVirtualSpace();
2025*8af74909SZhong Yang 				} else {
2026*8af74909SZhong Yang 					// Range is all virtual so collapse to start of virtual space
2027*8af74909SZhong Yang 					sel.Range(r).MinimizeVirtualSpace();
2028*8af74909SZhong Yang 				}
2029*8af74909SZhong Yang 			}
2030*8af74909SZhong Yang 			RealizeVirtualSpace(positionInsert, sel.Range(r).caret.VirtualSpace());
2031*8af74909SZhong Yang 			sel.Range(r).ClearVirtualSpace();
2032*8af74909SZhong Yang 		}
2033*8af74909SZhong Yang 	}
2034*8af74909SZhong Yang }
2035*8af74909SZhong Yang 
InsertPaste(const char * text,Sci::Position len)2036*8af74909SZhong Yang void Editor::InsertPaste(const char *text, Sci::Position len) {
2037*8af74909SZhong Yang 	if (multiPasteMode == SC_MULTIPASTE_ONCE) {
2038*8af74909SZhong Yang 		SelectionPosition selStart = sel.Start();
2039*8af74909SZhong Yang 		selStart = RealizeVirtualSpace(selStart);
2040*8af74909SZhong Yang 		const Sci::Position lengthInserted = pdoc->InsertString(selStart.Position(), text, len);
2041*8af74909SZhong Yang 		if (lengthInserted > 0) {
2042*8af74909SZhong Yang 			SetEmptySelection(selStart.Position() + lengthInserted);
2043*8af74909SZhong Yang 		}
2044*8af74909SZhong Yang 	} else {
2045*8af74909SZhong Yang 		// SC_MULTIPASTE_EACH
2046*8af74909SZhong Yang 		for (size_t r=0; r<sel.Count(); r++) {
2047*8af74909SZhong Yang 			if (!RangeContainsProtected(sel.Range(r).Start().Position(),
2048*8af74909SZhong Yang 				sel.Range(r).End().Position())) {
2049*8af74909SZhong Yang 				Sci::Position positionInsert = sel.Range(r).Start().Position();
2050*8af74909SZhong Yang 				if (!sel.Range(r).Empty()) {
2051*8af74909SZhong Yang 					if (sel.Range(r).Length()) {
2052*8af74909SZhong Yang 						pdoc->DeleteChars(positionInsert, sel.Range(r).Length());
2053*8af74909SZhong Yang 						sel.Range(r).ClearVirtualSpace();
2054*8af74909SZhong Yang 					} else {
2055*8af74909SZhong Yang 						// Range is all virtual so collapse to start of virtual space
2056*8af74909SZhong Yang 						sel.Range(r).MinimizeVirtualSpace();
2057*8af74909SZhong Yang 					}
2058*8af74909SZhong Yang 				}
2059*8af74909SZhong Yang 				positionInsert = RealizeVirtualSpace(positionInsert, sel.Range(r).caret.VirtualSpace());
2060*8af74909SZhong Yang 				const Sci::Position lengthInserted = pdoc->InsertString(positionInsert, text, len);
2061*8af74909SZhong Yang 				if (lengthInserted > 0) {
2062*8af74909SZhong Yang 					sel.Range(r).caret.SetPosition(positionInsert + lengthInserted);
2063*8af74909SZhong Yang 					sel.Range(r).anchor.SetPosition(positionInsert + lengthInserted);
2064*8af74909SZhong Yang 				}
2065*8af74909SZhong Yang 				sel.Range(r).ClearVirtualSpace();
2066*8af74909SZhong Yang 			}
2067*8af74909SZhong Yang 		}
2068*8af74909SZhong Yang 	}
2069*8af74909SZhong Yang }
2070*8af74909SZhong Yang 
InsertPasteShape(const char * text,Sci::Position len,PasteShape shape)2071*8af74909SZhong Yang void Editor::InsertPasteShape(const char *text, Sci::Position len, PasteShape shape) {
2072*8af74909SZhong Yang 	std::string convertedText;
2073*8af74909SZhong Yang 	if (convertPastes) {
2074*8af74909SZhong Yang 		// Convert line endings of the paste into our local line-endings mode
2075*8af74909SZhong Yang 		convertedText = Document::TransformLineEnds(text, len, pdoc->eolMode);
2076*8af74909SZhong Yang 		len = convertedText.length();
2077*8af74909SZhong Yang 		text = convertedText.c_str();
2078*8af74909SZhong Yang 	}
2079*8af74909SZhong Yang 	if (shape == pasteRectangular) {
2080*8af74909SZhong Yang 		PasteRectangular(sel.Start(), text, len);
2081*8af74909SZhong Yang 	} else {
2082*8af74909SZhong Yang 		if (shape == pasteLine) {
2083*8af74909SZhong Yang 			const Sci::Position insertPos =
2084*8af74909SZhong Yang 				pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret()));
2085*8af74909SZhong Yang 			Sci::Position lengthInserted = pdoc->InsertString(insertPos, text, len);
2086*8af74909SZhong Yang 			// add the newline if necessary
2087*8af74909SZhong Yang 			if ((len > 0) && (text[len - 1] != '\n' && text[len - 1] != '\r')) {
2088*8af74909SZhong Yang 				const char *endline = StringFromEOLMode(pdoc->eolMode);
2089*8af74909SZhong Yang 				const Sci::Position length = strlen(endline);
2090*8af74909SZhong Yang 				lengthInserted += pdoc->InsertString(insertPos + lengthInserted, endline, length);
2091*8af74909SZhong Yang 			}
2092*8af74909SZhong Yang 			if (sel.MainCaret() == insertPos) {
2093*8af74909SZhong Yang 				SetEmptySelection(sel.MainCaret() + lengthInserted);
2094*8af74909SZhong Yang 			}
2095*8af74909SZhong Yang 		} else {
2096*8af74909SZhong Yang 			InsertPaste(text, len);
2097*8af74909SZhong Yang 		}
2098*8af74909SZhong Yang 	}
2099*8af74909SZhong Yang }
2100*8af74909SZhong Yang 
ClearSelection(bool retainMultipleSelections)2101*8af74909SZhong Yang void Editor::ClearSelection(bool retainMultipleSelections) {
2102*8af74909SZhong Yang 	if (!sel.IsRectangular() && !retainMultipleSelections)
2103*8af74909SZhong Yang 		FilterSelections();
2104*8af74909SZhong Yang 	UndoGroup ug(pdoc);
2105*8af74909SZhong Yang 	for (size_t r=0; r<sel.Count(); r++) {
2106*8af74909SZhong Yang 		if (!sel.Range(r).Empty()) {
2107*8af74909SZhong Yang 			if (!RangeContainsProtected(sel.Range(r).Start().Position(),
2108*8af74909SZhong Yang 				sel.Range(r).End().Position())) {
2109*8af74909SZhong Yang 				pdoc->DeleteChars(sel.Range(r).Start().Position(),
2110*8af74909SZhong Yang 					sel.Range(r).Length());
2111*8af74909SZhong Yang 				sel.Range(r) = SelectionRange(sel.Range(r).Start());
2112*8af74909SZhong Yang 			}
2113*8af74909SZhong Yang 		}
2114*8af74909SZhong Yang 	}
2115*8af74909SZhong Yang 	ThinRectangularRange();
2116*8af74909SZhong Yang 	sel.RemoveDuplicates();
2117*8af74909SZhong Yang 	ClaimSelection();
2118*8af74909SZhong Yang 	SetHoverIndicatorPosition(sel.MainCaret());
2119*8af74909SZhong Yang }
2120*8af74909SZhong Yang 
ClearAll()2121*8af74909SZhong Yang void Editor::ClearAll() {
2122*8af74909SZhong Yang 	{
2123*8af74909SZhong Yang 		UndoGroup ug(pdoc);
2124*8af74909SZhong Yang 		if (0 != pdoc->Length()) {
2125*8af74909SZhong Yang 			pdoc->DeleteChars(0, pdoc->Length());
2126*8af74909SZhong Yang 		}
2127*8af74909SZhong Yang 		if (!pdoc->IsReadOnly()) {
2128*8af74909SZhong Yang 			pcs->Clear();
2129*8af74909SZhong Yang 			pdoc->AnnotationClearAll();
2130*8af74909SZhong Yang 			pdoc->EOLAnnotationClearAll();
2131*8af74909SZhong Yang 			pdoc->MarginClearAll();
2132*8af74909SZhong Yang 		}
2133*8af74909SZhong Yang 	}
2134*8af74909SZhong Yang 
2135*8af74909SZhong Yang 	view.ClearAllTabstops();
2136*8af74909SZhong Yang 
2137*8af74909SZhong Yang 	sel.Clear();
2138*8af74909SZhong Yang 	SetTopLine(0);
2139*8af74909SZhong Yang 	SetVerticalScrollPos();
2140*8af74909SZhong Yang 	InvalidateStyleRedraw();
2141*8af74909SZhong Yang }
2142*8af74909SZhong Yang 
ClearDocumentStyle()2143*8af74909SZhong Yang void Editor::ClearDocumentStyle() {
2144*8af74909SZhong Yang 	pdoc->decorations->DeleteLexerDecorations();
2145*8af74909SZhong Yang 	pdoc->StartStyling(0);
2146*8af74909SZhong Yang 	pdoc->SetStyleFor(pdoc->Length(), 0);
2147*8af74909SZhong Yang 	pcs->ShowAll();
2148*8af74909SZhong Yang 	SetAnnotationHeights(0, pdoc->LinesTotal());
2149*8af74909SZhong Yang 	pdoc->ClearLevels();
2150*8af74909SZhong Yang }
2151*8af74909SZhong Yang 
CopyAllowLine()2152*8af74909SZhong Yang void Editor::CopyAllowLine() {
2153*8af74909SZhong Yang 	SelectionText selectedText;
2154*8af74909SZhong Yang 	CopySelectionRange(&selectedText, true);
2155*8af74909SZhong Yang 	CopyToClipboard(selectedText);
2156*8af74909SZhong Yang }
2157*8af74909SZhong Yang 
Cut()2158*8af74909SZhong Yang void Editor::Cut() {
2159*8af74909SZhong Yang 	pdoc->CheckReadOnly();
2160*8af74909SZhong Yang 	if (!pdoc->IsReadOnly() && !SelectionContainsProtected()) {
2161*8af74909SZhong Yang 		Copy();
2162*8af74909SZhong Yang 		ClearSelection();
2163*8af74909SZhong Yang 	}
2164*8af74909SZhong Yang }
2165*8af74909SZhong Yang 
PasteRectangular(SelectionPosition pos,const char * ptr,Sci::Position len)2166*8af74909SZhong Yang void Editor::PasteRectangular(SelectionPosition pos, const char *ptr, Sci::Position len) {
2167*8af74909SZhong Yang 	if (pdoc->IsReadOnly() || SelectionContainsProtected()) {
2168*8af74909SZhong Yang 		return;
2169*8af74909SZhong Yang 	}
2170*8af74909SZhong Yang 	sel.Clear();
2171*8af74909SZhong Yang 	sel.RangeMain() = SelectionRange(pos);
2172*8af74909SZhong Yang 	Sci::Line line = pdoc->SciLineFromPosition(sel.MainCaret());
2173*8af74909SZhong Yang 	UndoGroup ug(pdoc);
2174*8af74909SZhong Yang 	sel.RangeMain().caret = RealizeVirtualSpace(sel.RangeMain().caret);
2175*8af74909SZhong Yang 	const int xInsert = XFromPosition(sel.RangeMain().caret);
2176*8af74909SZhong Yang 	bool prevCr = false;
2177*8af74909SZhong Yang 	while ((len > 0) && IsEOLChar(ptr[len-1]))
2178*8af74909SZhong Yang 		len--;
2179*8af74909SZhong Yang 	for (Sci::Position i = 0; i < len; i++) {
2180*8af74909SZhong Yang 		if (IsEOLChar(ptr[i])) {
2181*8af74909SZhong Yang 			if ((ptr[i] == '\r') || (!prevCr))
2182*8af74909SZhong Yang 				line++;
2183*8af74909SZhong Yang 			if (line >= pdoc->LinesTotal()) {
2184*8af74909SZhong Yang 				if (pdoc->eolMode != SC_EOL_LF)
2185*8af74909SZhong Yang 					pdoc->InsertString(pdoc->Length(), "\r", 1);
2186*8af74909SZhong Yang 				if (pdoc->eolMode != SC_EOL_CR)
2187*8af74909SZhong Yang 					pdoc->InsertString(pdoc->Length(), "\n", 1);
2188*8af74909SZhong Yang 			}
2189*8af74909SZhong Yang 			// Pad the end of lines with spaces if required
2190*8af74909SZhong Yang 			sel.RangeMain().caret.SetPosition(PositionFromLineX(line, xInsert));
2191*8af74909SZhong Yang 			if ((XFromPosition(sel.RangeMain().caret) < xInsert) && (i + 1 < len)) {
2192*8af74909SZhong Yang 				while (XFromPosition(sel.RangeMain().caret) < xInsert) {
2193*8af74909SZhong Yang 					assert(pdoc);
2194*8af74909SZhong Yang 					const Sci::Position lengthInserted = pdoc->InsertString(sel.MainCaret(), " ", 1);
2195*8af74909SZhong Yang 					sel.RangeMain().caret.Add(lengthInserted);
2196*8af74909SZhong Yang 				}
2197*8af74909SZhong Yang 			}
2198*8af74909SZhong Yang 			prevCr = ptr[i] == '\r';
2199*8af74909SZhong Yang 		} else {
2200*8af74909SZhong Yang 			const Sci::Position lengthInserted = pdoc->InsertString(sel.MainCaret(), ptr + i, 1);
2201*8af74909SZhong Yang 			sel.RangeMain().caret.Add(lengthInserted);
2202*8af74909SZhong Yang 			prevCr = false;
2203*8af74909SZhong Yang 		}
2204*8af74909SZhong Yang 	}
2205*8af74909SZhong Yang 	SetEmptySelection(pos);
2206*8af74909SZhong Yang }
2207*8af74909SZhong Yang 
CanPaste()2208*8af74909SZhong Yang bool Editor::CanPaste() {
2209*8af74909SZhong Yang 	return !pdoc->IsReadOnly() && !SelectionContainsProtected();
2210*8af74909SZhong Yang }
2211*8af74909SZhong Yang 
Clear()2212*8af74909SZhong Yang void Editor::Clear() {
2213*8af74909SZhong Yang 	// If multiple selections, don't delete EOLS
2214*8af74909SZhong Yang 	if (sel.Empty()) {
2215*8af74909SZhong Yang 		bool singleVirtual = false;
2216*8af74909SZhong Yang 		if ((sel.Count() == 1) &&
2217*8af74909SZhong Yang 			!RangeContainsProtected(sel.MainCaret(), sel.MainCaret() + 1) &&
2218*8af74909SZhong Yang 			sel.RangeMain().Start().VirtualSpace()) {
2219*8af74909SZhong Yang 			singleVirtual = true;
2220*8af74909SZhong Yang 		}
2221*8af74909SZhong Yang 		UndoGroup ug(pdoc, (sel.Count() > 1) || singleVirtual);
2222*8af74909SZhong Yang 		for (size_t r=0; r<sel.Count(); r++) {
2223*8af74909SZhong Yang 			if (!RangeContainsProtected(sel.Range(r).caret.Position(), sel.Range(r).caret.Position() + 1)) {
2224*8af74909SZhong Yang 				if (sel.Range(r).Start().VirtualSpace()) {
2225*8af74909SZhong Yang 					if (sel.Range(r).anchor < sel.Range(r).caret)
2226*8af74909SZhong Yang 						sel.Range(r) = SelectionRange(RealizeVirtualSpace(sel.Range(r).anchor.Position(), sel.Range(r).anchor.VirtualSpace()));
2227*8af74909SZhong Yang 					else
2228*8af74909SZhong Yang 						sel.Range(r) = SelectionRange(RealizeVirtualSpace(sel.Range(r).caret.Position(), sel.Range(r).caret.VirtualSpace()));
2229*8af74909SZhong Yang 				}
2230*8af74909SZhong Yang 				if ((sel.Count() == 1) || !pdoc->IsPositionInLineEnd(sel.Range(r).caret.Position())) {
2231*8af74909SZhong Yang 					pdoc->DelChar(sel.Range(r).caret.Position());
2232*8af74909SZhong Yang 					sel.Range(r).ClearVirtualSpace();
2233*8af74909SZhong Yang 				}  // else multiple selection so don't eat line ends
2234*8af74909SZhong Yang 			} else {
2235*8af74909SZhong Yang 				sel.Range(r).ClearVirtualSpace();
2236*8af74909SZhong Yang 			}
2237*8af74909SZhong Yang 		}
2238*8af74909SZhong Yang 	} else {
2239*8af74909SZhong Yang 		ClearSelection();
2240*8af74909SZhong Yang 	}
2241*8af74909SZhong Yang 	sel.RemoveDuplicates();
2242*8af74909SZhong Yang 	ShowCaretAtCurrentPosition();		// Avoid blinking
2243*8af74909SZhong Yang }
2244*8af74909SZhong Yang 
SelectAll()2245*8af74909SZhong Yang void Editor::SelectAll() {
2246*8af74909SZhong Yang 	sel.Clear();
2247*8af74909SZhong Yang 	SetSelection(0, pdoc->Length());
2248*8af74909SZhong Yang 	Redraw();
2249*8af74909SZhong Yang }
2250*8af74909SZhong Yang 
Undo()2251*8af74909SZhong Yang void Editor::Undo() {
2252*8af74909SZhong Yang 	if (pdoc->CanUndo()) {
2253*8af74909SZhong Yang 		InvalidateCaret();
2254*8af74909SZhong Yang 		const Sci::Position newPos = pdoc->Undo();
2255*8af74909SZhong Yang 		if (newPos >= 0)
2256*8af74909SZhong Yang 			SetEmptySelection(newPos);
2257*8af74909SZhong Yang 		EnsureCaretVisible();
2258*8af74909SZhong Yang 	}
2259*8af74909SZhong Yang }
2260*8af74909SZhong Yang 
Redo()2261*8af74909SZhong Yang void Editor::Redo() {
2262*8af74909SZhong Yang 	if (pdoc->CanRedo()) {
2263*8af74909SZhong Yang 		const Sci::Position newPos = pdoc->Redo();
2264*8af74909SZhong Yang 		if (newPos >= 0)
2265*8af74909SZhong Yang 			SetEmptySelection(newPos);
2266*8af74909SZhong Yang 		EnsureCaretVisible();
2267*8af74909SZhong Yang 	}
2268*8af74909SZhong Yang }
2269*8af74909SZhong Yang 
DelCharBack(bool allowLineStartDeletion)2270*8af74909SZhong Yang void Editor::DelCharBack(bool allowLineStartDeletion) {
2271*8af74909SZhong Yang 	RefreshStyleData();
2272*8af74909SZhong Yang 	if (!sel.IsRectangular())
2273*8af74909SZhong Yang 		FilterSelections();
2274*8af74909SZhong Yang 	if (sel.IsRectangular())
2275*8af74909SZhong Yang 		allowLineStartDeletion = false;
2276*8af74909SZhong Yang 	UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty());
2277*8af74909SZhong Yang 	if (sel.Empty()) {
2278*8af74909SZhong Yang 		for (size_t r=0; r<sel.Count(); r++) {
2279*8af74909SZhong Yang 			if (!RangeContainsProtected(sel.Range(r).caret.Position() - 1, sel.Range(r).caret.Position())) {
2280*8af74909SZhong Yang 				if (sel.Range(r).caret.VirtualSpace()) {
2281*8af74909SZhong Yang 					sel.Range(r).caret.SetVirtualSpace(sel.Range(r).caret.VirtualSpace() - 1);
2282*8af74909SZhong Yang 					sel.Range(r).anchor.SetVirtualSpace(sel.Range(r).caret.VirtualSpace());
2283*8af74909SZhong Yang 				} else {
2284*8af74909SZhong Yang 					const Sci::Line lineCurrentPos =
2285*8af74909SZhong Yang 						pdoc->SciLineFromPosition(sel.Range(r).caret.Position());
2286*8af74909SZhong Yang 					if (allowLineStartDeletion || (pdoc->LineStart(lineCurrentPos) != sel.Range(r).caret.Position())) {
2287*8af74909SZhong Yang 						if (pdoc->GetColumn(sel.Range(r).caret.Position()) <= pdoc->GetLineIndentation(lineCurrentPos) &&
2288*8af74909SZhong Yang 								pdoc->GetColumn(sel.Range(r).caret.Position()) > 0 && pdoc->backspaceUnindents) {
2289*8af74909SZhong Yang 							UndoGroup ugInner(pdoc, !ug.Needed());
2290*8af74909SZhong Yang 							const int indentation = pdoc->GetLineIndentation(lineCurrentPos);
2291*8af74909SZhong Yang 							const int indentationStep = pdoc->IndentSize();
2292*8af74909SZhong Yang 							int indentationChange = indentation % indentationStep;
2293*8af74909SZhong Yang 							if (indentationChange == 0)
2294*8af74909SZhong Yang 								indentationChange = indentationStep;
2295*8af74909SZhong Yang 							const Sci::Position posSelect = pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationChange);
2296*8af74909SZhong Yang 							// SetEmptySelection
2297*8af74909SZhong Yang 							sel.Range(r) = SelectionRange(posSelect);
2298*8af74909SZhong Yang 						} else {
2299*8af74909SZhong Yang 							pdoc->DelCharBack(sel.Range(r).caret.Position());
2300*8af74909SZhong Yang 						}
2301*8af74909SZhong Yang 					}
2302*8af74909SZhong Yang 				}
2303*8af74909SZhong Yang 			} else {
2304*8af74909SZhong Yang 				sel.Range(r).ClearVirtualSpace();
2305*8af74909SZhong Yang 			}
2306*8af74909SZhong Yang 		}
2307*8af74909SZhong Yang 		ThinRectangularRange();
2308*8af74909SZhong Yang 	} else {
2309*8af74909SZhong Yang 		ClearSelection();
2310*8af74909SZhong Yang 	}
2311*8af74909SZhong Yang 	sel.RemoveDuplicates();
2312*8af74909SZhong Yang 	ContainerNeedsUpdate(SC_UPDATE_SELECTION);
2313*8af74909SZhong Yang 	// Avoid blinking during rapid typing:
2314*8af74909SZhong Yang 	ShowCaretAtCurrentPosition();
2315*8af74909SZhong Yang }
2316*8af74909SZhong Yang 
ModifierFlags(bool shift,bool ctrl,bool alt,bool meta,bool super)2317*8af74909SZhong Yang int Editor::ModifierFlags(bool shift, bool ctrl, bool alt, bool meta, bool super) noexcept {
2318*8af74909SZhong Yang 	return
2319*8af74909SZhong Yang 		(shift ? SCI_SHIFT : 0) |
2320*8af74909SZhong Yang 		(ctrl ? SCI_CTRL : 0) |
2321*8af74909SZhong Yang 		(alt ? SCI_ALT : 0) |
2322*8af74909SZhong Yang 		(meta ? SCI_META : 0) |
2323*8af74909SZhong Yang 		(super ? SCI_SUPER : 0);
2324*8af74909SZhong Yang }
2325*8af74909SZhong Yang 
NotifyFocus(bool focus)2326*8af74909SZhong Yang void Editor::NotifyFocus(bool focus) {
2327*8af74909SZhong Yang 	SCNotification scn = {};
2328*8af74909SZhong Yang 	scn.nmhdr.code = focus ? SCN_FOCUSIN : SCN_FOCUSOUT;
2329*8af74909SZhong Yang 	NotifyParent(scn);
2330*8af74909SZhong Yang }
2331*8af74909SZhong Yang 
SetCtrlID(int identifier)2332*8af74909SZhong Yang void Editor::SetCtrlID(int identifier) {
2333*8af74909SZhong Yang 	ctrlID = identifier;
2334*8af74909SZhong Yang }
2335*8af74909SZhong Yang 
NotifyStyleToNeeded(Sci::Position endStyleNeeded)2336*8af74909SZhong Yang void Editor::NotifyStyleToNeeded(Sci::Position endStyleNeeded) {
2337*8af74909SZhong Yang 	SCNotification scn = {};
2338*8af74909SZhong Yang 	scn.nmhdr.code = SCN_STYLENEEDED;
2339*8af74909SZhong Yang 	scn.position = endStyleNeeded;
2340*8af74909SZhong Yang 	NotifyParent(scn);
2341*8af74909SZhong Yang }
2342*8af74909SZhong Yang 
NotifyStyleNeeded(Document *,void *,Sci::Position endStyleNeeded)2343*8af74909SZhong Yang void Editor::NotifyStyleNeeded(Document *, void *, Sci::Position endStyleNeeded) {
2344*8af74909SZhong Yang 	NotifyStyleToNeeded(endStyleNeeded);
2345*8af74909SZhong Yang }
2346*8af74909SZhong Yang 
NotifyLexerChanged(Document *,void *)2347*8af74909SZhong Yang void Editor::NotifyLexerChanged(Document *, void *) {
2348*8af74909SZhong Yang }
2349*8af74909SZhong Yang 
NotifyErrorOccurred(Document *,void *,int status)2350*8af74909SZhong Yang void Editor::NotifyErrorOccurred(Document *, void *, int status) {
2351*8af74909SZhong Yang 	errorStatus = status;
2352*8af74909SZhong Yang }
2353*8af74909SZhong Yang 
NotifyChar(int ch,CharacterSource charSource)2354*8af74909SZhong Yang void Editor::NotifyChar(int ch, CharacterSource charSource) {
2355*8af74909SZhong Yang 	SCNotification scn = {};
2356*8af74909SZhong Yang 	scn.nmhdr.code = SCN_CHARADDED;
2357*8af74909SZhong Yang 	scn.ch = ch;
2358*8af74909SZhong Yang 	scn.characterSource = static_cast<int>(charSource);
2359*8af74909SZhong Yang 	NotifyParent(scn);
2360*8af74909SZhong Yang }
2361*8af74909SZhong Yang 
NotifySavePoint(bool isSavePoint)2362*8af74909SZhong Yang void Editor::NotifySavePoint(bool isSavePoint) {
2363*8af74909SZhong Yang 	SCNotification scn = {};
2364*8af74909SZhong Yang 	if (isSavePoint) {
2365*8af74909SZhong Yang 		scn.nmhdr.code = SCN_SAVEPOINTREACHED;
2366*8af74909SZhong Yang 	} else {
2367*8af74909SZhong Yang 		scn.nmhdr.code = SCN_SAVEPOINTLEFT;
2368*8af74909SZhong Yang 	}
2369*8af74909SZhong Yang 	NotifyParent(scn);
2370*8af74909SZhong Yang }
2371*8af74909SZhong Yang 
NotifyModifyAttempt()2372*8af74909SZhong Yang void Editor::NotifyModifyAttempt() {
2373*8af74909SZhong Yang 	SCNotification scn = {};
2374*8af74909SZhong Yang 	scn.nmhdr.code = SCN_MODIFYATTEMPTRO;
2375*8af74909SZhong Yang 	NotifyParent(scn);
2376*8af74909SZhong Yang }
2377*8af74909SZhong Yang 
NotifyDoubleClick(Point pt,int modifiers)2378*8af74909SZhong Yang void Editor::NotifyDoubleClick(Point pt, int modifiers) {
2379*8af74909SZhong Yang 	SCNotification scn = {};
2380*8af74909SZhong Yang 	scn.nmhdr.code = SCN_DOUBLECLICK;
2381*8af74909SZhong Yang 	scn.line = LineFromLocation(pt);
2382*8af74909SZhong Yang 	scn.position = PositionFromLocation(pt, true);
2383*8af74909SZhong Yang 	scn.modifiers = modifiers;
2384*8af74909SZhong Yang 	NotifyParent(scn);
2385*8af74909SZhong Yang }
2386*8af74909SZhong Yang 
NotifyHotSpotDoubleClicked(Sci::Position position,int modifiers)2387*8af74909SZhong Yang void Editor::NotifyHotSpotDoubleClicked(Sci::Position position, int modifiers) {
2388*8af74909SZhong Yang 	SCNotification scn = {};
2389*8af74909SZhong Yang 	scn.nmhdr.code = SCN_HOTSPOTDOUBLECLICK;
2390*8af74909SZhong Yang 	scn.position = position;
2391*8af74909SZhong Yang 	scn.modifiers = modifiers;
2392*8af74909SZhong Yang 	NotifyParent(scn);
2393*8af74909SZhong Yang }
2394*8af74909SZhong Yang 
NotifyHotSpotClicked(Sci::Position position,int modifiers)2395*8af74909SZhong Yang void Editor::NotifyHotSpotClicked(Sci::Position position, int modifiers) {
2396*8af74909SZhong Yang 	SCNotification scn = {};
2397*8af74909SZhong Yang 	scn.nmhdr.code = SCN_HOTSPOTCLICK;
2398*8af74909SZhong Yang 	scn.position = position;
2399*8af74909SZhong Yang 	scn.modifiers = modifiers;
2400*8af74909SZhong Yang 	NotifyParent(scn);
2401*8af74909SZhong Yang }
2402*8af74909SZhong Yang 
NotifyHotSpotReleaseClick(Sci::Position position,int modifiers)2403*8af74909SZhong Yang void Editor::NotifyHotSpotReleaseClick(Sci::Position position, int modifiers) {
2404*8af74909SZhong Yang 	SCNotification scn = {};
2405*8af74909SZhong Yang 	scn.nmhdr.code = SCN_HOTSPOTRELEASECLICK;
2406*8af74909SZhong Yang 	scn.position = position;
2407*8af74909SZhong Yang 	scn.modifiers = modifiers;
2408*8af74909SZhong Yang 	NotifyParent(scn);
2409*8af74909SZhong Yang }
2410*8af74909SZhong Yang 
NotifyUpdateUI()2411*8af74909SZhong Yang bool Editor::NotifyUpdateUI() {
2412*8af74909SZhong Yang 	if (needUpdateUI) {
2413*8af74909SZhong Yang 		SCNotification scn = {};
2414*8af74909SZhong Yang 		scn.nmhdr.code = SCN_UPDATEUI;
2415*8af74909SZhong Yang 		scn.updated = needUpdateUI;
2416*8af74909SZhong Yang 		NotifyParent(scn);
2417*8af74909SZhong Yang 		needUpdateUI = 0;
2418*8af74909SZhong Yang 		return true;
2419*8af74909SZhong Yang 	}
2420*8af74909SZhong Yang 	return false;
2421*8af74909SZhong Yang }
2422*8af74909SZhong Yang 
NotifyPainted()2423*8af74909SZhong Yang void Editor::NotifyPainted() {
2424*8af74909SZhong Yang 	SCNotification scn = {};
2425*8af74909SZhong Yang 	scn.nmhdr.code = SCN_PAINTED;
2426*8af74909SZhong Yang 	NotifyParent(scn);
2427*8af74909SZhong Yang }
2428*8af74909SZhong Yang 
NotifyIndicatorClick(bool click,Sci::Position position,int modifiers)2429*8af74909SZhong Yang void Editor::NotifyIndicatorClick(bool click, Sci::Position position, int modifiers) {
2430*8af74909SZhong Yang 	const int mask = pdoc->decorations->AllOnFor(position);
2431*8af74909SZhong Yang 	if ((click && mask) || pdoc->decorations->ClickNotified()) {
2432*8af74909SZhong Yang 		SCNotification scn = {};
2433*8af74909SZhong Yang 		pdoc->decorations->SetClickNotified(click);
2434*8af74909SZhong Yang 		scn.nmhdr.code = click ? SCN_INDICATORCLICK : SCN_INDICATORRELEASE;
2435*8af74909SZhong Yang 		scn.modifiers = modifiers;
2436*8af74909SZhong Yang 		scn.position = position;
2437*8af74909SZhong Yang 		NotifyParent(scn);
2438*8af74909SZhong Yang 	}
2439*8af74909SZhong Yang }
2440*8af74909SZhong Yang 
NotifyMarginClick(Point pt,int modifiers)2441*8af74909SZhong Yang bool Editor::NotifyMarginClick(Point pt, int modifiers) {
2442*8af74909SZhong Yang 	const int marginClicked = vs.MarginFromLocation(pt);
2443*8af74909SZhong Yang 	if ((marginClicked >= 0) && vs.ms[marginClicked].sensitive) {
2444*8af74909SZhong Yang 		const Sci::Position position = pdoc->LineStart(LineFromLocation(pt));
2445*8af74909SZhong Yang 		if ((vs.ms[marginClicked].mask & SC_MASK_FOLDERS) && (foldAutomatic & SC_AUTOMATICFOLD_CLICK)) {
2446*8af74909SZhong Yang 			const bool ctrl = (modifiers & SCI_CTRL) != 0;
2447*8af74909SZhong Yang 			const bool shift = (modifiers & SCI_SHIFT) != 0;
2448*8af74909SZhong Yang 			const Sci::Line lineClick = pdoc->SciLineFromPosition(position);
2449*8af74909SZhong Yang 			if (shift && ctrl) {
2450*8af74909SZhong Yang 				FoldAll(SC_FOLDACTION_TOGGLE);
2451*8af74909SZhong Yang 			} else {
2452*8af74909SZhong Yang 				const int levelClick = pdoc->GetLevel(lineClick);
2453*8af74909SZhong Yang 				if (levelClick & SC_FOLDLEVELHEADERFLAG) {
2454*8af74909SZhong Yang 					if (shift) {
2455*8af74909SZhong Yang 						// Ensure all children visible
2456*8af74909SZhong Yang 						FoldExpand(lineClick, SC_FOLDACTION_EXPAND, levelClick);
2457*8af74909SZhong Yang 					} else if (ctrl) {
2458*8af74909SZhong Yang 						FoldExpand(lineClick, SC_FOLDACTION_TOGGLE, levelClick);
2459*8af74909SZhong Yang 					} else {
2460*8af74909SZhong Yang 						// Toggle this line
2461*8af74909SZhong Yang 						FoldLine(lineClick, SC_FOLDACTION_TOGGLE);
2462*8af74909SZhong Yang 					}
2463*8af74909SZhong Yang 				}
2464*8af74909SZhong Yang 			}
2465*8af74909SZhong Yang 			return true;
2466*8af74909SZhong Yang 		}
2467*8af74909SZhong Yang 		SCNotification scn = {};
2468*8af74909SZhong Yang 		scn.nmhdr.code = SCN_MARGINCLICK;
2469*8af74909SZhong Yang 		scn.modifiers = modifiers;
2470*8af74909SZhong Yang 		scn.position = position;
2471*8af74909SZhong Yang 		scn.margin = marginClicked;
2472*8af74909SZhong Yang 		NotifyParent(scn);
2473*8af74909SZhong Yang 		return true;
2474*8af74909SZhong Yang 	} else {
2475*8af74909SZhong Yang 		return false;
2476*8af74909SZhong Yang 	}
2477*8af74909SZhong Yang }
2478*8af74909SZhong Yang 
NotifyMarginRightClick(Point pt,int modifiers)2479*8af74909SZhong Yang bool Editor::NotifyMarginRightClick(Point pt, int modifiers) {
2480*8af74909SZhong Yang 	const int marginRightClicked = vs.MarginFromLocation(pt);
2481*8af74909SZhong Yang 	if ((marginRightClicked >= 0) && vs.ms[marginRightClicked].sensitive) {
2482*8af74909SZhong Yang 		const Sci::Position position = pdoc->LineStart(LineFromLocation(pt));
2483*8af74909SZhong Yang 		SCNotification scn = {};
2484*8af74909SZhong Yang 		scn.nmhdr.code = SCN_MARGINRIGHTCLICK;
2485*8af74909SZhong Yang 		scn.modifiers = modifiers;
2486*8af74909SZhong Yang 		scn.position = position;
2487*8af74909SZhong Yang 		scn.margin = marginRightClicked;
2488*8af74909SZhong Yang 		NotifyParent(scn);
2489*8af74909SZhong Yang 		return true;
2490*8af74909SZhong Yang 	} else {
2491*8af74909SZhong Yang 		return false;
2492*8af74909SZhong Yang 	}
2493*8af74909SZhong Yang }
2494*8af74909SZhong Yang 
NotifyNeedShown(Sci::Position pos,Sci::Position len)2495*8af74909SZhong Yang void Editor::NotifyNeedShown(Sci::Position pos, Sci::Position len) {
2496*8af74909SZhong Yang 	SCNotification scn = {};
2497*8af74909SZhong Yang 	scn.nmhdr.code = SCN_NEEDSHOWN;
2498*8af74909SZhong Yang 	scn.position = pos;
2499*8af74909SZhong Yang 	scn.length = len;
2500*8af74909SZhong Yang 	NotifyParent(scn);
2501*8af74909SZhong Yang }
2502*8af74909SZhong Yang 
NotifyDwelling(Point pt,bool state)2503*8af74909SZhong Yang void Editor::NotifyDwelling(Point pt, bool state) {
2504*8af74909SZhong Yang 	SCNotification scn = {};
2505*8af74909SZhong Yang 	scn.nmhdr.code = state ? SCN_DWELLSTART : SCN_DWELLEND;
2506*8af74909SZhong Yang 	scn.position = PositionFromLocation(pt, true);
2507*8af74909SZhong Yang 	scn.x = static_cast<int>(pt.x + vs.ExternalMarginWidth());
2508*8af74909SZhong Yang 	scn.y = static_cast<int>(pt.y);
2509*8af74909SZhong Yang 	NotifyParent(scn);
2510*8af74909SZhong Yang }
2511*8af74909SZhong Yang 
NotifyZoom()2512*8af74909SZhong Yang void Editor::NotifyZoom() {
2513*8af74909SZhong Yang 	SCNotification scn = {};
2514*8af74909SZhong Yang 	scn.nmhdr.code = SCN_ZOOM;
2515*8af74909SZhong Yang 	NotifyParent(scn);
2516*8af74909SZhong Yang }
2517*8af74909SZhong Yang 
2518*8af74909SZhong Yang // Notifications from document
NotifyModifyAttempt(Document *,void *)2519*8af74909SZhong Yang void Editor::NotifyModifyAttempt(Document *, void *) {
2520*8af74909SZhong Yang 	//Platform::DebugPrintf("** Modify Attempt\n");
2521*8af74909SZhong Yang 	NotifyModifyAttempt();
2522*8af74909SZhong Yang }
2523*8af74909SZhong Yang 
NotifySavePoint(Document *,void *,bool atSavePoint)2524*8af74909SZhong Yang void Editor::NotifySavePoint(Document *, void *, bool atSavePoint) {
2525*8af74909SZhong Yang 	//Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off");
2526*8af74909SZhong Yang 	NotifySavePoint(atSavePoint);
2527*8af74909SZhong Yang }
2528*8af74909SZhong Yang 
CheckModificationForWrap(DocModification mh)2529*8af74909SZhong Yang void Editor::CheckModificationForWrap(DocModification mh) {
2530*8af74909SZhong Yang 	if (mh.modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) {
2531*8af74909SZhong Yang 		view.llc.Invalidate(LineLayout::ValidLevel::checkTextAndStyle);
2532*8af74909SZhong Yang 		const Sci::Line lineDoc = pdoc->SciLineFromPosition(mh.position);
2533*8af74909SZhong Yang 		const Sci::Line lines = std::max(static_cast<Sci::Line>(0), mh.linesAdded);
2534*8af74909SZhong Yang 		if (Wrapping()) {
2535*8af74909SZhong Yang 			NeedWrapping(lineDoc, lineDoc + lines + 1);
2536*8af74909SZhong Yang 		}
2537*8af74909SZhong Yang 		RefreshStyleData();
2538*8af74909SZhong Yang 		// Fix up annotation heights
2539*8af74909SZhong Yang 		SetAnnotationHeights(lineDoc, lineDoc + lines + 2);
2540*8af74909SZhong Yang 	}
2541*8af74909SZhong Yang }
2542*8af74909SZhong Yang 
2543*8af74909SZhong Yang namespace {
2544*8af74909SZhong Yang 
2545*8af74909SZhong Yang // Move a position so it is still after the same character as before the insertion.
MovePositionForInsertion(Sci::Position position,Sci::Position startInsertion,Sci::Position length)2546*8af74909SZhong Yang constexpr Sci::Position MovePositionForInsertion(Sci::Position position, Sci::Position startInsertion, Sci::Position length) noexcept {
2547*8af74909SZhong Yang 	if (position > startInsertion) {
2548*8af74909SZhong Yang 		return position + length;
2549*8af74909SZhong Yang 	}
2550*8af74909SZhong Yang 	return position;
2551*8af74909SZhong Yang }
2552*8af74909SZhong Yang 
2553*8af74909SZhong Yang // Move a position so it is still after the same character as before the deletion if that
2554*8af74909SZhong Yang // character is still present else after the previous surviving character.
MovePositionForDeletion(Sci::Position position,Sci::Position startDeletion,Sci::Position length)2555*8af74909SZhong Yang constexpr Sci::Position MovePositionForDeletion(Sci::Position position, Sci::Position startDeletion, Sci::Position length) noexcept {
2556*8af74909SZhong Yang 	if (position > startDeletion) {
2557*8af74909SZhong Yang 		const Sci::Position endDeletion = startDeletion + length;
2558*8af74909SZhong Yang 		if (position > endDeletion) {
2559*8af74909SZhong Yang 			return position - length;
2560*8af74909SZhong Yang 		} else {
2561*8af74909SZhong Yang 			return startDeletion;
2562*8af74909SZhong Yang 		}
2563*8af74909SZhong Yang 	} else {
2564*8af74909SZhong Yang 		return position;
2565*8af74909SZhong Yang 	}
2566*8af74909SZhong Yang }
2567*8af74909SZhong Yang 
2568*8af74909SZhong Yang }
2569*8af74909SZhong Yang 
NotifyModified(Document *,DocModification mh,void *)2570*8af74909SZhong Yang void Editor::NotifyModified(Document *, DocModification mh, void *) {
2571*8af74909SZhong Yang 	ContainerNeedsUpdate(SC_UPDATE_CONTENT);
2572*8af74909SZhong Yang 	if (paintState == painting) {
2573*8af74909SZhong Yang 		CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length));
2574*8af74909SZhong Yang 	}
2575*8af74909SZhong Yang 	if (mh.modificationType & SC_MOD_CHANGELINESTATE) {
2576*8af74909SZhong Yang 		if (paintState == painting) {
2577*8af74909SZhong Yang 			CheckForChangeOutsidePaint(
2578*8af74909SZhong Yang 			    Range(pdoc->LineStart(mh.line),
2579*8af74909SZhong Yang 					pdoc->LineStart(mh.line + 1)));
2580*8af74909SZhong Yang 		} else {
2581*8af74909SZhong Yang 			// Could check that change is before last visible line.
2582*8af74909SZhong Yang 			Redraw();
2583*8af74909SZhong Yang 		}
2584*8af74909SZhong Yang 	}
2585*8af74909SZhong Yang 	if (mh.modificationType & SC_MOD_CHANGETABSTOPS) {
2586*8af74909SZhong Yang 		Redraw();
2587*8af74909SZhong Yang 	}
2588*8af74909SZhong Yang 	if (mh.modificationType & SC_MOD_LEXERSTATE) {
2589*8af74909SZhong Yang 		if (paintState == painting) {
2590*8af74909SZhong Yang 			CheckForChangeOutsidePaint(
2591*8af74909SZhong Yang 			    Range(mh.position, mh.position + mh.length));
2592*8af74909SZhong Yang 		} else {
2593*8af74909SZhong Yang 			Redraw();
2594*8af74909SZhong Yang 		}
2595*8af74909SZhong Yang 	}
2596*8af74909SZhong Yang 	if (mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) {
2597*8af74909SZhong Yang 		if (mh.modificationType & SC_MOD_CHANGESTYLE) {
2598*8af74909SZhong Yang 			pdoc->IncrementStyleClock();
2599*8af74909SZhong Yang 		}
2600*8af74909SZhong Yang 		if (paintState == notPainting) {
2601*8af74909SZhong Yang 			const Sci::Line lineDocTop = pcs->DocFromDisplay(topLine);
2602*8af74909SZhong Yang 			if (mh.position < pdoc->LineStart(lineDocTop)) {
2603*8af74909SZhong Yang 				// Styling performed before this view
2604*8af74909SZhong Yang 				Redraw();
2605*8af74909SZhong Yang 			} else {
2606*8af74909SZhong Yang 				InvalidateRange(mh.position, mh.position + mh.length);
2607*8af74909SZhong Yang 			}
2608*8af74909SZhong Yang 		}
2609*8af74909SZhong Yang 		if (mh.modificationType & SC_MOD_CHANGESTYLE) {
2610*8af74909SZhong Yang 			view.llc.Invalidate(LineLayout::ValidLevel::checkTextAndStyle);
2611*8af74909SZhong Yang 		}
2612*8af74909SZhong Yang 	} else {
2613*8af74909SZhong Yang 		// Move selection and brace highlights
2614*8af74909SZhong Yang 		if (mh.modificationType & SC_MOD_INSERTTEXT) {
2615*8af74909SZhong Yang 			sel.MovePositions(true, mh.position, mh.length);
2616*8af74909SZhong Yang 			braces[0] = MovePositionForInsertion(braces[0], mh.position, mh.length);
2617*8af74909SZhong Yang 			braces[1] = MovePositionForInsertion(braces[1], mh.position, mh.length);
2618*8af74909SZhong Yang 		} else if (mh.modificationType & SC_MOD_DELETETEXT) {
2619*8af74909SZhong Yang 			sel.MovePositions(false, mh.position, mh.length);
2620*8af74909SZhong Yang 			braces[0] = MovePositionForDeletion(braces[0], mh.position, mh.length);
2621*8af74909SZhong Yang 			braces[1] = MovePositionForDeletion(braces[1], mh.position, mh.length);
2622*8af74909SZhong Yang 		}
2623*8af74909SZhong Yang 		if ((mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) && pcs->HiddenLines()) {
2624*8af74909SZhong Yang 			// Some lines are hidden so may need shown.
2625*8af74909SZhong Yang 			const Sci::Line lineOfPos = pdoc->SciLineFromPosition(mh.position);
2626*8af74909SZhong Yang 			Sci::Position endNeedShown = mh.position;
2627*8af74909SZhong Yang 			if (mh.modificationType & SC_MOD_BEFOREINSERT) {
2628*8af74909SZhong Yang 				if (pdoc->ContainsLineEnd(mh.text, mh.length) && (mh.position != pdoc->LineStart(lineOfPos)))
2629*8af74909SZhong Yang 					endNeedShown = pdoc->LineStart(lineOfPos+1);
2630*8af74909SZhong Yang 			} else if (mh.modificationType & SC_MOD_BEFOREDELETE) {
2631*8af74909SZhong Yang 				// If the deletion includes any EOL then we extend the need shown area.
2632*8af74909SZhong Yang 				endNeedShown = mh.position + mh.length;
2633*8af74909SZhong Yang 				Sci::Line lineLast = pdoc->SciLineFromPosition(mh.position+mh.length);
2634*8af74909SZhong Yang 				for (Sci::Line line = lineOfPos + 1; line <= lineLast; line++) {
2635*8af74909SZhong Yang 					const Sci::Line lineMaxSubord = pdoc->GetLastChild(line, -1, -1);
2636*8af74909SZhong Yang 					if (lineLast < lineMaxSubord) {
2637*8af74909SZhong Yang 						lineLast = lineMaxSubord;
2638*8af74909SZhong Yang 						endNeedShown = pdoc->LineEnd(lineLast);
2639*8af74909SZhong Yang 					}
2640*8af74909SZhong Yang 				}
2641*8af74909SZhong Yang 			}
2642*8af74909SZhong Yang 			NeedShown(mh.position, endNeedShown - mh.position);
2643*8af74909SZhong Yang 		}
2644*8af74909SZhong Yang 		if (mh.linesAdded != 0) {
2645*8af74909SZhong Yang 			// Update contraction state for inserted and removed lines
2646*8af74909SZhong Yang 			// lineOfPos should be calculated in context of state before modification, shouldn't it
2647*8af74909SZhong Yang 			Sci::Line lineOfPos = pdoc->SciLineFromPosition(mh.position);
2648*8af74909SZhong Yang 			if (mh.position > pdoc->LineStart(lineOfPos))
2649*8af74909SZhong Yang 				lineOfPos++;	// Affecting subsequent lines
2650*8af74909SZhong Yang 			if (mh.linesAdded > 0) {
2651*8af74909SZhong Yang 				pcs->InsertLines(lineOfPos, mh.linesAdded);
2652*8af74909SZhong Yang 			} else {
2653*8af74909SZhong Yang 				pcs->DeleteLines(lineOfPos, -mh.linesAdded);
2654*8af74909SZhong Yang 			}
2655*8af74909SZhong Yang 			view.LinesAddedOrRemoved(lineOfPos, mh.linesAdded);
2656*8af74909SZhong Yang 		}
2657*8af74909SZhong Yang 		if (mh.modificationType & SC_MOD_CHANGEANNOTATION) {
2658*8af74909SZhong Yang 			const Sci::Line lineDoc = pdoc->SciLineFromPosition(mh.position);
2659*8af74909SZhong Yang 			if (vs.annotationVisible) {
2660*8af74909SZhong Yang 				if (pcs->SetHeight(lineDoc, pcs->GetHeight(lineDoc) + static_cast<int>(mh.annotationLinesAdded))) {
2661*8af74909SZhong Yang 					SetScrollBars();
2662*8af74909SZhong Yang 				}
2663*8af74909SZhong Yang 				Redraw();
2664*8af74909SZhong Yang 			}
2665*8af74909SZhong Yang 		}
2666*8af74909SZhong Yang 		if (mh.modificationType & SC_MOD_CHANGEEOLANNOTATION) {
2667*8af74909SZhong Yang 			if (vs.eolAnnotationVisible) {
2668*8af74909SZhong Yang 				Redraw();
2669*8af74909SZhong Yang 			}
2670*8af74909SZhong Yang 		}
2671*8af74909SZhong Yang 		CheckModificationForWrap(mh);
2672*8af74909SZhong Yang 		if (mh.linesAdded != 0) {
2673*8af74909SZhong Yang 			// Avoid scrolling of display if change before current display
2674*8af74909SZhong Yang 			if (mh.position < posTopLine && !CanDeferToLastStep(mh)) {
2675*8af74909SZhong Yang 				const Sci::Line newTop = std::clamp<Sci::Line>(topLine + mh.linesAdded, 0, MaxScrollPos());
2676*8af74909SZhong Yang 				if (newTop != topLine) {
2677*8af74909SZhong Yang 					SetTopLine(newTop);
2678*8af74909SZhong Yang 					SetVerticalScrollPos();
2679*8af74909SZhong Yang 				}
2680*8af74909SZhong Yang 			}
2681*8af74909SZhong Yang 
2682*8af74909SZhong Yang 			if (paintState == notPainting && !CanDeferToLastStep(mh)) {
2683*8af74909SZhong Yang 				if (SynchronousStylingToVisible()) {
2684*8af74909SZhong Yang 					QueueIdleWork(WorkNeeded::workStyle, pdoc->Length());
2685*8af74909SZhong Yang 				}
2686*8af74909SZhong Yang 				Redraw();
2687*8af74909SZhong Yang 			}
2688*8af74909SZhong Yang 		} else {
2689*8af74909SZhong Yang 			if (paintState == notPainting && mh.length && !CanEliminate(mh)) {
2690*8af74909SZhong Yang 				if (SynchronousStylingToVisible()) {
2691*8af74909SZhong Yang 					QueueIdleWork(WorkNeeded::workStyle, mh.position + mh.length);
2692*8af74909SZhong Yang 				}
2693*8af74909SZhong Yang 				InvalidateRange(mh.position, mh.position + mh.length);
2694*8af74909SZhong Yang 			}
2695*8af74909SZhong Yang 		}
2696*8af74909SZhong Yang 	}
2697*8af74909SZhong Yang 
2698*8af74909SZhong Yang 	if (mh.linesAdded != 0 && !CanDeferToLastStep(mh)) {
2699*8af74909SZhong Yang 		SetScrollBars();
2700*8af74909SZhong Yang 	}
2701*8af74909SZhong Yang 
2702*8af74909SZhong Yang 	if ((mh.modificationType & SC_MOD_CHANGEMARKER) || (mh.modificationType & SC_MOD_CHANGEMARGIN)) {
2703*8af74909SZhong Yang 		if ((!willRedrawAll) && ((paintState == notPainting) || !PaintContainsMargin())) {
2704*8af74909SZhong Yang 			if (mh.modificationType & SC_MOD_CHANGEFOLD) {
2705*8af74909SZhong Yang 				// Fold changes can affect the drawing of following lines so redraw whole margin
2706*8af74909SZhong Yang 				RedrawSelMargin(marginView.highlightDelimiter.isEnabled ? -1 : mh.line - 1, true);
2707*8af74909SZhong Yang 			} else {
2708*8af74909SZhong Yang 				RedrawSelMargin(mh.line);
2709*8af74909SZhong Yang 			}
2710*8af74909SZhong Yang 		}
2711*8af74909SZhong Yang 	}
2712*8af74909SZhong Yang 	if ((mh.modificationType & SC_MOD_CHANGEFOLD) && (foldAutomatic & SC_AUTOMATICFOLD_CHANGE)) {
2713*8af74909SZhong Yang 		FoldChanged(mh.line, mh.foldLevelNow, mh.foldLevelPrev);
2714*8af74909SZhong Yang 	}
2715*8af74909SZhong Yang 
2716*8af74909SZhong Yang 	// NOW pay the piper WRT "deferred" visual updates
2717*8af74909SZhong Yang 	if (IsLastStep(mh)) {
2718*8af74909SZhong Yang 		SetScrollBars();
2719*8af74909SZhong Yang 		Redraw();
2720*8af74909SZhong Yang 	}
2721*8af74909SZhong Yang 
2722*8af74909SZhong Yang 	// If client wants to see this modification
2723*8af74909SZhong Yang 	if (mh.modificationType & modEventMask) {
2724*8af74909SZhong Yang 		if (commandEvents) {
2725*8af74909SZhong Yang 			if ((mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) == 0) {
2726*8af74909SZhong Yang 				// Real modification made to text of document.
2727*8af74909SZhong Yang 				NotifyChange();	// Send EN_CHANGE
2728*8af74909SZhong Yang 			}
2729*8af74909SZhong Yang 		}
2730*8af74909SZhong Yang 
2731*8af74909SZhong Yang 		SCNotification scn = {};
2732*8af74909SZhong Yang 		scn.nmhdr.code = SCN_MODIFIED;
2733*8af74909SZhong Yang 		scn.position = mh.position;
2734*8af74909SZhong Yang 		scn.modificationType = mh.modificationType;
2735*8af74909SZhong Yang 		scn.text = mh.text;
2736*8af74909SZhong Yang 		scn.length = mh.length;
2737*8af74909SZhong Yang 		scn.linesAdded = mh.linesAdded;
2738*8af74909SZhong Yang 		scn.line = mh.line;
2739*8af74909SZhong Yang 		scn.foldLevelNow = mh.foldLevelNow;
2740*8af74909SZhong Yang 		scn.foldLevelPrev = mh.foldLevelPrev;
2741*8af74909SZhong Yang 		scn.token = static_cast<int>(mh.token);
2742*8af74909SZhong Yang 		scn.annotationLinesAdded = mh.annotationLinesAdded;
2743*8af74909SZhong Yang 		NotifyParent(scn);
2744*8af74909SZhong Yang 	}
2745*8af74909SZhong Yang }
2746*8af74909SZhong Yang 
NotifyDeleted(Document *,void *)2747*8af74909SZhong Yang void Editor::NotifyDeleted(Document *, void *) noexcept {
2748*8af74909SZhong Yang 	/* Do nothing */
2749*8af74909SZhong Yang }
2750*8af74909SZhong Yang 
NotifyMacroRecord(unsigned int iMessage,uptr_t wParam,sptr_t lParam)2751*8af74909SZhong Yang void Editor::NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
2752*8af74909SZhong Yang 
2753*8af74909SZhong Yang 	// Enumerates all macroable messages
2754*8af74909SZhong Yang 	switch (iMessage) {
2755*8af74909SZhong Yang 	case SCI_CUT:
2756*8af74909SZhong Yang 	case SCI_COPY:
2757*8af74909SZhong Yang 	case SCI_PASTE:
2758*8af74909SZhong Yang 	case SCI_CLEAR:
2759*8af74909SZhong Yang 	case SCI_REPLACESEL:
2760*8af74909SZhong Yang 	case SCI_ADDTEXT:
2761*8af74909SZhong Yang 	case SCI_INSERTTEXT:
2762*8af74909SZhong Yang 	case SCI_APPENDTEXT:
2763*8af74909SZhong Yang 	case SCI_CLEARALL:
2764*8af74909SZhong Yang 	case SCI_SELECTALL:
2765*8af74909SZhong Yang 	case SCI_GOTOLINE:
2766*8af74909SZhong Yang 	case SCI_GOTOPOS:
2767*8af74909SZhong Yang 	case SCI_SEARCHANCHOR:
2768*8af74909SZhong Yang 	case SCI_SEARCHNEXT:
2769*8af74909SZhong Yang 	case SCI_SEARCHPREV:
2770*8af74909SZhong Yang 	case SCI_LINEDOWN:
2771*8af74909SZhong Yang 	case SCI_LINEDOWNEXTEND:
2772*8af74909SZhong Yang 	case SCI_PARADOWN:
2773*8af74909SZhong Yang 	case SCI_PARADOWNEXTEND:
2774*8af74909SZhong Yang 	case SCI_LINEUP:
2775*8af74909SZhong Yang 	case SCI_LINEUPEXTEND:
2776*8af74909SZhong Yang 	case SCI_PARAUP:
2777*8af74909SZhong Yang 	case SCI_PARAUPEXTEND:
2778*8af74909SZhong Yang 	case SCI_CHARLEFT:
2779*8af74909SZhong Yang 	case SCI_CHARLEFTEXTEND:
2780*8af74909SZhong Yang 	case SCI_CHARRIGHT:
2781*8af74909SZhong Yang 	case SCI_CHARRIGHTEXTEND:
2782*8af74909SZhong Yang 	case SCI_WORDLEFT:
2783*8af74909SZhong Yang 	case SCI_WORDLEFTEXTEND:
2784*8af74909SZhong Yang 	case SCI_WORDRIGHT:
2785*8af74909SZhong Yang 	case SCI_WORDRIGHTEXTEND:
2786*8af74909SZhong Yang 	case SCI_WORDPARTLEFT:
2787*8af74909SZhong Yang 	case SCI_WORDPARTLEFTEXTEND:
2788*8af74909SZhong Yang 	case SCI_WORDPARTRIGHT:
2789*8af74909SZhong Yang 	case SCI_WORDPARTRIGHTEXTEND:
2790*8af74909SZhong Yang 	case SCI_WORDLEFTEND:
2791*8af74909SZhong Yang 	case SCI_WORDLEFTENDEXTEND:
2792*8af74909SZhong Yang 	case SCI_WORDRIGHTEND:
2793*8af74909SZhong Yang 	case SCI_WORDRIGHTENDEXTEND:
2794*8af74909SZhong Yang 	case SCI_HOME:
2795*8af74909SZhong Yang 	case SCI_HOMEEXTEND:
2796*8af74909SZhong Yang 	case SCI_LINEEND:
2797*8af74909SZhong Yang 	case SCI_LINEENDEXTEND:
2798*8af74909SZhong Yang 	case SCI_HOMEWRAP:
2799*8af74909SZhong Yang 	case SCI_HOMEWRAPEXTEND:
2800*8af74909SZhong Yang 	case SCI_LINEENDWRAP:
2801*8af74909SZhong Yang 	case SCI_LINEENDWRAPEXTEND:
2802*8af74909SZhong Yang 	case SCI_DOCUMENTSTART:
2803*8af74909SZhong Yang 	case SCI_DOCUMENTSTARTEXTEND:
2804*8af74909SZhong Yang 	case SCI_DOCUMENTEND:
2805*8af74909SZhong Yang 	case SCI_DOCUMENTENDEXTEND:
2806*8af74909SZhong Yang 	case SCI_STUTTEREDPAGEUP:
2807*8af74909SZhong Yang 	case SCI_STUTTEREDPAGEUPEXTEND:
2808*8af74909SZhong Yang 	case SCI_STUTTEREDPAGEDOWN:
2809*8af74909SZhong Yang 	case SCI_STUTTEREDPAGEDOWNEXTEND:
2810*8af74909SZhong Yang 	case SCI_PAGEUP:
2811*8af74909SZhong Yang 	case SCI_PAGEUPEXTEND:
2812*8af74909SZhong Yang 	case SCI_PAGEDOWN:
2813*8af74909SZhong Yang 	case SCI_PAGEDOWNEXTEND:
2814*8af74909SZhong Yang 	case SCI_EDITTOGGLEOVERTYPE:
2815*8af74909SZhong Yang 	case SCI_CANCEL:
2816*8af74909SZhong Yang 	case SCI_DELETEBACK:
2817*8af74909SZhong Yang 	case SCI_TAB:
2818*8af74909SZhong Yang 	case SCI_BACKTAB:
2819*8af74909SZhong Yang 	case SCI_FORMFEED:
2820*8af74909SZhong Yang 	case SCI_VCHOME:
2821*8af74909SZhong Yang 	case SCI_VCHOMEEXTEND:
2822*8af74909SZhong Yang 	case SCI_VCHOMEWRAP:
2823*8af74909SZhong Yang 	case SCI_VCHOMEWRAPEXTEND:
2824*8af74909SZhong Yang 	case SCI_VCHOMEDISPLAY:
2825*8af74909SZhong Yang 	case SCI_VCHOMEDISPLAYEXTEND:
2826*8af74909SZhong Yang 	case SCI_DELWORDLEFT:
2827*8af74909SZhong Yang 	case SCI_DELWORDRIGHT:
2828*8af74909SZhong Yang 	case SCI_DELWORDRIGHTEND:
2829*8af74909SZhong Yang 	case SCI_DELLINELEFT:
2830*8af74909SZhong Yang 	case SCI_DELLINERIGHT:
2831*8af74909SZhong Yang 	case SCI_LINECOPY:
2832*8af74909SZhong Yang 	case SCI_LINECUT:
2833*8af74909SZhong Yang 	case SCI_LINEDELETE:
2834*8af74909SZhong Yang 	case SCI_LINETRANSPOSE:
2835*8af74909SZhong Yang 	case SCI_LINEREVERSE:
2836*8af74909SZhong Yang 	case SCI_LINEDUPLICATE:
2837*8af74909SZhong Yang 	case SCI_LOWERCASE:
2838*8af74909SZhong Yang 	case SCI_UPPERCASE:
2839*8af74909SZhong Yang 	case SCI_LINESCROLLDOWN:
2840*8af74909SZhong Yang 	case SCI_LINESCROLLUP:
2841*8af74909SZhong Yang 	case SCI_DELETEBACKNOTLINE:
2842*8af74909SZhong Yang 	case SCI_HOMEDISPLAY:
2843*8af74909SZhong Yang 	case SCI_HOMEDISPLAYEXTEND:
2844*8af74909SZhong Yang 	case SCI_LINEENDDISPLAY:
2845*8af74909SZhong Yang 	case SCI_LINEENDDISPLAYEXTEND:
2846*8af74909SZhong Yang 	case SCI_SETSELECTIONMODE:
2847*8af74909SZhong Yang 	case SCI_LINEDOWNRECTEXTEND:
2848*8af74909SZhong Yang 	case SCI_LINEUPRECTEXTEND:
2849*8af74909SZhong Yang 	case SCI_CHARLEFTRECTEXTEND:
2850*8af74909SZhong Yang 	case SCI_CHARRIGHTRECTEXTEND:
2851*8af74909SZhong Yang 	case SCI_HOMERECTEXTEND:
2852*8af74909SZhong Yang 	case SCI_VCHOMERECTEXTEND:
2853*8af74909SZhong Yang 	case SCI_LINEENDRECTEXTEND:
2854*8af74909SZhong Yang 	case SCI_PAGEUPRECTEXTEND:
2855*8af74909SZhong Yang 	case SCI_PAGEDOWNRECTEXTEND:
2856*8af74909SZhong Yang 	case SCI_SELECTIONDUPLICATE:
2857*8af74909SZhong Yang 	case SCI_COPYALLOWLINE:
2858*8af74909SZhong Yang 	case SCI_VERTICALCENTRECARET:
2859*8af74909SZhong Yang 	case SCI_MOVESELECTEDLINESUP:
2860*8af74909SZhong Yang 	case SCI_MOVESELECTEDLINESDOWN:
2861*8af74909SZhong Yang 	case SCI_SCROLLTOSTART:
2862*8af74909SZhong Yang 	case SCI_SCROLLTOEND:
2863*8af74909SZhong Yang 		break;
2864*8af74909SZhong Yang 
2865*8af74909SZhong Yang 		// Filter out all others like display changes. Also, newlines are redundant
2866*8af74909SZhong Yang 		// with char insert messages.
2867*8af74909SZhong Yang 	case SCI_NEWLINE:
2868*8af74909SZhong Yang 	default:
2869*8af74909SZhong Yang 		//		printf("Filtered out %ld of macro recording\n", iMessage);
2870*8af74909SZhong Yang 		return;
2871*8af74909SZhong Yang 	}
2872*8af74909SZhong Yang 
2873*8af74909SZhong Yang 	// Send notification
2874*8af74909SZhong Yang 	SCNotification scn = {};
2875*8af74909SZhong Yang 	scn.nmhdr.code = SCN_MACRORECORD;
2876*8af74909SZhong Yang 	scn.message = iMessage;
2877*8af74909SZhong Yang 	scn.wParam = wParam;
2878*8af74909SZhong Yang 	scn.lParam = lParam;
2879*8af74909SZhong Yang 	NotifyParent(scn);
2880*8af74909SZhong Yang }
2881*8af74909SZhong Yang 
2882*8af74909SZhong Yang // Something has changed that the container should know about
ContainerNeedsUpdate(int flags)2883*8af74909SZhong Yang void Editor::ContainerNeedsUpdate(int flags) noexcept {
2884*8af74909SZhong Yang 	needUpdateUI |= flags;
2885*8af74909SZhong Yang }
2886*8af74909SZhong Yang 
2887*8af74909SZhong Yang /**
2888*8af74909SZhong Yang  * Force scroll and keep position relative to top of window.
2889*8af74909SZhong Yang  *
2890*8af74909SZhong Yang  * If stuttered = true and not already at first/last row, move to first/last row of window.
2891*8af74909SZhong Yang  * If stuttered = true and already at first/last row, scroll as normal.
2892*8af74909SZhong Yang  */
PageMove(int direction,Selection::selTypes selt,bool stuttered)2893*8af74909SZhong Yang void Editor::PageMove(int direction, Selection::selTypes selt, bool stuttered) {
2894*8af74909SZhong Yang 	Sci::Line topLineNew;
2895*8af74909SZhong Yang 	SelectionPosition newPos;
2896*8af74909SZhong Yang 
2897*8af74909SZhong Yang 	const Sci::Line currentLine = pdoc->SciLineFromPosition(sel.MainCaret());
2898*8af74909SZhong Yang 	const Sci::Line topStutterLine = topLine + caretPolicies.y.slop;
2899*8af74909SZhong Yang 	const Sci::Line bottomStutterLine =
2900*8af74909SZhong Yang 	    pdoc->SciLineFromPosition(PositionFromLocation(
2901*8af74909SZhong Yang 	                Point::FromInts(lastXChosen - xOffset, direction * vs.lineHeight * static_cast<int>(LinesToScroll()))))
2902*8af74909SZhong Yang 	    - caretPolicies.y.slop - 1;
2903*8af74909SZhong Yang 
2904*8af74909SZhong Yang 	if (stuttered && (direction < 0 && currentLine > topStutterLine)) {
2905*8af74909SZhong Yang 		topLineNew = topLine;
2906*8af74909SZhong Yang 		newPos = SPositionFromLocation(Point::FromInts(lastXChosen - xOffset, vs.lineHeight * caretPolicies.y.slop),
2907*8af74909SZhong Yang 			false, false, UserVirtualSpace());
2908*8af74909SZhong Yang 
2909*8af74909SZhong Yang 	} else if (stuttered && (direction > 0 && currentLine < bottomStutterLine)) {
2910*8af74909SZhong Yang 		topLineNew = topLine;
2911*8af74909SZhong Yang 		newPos = SPositionFromLocation(Point::FromInts(lastXChosen - xOffset, vs.lineHeight * static_cast<int>(LinesToScroll() - caretPolicies.y.slop)),
2912*8af74909SZhong Yang 			false, false, UserVirtualSpace());
2913*8af74909SZhong Yang 
2914*8af74909SZhong Yang 	} else {
2915*8af74909SZhong Yang 		const Point pt = LocationFromPosition(sel.MainCaret());
2916*8af74909SZhong Yang 
2917*8af74909SZhong Yang 		topLineNew = std::clamp<Sci::Line>(
2918*8af74909SZhong Yang 		            topLine + direction * LinesToScroll(), 0, MaxScrollPos());
2919*8af74909SZhong Yang 		newPos = SPositionFromLocation(
2920*8af74909SZhong Yang 			Point::FromInts(lastXChosen - xOffset, static_cast<int>(pt.y) +
2921*8af74909SZhong Yang 				direction * (vs.lineHeight * static_cast<int>(LinesToScroll()))),
2922*8af74909SZhong Yang 			false, false, UserVirtualSpace());
2923*8af74909SZhong Yang 	}
2924*8af74909SZhong Yang 
2925*8af74909SZhong Yang 	if (topLineNew != topLine) {
2926*8af74909SZhong Yang 		SetTopLine(topLineNew);
2927*8af74909SZhong Yang 		MovePositionTo(newPos, selt);
2928*8af74909SZhong Yang 		Redraw();
2929*8af74909SZhong Yang 		SetVerticalScrollPos();
2930*8af74909SZhong Yang 	} else {
2931*8af74909SZhong Yang 		MovePositionTo(newPos, selt);
2932*8af74909SZhong Yang 	}
2933*8af74909SZhong Yang }
2934*8af74909SZhong Yang 
ChangeCaseOfSelection(int caseMapping)2935*8af74909SZhong Yang void Editor::ChangeCaseOfSelection(int caseMapping) {
2936*8af74909SZhong Yang 	UndoGroup ug(pdoc);
2937*8af74909SZhong Yang 	for (size_t r=0; r<sel.Count(); r++) {
2938*8af74909SZhong Yang 		SelectionRange current = sel.Range(r);
2939*8af74909SZhong Yang 		SelectionRange currentNoVS = current;
2940*8af74909SZhong Yang 		currentNoVS.ClearVirtualSpace();
2941*8af74909SZhong Yang 		const size_t rangeBytes = currentNoVS.Length();
2942*8af74909SZhong Yang 		if (rangeBytes > 0) {
2943*8af74909SZhong Yang 			std::string sText = RangeText(currentNoVS.Start().Position(), currentNoVS.End().Position());
2944*8af74909SZhong Yang 
2945*8af74909SZhong Yang 			std::string sMapped = CaseMapString(sText, caseMapping);
2946*8af74909SZhong Yang 
2947*8af74909SZhong Yang 			if (sMapped != sText) {
2948*8af74909SZhong Yang 				size_t firstDifference = 0;
2949*8af74909SZhong Yang 				while (sMapped[firstDifference] == sText[firstDifference])
2950*8af74909SZhong Yang 					firstDifference++;
2951*8af74909SZhong Yang 				size_t lastDifferenceText = sText.size() - 1;
2952*8af74909SZhong Yang 				size_t lastDifferenceMapped = sMapped.size() - 1;
2953*8af74909SZhong Yang 				while (sMapped[lastDifferenceMapped] == sText[lastDifferenceText]) {
2954*8af74909SZhong Yang 					lastDifferenceText--;
2955*8af74909SZhong Yang 					lastDifferenceMapped--;
2956*8af74909SZhong Yang 				}
2957*8af74909SZhong Yang 				const size_t endDifferenceText = sText.size() - 1 - lastDifferenceText;
2958*8af74909SZhong Yang 				pdoc->DeleteChars(
2959*8af74909SZhong Yang 					currentNoVS.Start().Position() + firstDifference,
2960*8af74909SZhong Yang 					rangeBytes - firstDifference - endDifferenceText);
2961*8af74909SZhong Yang 				const Sci::Position lengthChange = lastDifferenceMapped - firstDifference + 1;
2962*8af74909SZhong Yang 				const Sci::Position lengthInserted = pdoc->InsertString(
2963*8af74909SZhong Yang 					currentNoVS.Start().Position() + firstDifference,
2964*8af74909SZhong Yang 					sMapped.c_str() + firstDifference,
2965*8af74909SZhong Yang 					lengthChange);
2966*8af74909SZhong Yang 				// Automatic movement changes selection so reset to exactly the same as it was.
2967*8af74909SZhong Yang 				const Sci::Position diffSizes = sMapped.size() - sText.size() + lengthInserted - lengthChange;
2968*8af74909SZhong Yang 				if (diffSizes != 0) {
2969*8af74909SZhong Yang 					if (current.anchor > current.caret)
2970*8af74909SZhong Yang 						current.anchor.Add(diffSizes);
2971*8af74909SZhong Yang 					else
2972*8af74909SZhong Yang 						current.caret.Add(diffSizes);
2973*8af74909SZhong Yang 				}
2974*8af74909SZhong Yang 				sel.Range(r) = current;
2975*8af74909SZhong Yang 			}
2976*8af74909SZhong Yang 		}
2977*8af74909SZhong Yang 	}
2978*8af74909SZhong Yang }
2979*8af74909SZhong Yang 
LineTranspose()2980*8af74909SZhong Yang void Editor::LineTranspose() {
2981*8af74909SZhong Yang 	const Sci::Line line = pdoc->SciLineFromPosition(sel.MainCaret());
2982*8af74909SZhong Yang 	if (line > 0) {
2983*8af74909SZhong Yang 		UndoGroup ug(pdoc);
2984*8af74909SZhong Yang 
2985*8af74909SZhong Yang 		const Sci::Position startPrevious = pdoc->LineStart(line - 1);
2986*8af74909SZhong Yang 		const std::string linePrevious = RangeText(startPrevious, pdoc->LineEnd(line - 1));
2987*8af74909SZhong Yang 
2988*8af74909SZhong Yang 		Sci::Position startCurrent = pdoc->LineStart(line);
2989*8af74909SZhong Yang 		const std::string lineCurrent = RangeText(startCurrent, pdoc->LineEnd(line));
2990*8af74909SZhong Yang 
2991*8af74909SZhong Yang 		pdoc->DeleteChars(startCurrent, lineCurrent.length());
2992*8af74909SZhong Yang 		pdoc->DeleteChars(startPrevious, linePrevious.length());
2993*8af74909SZhong Yang 		startCurrent -= linePrevious.length();
2994*8af74909SZhong Yang 
2995*8af74909SZhong Yang 		startCurrent += pdoc->InsertString(startPrevious, lineCurrent.c_str(),
2996*8af74909SZhong Yang 			lineCurrent.length());
2997*8af74909SZhong Yang 		pdoc->InsertString(startCurrent, linePrevious.c_str(),
2998*8af74909SZhong Yang 			linePrevious.length());
2999*8af74909SZhong Yang 		// Move caret to start of current line
3000*8af74909SZhong Yang 		MovePositionTo(SelectionPosition(startCurrent));
3001*8af74909SZhong Yang 	}
3002*8af74909SZhong Yang }
3003*8af74909SZhong Yang 
LineReverse()3004*8af74909SZhong Yang void Editor::LineReverse() {
3005*8af74909SZhong Yang 	const Sci::Line lineStart =
3006*8af74909SZhong Yang 		pdoc->SciLineFromPosition(sel.RangeMain().Start().Position());
3007*8af74909SZhong Yang 	const Sci::Line lineEnd =
3008*8af74909SZhong Yang 		pdoc->SciLineFromPosition(sel.RangeMain().End().Position()-1);
3009*8af74909SZhong Yang 	const Sci::Line lineDiff = lineEnd - lineStart;
3010*8af74909SZhong Yang 	if (lineDiff <= 0)
3011*8af74909SZhong Yang 		return;
3012*8af74909SZhong Yang 	UndoGroup ug(pdoc);
3013*8af74909SZhong Yang 	for (Sci::Line i=(lineDiff+1)/2-1; i>=0; --i) {
3014*8af74909SZhong Yang 		const Sci::Line lineNum2 = lineEnd - i;
3015*8af74909SZhong Yang 		const Sci::Line lineNum1 = lineStart + i;
3016*8af74909SZhong Yang 		Sci::Position lineStart2 = pdoc->LineStart(lineNum2);
3017*8af74909SZhong Yang 		const Sci::Position lineStart1 = pdoc->LineStart(lineNum1);
3018*8af74909SZhong Yang 		const std::string line2 = RangeText(lineStart2, pdoc->LineEnd(lineNum2));
3019*8af74909SZhong Yang 		const std::string line1 = RangeText(lineStart1, pdoc->LineEnd(lineNum1));
3020*8af74909SZhong Yang 		const Sci::Position lineLen2 = line2.length();
3021*8af74909SZhong Yang 		const Sci::Position lineLen1 = line1.length();
3022*8af74909SZhong Yang 		pdoc->DeleteChars(lineStart2, lineLen2);
3023*8af74909SZhong Yang 		pdoc->DeleteChars(lineStart1, lineLen1);
3024*8af74909SZhong Yang 		lineStart2 -= lineLen1;
3025*8af74909SZhong Yang 		pdoc->InsertString(lineStart2, line1.c_str(), lineLen1);
3026*8af74909SZhong Yang 		pdoc->InsertString(lineStart1, line2.c_str(), lineLen2);
3027*8af74909SZhong Yang 	}
3028*8af74909SZhong Yang 	// Wholly select all affected lines
3029*8af74909SZhong Yang 	sel.RangeMain() = SelectionRange(pdoc->LineStart(lineStart),
3030*8af74909SZhong Yang 		pdoc->LineStart(lineEnd+1));
3031*8af74909SZhong Yang }
3032*8af74909SZhong Yang 
Duplicate(bool forLine)3033*8af74909SZhong Yang void Editor::Duplicate(bool forLine) {
3034*8af74909SZhong Yang 	if (sel.Empty()) {
3035*8af74909SZhong Yang 		forLine = true;
3036*8af74909SZhong Yang 	}
3037*8af74909SZhong Yang 	UndoGroup ug(pdoc);
3038*8af74909SZhong Yang 	const char *eol = "";
3039*8af74909SZhong Yang 	Sci::Position eolLen = 0;
3040*8af74909SZhong Yang 	if (forLine) {
3041*8af74909SZhong Yang 		eol = StringFromEOLMode(pdoc->eolMode);
3042*8af74909SZhong Yang 		eolLen = strlen(eol);
3043*8af74909SZhong Yang 	}
3044*8af74909SZhong Yang 	for (size_t r=0; r<sel.Count(); r++) {
3045*8af74909SZhong Yang 		SelectionPosition start = sel.Range(r).Start();
3046*8af74909SZhong Yang 		SelectionPosition end = sel.Range(r).End();
3047*8af74909SZhong Yang 		if (forLine) {
3048*8af74909SZhong Yang 			const Sci::Line line = pdoc->SciLineFromPosition(sel.Range(r).caret.Position());
3049*8af74909SZhong Yang 			start = SelectionPosition(pdoc->LineStart(line));
3050*8af74909SZhong Yang 			end = SelectionPosition(pdoc->LineEnd(line));
3051*8af74909SZhong Yang 		}
3052*8af74909SZhong Yang 		std::string text = RangeText(start.Position(), end.Position());
3053*8af74909SZhong Yang 		Sci::Position lengthInserted = eolLen;
3054*8af74909SZhong Yang 		if (forLine)
3055*8af74909SZhong Yang 			lengthInserted = pdoc->InsertString(end.Position(), eol, eolLen);
3056*8af74909SZhong Yang 		pdoc->InsertString(end.Position() + lengthInserted, text.c_str(), text.length());
3057*8af74909SZhong Yang 	}
3058*8af74909SZhong Yang 	if (sel.Count() && sel.IsRectangular()) {
3059*8af74909SZhong Yang 		SelectionPosition last = sel.Last();
3060*8af74909SZhong Yang 		if (forLine) {
3061*8af74909SZhong Yang 			const Sci::Line line = pdoc->SciLineFromPosition(last.Position());
3062*8af74909SZhong Yang 			last = SelectionPosition(last.Position() +
3063*8af74909SZhong Yang 				pdoc->LineStart(line+1) - pdoc->LineStart(line));
3064*8af74909SZhong Yang 		}
3065*8af74909SZhong Yang 		if (sel.Rectangular().anchor > sel.Rectangular().caret)
3066*8af74909SZhong Yang 			sel.Rectangular().anchor = last;
3067*8af74909SZhong Yang 		else
3068*8af74909SZhong Yang 			sel.Rectangular().caret = last;
3069*8af74909SZhong Yang 		SetRectangularRange();
3070*8af74909SZhong Yang 	}
3071*8af74909SZhong Yang }
3072*8af74909SZhong Yang 
CancelModes()3073*8af74909SZhong Yang void Editor::CancelModes() {
3074*8af74909SZhong Yang 	sel.SetMoveExtends(false);
3075*8af74909SZhong Yang }
3076*8af74909SZhong Yang 
NewLine()3077*8af74909SZhong Yang void Editor::NewLine() {
3078*8af74909SZhong Yang 	InvalidateWholeSelection();
3079*8af74909SZhong Yang 	if (sel.IsRectangular() || !additionalSelectionTyping) {
3080*8af74909SZhong Yang 		// Remove non-main ranges
3081*8af74909SZhong Yang 		sel.DropAdditionalRanges();
3082*8af74909SZhong Yang 	}
3083*8af74909SZhong Yang 
3084*8af74909SZhong Yang 	UndoGroup ug(pdoc, !sel.Empty() || (sel.Count() > 1));
3085*8af74909SZhong Yang 
3086*8af74909SZhong Yang 	// Clear each range
3087*8af74909SZhong Yang 	if (!sel.Empty()) {
3088*8af74909SZhong Yang 		ClearSelection();
3089*8af74909SZhong Yang 	}
3090*8af74909SZhong Yang 
3091*8af74909SZhong Yang 	// Insert each line end
3092*8af74909SZhong Yang 	size_t countInsertions = 0;
3093*8af74909SZhong Yang 	for (size_t r = 0; r < sel.Count(); r++) {
3094*8af74909SZhong Yang 		sel.Range(r).ClearVirtualSpace();
3095*8af74909SZhong Yang 		const char *eol = StringFromEOLMode(pdoc->eolMode);
3096*8af74909SZhong Yang 		const Sci::Position positionInsert = sel.Range(r).caret.Position();
3097*8af74909SZhong Yang 		const Sci::Position insertLength = pdoc->InsertString(positionInsert, eol, strlen(eol));
3098*8af74909SZhong Yang 		if (insertLength > 0) {
3099*8af74909SZhong Yang 			sel.Range(r) = SelectionRange(positionInsert + insertLength);
3100*8af74909SZhong Yang 			countInsertions++;
3101*8af74909SZhong Yang 		}
3102*8af74909SZhong Yang 	}
3103*8af74909SZhong Yang 
3104*8af74909SZhong Yang 	// Perform notifications after all the changes as the application may change the
3105*8af74909SZhong Yang 	// selections in response to the characters.
3106*8af74909SZhong Yang 	for (size_t i = 0; i < countInsertions; i++) {
3107*8af74909SZhong Yang 		const char *eol = StringFromEOLMode(pdoc->eolMode);
3108*8af74909SZhong Yang 		while (*eol) {
3109*8af74909SZhong Yang 			NotifyChar(*eol, CharacterSource::directInput);
3110*8af74909SZhong Yang 			if (recordingMacro) {
3111*8af74909SZhong Yang 				char txt[2];
3112*8af74909SZhong Yang 				txt[0] = *eol;
3113*8af74909SZhong Yang 				txt[1] = '\0';
3114*8af74909SZhong Yang 				NotifyMacroRecord(SCI_REPLACESEL, 0, reinterpret_cast<sptr_t>(txt));
3115*8af74909SZhong Yang 			}
3116*8af74909SZhong Yang 			eol++;
3117*8af74909SZhong Yang 		}
3118*8af74909SZhong Yang 	}
3119*8af74909SZhong Yang 
3120*8af74909SZhong Yang 	SetLastXChosen();
3121*8af74909SZhong Yang 	SetScrollBars();
3122*8af74909SZhong Yang 	EnsureCaretVisible();
3123*8af74909SZhong Yang 	// Avoid blinking during rapid typing:
3124*8af74909SZhong Yang 	ShowCaretAtCurrentPosition();
3125*8af74909SZhong Yang }
3126*8af74909SZhong Yang 
PositionUpOrDown(SelectionPosition spStart,int direction,int lastX)3127*8af74909SZhong Yang SelectionPosition Editor::PositionUpOrDown(SelectionPosition spStart, int direction, int lastX) {
3128*8af74909SZhong Yang 	const Point pt = LocationFromPosition(spStart);
3129*8af74909SZhong Yang 	int skipLines = 0;
3130*8af74909SZhong Yang 
3131*8af74909SZhong Yang 	if (vs.annotationVisible) {
3132*8af74909SZhong Yang 		const Sci::Line lineDoc = pdoc->SciLineFromPosition(spStart.Position());
3133*8af74909SZhong Yang 		const Point ptStartLine = LocationFromPosition(pdoc->LineStart(lineDoc));
3134*8af74909SZhong Yang 		const int subLine = static_cast<int>(pt.y - ptStartLine.y) / vs.lineHeight;
3135*8af74909SZhong Yang 
3136*8af74909SZhong Yang 		if (direction < 0 && subLine == 0) {
3137*8af74909SZhong Yang 			const Sci::Line lineDisplay = pcs->DisplayFromDoc(lineDoc);
3138*8af74909SZhong Yang 			if (lineDisplay > 0) {
3139*8af74909SZhong Yang 				skipLines = pdoc->AnnotationLines(pcs->DocFromDisplay(lineDisplay - 1));
3140*8af74909SZhong Yang 			}
3141*8af74909SZhong Yang 		} else if (direction > 0 && subLine >= (pcs->GetHeight(lineDoc) - 1 - pdoc->AnnotationLines(lineDoc))) {
3142*8af74909SZhong Yang 			skipLines = pdoc->AnnotationLines(lineDoc);
3143*8af74909SZhong Yang 		}
3144*8af74909SZhong Yang 	}
3145*8af74909SZhong Yang 
3146*8af74909SZhong Yang 	const Sci::Line newY = static_cast<Sci::Line>(pt.y) + (1 + skipLines) * direction * vs.lineHeight;
3147*8af74909SZhong Yang 	if (lastX < 0) {
3148*8af74909SZhong Yang 		lastX = static_cast<int>(pt.x) + xOffset;
3149*8af74909SZhong Yang 	}
3150*8af74909SZhong Yang 	SelectionPosition posNew = SPositionFromLocation(
3151*8af74909SZhong Yang 		Point::FromInts(lastX - xOffset, static_cast<int>(newY)), false, false, UserVirtualSpace());
3152*8af74909SZhong Yang 
3153*8af74909SZhong Yang 	if (direction < 0) {
3154*8af74909SZhong Yang 		// Line wrapping may lead to a location on the same line, so
3155*8af74909SZhong Yang 		// seek back if that is the case.
3156*8af74909SZhong Yang 		Point ptNew = LocationFromPosition(posNew.Position());
3157*8af74909SZhong Yang 		while ((posNew.Position() > 0) && (pt.y == ptNew.y)) {
3158*8af74909SZhong Yang 			posNew.Add(-1);
3159*8af74909SZhong Yang 			posNew.SetVirtualSpace(0);
3160*8af74909SZhong Yang 			ptNew = LocationFromPosition(posNew.Position());
3161*8af74909SZhong Yang 		}
3162*8af74909SZhong Yang 	} else if (direction > 0 && posNew.Position() != pdoc->Length()) {
3163*8af74909SZhong Yang 		// There is an equivalent case when moving down which skips
3164*8af74909SZhong Yang 		// over a line.
3165*8af74909SZhong Yang 		Point ptNew = LocationFromPosition(posNew.Position());
3166*8af74909SZhong Yang 		while ((posNew.Position() > spStart.Position()) && (ptNew.y > newY)) {
3167*8af74909SZhong Yang 			posNew.Add(-1);
3168*8af74909SZhong Yang 			posNew.SetVirtualSpace(0);
3169*8af74909SZhong Yang 			ptNew = LocationFromPosition(posNew.Position());
3170*8af74909SZhong Yang 		}
3171*8af74909SZhong Yang 	}
3172*8af74909SZhong Yang 	return posNew;
3173*8af74909SZhong Yang }
3174*8af74909SZhong Yang 
CursorUpOrDown(int direction,Selection::selTypes selt)3175*8af74909SZhong Yang void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) {
3176*8af74909SZhong Yang 	if ((selt == Selection::noSel) && sel.MoveExtends()) {
3177*8af74909SZhong Yang 		selt = !sel.IsRectangular() ? Selection::selStream : Selection::selRectangle;
3178*8af74909SZhong Yang 	}
3179*8af74909SZhong Yang 	SelectionPosition caretToUse = sel.Range(sel.Main()).caret;
3180*8af74909SZhong Yang 	if (sel.IsRectangular()) {
3181*8af74909SZhong Yang 		if (selt ==  Selection::noSel) {
3182*8af74909SZhong Yang 			caretToUse = (direction > 0) ? sel.Limits().end : sel.Limits().start;
3183*8af74909SZhong Yang 		} else {
3184*8af74909SZhong Yang 			caretToUse = sel.Rectangular().caret;
3185*8af74909SZhong Yang 		}
3186*8af74909SZhong Yang 	}
3187*8af74909SZhong Yang 	if (selt == Selection::selRectangle) {
3188*8af74909SZhong Yang 		const SelectionRange rangeBase = sel.IsRectangular() ? sel.Rectangular() : sel.RangeMain();
3189*8af74909SZhong Yang 		if (!sel.IsRectangular()) {
3190*8af74909SZhong Yang 			InvalidateWholeSelection();
3191*8af74909SZhong Yang 			sel.DropAdditionalRanges();
3192*8af74909SZhong Yang 		}
3193*8af74909SZhong Yang 		const SelectionPosition posNew = MovePositionSoVisible(
3194*8af74909SZhong Yang 			PositionUpOrDown(caretToUse, direction, lastXChosen), direction);
3195*8af74909SZhong Yang 		sel.selType = Selection::selRectangle;
3196*8af74909SZhong Yang 		sel.Rectangular() = SelectionRange(posNew, rangeBase.anchor);
3197*8af74909SZhong Yang 		SetRectangularRange();
3198*8af74909SZhong Yang 		MovedCaret(posNew, caretToUse, true, caretPolicies);
3199*8af74909SZhong Yang 	} else if (sel.selType == Selection::selLines && sel.MoveExtends()) {
3200*8af74909SZhong Yang 		// Calculate new caret position and call SetSelection(), which will ensure whole lines are selected.
3201*8af74909SZhong Yang 		const SelectionPosition posNew = MovePositionSoVisible(
3202*8af74909SZhong Yang 			PositionUpOrDown(caretToUse, direction, -1), direction);
3203*8af74909SZhong Yang 		SetSelection(posNew, sel.Range(sel.Main()).anchor);
3204*8af74909SZhong Yang 	} else {
3205*8af74909SZhong Yang 		InvalidateWholeSelection();
3206*8af74909SZhong Yang 		if (!additionalSelectionTyping || (sel.IsRectangular())) {
3207*8af74909SZhong Yang 			sel.DropAdditionalRanges();
3208*8af74909SZhong Yang 		}
3209*8af74909SZhong Yang 		sel.selType = Selection::selStream;
3210*8af74909SZhong Yang 		for (size_t r = 0; r < sel.Count(); r++) {
3211*8af74909SZhong Yang 			const int lastX = (r == sel.Main()) ? lastXChosen : -1;
3212*8af74909SZhong Yang 			const SelectionPosition spCaretNow = sel.Range(r).caret;
3213*8af74909SZhong Yang 			const SelectionPosition posNew = MovePositionSoVisible(
3214*8af74909SZhong Yang 				PositionUpOrDown(spCaretNow, direction, lastX), direction);
3215*8af74909SZhong Yang 			sel.Range(r) = selt == Selection::selStream ?
3216*8af74909SZhong Yang 				SelectionRange(posNew, sel.Range(r).anchor) : SelectionRange(posNew);
3217*8af74909SZhong Yang 		}
3218*8af74909SZhong Yang 		sel.RemoveDuplicates();
3219*8af74909SZhong Yang 		MovedCaret(sel.RangeMain().caret, caretToUse, true, caretPolicies);
3220*8af74909SZhong Yang 	}
3221*8af74909SZhong Yang }
3222*8af74909SZhong Yang 
ParaUpOrDown(int direction,Selection::selTypes selt)3223*8af74909SZhong Yang void Editor::ParaUpOrDown(int direction, Selection::selTypes selt) {
3224*8af74909SZhong Yang 	Sci::Line lineDoc;
3225*8af74909SZhong Yang 	const Sci::Position savedPos = sel.MainCaret();
3226*8af74909SZhong Yang 	do {
3227*8af74909SZhong Yang 		MovePositionTo(SelectionPosition(direction > 0 ? pdoc->ParaDown(sel.MainCaret()) : pdoc->ParaUp(sel.MainCaret())), selt);
3228*8af74909SZhong Yang 		lineDoc = pdoc->SciLineFromPosition(sel.MainCaret());
3229*8af74909SZhong Yang 		if (direction > 0) {
3230*8af74909SZhong Yang 			if (sel.MainCaret() >= pdoc->Length() && !pcs->GetVisible(lineDoc)) {
3231*8af74909SZhong Yang 				if (selt == Selection::noSel) {
3232*8af74909SZhong Yang 					MovePositionTo(SelectionPosition(pdoc->LineEndPosition(savedPos)));
3233*8af74909SZhong Yang 				}
3234*8af74909SZhong Yang 				break;
3235*8af74909SZhong Yang 			}
3236*8af74909SZhong Yang 		}
3237*8af74909SZhong Yang 	} while (!pcs->GetVisible(lineDoc));
3238*8af74909SZhong Yang }
3239*8af74909SZhong Yang 
RangeDisplayLine(Sci::Line lineVisible)3240*8af74909SZhong Yang Range Editor::RangeDisplayLine(Sci::Line lineVisible) {
3241*8af74909SZhong Yang 	RefreshStyleData();
3242*8af74909SZhong Yang 	AutoSurface surface(this);
3243*8af74909SZhong Yang 	return view.RangeDisplayLine(surface, *this, lineVisible, vs);
3244*8af74909SZhong Yang }
3245*8af74909SZhong Yang 
StartEndDisplayLine(Sci::Position pos,bool start)3246*8af74909SZhong Yang Sci::Position Editor::StartEndDisplayLine(Sci::Position pos, bool start) {
3247*8af74909SZhong Yang 	RefreshStyleData();
3248*8af74909SZhong Yang 	AutoSurface surface(this);
3249*8af74909SZhong Yang 	const Sci::Position posRet = view.StartEndDisplayLine(surface, *this, pos, start, vs);
3250*8af74909SZhong Yang 	if (posRet == INVALID_POSITION) {
3251*8af74909SZhong Yang 		return pos;
3252*8af74909SZhong Yang 	} else {
3253*8af74909SZhong Yang 		return posRet;
3254*8af74909SZhong Yang 	}
3255*8af74909SZhong Yang }
3256*8af74909SZhong Yang 
3257*8af74909SZhong Yang namespace {
3258*8af74909SZhong Yang 
HighShortFromWParam(uptr_t x)3259*8af74909SZhong Yang constexpr short HighShortFromWParam(uptr_t x) {
3260*8af74909SZhong Yang 	return static_cast<short>(x >> 16);
3261*8af74909SZhong Yang }
3262*8af74909SZhong Yang 
LowShortFromWParam(uptr_t x)3263*8af74909SZhong Yang constexpr short LowShortFromWParam(uptr_t x) {
3264*8af74909SZhong Yang 	return static_cast<short>(x & 0xffff);
3265*8af74909SZhong Yang }
3266*8af74909SZhong Yang 
WithExtends(unsigned int iMessage)3267*8af74909SZhong Yang constexpr unsigned int WithExtends(unsigned int iMessage) noexcept {
3268*8af74909SZhong Yang 	switch (iMessage) {
3269*8af74909SZhong Yang 	case SCI_CHARLEFT: return SCI_CHARLEFTEXTEND;
3270*8af74909SZhong Yang 	case SCI_CHARRIGHT: return SCI_CHARRIGHTEXTEND;
3271*8af74909SZhong Yang 
3272*8af74909SZhong Yang 	case SCI_WORDLEFT: return SCI_WORDLEFTEXTEND;
3273*8af74909SZhong Yang 	case SCI_WORDRIGHT: return SCI_WORDRIGHTEXTEND;
3274*8af74909SZhong Yang 	case SCI_WORDLEFTEND: return SCI_WORDLEFTENDEXTEND;
3275*8af74909SZhong Yang 	case SCI_WORDRIGHTEND: return SCI_WORDRIGHTENDEXTEND;
3276*8af74909SZhong Yang 	case SCI_WORDPARTLEFT: return SCI_WORDPARTLEFTEXTEND;
3277*8af74909SZhong Yang 	case SCI_WORDPARTRIGHT: return SCI_WORDPARTRIGHTEXTEND;
3278*8af74909SZhong Yang 
3279*8af74909SZhong Yang 	case SCI_HOME: return SCI_HOMEEXTEND;
3280*8af74909SZhong Yang 	case SCI_HOMEDISPLAY: return SCI_HOMEDISPLAYEXTEND;
3281*8af74909SZhong Yang 	case SCI_HOMEWRAP: return SCI_HOMEWRAPEXTEND;
3282*8af74909SZhong Yang 	case SCI_VCHOME: return SCI_VCHOMEEXTEND;
3283*8af74909SZhong Yang 	case SCI_VCHOMEDISPLAY: return SCI_VCHOMEDISPLAYEXTEND;
3284*8af74909SZhong Yang 	case SCI_VCHOMEWRAP: return SCI_VCHOMEWRAPEXTEND;
3285*8af74909SZhong Yang 
3286*8af74909SZhong Yang 	case SCI_LINEEND: return SCI_LINEENDEXTEND;
3287*8af74909SZhong Yang 	case SCI_LINEENDDISPLAY: return SCI_LINEENDDISPLAYEXTEND;
3288*8af74909SZhong Yang 	case SCI_LINEENDWRAP: return SCI_LINEENDWRAPEXTEND;
3289*8af74909SZhong Yang 
3290*8af74909SZhong Yang 	default:	return iMessage;
3291*8af74909SZhong Yang 	}
3292*8af74909SZhong Yang }
3293*8af74909SZhong Yang 
NaturalDirection(unsigned int iMessage)3294*8af74909SZhong Yang constexpr int NaturalDirection(unsigned int iMessage) noexcept {
3295*8af74909SZhong Yang 	switch (iMessage) {
3296*8af74909SZhong Yang 	case SCI_CHARLEFT:
3297*8af74909SZhong Yang 	case SCI_CHARLEFTEXTEND:
3298*8af74909SZhong Yang 	case SCI_CHARLEFTRECTEXTEND:
3299*8af74909SZhong Yang 	case SCI_WORDLEFT:
3300*8af74909SZhong Yang 	case SCI_WORDLEFTEXTEND:
3301*8af74909SZhong Yang 	case SCI_WORDLEFTEND:
3302*8af74909SZhong Yang 	case SCI_WORDLEFTENDEXTEND:
3303*8af74909SZhong Yang 	case SCI_WORDPARTLEFT:
3304*8af74909SZhong Yang 	case SCI_WORDPARTLEFTEXTEND:
3305*8af74909SZhong Yang 	case SCI_HOME:
3306*8af74909SZhong Yang 	case SCI_HOMEEXTEND:
3307*8af74909SZhong Yang 	case SCI_HOMEDISPLAY:
3308*8af74909SZhong Yang 	case SCI_HOMEDISPLAYEXTEND:
3309*8af74909SZhong Yang 	case SCI_HOMEWRAP:
3310*8af74909SZhong Yang 	case SCI_HOMEWRAPEXTEND:
3311*8af74909SZhong Yang 		// VC_HOME* mostly goes back
3312*8af74909SZhong Yang 	case SCI_VCHOME:
3313*8af74909SZhong Yang 	case SCI_VCHOMEEXTEND:
3314*8af74909SZhong Yang 	case SCI_VCHOMEDISPLAY:
3315*8af74909SZhong Yang 	case SCI_VCHOMEDISPLAYEXTEND:
3316*8af74909SZhong Yang 	case SCI_VCHOMEWRAP:
3317*8af74909SZhong Yang 	case SCI_VCHOMEWRAPEXTEND:
3318*8af74909SZhong Yang 		return -1;
3319*8af74909SZhong Yang 
3320*8af74909SZhong Yang 	default:
3321*8af74909SZhong Yang 		return 1;
3322*8af74909SZhong Yang 	}
3323*8af74909SZhong Yang }
3324*8af74909SZhong Yang 
IsRectExtend(unsigned int iMessage,bool isRectMoveExtends)3325*8af74909SZhong Yang constexpr bool IsRectExtend(unsigned int iMessage, bool isRectMoveExtends) noexcept {
3326*8af74909SZhong Yang 	switch (iMessage) {
3327*8af74909SZhong Yang 	case SCI_CHARLEFTRECTEXTEND:
3328*8af74909SZhong Yang 	case SCI_CHARRIGHTRECTEXTEND:
3329*8af74909SZhong Yang 	case SCI_HOMERECTEXTEND:
3330*8af74909SZhong Yang 	case SCI_VCHOMERECTEXTEND:
3331*8af74909SZhong Yang 	case SCI_LINEENDRECTEXTEND:
3332*8af74909SZhong Yang 		return true;
3333*8af74909SZhong Yang 	default:
3334*8af74909SZhong Yang 		if (isRectMoveExtends) {
3335*8af74909SZhong Yang 			// Handle SCI_SETSELECTIONMODE(SC_SEL_RECTANGLE) and subsequent movements.
3336*8af74909SZhong Yang 			switch (iMessage) {
3337*8af74909SZhong Yang 			case SCI_CHARLEFTEXTEND:
3338*8af74909SZhong Yang 			case SCI_CHARRIGHTEXTEND:
3339*8af74909SZhong Yang 			case SCI_HOMEEXTEND:
3340*8af74909SZhong Yang 			case SCI_VCHOMEEXTEND:
3341*8af74909SZhong Yang 			case SCI_LINEENDEXTEND:
3342*8af74909SZhong Yang 				return true;
3343*8af74909SZhong Yang 			default:
3344*8af74909SZhong Yang 				return false;
3345*8af74909SZhong Yang 			}
3346*8af74909SZhong Yang 		}
3347*8af74909SZhong Yang 		return false;
3348*8af74909SZhong Yang 	}
3349*8af74909SZhong Yang }
3350*8af74909SZhong Yang 
3351*8af74909SZhong Yang }
3352*8af74909SZhong Yang 
VCHomeDisplayPosition(Sci::Position position)3353*8af74909SZhong Yang Sci::Position Editor::VCHomeDisplayPosition(Sci::Position position) {
3354*8af74909SZhong Yang 	const Sci::Position homePos = pdoc->VCHomePosition(position);
3355*8af74909SZhong Yang 	const Sci::Position viewLineStart = StartEndDisplayLine(position, true);
3356*8af74909SZhong Yang 	if (viewLineStart > homePos)
3357*8af74909SZhong Yang 		return viewLineStart;
3358*8af74909SZhong Yang 	else
3359*8af74909SZhong Yang 		return homePos;
3360*8af74909SZhong Yang }
3361*8af74909SZhong Yang 
VCHomeWrapPosition(Sci::Position position)3362*8af74909SZhong Yang Sci::Position Editor::VCHomeWrapPosition(Sci::Position position) {
3363*8af74909SZhong Yang 	const Sci::Position homePos = pdoc->VCHomePosition(position);
3364*8af74909SZhong Yang 	const Sci::Position viewLineStart = StartEndDisplayLine(position, true);
3365*8af74909SZhong Yang 	if ((viewLineStart < position) && (viewLineStart > homePos))
3366*8af74909SZhong Yang 		return viewLineStart;
3367*8af74909SZhong Yang 	else
3368*8af74909SZhong Yang 		return homePos;
3369*8af74909SZhong Yang }
3370*8af74909SZhong Yang 
LineEndWrapPosition(Sci::Position position)3371*8af74909SZhong Yang Sci::Position Editor::LineEndWrapPosition(Sci::Position position) {
3372*8af74909SZhong Yang 	const Sci::Position endPos = StartEndDisplayLine(position, false);
3373*8af74909SZhong Yang 	const Sci::Position realEndPos = pdoc->LineEndPosition(position);
3374*8af74909SZhong Yang 	if (endPos > realEndPos      // if moved past visible EOLs
3375*8af74909SZhong Yang 		|| position >= endPos) // if at end of display line already
3376*8af74909SZhong Yang 		return realEndPos;
3377*8af74909SZhong Yang 	else
3378*8af74909SZhong Yang 		return endPos;
3379*8af74909SZhong Yang }
3380*8af74909SZhong Yang 
HorizontalMove(unsigned int iMessage)3381*8af74909SZhong Yang int Editor::HorizontalMove(unsigned int iMessage) {
3382*8af74909SZhong Yang 	if (sel.selType == Selection::selLines) {
3383*8af74909SZhong Yang 		return 0; // horizontal moves with line selection have no effect
3384*8af74909SZhong Yang 	}
3385*8af74909SZhong Yang 	if (sel.MoveExtends()) {
3386*8af74909SZhong Yang 		iMessage = WithExtends(iMessage);
3387*8af74909SZhong Yang 	}
3388*8af74909SZhong Yang 
3389*8af74909SZhong Yang 	if (!multipleSelection && !sel.IsRectangular()) {
3390*8af74909SZhong Yang 		// Simplify selection down to 1
3391*8af74909SZhong Yang 		sel.SetSelection(sel.RangeMain());
3392*8af74909SZhong Yang 	}
3393*8af74909SZhong Yang 
3394*8af74909SZhong Yang 	// Invalidate each of the current selections
3395*8af74909SZhong Yang 	InvalidateWholeSelection();
3396*8af74909SZhong Yang 
3397*8af74909SZhong Yang 	if (IsRectExtend(iMessage, sel.IsRectangular() && sel.MoveExtends())) {
3398*8af74909SZhong Yang 		const SelectionRange rangeBase = sel.IsRectangular() ? sel.Rectangular() : sel.RangeMain();
3399*8af74909SZhong Yang 		if (!sel.IsRectangular()) {
3400*8af74909SZhong Yang 			sel.DropAdditionalRanges();
3401*8af74909SZhong Yang 		}
3402*8af74909SZhong Yang 		// Will change to rectangular if not currently rectangular
3403*8af74909SZhong Yang 		SelectionPosition spCaret = rangeBase.caret;
3404*8af74909SZhong Yang 		switch (iMessage) {
3405*8af74909SZhong Yang 		case SCI_CHARLEFTRECTEXTEND:
3406*8af74909SZhong Yang 		case SCI_CHARLEFTEXTEND: // only when sel.IsRectangular() && sel.MoveExtends()
3407*8af74909SZhong Yang 			if (pdoc->IsLineEndPosition(spCaret.Position()) && spCaret.VirtualSpace()) {
3408*8af74909SZhong Yang 				spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
3409*8af74909SZhong Yang 			} else if ((virtualSpaceOptions & SCVS_NOWRAPLINESTART) == 0 || pdoc->GetColumn(spCaret.Position()) > 0) {
3410*8af74909SZhong Yang 				spCaret = SelectionPosition(spCaret.Position() - 1);
3411*8af74909SZhong Yang 			}
3412*8af74909SZhong Yang 			break;
3413*8af74909SZhong Yang 		case SCI_CHARRIGHTRECTEXTEND:
3414*8af74909SZhong Yang 		case SCI_CHARRIGHTEXTEND: // only when sel.IsRectangular() && sel.MoveExtends()
3415*8af74909SZhong Yang 			if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) && pdoc->IsLineEndPosition(sel.MainCaret())) {
3416*8af74909SZhong Yang 				spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
3417*8af74909SZhong Yang 			} else {
3418*8af74909SZhong Yang 				spCaret = SelectionPosition(spCaret.Position() + 1);
3419*8af74909SZhong Yang 			}
3420*8af74909SZhong Yang 			break;
3421*8af74909SZhong Yang 		case SCI_HOMERECTEXTEND:
3422*8af74909SZhong Yang 		case SCI_HOMEEXTEND: // only when sel.IsRectangular() && sel.MoveExtends()
3423*8af74909SZhong Yang 			spCaret = SelectionPosition(
3424*8af74909SZhong Yang 				pdoc->LineStart(pdoc->LineFromPosition(spCaret.Position())));
3425*8af74909SZhong Yang 			break;
3426*8af74909SZhong Yang 		case SCI_VCHOMERECTEXTEND:
3427*8af74909SZhong Yang 		case SCI_VCHOMEEXTEND: // only when sel.IsRectangular() && sel.MoveExtends()
3428*8af74909SZhong Yang 			spCaret = SelectionPosition(pdoc->VCHomePosition(spCaret.Position()));
3429*8af74909SZhong Yang 			break;
3430*8af74909SZhong Yang 		case SCI_LINEENDRECTEXTEND:
3431*8af74909SZhong Yang 		case SCI_LINEENDEXTEND: // only when sel.IsRectangular() && sel.MoveExtends()
3432*8af74909SZhong Yang 			spCaret = SelectionPosition(pdoc->LineEndPosition(spCaret.Position()));
3433*8af74909SZhong Yang 			break;
3434*8af74909SZhong Yang 		}
3435*8af74909SZhong Yang 		const int directionMove = (spCaret < rangeBase.caret) ? -1 : 1;
3436*8af74909SZhong Yang 		spCaret = MovePositionSoVisible(spCaret, directionMove);
3437*8af74909SZhong Yang 		sel.selType = Selection::selRectangle;
3438*8af74909SZhong Yang 		sel.Rectangular() = SelectionRange(spCaret, rangeBase.anchor);
3439*8af74909SZhong Yang 		SetRectangularRange();
3440*8af74909SZhong Yang 	} else if (sel.IsRectangular()) {
3441*8af74909SZhong Yang 		// Not a rectangular extension so switch to stream.
3442*8af74909SZhong Yang 		SelectionPosition selAtLimit = (NaturalDirection(iMessage) > 0) ? sel.Limits().end : sel.Limits().start;
3443*8af74909SZhong Yang 		switch (iMessage) {
3444*8af74909SZhong Yang 		case SCI_HOME:
3445*8af74909SZhong Yang 			selAtLimit = SelectionPosition(
3446*8af74909SZhong Yang 				pdoc->LineStart(pdoc->LineFromPosition(selAtLimit.Position())));
3447*8af74909SZhong Yang 			break;
3448*8af74909SZhong Yang 		case SCI_VCHOME:
3449*8af74909SZhong Yang 			selAtLimit = SelectionPosition(pdoc->VCHomePosition(selAtLimit.Position()));
3450*8af74909SZhong Yang 			break;
3451*8af74909SZhong Yang 		case SCI_LINEEND:
3452*8af74909SZhong Yang 			selAtLimit = SelectionPosition(pdoc->LineEndPosition(selAtLimit.Position()));
3453*8af74909SZhong Yang 			break;
3454*8af74909SZhong Yang 		}
3455*8af74909SZhong Yang 		sel.selType = Selection::selStream;
3456*8af74909SZhong Yang 		sel.SetSelection(SelectionRange(selAtLimit));
3457*8af74909SZhong Yang 	} else {
3458*8af74909SZhong Yang 		if (!additionalSelectionTyping) {
3459*8af74909SZhong Yang 			InvalidateWholeSelection();
3460*8af74909SZhong Yang 			sel.DropAdditionalRanges();
3461*8af74909SZhong Yang 		}
3462*8af74909SZhong Yang 		for (size_t r = 0; r < sel.Count(); r++) {
3463*8af74909SZhong Yang 			const SelectionPosition spCaretNow = sel.Range(r).caret;
3464*8af74909SZhong Yang 			SelectionPosition spCaret = spCaretNow;
3465*8af74909SZhong Yang 			switch (iMessage) {
3466*8af74909SZhong Yang 			case SCI_CHARLEFT:
3467*8af74909SZhong Yang 			case SCI_CHARLEFTEXTEND:
3468*8af74909SZhong Yang 				if (spCaret.VirtualSpace()) {
3469*8af74909SZhong Yang 					spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
3470*8af74909SZhong Yang 				} else if ((virtualSpaceOptions & SCVS_NOWRAPLINESTART) == 0 || pdoc->GetColumn(spCaret.Position()) > 0) {
3471*8af74909SZhong Yang 					spCaret = SelectionPosition(spCaret.Position() - 1);
3472*8af74909SZhong Yang 				}
3473*8af74909SZhong Yang 				break;
3474*8af74909SZhong Yang 			case SCI_CHARRIGHT:
3475*8af74909SZhong Yang 			case SCI_CHARRIGHTEXTEND:
3476*8af74909SZhong Yang 				if ((virtualSpaceOptions & SCVS_USERACCESSIBLE) && pdoc->IsLineEndPosition(spCaret.Position())) {
3477*8af74909SZhong Yang 					spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
3478*8af74909SZhong Yang 				} else {
3479*8af74909SZhong Yang 					spCaret = SelectionPosition(spCaret.Position() + 1);
3480*8af74909SZhong Yang 				}
3481*8af74909SZhong Yang 				break;
3482*8af74909SZhong Yang 			case SCI_WORDLEFT:
3483*8af74909SZhong Yang 			case SCI_WORDLEFTEXTEND:
3484*8af74909SZhong Yang 				spCaret = SelectionPosition(pdoc->NextWordStart(spCaret.Position(), -1));
3485*8af74909SZhong Yang 				break;
3486*8af74909SZhong Yang 			case SCI_WORDRIGHT:
3487*8af74909SZhong Yang 			case SCI_WORDRIGHTEXTEND:
3488*8af74909SZhong Yang 				spCaret = SelectionPosition(pdoc->NextWordStart(spCaret.Position(), 1));
3489*8af74909SZhong Yang 				break;
3490*8af74909SZhong Yang 			case SCI_WORDLEFTEND:
3491*8af74909SZhong Yang 			case SCI_WORDLEFTENDEXTEND:
3492*8af74909SZhong Yang 				spCaret = SelectionPosition(pdoc->NextWordEnd(spCaret.Position(), -1));
3493*8af74909SZhong Yang 				break;
3494*8af74909SZhong Yang 			case SCI_WORDRIGHTEND:
3495*8af74909SZhong Yang 			case SCI_WORDRIGHTENDEXTEND:
3496*8af74909SZhong Yang 				spCaret = SelectionPosition(pdoc->NextWordEnd(spCaret.Position(), 1));
3497*8af74909SZhong Yang 				break;
3498*8af74909SZhong Yang 			case SCI_WORDPARTLEFT:
3499*8af74909SZhong Yang 			case SCI_WORDPARTLEFTEXTEND:
3500*8af74909SZhong Yang 				spCaret = SelectionPosition(pdoc->WordPartLeft(spCaret.Position()));
3501*8af74909SZhong Yang 				break;
3502*8af74909SZhong Yang 			case SCI_WORDPARTRIGHT:
3503*8af74909SZhong Yang 			case SCI_WORDPARTRIGHTEXTEND:
3504*8af74909SZhong Yang 				spCaret = SelectionPosition(pdoc->WordPartRight(spCaret.Position()));
3505*8af74909SZhong Yang 				break;
3506*8af74909SZhong Yang 			case SCI_HOME:
3507*8af74909SZhong Yang 			case SCI_HOMEEXTEND:
3508*8af74909SZhong Yang 				spCaret = SelectionPosition(
3509*8af74909SZhong Yang 					pdoc->LineStart(pdoc->LineFromPosition(spCaret.Position())));
3510*8af74909SZhong Yang 				break;
3511*8af74909SZhong Yang 			case SCI_HOMEDISPLAY:
3512*8af74909SZhong Yang 			case SCI_HOMEDISPLAYEXTEND:
3513*8af74909SZhong Yang 				spCaret = SelectionPosition(StartEndDisplayLine(spCaret.Position(), true));
3514*8af74909SZhong Yang 				break;
3515*8af74909SZhong Yang 			case SCI_HOMEWRAP:
3516*8af74909SZhong Yang 			case SCI_HOMEWRAPEXTEND:
3517*8af74909SZhong Yang 				spCaret = MovePositionSoVisible(StartEndDisplayLine(spCaret.Position(), true), -1);
3518*8af74909SZhong Yang 				if (spCaretNow <= spCaret)
3519*8af74909SZhong Yang 					spCaret = SelectionPosition(
3520*8af74909SZhong Yang 						pdoc->LineStart(pdoc->LineFromPosition(spCaret.Position())));
3521*8af74909SZhong Yang 				break;
3522*8af74909SZhong Yang 			case SCI_VCHOME:
3523*8af74909SZhong Yang 			case SCI_VCHOMEEXTEND:
3524*8af74909SZhong Yang 				// VCHome alternates between beginning of line and beginning of text so may move back or forwards
3525*8af74909SZhong Yang 				spCaret = SelectionPosition(pdoc->VCHomePosition(spCaret.Position()));
3526*8af74909SZhong Yang 				break;
3527*8af74909SZhong Yang 			case SCI_VCHOMEDISPLAY:
3528*8af74909SZhong Yang 			case SCI_VCHOMEDISPLAYEXTEND:
3529*8af74909SZhong Yang 				spCaret = SelectionPosition(VCHomeDisplayPosition(spCaret.Position()));
3530*8af74909SZhong Yang 				break;
3531*8af74909SZhong Yang 			case SCI_VCHOMEWRAP:
3532*8af74909SZhong Yang 			case SCI_VCHOMEWRAPEXTEND:
3533*8af74909SZhong Yang 				spCaret = SelectionPosition(VCHomeWrapPosition(spCaret.Position()));
3534*8af74909SZhong Yang 				break;
3535*8af74909SZhong Yang 			case SCI_LINEEND:
3536*8af74909SZhong Yang 			case SCI_LINEENDEXTEND:
3537*8af74909SZhong Yang 				spCaret = SelectionPosition(pdoc->LineEndPosition(spCaret.Position()));
3538*8af74909SZhong Yang 				break;
3539*8af74909SZhong Yang 			case SCI_LINEENDDISPLAY:
3540*8af74909SZhong Yang 			case SCI_LINEENDDISPLAYEXTEND:
3541*8af74909SZhong Yang 				spCaret = SelectionPosition(StartEndDisplayLine(spCaret.Position(), false));
3542*8af74909SZhong Yang 				break;
3543*8af74909SZhong Yang 			case SCI_LINEENDWRAP:
3544*8af74909SZhong Yang 			case SCI_LINEENDWRAPEXTEND:
3545*8af74909SZhong Yang 				spCaret = SelectionPosition(LineEndWrapPosition(spCaret.Position()));
3546*8af74909SZhong Yang 				break;
3547*8af74909SZhong Yang 
3548*8af74909SZhong Yang 			default:
3549*8af74909SZhong Yang 				PLATFORM_ASSERT(false);
3550*8af74909SZhong Yang 			}
3551*8af74909SZhong Yang 
3552*8af74909SZhong Yang 			const int directionMove = (spCaret < spCaretNow) ? -1 : 1;
3553*8af74909SZhong Yang 			spCaret = MovePositionSoVisible(spCaret, directionMove);
3554*8af74909SZhong Yang 
3555*8af74909SZhong Yang 			// Handle move versus extend, and special behaviour for non-empty left/right
3556*8af74909SZhong Yang 			switch (iMessage) {
3557*8af74909SZhong Yang 			case SCI_CHARLEFT:
3558*8af74909SZhong Yang 			case SCI_CHARRIGHT:
3559*8af74909SZhong Yang 				if (sel.Range(r).Empty()) {
3560*8af74909SZhong Yang 					sel.Range(r) = SelectionRange(spCaret);
3561*8af74909SZhong Yang 				} else {
3562*8af74909SZhong Yang 					sel.Range(r) = SelectionRange(
3563*8af74909SZhong Yang 						(iMessage == SCI_CHARLEFT) ? sel.Range(r).Start() : sel.Range(r).End());
3564*8af74909SZhong Yang 				}
3565*8af74909SZhong Yang 				break;
3566*8af74909SZhong Yang 
3567*8af74909SZhong Yang 			case SCI_WORDLEFT:
3568*8af74909SZhong Yang 			case SCI_WORDRIGHT:
3569*8af74909SZhong Yang 			case SCI_WORDLEFTEND:
3570*8af74909SZhong Yang 			case SCI_WORDRIGHTEND:
3571*8af74909SZhong Yang 			case SCI_WORDPARTLEFT:
3572*8af74909SZhong Yang 			case SCI_WORDPARTRIGHT:
3573*8af74909SZhong Yang 			case SCI_HOME:
3574*8af74909SZhong Yang 			case SCI_HOMEDISPLAY:
3575*8af74909SZhong Yang 			case SCI_HOMEWRAP:
3576*8af74909SZhong Yang 			case SCI_VCHOME:
3577*8af74909SZhong Yang 			case SCI_VCHOMEDISPLAY:
3578*8af74909SZhong Yang 			case SCI_VCHOMEWRAP:
3579*8af74909SZhong Yang 			case SCI_LINEEND:
3580*8af74909SZhong Yang 			case SCI_LINEENDDISPLAY:
3581*8af74909SZhong Yang 			case SCI_LINEENDWRAP:
3582*8af74909SZhong Yang 				sel.Range(r) = SelectionRange(spCaret);
3583*8af74909SZhong Yang 				break;
3584*8af74909SZhong Yang 
3585*8af74909SZhong Yang 			case SCI_CHARLEFTEXTEND:
3586*8af74909SZhong Yang 			case SCI_CHARRIGHTEXTEND:
3587*8af74909SZhong Yang 			case SCI_WORDLEFTEXTEND:
3588*8af74909SZhong Yang 			case SCI_WORDRIGHTEXTEND:
3589*8af74909SZhong Yang 			case SCI_WORDLEFTENDEXTEND:
3590*8af74909SZhong Yang 			case SCI_WORDRIGHTENDEXTEND:
3591*8af74909SZhong Yang 			case SCI_WORDPARTLEFTEXTEND:
3592*8af74909SZhong Yang 			case SCI_WORDPARTRIGHTEXTEND:
3593*8af74909SZhong Yang 			case SCI_HOMEEXTEND:
3594*8af74909SZhong Yang 			case SCI_HOMEDISPLAYEXTEND:
3595*8af74909SZhong Yang 			case SCI_HOMEWRAPEXTEND:
3596*8af74909SZhong Yang 			case SCI_VCHOMEEXTEND:
3597*8af74909SZhong Yang 			case SCI_VCHOMEDISPLAYEXTEND:
3598*8af74909SZhong Yang 			case SCI_VCHOMEWRAPEXTEND:
3599*8af74909SZhong Yang 			case SCI_LINEENDEXTEND:
3600*8af74909SZhong Yang 			case SCI_LINEENDDISPLAYEXTEND:
3601*8af74909SZhong Yang 			case SCI_LINEENDWRAPEXTEND: {
3602*8af74909SZhong Yang 				SelectionRange rangeNew = SelectionRange(spCaret, sel.Range(r).anchor);
3603*8af74909SZhong Yang 				sel.TrimOtherSelections(r, SelectionRange(rangeNew));
3604*8af74909SZhong Yang 				sel.Range(r) = rangeNew;
3605*8af74909SZhong Yang 				}
3606*8af74909SZhong Yang 				break;
3607*8af74909SZhong Yang 
3608*8af74909SZhong Yang 			default:
3609*8af74909SZhong Yang 				PLATFORM_ASSERT(false);
3610*8af74909SZhong Yang 			}
3611*8af74909SZhong Yang 		}
3612*8af74909SZhong Yang 	}
3613*8af74909SZhong Yang 
3614*8af74909SZhong Yang 	sel.RemoveDuplicates();
3615*8af74909SZhong Yang 
3616*8af74909SZhong Yang 	MovedCaret(sel.RangeMain().caret, SelectionPosition(INVALID_POSITION), true, caretPolicies);
3617*8af74909SZhong Yang 
3618*8af74909SZhong Yang 	// Invalidate the new state of the selection
3619*8af74909SZhong Yang 	InvalidateWholeSelection();
3620*8af74909SZhong Yang 
3621*8af74909SZhong Yang 	SetLastXChosen();
3622*8af74909SZhong Yang 	// Need the line moving and so forth from MovePositionTo
3623*8af74909SZhong Yang 	return 0;
3624*8af74909SZhong Yang }
3625*8af74909SZhong Yang 
DelWordOrLine(unsigned int iMessage)3626*8af74909SZhong Yang int Editor::DelWordOrLine(unsigned int iMessage) {
3627*8af74909SZhong Yang 	// Virtual space may be realised for SCI_DELWORDRIGHT or SCI_DELWORDRIGHTEND
3628*8af74909SZhong Yang 	// which means 2 actions so wrap in an undo group.
3629*8af74909SZhong Yang 
3630*8af74909SZhong Yang 	// Rightwards and leftwards deletions differ in treatment of virtual space.
3631*8af74909SZhong Yang 	// Clear virtual space for leftwards, realise for rightwards.
3632*8af74909SZhong Yang 	const bool leftwards = (iMessage == SCI_DELWORDLEFT) || (iMessage == SCI_DELLINELEFT);
3633*8af74909SZhong Yang 
3634*8af74909SZhong Yang 	if (!additionalSelectionTyping) {
3635*8af74909SZhong Yang 		InvalidateWholeSelection();
3636*8af74909SZhong Yang 		sel.DropAdditionalRanges();
3637*8af74909SZhong Yang 	}
3638*8af74909SZhong Yang 
3639*8af74909SZhong Yang 	UndoGroup ug0(pdoc, (sel.Count() > 1) || !leftwards);
3640*8af74909SZhong Yang 
3641*8af74909SZhong Yang 	for (size_t r = 0; r < sel.Count(); r++) {
3642*8af74909SZhong Yang 		if (leftwards) {
3643*8af74909SZhong Yang 			// Delete to the left so first clear the virtual space.
3644*8af74909SZhong Yang 			sel.Range(r).ClearVirtualSpace();
3645*8af74909SZhong Yang 		} else {
3646*8af74909SZhong Yang 			// Delete to the right so first realise the virtual space.
3647*8af74909SZhong Yang 			sel.Range(r) = SelectionRange(
3648*8af74909SZhong Yang 				RealizeVirtualSpace(sel.Range(r).caret));
3649*8af74909SZhong Yang 		}
3650*8af74909SZhong Yang 
3651*8af74909SZhong Yang 		Range rangeDelete;
3652*8af74909SZhong Yang 		switch (iMessage) {
3653*8af74909SZhong Yang 		case SCI_DELWORDLEFT:
3654*8af74909SZhong Yang 			rangeDelete = Range(
3655*8af74909SZhong Yang 				pdoc->NextWordStart(sel.Range(r).caret.Position(), -1),
3656*8af74909SZhong Yang 				sel.Range(r).caret.Position());
3657*8af74909SZhong Yang 			break;
3658*8af74909SZhong Yang 		case SCI_DELWORDRIGHT:
3659*8af74909SZhong Yang 			rangeDelete = Range(
3660*8af74909SZhong Yang 				sel.Range(r).caret.Position(),
3661*8af74909SZhong Yang 				pdoc->NextWordStart(sel.Range(r).caret.Position(), 1));
3662*8af74909SZhong Yang 			break;
3663*8af74909SZhong Yang 		case SCI_DELWORDRIGHTEND:
3664*8af74909SZhong Yang 			rangeDelete = Range(
3665*8af74909SZhong Yang 				sel.Range(r).caret.Position(),
3666*8af74909SZhong Yang 				pdoc->NextWordEnd(sel.Range(r).caret.Position(), 1));
3667*8af74909SZhong Yang 			break;
3668*8af74909SZhong Yang 		case SCI_DELLINELEFT:
3669*8af74909SZhong Yang 			rangeDelete = Range(
3670*8af74909SZhong Yang 				pdoc->LineStart(pdoc->LineFromPosition(sel.Range(r).caret.Position())),
3671*8af74909SZhong Yang 				sel.Range(r).caret.Position());
3672*8af74909SZhong Yang 			break;
3673*8af74909SZhong Yang 		case SCI_DELLINERIGHT:
3674*8af74909SZhong Yang 			rangeDelete = Range(
3675*8af74909SZhong Yang 				sel.Range(r).caret.Position(),
3676*8af74909SZhong Yang 				pdoc->LineEnd(pdoc->LineFromPosition(sel.Range(r).caret.Position())));
3677*8af74909SZhong Yang 			break;
3678*8af74909SZhong Yang 		}
3679*8af74909SZhong Yang 		if (!RangeContainsProtected(rangeDelete.start, rangeDelete.end)) {
3680*8af74909SZhong Yang 			pdoc->DeleteChars(rangeDelete.start, rangeDelete.end - rangeDelete.start);
3681*8af74909SZhong Yang 		}
3682*8af74909SZhong Yang 	}
3683*8af74909SZhong Yang 
3684*8af74909SZhong Yang 	// May need something stronger here: can selections overlap at this point?
3685*8af74909SZhong Yang 	sel.RemoveDuplicates();
3686*8af74909SZhong Yang 
3687*8af74909SZhong Yang 	MovedCaret(sel.RangeMain().caret, SelectionPosition(INVALID_POSITION), true, caretPolicies);
3688*8af74909SZhong Yang 
3689*8af74909SZhong Yang 	// Invalidate the new state of the selection
3690*8af74909SZhong Yang 	InvalidateWholeSelection();
3691*8af74909SZhong Yang 
3692*8af74909SZhong Yang 	SetLastXChosen();
3693*8af74909SZhong Yang 	return 0;
3694*8af74909SZhong Yang }
3695*8af74909SZhong Yang 
KeyCommand(unsigned int iMessage)3696*8af74909SZhong Yang int Editor::KeyCommand(unsigned int iMessage) {
3697*8af74909SZhong Yang 	switch (iMessage) {
3698*8af74909SZhong Yang 	case SCI_LINEDOWN:
3699*8af74909SZhong Yang 		CursorUpOrDown(1, Selection::noSel);
3700*8af74909SZhong Yang 		break;
3701*8af74909SZhong Yang 	case SCI_LINEDOWNEXTEND:
3702*8af74909SZhong Yang 		CursorUpOrDown(1, Selection::selStream);
3703*8af74909SZhong Yang 		break;
3704*8af74909SZhong Yang 	case SCI_LINEDOWNRECTEXTEND:
3705*8af74909SZhong Yang 		CursorUpOrDown(1, Selection::selRectangle);
3706*8af74909SZhong Yang 		break;
3707*8af74909SZhong Yang 	case SCI_PARADOWN:
3708*8af74909SZhong Yang 		ParaUpOrDown(1, Selection::noSel);
3709*8af74909SZhong Yang 		break;
3710*8af74909SZhong Yang 	case SCI_PARADOWNEXTEND:
3711*8af74909SZhong Yang 		ParaUpOrDown(1, Selection::selStream);
3712*8af74909SZhong Yang 		break;
3713*8af74909SZhong Yang 	case SCI_LINESCROLLDOWN:
3714*8af74909SZhong Yang 		ScrollTo(topLine + 1);
3715*8af74909SZhong Yang 		MoveCaretInsideView(false);
3716*8af74909SZhong Yang 		break;
3717*8af74909SZhong Yang 	case SCI_LINEUP:
3718*8af74909SZhong Yang 		CursorUpOrDown(-1, Selection::noSel);
3719*8af74909SZhong Yang 		break;
3720*8af74909SZhong Yang 	case SCI_LINEUPEXTEND:
3721*8af74909SZhong Yang 		CursorUpOrDown(-1, Selection::selStream);
3722*8af74909SZhong Yang 		break;
3723*8af74909SZhong Yang 	case SCI_LINEUPRECTEXTEND:
3724*8af74909SZhong Yang 		CursorUpOrDown(-1, Selection::selRectangle);
3725*8af74909SZhong Yang 		break;
3726*8af74909SZhong Yang 	case SCI_PARAUP:
3727*8af74909SZhong Yang 		ParaUpOrDown(-1, Selection::noSel);
3728*8af74909SZhong Yang 		break;
3729*8af74909SZhong Yang 	case SCI_PARAUPEXTEND:
3730*8af74909SZhong Yang 		ParaUpOrDown(-1, Selection::selStream);
3731*8af74909SZhong Yang 		break;
3732*8af74909SZhong Yang 	case SCI_LINESCROLLUP:
3733*8af74909SZhong Yang 		ScrollTo(topLine - 1);
3734*8af74909SZhong Yang 		MoveCaretInsideView(false);
3735*8af74909SZhong Yang 		break;
3736*8af74909SZhong Yang 
3737*8af74909SZhong Yang 	case SCI_CHARLEFT:
3738*8af74909SZhong Yang 	case SCI_CHARLEFTEXTEND:
3739*8af74909SZhong Yang 	case SCI_CHARLEFTRECTEXTEND:
3740*8af74909SZhong Yang 	case SCI_CHARRIGHT:
3741*8af74909SZhong Yang 	case SCI_CHARRIGHTEXTEND:
3742*8af74909SZhong Yang 	case SCI_CHARRIGHTRECTEXTEND:
3743*8af74909SZhong Yang 	case SCI_WORDLEFT:
3744*8af74909SZhong Yang 	case SCI_WORDLEFTEXTEND:
3745*8af74909SZhong Yang 	case SCI_WORDRIGHT:
3746*8af74909SZhong Yang 	case SCI_WORDRIGHTEXTEND:
3747*8af74909SZhong Yang 	case SCI_WORDLEFTEND:
3748*8af74909SZhong Yang 	case SCI_WORDLEFTENDEXTEND:
3749*8af74909SZhong Yang 	case SCI_WORDRIGHTEND:
3750*8af74909SZhong Yang 	case SCI_WORDRIGHTENDEXTEND:
3751*8af74909SZhong Yang 	case SCI_WORDPARTLEFT:
3752*8af74909SZhong Yang 	case SCI_WORDPARTLEFTEXTEND:
3753*8af74909SZhong Yang 	case SCI_WORDPARTRIGHT:
3754*8af74909SZhong Yang 	case SCI_WORDPARTRIGHTEXTEND:
3755*8af74909SZhong Yang 	case SCI_HOME:
3756*8af74909SZhong Yang 	case SCI_HOMEEXTEND:
3757*8af74909SZhong Yang 	case SCI_HOMERECTEXTEND:
3758*8af74909SZhong Yang 	case SCI_HOMEDISPLAY:
3759*8af74909SZhong Yang 	case SCI_HOMEDISPLAYEXTEND:
3760*8af74909SZhong Yang 	case SCI_HOMEWRAP:
3761*8af74909SZhong Yang 	case SCI_HOMEWRAPEXTEND:
3762*8af74909SZhong Yang 	case SCI_VCHOME:
3763*8af74909SZhong Yang 	case SCI_VCHOMEEXTEND:
3764*8af74909SZhong Yang 	case SCI_VCHOMERECTEXTEND:
3765*8af74909SZhong Yang 	case SCI_VCHOMEDISPLAY:
3766*8af74909SZhong Yang 	case SCI_VCHOMEDISPLAYEXTEND:
3767*8af74909SZhong Yang 	case SCI_VCHOMEWRAP:
3768*8af74909SZhong Yang 	case SCI_VCHOMEWRAPEXTEND:
3769*8af74909SZhong Yang 	case SCI_LINEEND:
3770*8af74909SZhong Yang 	case SCI_LINEENDEXTEND:
3771*8af74909SZhong Yang 	case SCI_LINEENDRECTEXTEND:
3772*8af74909SZhong Yang 	case SCI_LINEENDDISPLAY:
3773*8af74909SZhong Yang 	case SCI_LINEENDDISPLAYEXTEND:
3774*8af74909SZhong Yang 	case SCI_LINEENDWRAP:
3775*8af74909SZhong Yang 	case SCI_LINEENDWRAPEXTEND:
3776*8af74909SZhong Yang 		return HorizontalMove(iMessage);
3777*8af74909SZhong Yang 
3778*8af74909SZhong Yang 	case SCI_DOCUMENTSTART:
3779*8af74909SZhong Yang 		MovePositionTo(0);
3780*8af74909SZhong Yang 		SetLastXChosen();
3781*8af74909SZhong Yang 		break;
3782*8af74909SZhong Yang 	case SCI_DOCUMENTSTARTEXTEND:
3783*8af74909SZhong Yang 		MovePositionTo(0, Selection::selStream);
3784*8af74909SZhong Yang 		SetLastXChosen();
3785*8af74909SZhong Yang 		break;
3786*8af74909SZhong Yang 	case SCI_DOCUMENTEND:
3787*8af74909SZhong Yang 		MovePositionTo(pdoc->Length());
3788*8af74909SZhong Yang 		SetLastXChosen();
3789*8af74909SZhong Yang 		break;
3790*8af74909SZhong Yang 	case SCI_DOCUMENTENDEXTEND:
3791*8af74909SZhong Yang 		MovePositionTo(pdoc->Length(), Selection::selStream);
3792*8af74909SZhong Yang 		SetLastXChosen();
3793*8af74909SZhong Yang 		break;
3794*8af74909SZhong Yang 	case SCI_STUTTEREDPAGEUP:
3795*8af74909SZhong Yang 		PageMove(-1, Selection::noSel, true);
3796*8af74909SZhong Yang 		break;
3797*8af74909SZhong Yang 	case SCI_STUTTEREDPAGEUPEXTEND:
3798*8af74909SZhong Yang 		PageMove(-1, Selection::selStream, true);
3799*8af74909SZhong Yang 		break;
3800*8af74909SZhong Yang 	case SCI_STUTTEREDPAGEDOWN:
3801*8af74909SZhong Yang 		PageMove(1, Selection::noSel, true);
3802*8af74909SZhong Yang 		break;
3803*8af74909SZhong Yang 	case SCI_STUTTEREDPAGEDOWNEXTEND:
3804*8af74909SZhong Yang 		PageMove(1, Selection::selStream, true);
3805*8af74909SZhong Yang 		break;
3806*8af74909SZhong Yang 	case SCI_PAGEUP:
3807*8af74909SZhong Yang 		PageMove(-1);
3808*8af74909SZhong Yang 		break;
3809*8af74909SZhong Yang 	case SCI_PAGEUPEXTEND:
3810*8af74909SZhong Yang 		PageMove(-1, Selection::selStream);
3811*8af74909SZhong Yang 		break;
3812*8af74909SZhong Yang 	case SCI_PAGEUPRECTEXTEND:
3813*8af74909SZhong Yang 		PageMove(-1, Selection::selRectangle);
3814*8af74909SZhong Yang 		break;
3815*8af74909SZhong Yang 	case SCI_PAGEDOWN:
3816*8af74909SZhong Yang 		PageMove(1);
3817*8af74909SZhong Yang 		break;
3818*8af74909SZhong Yang 	case SCI_PAGEDOWNEXTEND:
3819*8af74909SZhong Yang 		PageMove(1, Selection::selStream);
3820*8af74909SZhong Yang 		break;
3821*8af74909SZhong Yang 	case SCI_PAGEDOWNRECTEXTEND:
3822*8af74909SZhong Yang 		PageMove(1, Selection::selRectangle);
3823*8af74909SZhong Yang 		break;
3824*8af74909SZhong Yang 	case SCI_EDITTOGGLEOVERTYPE:
3825*8af74909SZhong Yang 		inOverstrike = !inOverstrike;
3826*8af74909SZhong Yang 		ContainerNeedsUpdate(SC_UPDATE_SELECTION);
3827*8af74909SZhong Yang 		ShowCaretAtCurrentPosition();
3828*8af74909SZhong Yang 		SetIdle(true);
3829*8af74909SZhong Yang 		break;
3830*8af74909SZhong Yang 	case SCI_CANCEL:            	// Cancel any modes - handled in subclass
3831*8af74909SZhong Yang 		// Also unselect text
3832*8af74909SZhong Yang 		CancelModes();
3833*8af74909SZhong Yang 		if ((sel.Count() > 1) && !sel.IsRectangular()) {
3834*8af74909SZhong Yang 			// Drop additional selections
3835*8af74909SZhong Yang 			InvalidateWholeSelection();
3836*8af74909SZhong Yang 			sel.DropAdditionalRanges();
3837*8af74909SZhong Yang 		}
3838*8af74909SZhong Yang 		break;
3839*8af74909SZhong Yang 	case SCI_DELETEBACK:
3840*8af74909SZhong Yang 		DelCharBack(true);
3841*8af74909SZhong Yang 		if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
3842*8af74909SZhong Yang 			SetLastXChosen();
3843*8af74909SZhong Yang 		}
3844*8af74909SZhong Yang 		EnsureCaretVisible();
3845*8af74909SZhong Yang 		break;
3846*8af74909SZhong Yang 	case SCI_DELETEBACKNOTLINE:
3847*8af74909SZhong Yang 		DelCharBack(false);
3848*8af74909SZhong Yang 		if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
3849*8af74909SZhong Yang 			SetLastXChosen();
3850*8af74909SZhong Yang 		}
3851*8af74909SZhong Yang 		EnsureCaretVisible();
3852*8af74909SZhong Yang 		break;
3853*8af74909SZhong Yang 	case SCI_TAB:
3854*8af74909SZhong Yang 		Indent(true);
3855*8af74909SZhong Yang 		if (caretSticky == SC_CARETSTICKY_OFF) {
3856*8af74909SZhong Yang 			SetLastXChosen();
3857*8af74909SZhong Yang 		}
3858*8af74909SZhong Yang 		EnsureCaretVisible();
3859*8af74909SZhong Yang 		ShowCaretAtCurrentPosition();		// Avoid blinking
3860*8af74909SZhong Yang 		break;
3861*8af74909SZhong Yang 	case SCI_BACKTAB:
3862*8af74909SZhong Yang 		Indent(false);
3863*8af74909SZhong Yang 		if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
3864*8af74909SZhong Yang 			SetLastXChosen();
3865*8af74909SZhong Yang 		}
3866*8af74909SZhong Yang 		EnsureCaretVisible();
3867*8af74909SZhong Yang 		ShowCaretAtCurrentPosition();		// Avoid blinking
3868*8af74909SZhong Yang 		break;
3869*8af74909SZhong Yang 	case SCI_NEWLINE:
3870*8af74909SZhong Yang 		NewLine();
3871*8af74909SZhong Yang 		break;
3872*8af74909SZhong Yang 	case SCI_FORMFEED:
3873*8af74909SZhong Yang 		AddChar('\f');
3874*8af74909SZhong Yang 		break;
3875*8af74909SZhong Yang 	case SCI_ZOOMIN:
3876*8af74909SZhong Yang 		if (vs.zoomLevel < 20) {
3877*8af74909SZhong Yang 			vs.zoomLevel++;
3878*8af74909SZhong Yang 			InvalidateStyleRedraw();
3879*8af74909SZhong Yang 			NotifyZoom();
3880*8af74909SZhong Yang 		}
3881*8af74909SZhong Yang 		break;
3882*8af74909SZhong Yang 	case SCI_ZOOMOUT:
3883*8af74909SZhong Yang 		if (vs.zoomLevel > -10) {
3884*8af74909SZhong Yang 			vs.zoomLevel--;
3885*8af74909SZhong Yang 			InvalidateStyleRedraw();
3886*8af74909SZhong Yang 			NotifyZoom();
3887*8af74909SZhong Yang 		}
3888*8af74909SZhong Yang 		break;
3889*8af74909SZhong Yang 
3890*8af74909SZhong Yang 	case SCI_DELWORDLEFT:
3891*8af74909SZhong Yang 	case SCI_DELWORDRIGHT:
3892*8af74909SZhong Yang 	case SCI_DELWORDRIGHTEND:
3893*8af74909SZhong Yang 	case SCI_DELLINELEFT:
3894*8af74909SZhong Yang 	case SCI_DELLINERIGHT:
3895*8af74909SZhong Yang 		return DelWordOrLine(iMessage);
3896*8af74909SZhong Yang 
3897*8af74909SZhong Yang 	case SCI_LINECOPY: {
3898*8af74909SZhong Yang 			const Sci::Line lineStart = pdoc->SciLineFromPosition(SelectionStart().Position());
3899*8af74909SZhong Yang 			const Sci::Line lineEnd = pdoc->SciLineFromPosition(SelectionEnd().Position());
3900*8af74909SZhong Yang 			CopyRangeToClipboard(pdoc->LineStart(lineStart),
3901*8af74909SZhong Yang 				pdoc->LineStart(lineEnd + 1));
3902*8af74909SZhong Yang 		}
3903*8af74909SZhong Yang 		break;
3904*8af74909SZhong Yang 	case SCI_LINECUT: {
3905*8af74909SZhong Yang 			const Sci::Line lineStart = pdoc->SciLineFromPosition(SelectionStart().Position());
3906*8af74909SZhong Yang 			const Sci::Line lineEnd = pdoc->SciLineFromPosition(SelectionEnd().Position());
3907*8af74909SZhong Yang 			const Sci::Position start = pdoc->LineStart(lineStart);
3908*8af74909SZhong Yang 			const Sci::Position end = pdoc->LineStart(lineEnd + 1);
3909*8af74909SZhong Yang 			SetSelection(start, end);
3910*8af74909SZhong Yang 			Cut();
3911*8af74909SZhong Yang 			SetLastXChosen();
3912*8af74909SZhong Yang 		}
3913*8af74909SZhong Yang 		break;
3914*8af74909SZhong Yang 	case SCI_LINEDELETE: {
3915*8af74909SZhong Yang 			const Sci::Line line = pdoc->SciLineFromPosition(sel.MainCaret());
3916*8af74909SZhong Yang 			const Sci::Position start = pdoc->LineStart(line);
3917*8af74909SZhong Yang 			const Sci::Position end = pdoc->LineStart(line + 1);
3918*8af74909SZhong Yang 			pdoc->DeleteChars(start, end - start);
3919*8af74909SZhong Yang 		}
3920*8af74909SZhong Yang 		break;
3921*8af74909SZhong Yang 	case SCI_LINETRANSPOSE:
3922*8af74909SZhong Yang 		LineTranspose();
3923*8af74909SZhong Yang 		break;
3924*8af74909SZhong Yang 	case SCI_LINEREVERSE:
3925*8af74909SZhong Yang 		LineReverse();
3926*8af74909SZhong Yang 		break;
3927*8af74909SZhong Yang 	case SCI_LINEDUPLICATE:
3928*8af74909SZhong Yang 		Duplicate(true);
3929*8af74909SZhong Yang 		break;
3930*8af74909SZhong Yang 	case SCI_SELECTIONDUPLICATE:
3931*8af74909SZhong Yang 		Duplicate(false);
3932*8af74909SZhong Yang 		break;
3933*8af74909SZhong Yang 	case SCI_LOWERCASE:
3934*8af74909SZhong Yang 		ChangeCaseOfSelection(cmLower);
3935*8af74909SZhong Yang 		break;
3936*8af74909SZhong Yang 	case SCI_UPPERCASE:
3937*8af74909SZhong Yang 		ChangeCaseOfSelection(cmUpper);
3938*8af74909SZhong Yang 		break;
3939*8af74909SZhong Yang 	case SCI_SCROLLTOSTART:
3940*8af74909SZhong Yang 		ScrollTo(0);
3941*8af74909SZhong Yang 		break;
3942*8af74909SZhong Yang 	case SCI_SCROLLTOEND:
3943*8af74909SZhong Yang 		ScrollTo(MaxScrollPos());
3944*8af74909SZhong Yang 		break;
3945*8af74909SZhong Yang 	}
3946*8af74909SZhong Yang 	return 0;
3947*8af74909SZhong Yang }
3948*8af74909SZhong Yang 
KeyDefault(int,int)3949*8af74909SZhong Yang int Editor::KeyDefault(int, int) {
3950*8af74909SZhong Yang 	return 0;
3951*8af74909SZhong Yang }
3952*8af74909SZhong Yang 
KeyDownWithModifiers(int key,int modifiers,bool * consumed)3953*8af74909SZhong Yang int Editor::KeyDownWithModifiers(int key, int modifiers, bool *consumed) {
3954*8af74909SZhong Yang 	DwellEnd(false);
3955*8af74909SZhong Yang 	const int msg = kmap.Find(key, modifiers);
3956*8af74909SZhong Yang 	if (msg) {
3957*8af74909SZhong Yang 		if (consumed)
3958*8af74909SZhong Yang 			*consumed = true;
3959*8af74909SZhong Yang 		return static_cast<int>(WndProc(msg, 0, 0));
3960*8af74909SZhong Yang 	} else {
3961*8af74909SZhong Yang 		if (consumed)
3962*8af74909SZhong Yang 			*consumed = false;
3963*8af74909SZhong Yang 		return KeyDefault(key, modifiers);
3964*8af74909SZhong Yang 	}
3965*8af74909SZhong Yang }
3966*8af74909SZhong Yang 
Indent(bool forwards)3967*8af74909SZhong Yang void Editor::Indent(bool forwards) {
3968*8af74909SZhong Yang 	UndoGroup ug(pdoc);
3969*8af74909SZhong Yang 	for (size_t r=0; r<sel.Count(); r++) {
3970*8af74909SZhong Yang 		const Sci::Line lineOfAnchor =
3971*8af74909SZhong Yang 			pdoc->SciLineFromPosition(sel.Range(r).anchor.Position());
3972*8af74909SZhong Yang 		Sci::Position caretPosition = sel.Range(r).caret.Position();
3973*8af74909SZhong Yang 		const Sci::Line lineCurrentPos = pdoc->SciLineFromPosition(caretPosition);
3974*8af74909SZhong Yang 		if (lineOfAnchor == lineCurrentPos) {
3975*8af74909SZhong Yang 			if (forwards) {
3976*8af74909SZhong Yang 				pdoc->DeleteChars(sel.Range(r).Start().Position(), sel.Range(r).Length());
3977*8af74909SZhong Yang 				caretPosition = sel.Range(r).caret.Position();
3978*8af74909SZhong Yang 				if (pdoc->GetColumn(caretPosition) <= pdoc->GetColumn(pdoc->GetLineIndentPosition(lineCurrentPos)) &&
3979*8af74909SZhong Yang 						pdoc->tabIndents) {
3980*8af74909SZhong Yang 					const int indentation = pdoc->GetLineIndentation(lineCurrentPos);
3981*8af74909SZhong Yang 					const int indentationStep = pdoc->IndentSize();
3982*8af74909SZhong Yang 					const Sci::Position posSelect = pdoc->SetLineIndentation(
3983*8af74909SZhong Yang 						lineCurrentPos, indentation + indentationStep - indentation % indentationStep);
3984*8af74909SZhong Yang 					sel.Range(r) = SelectionRange(posSelect);
3985*8af74909SZhong Yang 				} else {
3986*8af74909SZhong Yang 					if (pdoc->useTabs) {
3987*8af74909SZhong Yang 						const Sci::Position lengthInserted = pdoc->InsertString(caretPosition, "\t", 1);
3988*8af74909SZhong Yang 						sel.Range(r) = SelectionRange(caretPosition + lengthInserted);
3989*8af74909SZhong Yang 					} else {
3990*8af74909SZhong Yang 						int numSpaces = (pdoc->tabInChars) -
3991*8af74909SZhong Yang 								(pdoc->GetColumn(caretPosition) % (pdoc->tabInChars));
3992*8af74909SZhong Yang 						if (numSpaces < 1)
3993*8af74909SZhong Yang 							numSpaces = pdoc->tabInChars;
3994*8af74909SZhong Yang 						const std::string spaceText(numSpaces, ' ');
3995*8af74909SZhong Yang 						const Sci::Position lengthInserted = pdoc->InsertString(caretPosition, spaceText.c_str(),
3996*8af74909SZhong Yang 							spaceText.length());
3997*8af74909SZhong Yang 						sel.Range(r) = SelectionRange(caretPosition + lengthInserted);
3998*8af74909SZhong Yang 					}
3999*8af74909SZhong Yang 				}
4000*8af74909SZhong Yang 			} else {
4001*8af74909SZhong Yang 				if (pdoc->GetColumn(caretPosition) <= pdoc->GetLineIndentation(lineCurrentPos) &&
4002*8af74909SZhong Yang 						pdoc->tabIndents) {
4003*8af74909SZhong Yang 					const int indentation = pdoc->GetLineIndentation(lineCurrentPos);
4004*8af74909SZhong Yang 					const int indentationStep = pdoc->IndentSize();
4005*8af74909SZhong Yang 					const Sci::Position posSelect = pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep);
4006*8af74909SZhong Yang 					sel.Range(r) = SelectionRange(posSelect);
4007*8af74909SZhong Yang 				} else {
4008*8af74909SZhong Yang 					Sci::Position newColumn = ((pdoc->GetColumn(caretPosition) - 1) / pdoc->tabInChars) *
4009*8af74909SZhong Yang 							pdoc->tabInChars;
4010*8af74909SZhong Yang 					if (newColumn < 0)
4011*8af74909SZhong Yang 						newColumn = 0;
4012*8af74909SZhong Yang 					Sci::Position newPos = caretPosition;
4013*8af74909SZhong Yang 					while (pdoc->GetColumn(newPos) > newColumn)
4014*8af74909SZhong Yang 						newPos--;
4015*8af74909SZhong Yang 					sel.Range(r) = SelectionRange(newPos);
4016*8af74909SZhong Yang 				}
4017*8af74909SZhong Yang 			}
4018*8af74909SZhong Yang 		} else {	// Multiline
4019*8af74909SZhong Yang 			const Sci::Position anchorPosOnLine = sel.Range(r).anchor.Position() -
4020*8af74909SZhong Yang 				pdoc->LineStart(lineOfAnchor);
4021*8af74909SZhong Yang 			const Sci::Position currentPosPosOnLine = caretPosition -
4022*8af74909SZhong Yang 				pdoc->LineStart(lineCurrentPos);
4023*8af74909SZhong Yang 			// Multiple lines selected so indent / dedent
4024*8af74909SZhong Yang 			const Sci::Line lineTopSel = std::min(lineOfAnchor, lineCurrentPos);
4025*8af74909SZhong Yang 			Sci::Line lineBottomSel = std::max(lineOfAnchor, lineCurrentPos);
4026*8af74909SZhong Yang 			if (pdoc->LineStart(lineBottomSel) == sel.Range(r).anchor.Position() || pdoc->LineStart(lineBottomSel) == caretPosition)
4027*8af74909SZhong Yang 				lineBottomSel--;  	// If not selecting any characters on a line, do not indent
4028*8af74909SZhong Yang 			pdoc->Indent(forwards, lineBottomSel, lineTopSel);
4029*8af74909SZhong Yang 			if (lineOfAnchor < lineCurrentPos) {
4030*8af74909SZhong Yang 				if (currentPosPosOnLine == 0)
4031*8af74909SZhong Yang 					sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos),
4032*8af74909SZhong Yang 						pdoc->LineStart(lineOfAnchor));
4033*8af74909SZhong Yang 				else
4034*8af74909SZhong Yang 					sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos + 1),
4035*8af74909SZhong Yang 						pdoc->LineStart(lineOfAnchor));
4036*8af74909SZhong Yang 			} else {
4037*8af74909SZhong Yang 				if (anchorPosOnLine == 0)
4038*8af74909SZhong Yang 					sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos),
4039*8af74909SZhong Yang 						pdoc->LineStart(lineOfAnchor));
4040*8af74909SZhong Yang 				else
4041*8af74909SZhong Yang 					sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos),
4042*8af74909SZhong Yang 						pdoc->LineStart(lineOfAnchor + 1));
4043*8af74909SZhong Yang 			}
4044*8af74909SZhong Yang 		}
4045*8af74909SZhong Yang 	}
4046*8af74909SZhong Yang 	ContainerNeedsUpdate(SC_UPDATE_SELECTION);
4047*8af74909SZhong Yang }
4048*8af74909SZhong Yang 
4049*8af74909SZhong Yang class CaseFolderASCII : public CaseFolderTable {
4050*8af74909SZhong Yang public:
CaseFolderASCII()4051*8af74909SZhong Yang 	CaseFolderASCII() noexcept {
4052*8af74909SZhong Yang 		StandardASCII();
4053*8af74909SZhong Yang 	}
4054*8af74909SZhong Yang };
4055*8af74909SZhong Yang 
4056*8af74909SZhong Yang 
CaseFolderForEncoding()4057*8af74909SZhong Yang CaseFolder *Editor::CaseFolderForEncoding() {
4058*8af74909SZhong Yang 	// Simple default that only maps ASCII upper case to lower case.
4059*8af74909SZhong Yang 	return new CaseFolderASCII();
4060*8af74909SZhong Yang }
4061*8af74909SZhong Yang 
4062*8af74909SZhong Yang /**
4063*8af74909SZhong Yang  * Search of a text in the document, in the given range.
4064*8af74909SZhong Yang  * @return The position of the found text, -1 if not found.
4065*8af74909SZhong Yang  */
FindText(uptr_t wParam,sptr_t lParam)4066*8af74909SZhong Yang Sci::Position Editor::FindText(
4067*8af74909SZhong Yang     uptr_t wParam,		///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD,
4068*8af74909SZhong Yang     ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
4069*8af74909SZhong Yang     sptr_t lParam) {	///< @c Sci_TextToFind structure: The text to search for in the given range.
4070*8af74909SZhong Yang 
4071*8af74909SZhong Yang 	Sci_TextToFind *ft = static_cast<Sci_TextToFind *>(PtrFromSPtr(lParam));
4072*8af74909SZhong Yang 	Sci::Position lengthFound = strlen(ft->lpstrText);
4073*8af74909SZhong Yang 	if (!pdoc->HasCaseFolder())
4074*8af74909SZhong Yang 		pdoc->SetCaseFolder(CaseFolderForEncoding());
4075*8af74909SZhong Yang 	try {
4076*8af74909SZhong Yang 		const Sci::Position pos = pdoc->FindText(
4077*8af74909SZhong Yang 			static_cast<Sci::Position>(ft->chrg.cpMin),
4078*8af74909SZhong Yang 			static_cast<Sci::Position>(ft->chrg.cpMax),
4079*8af74909SZhong Yang 			ft->lpstrText,
4080*8af74909SZhong Yang 			static_cast<int>(wParam),
4081*8af74909SZhong Yang 			&lengthFound);
4082*8af74909SZhong Yang 		if (pos != -1) {
4083*8af74909SZhong Yang 			ft->chrgText.cpMin = static_cast<Sci_PositionCR>(pos);
4084*8af74909SZhong Yang 			ft->chrgText.cpMax = static_cast<Sci_PositionCR>(pos + lengthFound);
4085*8af74909SZhong Yang 		}
4086*8af74909SZhong Yang 		return pos;
4087*8af74909SZhong Yang 	} catch (RegexError &) {
4088*8af74909SZhong Yang 		errorStatus = SC_STATUS_WARN_REGEX;
4089*8af74909SZhong Yang 		return -1;
4090*8af74909SZhong Yang 	}
4091*8af74909SZhong Yang }
4092*8af74909SZhong Yang 
4093*8af74909SZhong Yang /**
4094*8af74909SZhong Yang  * Relocatable search support : Searches relative to current selection
4095*8af74909SZhong Yang  * point and sets the selection to the found text range with
4096*8af74909SZhong Yang  * each search.
4097*8af74909SZhong Yang  */
4098*8af74909SZhong Yang /**
4099*8af74909SZhong Yang  * Anchor following searches at current selection start: This allows
4100*8af74909SZhong Yang  * multiple incremental interactive searches to be macro recorded
4101*8af74909SZhong Yang  * while still setting the selection to found text so the find/select
4102*8af74909SZhong Yang  * operation is self-contained.
4103*8af74909SZhong Yang  */
SearchAnchor()4104*8af74909SZhong Yang void Editor::SearchAnchor() {
4105*8af74909SZhong Yang 	searchAnchor = SelectionStart().Position();
4106*8af74909SZhong Yang }
4107*8af74909SZhong Yang 
4108*8af74909SZhong Yang /**
4109*8af74909SZhong Yang  * Find text from current search anchor: Must call @c SearchAnchor first.
4110*8af74909SZhong Yang  * Used for next text and previous text requests.
4111*8af74909SZhong Yang  * @return The position of the found text, -1 if not found.
4112*8af74909SZhong Yang  */
SearchText(unsigned int iMessage,uptr_t wParam,sptr_t lParam)4113*8af74909SZhong Yang Sci::Position Editor::SearchText(
4114*8af74909SZhong Yang     unsigned int iMessage,		///< Accepts both @c SCI_SEARCHNEXT and @c SCI_SEARCHPREV.
4115*8af74909SZhong Yang     uptr_t wParam,				///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD,
4116*8af74909SZhong Yang     ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
4117*8af74909SZhong Yang     sptr_t lParam) {			///< The text to search for.
4118*8af74909SZhong Yang 
4119*8af74909SZhong Yang 	const char *txt = CharPtrFromSPtr(lParam);
4120*8af74909SZhong Yang 	Sci::Position pos = INVALID_POSITION;
4121*8af74909SZhong Yang 	Sci::Position lengthFound = strlen(txt);
4122*8af74909SZhong Yang 	if (!pdoc->HasCaseFolder())
4123*8af74909SZhong Yang 		pdoc->SetCaseFolder(CaseFolderForEncoding());
4124*8af74909SZhong Yang 	try {
4125*8af74909SZhong Yang 		if (iMessage == SCI_SEARCHNEXT) {
4126*8af74909SZhong Yang 			pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt,
4127*8af74909SZhong Yang 					static_cast<int>(wParam),
4128*8af74909SZhong Yang 					&lengthFound);
4129*8af74909SZhong Yang 		} else {
4130*8af74909SZhong Yang 			pos = pdoc->FindText(searchAnchor, 0, txt,
4131*8af74909SZhong Yang 					static_cast<int>(wParam),
4132*8af74909SZhong Yang 					&lengthFound);
4133*8af74909SZhong Yang 		}
4134*8af74909SZhong Yang 	} catch (RegexError &) {
4135*8af74909SZhong Yang 		errorStatus = SC_STATUS_WARN_REGEX;
4136*8af74909SZhong Yang 		return INVALID_POSITION;
4137*8af74909SZhong Yang 	}
4138*8af74909SZhong Yang 	if (pos != INVALID_POSITION) {
4139*8af74909SZhong Yang 		SetSelection(pos, pos + lengthFound);
4140*8af74909SZhong Yang 	}
4141*8af74909SZhong Yang 
4142*8af74909SZhong Yang 	return pos;
4143*8af74909SZhong Yang }
4144*8af74909SZhong Yang 
CaseMapString(const std::string & s,int caseMapping)4145*8af74909SZhong Yang std::string Editor::CaseMapString(const std::string &s, int caseMapping) {
4146*8af74909SZhong Yang 	std::string ret(s);
4147*8af74909SZhong Yang 	for (char &ch : ret) {
4148*8af74909SZhong Yang 		switch (caseMapping) {
4149*8af74909SZhong Yang 			case cmUpper:
4150*8af74909SZhong Yang 				ch = MakeUpperCase(ch);
4151*8af74909SZhong Yang 				break;
4152*8af74909SZhong Yang 			case cmLower:
4153*8af74909SZhong Yang 				ch = MakeLowerCase(ch);
4154*8af74909SZhong Yang 				break;
4155*8af74909SZhong Yang 		}
4156*8af74909SZhong Yang 	}
4157*8af74909SZhong Yang 	return ret;
4158*8af74909SZhong Yang }
4159*8af74909SZhong Yang 
4160*8af74909SZhong Yang /**
4161*8af74909SZhong Yang  * Search for text in the target range of the document.
4162*8af74909SZhong Yang  * @return The position of the found text, -1 if not found.
4163*8af74909SZhong Yang  */
SearchInTarget(const char * text,Sci::Position length)4164*8af74909SZhong Yang Sci::Position Editor::SearchInTarget(const char *text, Sci::Position length) {
4165*8af74909SZhong Yang 	Sci::Position lengthFound = length;
4166*8af74909SZhong Yang 
4167*8af74909SZhong Yang 	if (!pdoc->HasCaseFolder())
4168*8af74909SZhong Yang 		pdoc->SetCaseFolder(CaseFolderForEncoding());
4169*8af74909SZhong Yang 	try {
4170*8af74909SZhong Yang 		const Sci::Position pos = pdoc->FindText(targetRange.start.Position(), targetRange.end.Position(), text,
4171*8af74909SZhong Yang 				searchFlags,
4172*8af74909SZhong Yang 				&lengthFound);
4173*8af74909SZhong Yang 		if (pos != -1) {
4174*8af74909SZhong Yang 			targetRange.start.SetPosition(pos);
4175*8af74909SZhong Yang 			targetRange.end.SetPosition(pos + lengthFound);
4176*8af74909SZhong Yang 		}
4177*8af74909SZhong Yang 		return pos;
4178*8af74909SZhong Yang 	} catch (RegexError &) {
4179*8af74909SZhong Yang 		errorStatus = SC_STATUS_WARN_REGEX;
4180*8af74909SZhong Yang 		return -1;
4181*8af74909SZhong Yang 	}
4182*8af74909SZhong Yang }
4183*8af74909SZhong Yang 
GoToLine(Sci::Line lineNo)4184*8af74909SZhong Yang void Editor::GoToLine(Sci::Line lineNo) {
4185*8af74909SZhong Yang 	if (lineNo > pdoc->LinesTotal())
4186*8af74909SZhong Yang 		lineNo = pdoc->LinesTotal();
4187*8af74909SZhong Yang 	if (lineNo < 0)
4188*8af74909SZhong Yang 		lineNo = 0;
4189*8af74909SZhong Yang 	SetEmptySelection(pdoc->LineStart(lineNo));
4190*8af74909SZhong Yang 	ShowCaretAtCurrentPosition();
4191*8af74909SZhong Yang 	EnsureCaretVisible();
4192*8af74909SZhong Yang }
4193*8af74909SZhong Yang 
Close(Point pt1,Point pt2,Point threshold)4194*8af74909SZhong Yang static bool Close(Point pt1, Point pt2, Point threshold) noexcept {
4195*8af74909SZhong Yang 	const Point ptDifference = pt2 - pt1;
4196*8af74909SZhong Yang 	if (std::abs(ptDifference.x) > threshold.x)
4197*8af74909SZhong Yang 		return false;
4198*8af74909SZhong Yang 	if (std::abs(ptDifference.y) > threshold.y)
4199*8af74909SZhong Yang 		return false;
4200*8af74909SZhong Yang 	return true;
4201*8af74909SZhong Yang }
4202*8af74909SZhong Yang 
RangeText(Sci::Position start,Sci::Position end) const4203*8af74909SZhong Yang std::string Editor::RangeText(Sci::Position start, Sci::Position end) const {
4204*8af74909SZhong Yang 	if (start < end) {
4205*8af74909SZhong Yang 		const Sci::Position len = end - start;
4206*8af74909SZhong Yang 		std::string ret(len, '\0');
4207*8af74909SZhong Yang 		pdoc->GetCharRange(ret.data(), start, len);
4208*8af74909SZhong Yang 		return ret;
4209*8af74909SZhong Yang 	}
4210*8af74909SZhong Yang 	return std::string();
4211*8af74909SZhong Yang }
4212*8af74909SZhong Yang 
CopySelectionRange(SelectionText * ss,bool allowLineCopy)4213*8af74909SZhong Yang void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
4214*8af74909SZhong Yang 	if (sel.Empty()) {
4215*8af74909SZhong Yang 		if (allowLineCopy) {
4216*8af74909SZhong Yang 			const Sci::Line currentLine = pdoc->SciLineFromPosition(sel.MainCaret());
4217*8af74909SZhong Yang 			const Sci::Position start = pdoc->LineStart(currentLine);
4218*8af74909SZhong Yang 			const Sci::Position end = pdoc->LineEnd(currentLine);
4219*8af74909SZhong Yang 
4220*8af74909SZhong Yang 			std::string text = RangeText(start, end);
4221*8af74909SZhong Yang 			if (pdoc->eolMode != SC_EOL_LF)
4222*8af74909SZhong Yang 				text.push_back('\r');
4223*8af74909SZhong Yang 			if (pdoc->eolMode != SC_EOL_CR)
4224*8af74909SZhong Yang 				text.push_back('\n');
4225*8af74909SZhong Yang 			ss->Copy(text, pdoc->dbcsCodePage,
4226*8af74909SZhong Yang 				vs.styles[STYLE_DEFAULT].characterSet, false, true);
4227*8af74909SZhong Yang 		}
4228*8af74909SZhong Yang 	} else {
4229*8af74909SZhong Yang 		std::string text;
4230*8af74909SZhong Yang 		std::vector<SelectionRange> rangesInOrder = sel.RangesCopy();
4231*8af74909SZhong Yang 		if (sel.selType == Selection::selRectangle)
4232*8af74909SZhong Yang 			std::sort(rangesInOrder.begin(), rangesInOrder.end());
4233*8af74909SZhong Yang 		for (const SelectionRange &current : rangesInOrder) {
4234*8af74909SZhong Yang 				text.append(RangeText(current.Start().Position(), current.End().Position()));
4235*8af74909SZhong Yang 			if (sel.selType == Selection::selRectangle) {
4236*8af74909SZhong Yang 				if (pdoc->eolMode != SC_EOL_LF)
4237*8af74909SZhong Yang 					text.push_back('\r');
4238*8af74909SZhong Yang 				if (pdoc->eolMode != SC_EOL_CR)
4239*8af74909SZhong Yang 					text.push_back('\n');
4240*8af74909SZhong Yang 			}
4241*8af74909SZhong Yang 		}
4242*8af74909SZhong Yang 		ss->Copy(text, pdoc->dbcsCodePage,
4243*8af74909SZhong Yang 			vs.styles[STYLE_DEFAULT].characterSet, sel.IsRectangular(), sel.selType == Selection::selLines);
4244*8af74909SZhong Yang 	}
4245*8af74909SZhong Yang }
4246*8af74909SZhong Yang 
CopyRangeToClipboard(Sci::Position start,Sci::Position end)4247*8af74909SZhong Yang void Editor::CopyRangeToClipboard(Sci::Position start, Sci::Position end) {
4248*8af74909SZhong Yang 	start = pdoc->ClampPositionIntoDocument(start);
4249*8af74909SZhong Yang 	end = pdoc->ClampPositionIntoDocument(end);
4250*8af74909SZhong Yang 	SelectionText selectedText;
4251*8af74909SZhong Yang 	std::string text = RangeText(start, end);
4252*8af74909SZhong Yang 	selectedText.Copy(text,
4253*8af74909SZhong Yang 		pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false);
4254*8af74909SZhong Yang 	CopyToClipboard(selectedText);
4255*8af74909SZhong Yang }
4256*8af74909SZhong Yang 
CopyText(size_t length,const char * text)4257*8af74909SZhong Yang void Editor::CopyText(size_t length, const char *text) {
4258*8af74909SZhong Yang 	SelectionText selectedText;
4259*8af74909SZhong Yang 	selectedText.Copy(std::string(text, length),
4260*8af74909SZhong Yang 		pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false);
4261*8af74909SZhong Yang 	CopyToClipboard(selectedText);
4262*8af74909SZhong Yang }
4263*8af74909SZhong Yang 
SetDragPosition(SelectionPosition newPos)4264*8af74909SZhong Yang void Editor::SetDragPosition(SelectionPosition newPos) {
4265*8af74909SZhong Yang 	if (newPos.Position() >= 0) {
4266*8af74909SZhong Yang 		newPos = MovePositionOutsideChar(newPos, 1);
4267*8af74909SZhong Yang 		posDrop = newPos;
4268*8af74909SZhong Yang 	}
4269*8af74909SZhong Yang 	if (!(posDrag == newPos)) {
4270*8af74909SZhong Yang 		const CaretPolicies dragCaretPolicies = {
4271*8af74909SZhong Yang 			CaretPolicy(CARET_SLOP | CARET_STRICT | CARET_EVEN, 50),
4272*8af74909SZhong Yang 			CaretPolicy(CARET_SLOP | CARET_STRICT | CARET_EVEN, 2)
4273*8af74909SZhong Yang 		};
4274*8af74909SZhong Yang 		MovedCaret(newPos, posDrag, true, dragCaretPolicies);
4275*8af74909SZhong Yang 
4276*8af74909SZhong Yang 		caret.on = true;
4277*8af74909SZhong Yang 		FineTickerCancel(tickCaret);
4278*8af74909SZhong Yang 		if ((caret.active) && (caret.period > 0) && (newPos.Position() < 0))
4279*8af74909SZhong Yang 			FineTickerStart(tickCaret, caret.period, caret.period/10);
4280*8af74909SZhong Yang 		InvalidateCaret();
4281*8af74909SZhong Yang 		posDrag = newPos;
4282*8af74909SZhong Yang 		InvalidateCaret();
4283*8af74909SZhong Yang 	}
4284*8af74909SZhong Yang }
4285*8af74909SZhong Yang 
DisplayCursor(Window::Cursor c)4286*8af74909SZhong Yang void Editor::DisplayCursor(Window::Cursor c) {
4287*8af74909SZhong Yang 	if (cursorMode == SC_CURSORNORMAL)
4288*8af74909SZhong Yang 		wMain.SetCursor(c);
4289*8af74909SZhong Yang 	else
4290*8af74909SZhong Yang 		wMain.SetCursor(static_cast<Window::Cursor>(cursorMode));
4291*8af74909SZhong Yang }
4292*8af74909SZhong Yang 
DragThreshold(Point ptStart,Point ptNow)4293*8af74909SZhong Yang bool Editor::DragThreshold(Point ptStart, Point ptNow) {
4294*8af74909SZhong Yang 	const Point ptDiff = ptStart - ptNow;
4295*8af74909SZhong Yang 	const XYPOSITION distanceSquared = ptDiff.x * ptDiff.x + ptDiff.y * ptDiff.y;
4296*8af74909SZhong Yang 	return distanceSquared > 16.0f;
4297*8af74909SZhong Yang }
4298*8af74909SZhong Yang 
StartDrag()4299*8af74909SZhong Yang void Editor::StartDrag() {
4300*8af74909SZhong Yang 	// Always handled by subclasses
4301*8af74909SZhong Yang 	//SetMouseCapture(true);
4302*8af74909SZhong Yang 	//DisplayCursor(Window::cursorArrow);
4303*8af74909SZhong Yang }
4304*8af74909SZhong Yang 
DropAt(SelectionPosition position,const char * value,size_t lengthValue,bool moving,bool rectangular)4305*8af74909SZhong Yang void Editor::DropAt(SelectionPosition position, const char *value, size_t lengthValue, bool moving, bool rectangular) {
4306*8af74909SZhong Yang 	//Platform::DebugPrintf("DropAt %d %d\n", inDragDrop, position);
4307*8af74909SZhong Yang 	if (inDragDrop == ddDragging)
4308*8af74909SZhong Yang 		dropWentOutside = false;
4309*8af74909SZhong Yang 
4310*8af74909SZhong Yang 	const bool positionWasInSelection = PositionInSelection(position.Position());
4311*8af74909SZhong Yang 
4312*8af74909SZhong Yang 	const bool positionOnEdgeOfSelection =
4313*8af74909SZhong Yang 	    (position == SelectionStart()) || (position == SelectionEnd());
4314*8af74909SZhong Yang 
4315*8af74909SZhong Yang 	if ((inDragDrop != ddDragging) || !(positionWasInSelection) ||
4316*8af74909SZhong Yang 	        (positionOnEdgeOfSelection && !moving)) {
4317*8af74909SZhong Yang 
4318*8af74909SZhong Yang 		const SelectionPosition selStart = SelectionStart();
4319*8af74909SZhong Yang 		const SelectionPosition selEnd = SelectionEnd();
4320*8af74909SZhong Yang 
4321*8af74909SZhong Yang 		UndoGroup ug(pdoc);
4322*8af74909SZhong Yang 
4323*8af74909SZhong Yang 		SelectionPosition positionAfterDeletion = position;
4324*8af74909SZhong Yang 		if ((inDragDrop == ddDragging) && moving) {
4325*8af74909SZhong Yang 			// Remove dragged out text
4326*8af74909SZhong Yang 			if (rectangular || sel.selType == Selection::selLines) {
4327*8af74909SZhong Yang 				for (size_t r=0; r<sel.Count(); r++) {
4328*8af74909SZhong Yang 					if (position >= sel.Range(r).Start()) {
4329*8af74909SZhong Yang 						if (position > sel.Range(r).End()) {
4330*8af74909SZhong Yang 							positionAfterDeletion.Add(-sel.Range(r).Length());
4331*8af74909SZhong Yang 						} else {
4332*8af74909SZhong Yang 							positionAfterDeletion.Add(-SelectionRange(position, sel.Range(r).Start()).Length());
4333*8af74909SZhong Yang 						}
4334*8af74909SZhong Yang 					}
4335*8af74909SZhong Yang 				}
4336*8af74909SZhong Yang 			} else {
4337*8af74909SZhong Yang 				if (position > selStart) {
4338*8af74909SZhong Yang 					positionAfterDeletion.Add(-SelectionRange(selEnd, selStart).Length());
4339*8af74909SZhong Yang 				}
4340*8af74909SZhong Yang 			}
4341*8af74909SZhong Yang 			ClearSelection();
4342*8af74909SZhong Yang 		}
4343*8af74909SZhong Yang 		position = positionAfterDeletion;
4344*8af74909SZhong Yang 
4345*8af74909SZhong Yang 		std::string convertedText = Document::TransformLineEnds(value, lengthValue, pdoc->eolMode);
4346*8af74909SZhong Yang 
4347*8af74909SZhong Yang 		if (rectangular) {
4348*8af74909SZhong Yang 			PasteRectangular(position, convertedText.c_str(), convertedText.length());
4349*8af74909SZhong Yang 			// Should try to select new rectangle but it may not be a rectangle now so just select the drop position
4350*8af74909SZhong Yang 			SetEmptySelection(position);
4351*8af74909SZhong Yang 		} else {
4352*8af74909SZhong Yang 			position = MovePositionOutsideChar(position, sel.MainCaret() - position.Position());
4353*8af74909SZhong Yang 			position = RealizeVirtualSpace(position);
4354*8af74909SZhong Yang 			const Sci::Position lengthInserted = pdoc->InsertString(
4355*8af74909SZhong Yang 				position.Position(), convertedText.c_str(), convertedText.length());
4356*8af74909SZhong Yang 			if (lengthInserted > 0) {
4357*8af74909SZhong Yang 				SelectionPosition posAfterInsertion = position;
4358*8af74909SZhong Yang 				posAfterInsertion.Add(lengthInserted);
4359*8af74909SZhong Yang 				SetSelection(posAfterInsertion, position);
4360*8af74909SZhong Yang 			}
4361*8af74909SZhong Yang 		}
4362*8af74909SZhong Yang 	} else if (inDragDrop == ddDragging) {
4363*8af74909SZhong Yang 		SetEmptySelection(position);
4364*8af74909SZhong Yang 	}
4365*8af74909SZhong Yang }
4366*8af74909SZhong Yang 
DropAt(SelectionPosition position,const char * value,bool moving,bool rectangular)4367*8af74909SZhong Yang void Editor::DropAt(SelectionPosition position, const char *value, bool moving, bool rectangular) {
4368*8af74909SZhong Yang 	DropAt(position, value, strlen(value), moving, rectangular);
4369*8af74909SZhong Yang }
4370*8af74909SZhong Yang 
4371*8af74909SZhong Yang /**
4372*8af74909SZhong Yang  * @return true if given position is inside the selection,
4373*8af74909SZhong Yang  */
PositionInSelection(Sci::Position pos)4374*8af74909SZhong Yang bool Editor::PositionInSelection(Sci::Position pos) {
4375*8af74909SZhong Yang 	pos = MovePositionOutsideChar(pos, sel.MainCaret() - pos);
4376*8af74909SZhong Yang 	for (size_t r=0; r<sel.Count(); r++) {
4377*8af74909SZhong Yang 		if (sel.Range(r).Contains(pos))
4378*8af74909SZhong Yang 			return true;
4379*8af74909SZhong Yang 	}
4380*8af74909SZhong Yang 	return false;
4381*8af74909SZhong Yang }
4382*8af74909SZhong Yang 
PointInSelection(Point pt)4383*8af74909SZhong Yang bool Editor::PointInSelection(Point pt) {
4384*8af74909SZhong Yang 	const SelectionPosition pos = SPositionFromLocation(pt, false, true);
4385*8af74909SZhong Yang 	const Point ptPos = LocationFromPosition(pos);
4386*8af74909SZhong Yang 	for (size_t r=0; r<sel.Count(); r++) {
4387*8af74909SZhong Yang 		const SelectionRange &range = sel.Range(r);
4388*8af74909SZhong Yang 		if (range.Contains(pos)) {
4389*8af74909SZhong Yang 			bool hit = true;
4390*8af74909SZhong Yang 			if (pos == range.Start()) {
4391*8af74909SZhong Yang 				// see if just before selection
4392*8af74909SZhong Yang 				if (pt.x < ptPos.x) {
4393*8af74909SZhong Yang 					hit = false;
4394*8af74909SZhong Yang 				}
4395*8af74909SZhong Yang 			}
4396*8af74909SZhong Yang 			if (pos == range.End()) {
4397*8af74909SZhong Yang 				// see if just after selection
4398*8af74909SZhong Yang 				if (pt.x > ptPos.x) {
4399*8af74909SZhong Yang 					hit = false;
4400*8af74909SZhong Yang 				}
4401*8af74909SZhong Yang 			}
4402*8af74909SZhong Yang 			if (hit)
4403*8af74909SZhong Yang 				return true;
4404*8af74909SZhong Yang 		}
4405*8af74909SZhong Yang 	}
4406*8af74909SZhong Yang 	return false;
4407*8af74909SZhong Yang }
4408*8af74909SZhong Yang 
PointInSelMargin(Point pt) const4409*8af74909SZhong Yang bool Editor::PointInSelMargin(Point pt) const {
4410*8af74909SZhong Yang 	// Really means: "Point in a margin"
4411*8af74909SZhong Yang 	if (vs.fixedColumnWidth > 0) {	// There is a margin
4412*8af74909SZhong Yang 		PRectangle rcSelMargin = GetClientRectangle();
4413*8af74909SZhong Yang 		rcSelMargin.right = static_cast<XYPOSITION>(vs.textStart - vs.leftMarginWidth);
4414*8af74909SZhong Yang 		rcSelMargin.left = static_cast<XYPOSITION>(vs.textStart - vs.fixedColumnWidth);
4415*8af74909SZhong Yang 		const Point ptOrigin = GetVisibleOriginInMain();
4416*8af74909SZhong Yang 		rcSelMargin.Move(0, -ptOrigin.y);
4417*8af74909SZhong Yang 		return rcSelMargin.ContainsWholePixel(pt);
4418*8af74909SZhong Yang 	} else {
4419*8af74909SZhong Yang 		return false;
4420*8af74909SZhong Yang 	}
4421*8af74909SZhong Yang }
4422*8af74909SZhong Yang 
GetMarginCursor(Point pt) const4423*8af74909SZhong Yang Window::Cursor Editor::GetMarginCursor(Point pt) const noexcept {
4424*8af74909SZhong Yang 	int x = 0;
4425*8af74909SZhong Yang 	for (const MarginStyle &m : vs.ms) {
4426*8af74909SZhong Yang 		if ((pt.x >= x) && (pt.x < x + m.width))
4427*8af74909SZhong Yang 			return static_cast<Window::Cursor>(m.cursor);
4428*8af74909SZhong Yang 		x += m.width;
4429*8af74909SZhong Yang 	}
4430*8af74909SZhong Yang 	return Window::cursorReverseArrow;
4431*8af74909SZhong Yang }
4432*8af74909SZhong Yang 
TrimAndSetSelection(Sci::Position currentPos_,Sci::Position anchor_)4433*8af74909SZhong Yang void Editor::TrimAndSetSelection(Sci::Position currentPos_, Sci::Position anchor_) {
4434*8af74909SZhong Yang 	sel.TrimSelection(SelectionRange(currentPos_, anchor_));
4435*8af74909SZhong Yang 	SetSelection(currentPos_, anchor_);
4436*8af74909SZhong Yang }
4437*8af74909SZhong Yang 
LineSelection(Sci::Position lineCurrentPos_,Sci::Position lineAnchorPos_,bool wholeLine)4438*8af74909SZhong Yang void Editor::LineSelection(Sci::Position lineCurrentPos_, Sci::Position lineAnchorPos_, bool wholeLine) {
4439*8af74909SZhong Yang 	Sci::Position selCurrentPos;
4440*8af74909SZhong Yang 	Sci::Position selAnchorPos;
4441*8af74909SZhong Yang 	if (wholeLine) {
4442*8af74909SZhong Yang 		const Sci::Line lineCurrent_ = pdoc->SciLineFromPosition(lineCurrentPos_);
4443*8af74909SZhong Yang 		const Sci::Line lineAnchor_ = pdoc->SciLineFromPosition(lineAnchorPos_);
4444*8af74909SZhong Yang 		if (lineAnchorPos_ < lineCurrentPos_) {
4445*8af74909SZhong Yang 			selCurrentPos = pdoc->LineStart(lineCurrent_ + 1);
4446*8af74909SZhong Yang 			selAnchorPos = pdoc->LineStart(lineAnchor_);
4447*8af74909SZhong Yang 		} else if (lineAnchorPos_ > lineCurrentPos_) {
4448*8af74909SZhong Yang 			selCurrentPos = pdoc->LineStart(lineCurrent_);
4449*8af74909SZhong Yang 			selAnchorPos = pdoc->LineStart(lineAnchor_ + 1);
4450*8af74909SZhong Yang 		} else { // Same line, select it
4451*8af74909SZhong Yang 			selCurrentPos = pdoc->LineStart(lineAnchor_ + 1);
4452*8af74909SZhong Yang 			selAnchorPos = pdoc->LineStart(lineAnchor_);
4453*8af74909SZhong Yang 		}
4454*8af74909SZhong Yang 	} else {
4455*8af74909SZhong Yang 		if (lineAnchorPos_ < lineCurrentPos_) {
4456*8af74909SZhong Yang 			selCurrentPos = StartEndDisplayLine(lineCurrentPos_, false) + 1;
4457*8af74909SZhong Yang 			selCurrentPos = pdoc->MovePositionOutsideChar(selCurrentPos, 1);
4458*8af74909SZhong Yang 			selAnchorPos = StartEndDisplayLine(lineAnchorPos_, true);
4459*8af74909SZhong Yang 		} else if (lineAnchorPos_ > lineCurrentPos_) {
4460*8af74909SZhong Yang 			selCurrentPos = StartEndDisplayLine(lineCurrentPos_, true);
4461*8af74909SZhong Yang 			selAnchorPos = StartEndDisplayLine(lineAnchorPos_, false) + 1;
4462*8af74909SZhong Yang 			selAnchorPos = pdoc->MovePositionOutsideChar(selAnchorPos, 1);
4463*8af74909SZhong Yang 		} else { // Same line, select it
4464*8af74909SZhong Yang 			selCurrentPos = StartEndDisplayLine(lineAnchorPos_, false) + 1;
4465*8af74909SZhong Yang 			selCurrentPos = pdoc->MovePositionOutsideChar(selCurrentPos, 1);
4466*8af74909SZhong Yang 			selAnchorPos = StartEndDisplayLine(lineAnchorPos_, true);
4467*8af74909SZhong Yang 		}
4468*8af74909SZhong Yang 	}
4469*8af74909SZhong Yang 	TrimAndSetSelection(selCurrentPos, selAnchorPos);
4470*8af74909SZhong Yang }
4471*8af74909SZhong Yang 
WordSelection(Sci::Position pos)4472*8af74909SZhong Yang void Editor::WordSelection(Sci::Position pos) {
4473*8af74909SZhong Yang 	if (pos < wordSelectAnchorStartPos) {
4474*8af74909SZhong Yang 		// Extend backward to the word containing pos.
4475*8af74909SZhong Yang 		// Skip ExtendWordSelect if the line is empty or if pos is after the last character.
4476*8af74909SZhong Yang 		// This ensures that a series of empty lines isn't counted as a single "word".
4477*8af74909SZhong Yang 		if (!pdoc->IsLineEndPosition(pos))
4478*8af74909SZhong Yang 			pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos + 1, 1), -1);
4479*8af74909SZhong Yang 		TrimAndSetSelection(pos, wordSelectAnchorEndPos);
4480*8af74909SZhong Yang 	} else if (pos > wordSelectAnchorEndPos) {
4481*8af74909SZhong Yang 		// Extend forward to the word containing the character to the left of pos.
4482*8af74909SZhong Yang 		// Skip ExtendWordSelect if the line is empty or if pos is the first position on the line.
4483*8af74909SZhong Yang 		// This ensures that a series of empty lines isn't counted as a single "word".
4484*8af74909SZhong Yang 		if (pos > pdoc->LineStart(pdoc->LineFromPosition(pos)))
4485*8af74909SZhong Yang 			pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos - 1, -1), 1);
4486*8af74909SZhong Yang 		TrimAndSetSelection(pos, wordSelectAnchorStartPos);
4487*8af74909SZhong Yang 	} else {
4488*8af74909SZhong Yang 		// Select only the anchored word
4489*8af74909SZhong Yang 		if (pos >= originalAnchorPos)
4490*8af74909SZhong Yang 			TrimAndSetSelection(wordSelectAnchorEndPos, wordSelectAnchorStartPos);
4491*8af74909SZhong Yang 		else
4492*8af74909SZhong Yang 			TrimAndSetSelection(wordSelectAnchorStartPos, wordSelectAnchorEndPos);
4493*8af74909SZhong Yang 	}
4494*8af74909SZhong Yang }
4495*8af74909SZhong Yang 
DwellEnd(bool mouseMoved)4496*8af74909SZhong Yang void Editor::DwellEnd(bool mouseMoved) {
4497*8af74909SZhong Yang 	if (mouseMoved)
4498*8af74909SZhong Yang 		ticksToDwell = dwellDelay;
4499*8af74909SZhong Yang 	else
4500*8af74909SZhong Yang 		ticksToDwell = SC_TIME_FOREVER;
4501*8af74909SZhong Yang 	if (dwelling && (dwellDelay < SC_TIME_FOREVER)) {
4502*8af74909SZhong Yang 		dwelling = false;
4503*8af74909SZhong Yang 		NotifyDwelling(ptMouseLast, dwelling);
4504*8af74909SZhong Yang 	}
4505*8af74909SZhong Yang 	FineTickerCancel(tickDwell);
4506*8af74909SZhong Yang }
4507*8af74909SZhong Yang 
MouseLeave()4508*8af74909SZhong Yang void Editor::MouseLeave() {
4509*8af74909SZhong Yang 	SetHotSpotRange(nullptr);
4510*8af74909SZhong Yang 	SetHoverIndicatorPosition(Sci::invalidPosition);
4511*8af74909SZhong Yang 	if (!HaveMouseCapture()) {
4512*8af74909SZhong Yang 		ptMouseLast = Point(-1, -1);
4513*8af74909SZhong Yang 		DwellEnd(true);
4514*8af74909SZhong Yang 	}
4515*8af74909SZhong Yang }
4516*8af74909SZhong Yang 
AllowVirtualSpace(int virtualSpaceOptions,bool rectangular)4517*8af74909SZhong Yang static constexpr bool AllowVirtualSpace(int virtualSpaceOptions, bool rectangular) noexcept {
4518*8af74909SZhong Yang 	return (!rectangular && ((virtualSpaceOptions & SCVS_USERACCESSIBLE) != 0))
4519*8af74909SZhong Yang 		|| (rectangular && ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) != 0));
4520*8af74909SZhong Yang }
4521*8af74909SZhong Yang 
ButtonDownWithModifiers(Point pt,unsigned int curTime,int modifiers)4522*8af74909SZhong Yang void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers) {
4523*8af74909SZhong Yang 	SetHoverIndicatorPoint(pt);
4524*8af74909SZhong Yang 	//Platform::DebugPrintf("ButtonDown %d %d = %d alt=%d %d\n", curTime, lastClickTime, curTime - lastClickTime, alt, inDragDrop);
4525*8af74909SZhong Yang 	ptMouseLast = pt;
4526*8af74909SZhong Yang 	const bool ctrl = (modifiers & SCI_CTRL) != 0;
4527*8af74909SZhong Yang 	const bool shift = (modifiers & SCI_SHIFT) != 0;
4528*8af74909SZhong Yang 	const bool alt = (modifiers & SCI_ALT) != 0;
4529*8af74909SZhong Yang 	SelectionPosition newPos = SPositionFromLocation(pt, false, false, AllowVirtualSpace(virtualSpaceOptions, alt));
4530*8af74909SZhong Yang 	newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position());
4531*8af74909SZhong Yang 	SelectionPosition newCharPos = SPositionFromLocation(pt, false, true, false);
4532*8af74909SZhong Yang 	newCharPos = MovePositionOutsideChar(newCharPos, -1);
4533*8af74909SZhong Yang 	inDragDrop = ddNone;
4534*8af74909SZhong Yang 	sel.SetMoveExtends(false);
4535*8af74909SZhong Yang 
4536*8af74909SZhong Yang 	if (NotifyMarginClick(pt, modifiers))
4537*8af74909SZhong Yang 		return;
4538*8af74909SZhong Yang 
4539*8af74909SZhong Yang 	NotifyIndicatorClick(true, newPos.Position(), modifiers);
4540*8af74909SZhong Yang 
4541*8af74909SZhong Yang 	const bool inSelMargin = PointInSelMargin(pt);
4542*8af74909SZhong Yang 	// In margin ctrl+(double)click should always select everything
4543*8af74909SZhong Yang 	if (ctrl && inSelMargin) {
4544*8af74909SZhong Yang 		SelectAll();
4545*8af74909SZhong Yang 		lastClickTime = curTime;
4546*8af74909SZhong Yang 		lastClick = pt;
4547*8af74909SZhong Yang 		return;
4548*8af74909SZhong Yang 	}
4549*8af74909SZhong Yang 	if (shift && !inSelMargin) {
4550*8af74909SZhong Yang 		SetSelection(newPos);
4551*8af74909SZhong Yang 	}
4552*8af74909SZhong Yang 	if ((curTime < (lastClickTime+Platform::DoubleClickTime())) && Close(pt, lastClick, doubleClickCloseThreshold)) {
4553*8af74909SZhong Yang 		//Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime);
4554*8af74909SZhong Yang 		SetMouseCapture(true);
4555*8af74909SZhong Yang 		FineTickerStart(tickScroll, 100, 10);
4556*8af74909SZhong Yang 		if (!ctrl || !multipleSelection || (selectionUnit != TextUnit::character && selectionUnit != TextUnit::word))
4557*8af74909SZhong Yang 			SetEmptySelection(newPos.Position());
4558*8af74909SZhong Yang 		bool doubleClick = false;
4559*8af74909SZhong Yang 		if (inSelMargin) {
4560*8af74909SZhong Yang 			// Inside margin selection type should be either subLine or wholeLine.
4561*8af74909SZhong Yang 			if (selectionUnit == TextUnit::subLine) {
4562*8af74909SZhong Yang 				// If it is subLine, we're inside a *double* click and word wrap is enabled,
4563*8af74909SZhong Yang 				// so we switch to wholeLine in order to select whole line.
4564*8af74909SZhong Yang 				selectionUnit = TextUnit::wholeLine;
4565*8af74909SZhong Yang 			} else if (selectionUnit != TextUnit::subLine && selectionUnit != TextUnit::wholeLine) {
4566*8af74909SZhong Yang 				// If it is neither, reset selection type to line selection.
4567*8af74909SZhong Yang 				selectionUnit = (Wrapping() && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? TextUnit::subLine : TextUnit::wholeLine;
4568*8af74909SZhong Yang 			}
4569*8af74909SZhong Yang 		} else {
4570*8af74909SZhong Yang 			if (selectionUnit == TextUnit::character) {
4571*8af74909SZhong Yang 				selectionUnit = TextUnit::word;
4572*8af74909SZhong Yang 				doubleClick = true;
4573*8af74909SZhong Yang 			} else if (selectionUnit == TextUnit::word) {
4574*8af74909SZhong Yang 				// Since we ended up here, we're inside a *triple* click, which should always select
4575*8af74909SZhong Yang 				// whole line regardless of word wrap being enabled or not.
4576*8af74909SZhong Yang 				selectionUnit = TextUnit::wholeLine;
4577*8af74909SZhong Yang 			} else {
4578*8af74909SZhong Yang 				selectionUnit = TextUnit::character;
4579*8af74909SZhong Yang 				originalAnchorPos = sel.MainCaret();
4580*8af74909SZhong Yang 			}
4581*8af74909SZhong Yang 		}
4582*8af74909SZhong Yang 
4583*8af74909SZhong Yang 		if (selectionUnit == TextUnit::word) {
4584*8af74909SZhong Yang 			Sci::Position charPos = originalAnchorPos;
4585*8af74909SZhong Yang 			if (sel.MainCaret() == originalAnchorPos) {
4586*8af74909SZhong Yang 				charPos = PositionFromLocation(pt, false, true);
4587*8af74909SZhong Yang 				charPos = MovePositionOutsideChar(charPos, -1);
4588*8af74909SZhong Yang 			}
4589*8af74909SZhong Yang 
4590*8af74909SZhong Yang 			Sci::Position startWord;
4591*8af74909SZhong Yang 			Sci::Position endWord;
4592*8af74909SZhong Yang 			if ((sel.MainCaret() >= originalAnchorPos) && !pdoc->IsLineEndPosition(charPos)) {
4593*8af74909SZhong Yang 				startWord = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(charPos + 1, 1), -1);
4594*8af74909SZhong Yang 				endWord = pdoc->ExtendWordSelect(charPos, 1);
4595*8af74909SZhong Yang 			} else {
4596*8af74909SZhong Yang 				// Selecting backwards, or anchor beyond last character on line. In these cases,
4597*8af74909SZhong Yang 				// we select the word containing the character to the *left* of the anchor.
4598*8af74909SZhong Yang 				if (charPos > pdoc->LineStart(pdoc->LineFromPosition(charPos))) {
4599*8af74909SZhong Yang 					startWord = pdoc->ExtendWordSelect(charPos, -1);
4600*8af74909SZhong Yang 					endWord = pdoc->ExtendWordSelect(startWord, 1);
4601*8af74909SZhong Yang 				} else {
4602*8af74909SZhong Yang 					// Anchor at start of line; select nothing to begin with.
4603*8af74909SZhong Yang 					startWord = charPos;
4604*8af74909SZhong Yang 					endWord = charPos;
4605*8af74909SZhong Yang 				}
4606*8af74909SZhong Yang 			}
4607*8af74909SZhong Yang 
4608*8af74909SZhong Yang 			wordSelectAnchorStartPos = startWord;
4609*8af74909SZhong Yang 			wordSelectAnchorEndPos = endWord;
4610*8af74909SZhong Yang 			wordSelectInitialCaretPos = sel.MainCaret();
4611*8af74909SZhong Yang 			WordSelection(wordSelectInitialCaretPos);
4612*8af74909SZhong Yang 		} else if (selectionUnit == TextUnit::subLine || selectionUnit == TextUnit::wholeLine) {
4613*8af74909SZhong Yang 			lineAnchorPos = newPos.Position();
4614*8af74909SZhong Yang 			LineSelection(lineAnchorPos, lineAnchorPos, selectionUnit == TextUnit::wholeLine);
4615*8af74909SZhong Yang 			//Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos);
4616*8af74909SZhong Yang 		} else {
4617*8af74909SZhong Yang 			SetEmptySelection(sel.MainCaret());
4618*8af74909SZhong Yang 		}
4619*8af74909SZhong Yang 		//Platform::DebugPrintf("Double click: %d - %d\n", anchor, currentPos);
4620*8af74909SZhong Yang 		if (doubleClick) {
4621*8af74909SZhong Yang 			NotifyDoubleClick(pt, modifiers);
4622*8af74909SZhong Yang 			if (PositionIsHotspot(newCharPos.Position()))
4623*8af74909SZhong Yang 				NotifyHotSpotDoubleClicked(newCharPos.Position(), modifiers);
4624*8af74909SZhong Yang 		}
4625*8af74909SZhong Yang 	} else {	// Single click
4626*8af74909SZhong Yang 		if (inSelMargin) {
4627*8af74909SZhong Yang 			if (sel.IsRectangular() || (sel.Count() > 1)) {
4628*8af74909SZhong Yang 				InvalidateWholeSelection();
4629*8af74909SZhong Yang 				sel.Clear();
4630*8af74909SZhong Yang 			}
4631*8af74909SZhong Yang 			sel.selType = Selection::selStream;
4632*8af74909SZhong Yang 			if (!shift) {
4633*8af74909SZhong Yang 				// Single click in margin: select wholeLine or only subLine if word wrap is enabled
4634*8af74909SZhong Yang 				lineAnchorPos = newPos.Position();
4635*8af74909SZhong Yang 				selectionUnit = (Wrapping() && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? TextUnit::subLine : TextUnit::wholeLine;
4636*8af74909SZhong Yang 				LineSelection(lineAnchorPos, lineAnchorPos, selectionUnit == TextUnit::wholeLine);
4637*8af74909SZhong Yang 			} else {
4638*8af74909SZhong Yang 				// Single shift+click in margin: select from line anchor to clicked line
4639*8af74909SZhong Yang 				if (sel.MainAnchor() > sel.MainCaret())
4640*8af74909SZhong Yang 					lineAnchorPos = sel.MainAnchor() - 1;
4641*8af74909SZhong Yang 				else
4642*8af74909SZhong Yang 					lineAnchorPos = sel.MainAnchor();
4643*8af74909SZhong Yang 				// Reset selection type if there is an empty selection.
4644*8af74909SZhong Yang 				// This ensures that we don't end up stuck in previous selection mode, which is no longer valid.
4645*8af74909SZhong Yang 				// Otherwise, if there's a non empty selection, reset selection type only if it differs from subLine and wholeLine.
4646*8af74909SZhong Yang 				// This ensures that we continue selecting in the same selection mode.
4647*8af74909SZhong Yang 				if (sel.Empty() || (selectionUnit != TextUnit::subLine && selectionUnit != TextUnit::wholeLine))
4648*8af74909SZhong Yang 					selectionUnit = (Wrapping() && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? TextUnit::subLine : TextUnit::wholeLine;
4649*8af74909SZhong Yang 				LineSelection(newPos.Position(), lineAnchorPos, selectionUnit == TextUnit::wholeLine);
4650*8af74909SZhong Yang 			}
4651*8af74909SZhong Yang 
4652*8af74909SZhong Yang 			SetDragPosition(SelectionPosition(Sci::invalidPosition));
4653*8af74909SZhong Yang 			SetMouseCapture(true);
4654*8af74909SZhong Yang 			FineTickerStart(tickScroll, 100, 10);
4655*8af74909SZhong Yang 		} else {
4656*8af74909SZhong Yang 			if (PointIsHotspot(pt)) {
4657*8af74909SZhong Yang 				NotifyHotSpotClicked(newCharPos.Position(), modifiers);
4658*8af74909SZhong Yang 				hotSpotClickPos = newCharPos.Position();
4659*8af74909SZhong Yang 			}
4660*8af74909SZhong Yang 			if (!shift) {
4661*8af74909SZhong Yang 				if (PointInSelection(pt) && !SelectionEmpty())
4662*8af74909SZhong Yang 					inDragDrop = ddInitial;
4663*8af74909SZhong Yang 				else
4664*8af74909SZhong Yang 					inDragDrop = ddNone;
4665*8af74909SZhong Yang 			}
4666*8af74909SZhong Yang 			SetMouseCapture(true);
4667*8af74909SZhong Yang 			FineTickerStart(tickScroll, 100, 10);
4668*8af74909SZhong Yang 			if (inDragDrop != ddInitial) {
4669*8af74909SZhong Yang 				SetDragPosition(SelectionPosition(Sci::invalidPosition));
4670*8af74909SZhong Yang 				if (!shift) {
4671*8af74909SZhong Yang 					if (ctrl && multipleSelection) {
4672*8af74909SZhong Yang 						const SelectionRange range(newPos);
4673*8af74909SZhong Yang 						sel.TentativeSelection(range);
4674*8af74909SZhong Yang 						InvalidateSelection(range, true);
4675*8af74909SZhong Yang 					} else {
4676*8af74909SZhong Yang 						InvalidateSelection(SelectionRange(newPos), true);
4677*8af74909SZhong Yang 						if (sel.Count() > 1)
4678*8af74909SZhong Yang 							Redraw();
4679*8af74909SZhong Yang 						if ((sel.Count() > 1) || (sel.selType != Selection::selStream))
4680*8af74909SZhong Yang 							sel.Clear();
4681*8af74909SZhong Yang 						sel.selType = alt ? Selection::selRectangle : Selection::selStream;
4682*8af74909SZhong Yang 						SetSelection(newPos, newPos);
4683*8af74909SZhong Yang 					}
4684*8af74909SZhong Yang 				}
4685*8af74909SZhong Yang 				SelectionPosition anchorCurrent = newPos;
4686*8af74909SZhong Yang 				if (shift)
4687*8af74909SZhong Yang 					anchorCurrent = sel.IsRectangular() ?
4688*8af74909SZhong Yang 						sel.Rectangular().anchor : sel.RangeMain().anchor;
4689*8af74909SZhong Yang 				sel.selType = alt ? Selection::selRectangle : Selection::selStream;
4690*8af74909SZhong Yang 				selectionUnit = TextUnit::character;
4691*8af74909SZhong Yang 				originalAnchorPos = sel.MainCaret();
4692*8af74909SZhong Yang 				sel.Rectangular() = SelectionRange(newPos, anchorCurrent);
4693*8af74909SZhong Yang 				SetRectangularRange();
4694*8af74909SZhong Yang 			}
4695*8af74909SZhong Yang 		}
4696*8af74909SZhong Yang 	}
4697*8af74909SZhong Yang 	lastClickTime = curTime;
4698*8af74909SZhong Yang 	lastClick = pt;
4699*8af74909SZhong Yang 	lastXChosen = static_cast<int>(pt.x) + xOffset;
4700*8af74909SZhong Yang 	ShowCaretAtCurrentPosition();
4701*8af74909SZhong Yang }
4702*8af74909SZhong Yang 
RightButtonDownWithModifiers(Point pt,unsigned int,int modifiers)4703*8af74909SZhong Yang void Editor::RightButtonDownWithModifiers(Point pt, unsigned int, int modifiers) {
4704*8af74909SZhong Yang 	if (NotifyMarginRightClick(pt, modifiers))
4705*8af74909SZhong Yang 		return;
4706*8af74909SZhong Yang }
4707*8af74909SZhong Yang 
PositionIsHotspot(Sci::Position position) const4708*8af74909SZhong Yang bool Editor::PositionIsHotspot(Sci::Position position) const {
4709*8af74909SZhong Yang 	return vs.styles[pdoc->StyleIndexAt(position)].hotspot;
4710*8af74909SZhong Yang }
4711*8af74909SZhong Yang 
PointIsHotspot(Point pt)4712*8af74909SZhong Yang bool Editor::PointIsHotspot(Point pt) {
4713*8af74909SZhong Yang 	const Sci::Position pos = PositionFromLocation(pt, true, true);
4714*8af74909SZhong Yang 	if (pos == INVALID_POSITION)
4715*8af74909SZhong Yang 		return false;
4716*8af74909SZhong Yang 	return PositionIsHotspot(pos);
4717*8af74909SZhong Yang }
4718*8af74909SZhong Yang 
SetHoverIndicatorPosition(Sci::Position position)4719*8af74909SZhong Yang void Editor::SetHoverIndicatorPosition(Sci::Position position) {
4720*8af74909SZhong Yang 	const Sci::Position hoverIndicatorPosPrev = hoverIndicatorPos;
4721*8af74909SZhong Yang 	hoverIndicatorPos = INVALID_POSITION;
4722*8af74909SZhong Yang 	if (!vs.indicatorsDynamic)
4723*8af74909SZhong Yang 		return;
4724*8af74909SZhong Yang 	if (position != INVALID_POSITION) {
4725*8af74909SZhong Yang 		for (const IDecoration *deco : pdoc->decorations->View()) {
4726*8af74909SZhong Yang 			if (vs.indicators[deco->Indicator()].IsDynamic()) {
4727*8af74909SZhong Yang 				if (pdoc->decorations->ValueAt(deco->Indicator(), position)) {
4728*8af74909SZhong Yang 					hoverIndicatorPos = position;
4729*8af74909SZhong Yang 				}
4730*8af74909SZhong Yang 			}
4731*8af74909SZhong Yang 		}
4732*8af74909SZhong Yang 	}
4733*8af74909SZhong Yang 	if (hoverIndicatorPosPrev != hoverIndicatorPos) {
4734*8af74909SZhong Yang 		Redraw();
4735*8af74909SZhong Yang 	}
4736*8af74909SZhong Yang }
4737*8af74909SZhong Yang 
SetHoverIndicatorPoint(Point pt)4738*8af74909SZhong Yang void Editor::SetHoverIndicatorPoint(Point pt) {
4739*8af74909SZhong Yang 	if (!vs.indicatorsDynamic) {
4740*8af74909SZhong Yang 		SetHoverIndicatorPosition(INVALID_POSITION);
4741*8af74909SZhong Yang 	} else {
4742*8af74909SZhong Yang 		SetHoverIndicatorPosition(PositionFromLocation(pt, true, true));
4743*8af74909SZhong Yang 	}
4744*8af74909SZhong Yang }
4745*8af74909SZhong Yang 
SetHotSpotRange(const Point * pt)4746*8af74909SZhong Yang void Editor::SetHotSpotRange(const Point *pt) {
4747*8af74909SZhong Yang 	if (pt) {
4748*8af74909SZhong Yang 		const Sci::Position pos = PositionFromLocation(*pt, false, true);
4749*8af74909SZhong Yang 
4750*8af74909SZhong Yang 		// If we don't limit this to word characters then the
4751*8af74909SZhong Yang 		// range can encompass more than the run range and then
4752*8af74909SZhong Yang 		// the underline will not be drawn properly.
4753*8af74909SZhong Yang 		Range hsNew;
4754*8af74909SZhong Yang 		hsNew.start = pdoc->ExtendStyleRange(pos, -1, vs.hotspotSingleLine);
4755*8af74909SZhong Yang 		hsNew.end = pdoc->ExtendStyleRange(pos, 1, vs.hotspotSingleLine);
4756*8af74909SZhong Yang 
4757*8af74909SZhong Yang 		// Only invalidate the range if the hotspot range has changed...
4758*8af74909SZhong Yang 		if (!(hsNew == hotspot)) {
4759*8af74909SZhong Yang 			if (hotspot.Valid()) {
4760*8af74909SZhong Yang 				InvalidateRange(hotspot.start, hotspot.end);
4761*8af74909SZhong Yang 			}
4762*8af74909SZhong Yang 			hotspot = hsNew;
4763*8af74909SZhong Yang 			InvalidateRange(hotspot.start, hotspot.end);
4764*8af74909SZhong Yang 		}
4765*8af74909SZhong Yang 	} else {
4766*8af74909SZhong Yang 		if (hotspot.Valid()) {
4767*8af74909SZhong Yang 			InvalidateRange(hotspot.start, hotspot.end);
4768*8af74909SZhong Yang 		}
4769*8af74909SZhong Yang 		hotspot = Range(Sci::invalidPosition);
4770*8af74909SZhong Yang 	}
4771*8af74909SZhong Yang }
4772*8af74909SZhong Yang 
GetHotSpotRange() const4773*8af74909SZhong Yang Range Editor::GetHotSpotRange() const noexcept {
4774*8af74909SZhong Yang 	return hotspot;
4775*8af74909SZhong Yang }
4776*8af74909SZhong Yang 
ButtonMoveWithModifiers(Point pt,unsigned int,int modifiers)4777*8af74909SZhong Yang void Editor::ButtonMoveWithModifiers(Point pt, unsigned int, int modifiers) {
4778*8af74909SZhong Yang 	if (ptMouseLast != pt) {
4779*8af74909SZhong Yang 		DwellEnd(true);
4780*8af74909SZhong Yang 	}
4781*8af74909SZhong Yang 
4782*8af74909SZhong Yang 	SelectionPosition movePos = SPositionFromLocation(pt, false, false,
4783*8af74909SZhong Yang 		AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular()));
4784*8af74909SZhong Yang 	movePos = MovePositionOutsideChar(movePos, sel.MainCaret() - movePos.Position());
4785*8af74909SZhong Yang 
4786*8af74909SZhong Yang 	if (inDragDrop == ddInitial) {
4787*8af74909SZhong Yang 		if (DragThreshold(ptMouseLast, pt)) {
4788*8af74909SZhong Yang 			SetMouseCapture(false);
4789*8af74909SZhong Yang 			FineTickerCancel(tickScroll);
4790*8af74909SZhong Yang 			SetDragPosition(movePos);
4791*8af74909SZhong Yang 			CopySelectionRange(&drag);
4792*8af74909SZhong Yang 			StartDrag();
4793*8af74909SZhong Yang 		}
4794*8af74909SZhong Yang 		return;
4795*8af74909SZhong Yang 	}
4796*8af74909SZhong Yang 
4797*8af74909SZhong Yang 	ptMouseLast = pt;
4798*8af74909SZhong Yang 	PRectangle rcClient = GetClientRectangle();
4799*8af74909SZhong Yang 	const Point ptOrigin = GetVisibleOriginInMain();
4800*8af74909SZhong Yang 	rcClient.Move(0, -ptOrigin.y);
4801*8af74909SZhong Yang 	if ((dwellDelay < SC_TIME_FOREVER) && rcClient.Contains(pt)) {
4802*8af74909SZhong Yang 		FineTickerStart(tickDwell, dwellDelay, dwellDelay/10);
4803*8af74909SZhong Yang 	}
4804*8af74909SZhong Yang 	//Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y);
4805*8af74909SZhong Yang 	if (HaveMouseCapture()) {
4806*8af74909SZhong Yang 
4807*8af74909SZhong Yang 		// Slow down autoscrolling/selection
4808*8af74909SZhong Yang 		autoScrollTimer.ticksToWait -= timer.tickSize;
4809*8af74909SZhong Yang 		if (autoScrollTimer.ticksToWait > 0)
4810*8af74909SZhong Yang 			return;
4811*8af74909SZhong Yang 		autoScrollTimer.ticksToWait = autoScrollDelay;
4812*8af74909SZhong Yang 
4813*8af74909SZhong Yang 		// Adjust selection
4814*8af74909SZhong Yang 		if (posDrag.IsValid()) {
4815*8af74909SZhong Yang 			SetDragPosition(movePos);
4816*8af74909SZhong Yang 		} else {
4817*8af74909SZhong Yang 			if (selectionUnit == TextUnit::character) {
4818*8af74909SZhong Yang 				if (sel.selType == Selection::selStream && (modifiers & SCI_ALT) && mouseSelectionRectangularSwitch) {
4819*8af74909SZhong Yang 					sel.selType = Selection::selRectangle;
4820*8af74909SZhong Yang 				}
4821*8af74909SZhong Yang 				if (sel.IsRectangular()) {
4822*8af74909SZhong Yang 					sel.Rectangular() = SelectionRange(movePos, sel.Rectangular().anchor);
4823*8af74909SZhong Yang 					SetSelection(movePos, sel.RangeMain().anchor);
4824*8af74909SZhong Yang 				} else if (sel.Count() > 1) {
4825*8af74909SZhong Yang 					InvalidateSelection(sel.RangeMain(), false);
4826*8af74909SZhong Yang 					const SelectionRange range(movePos, sel.RangeMain().anchor);
4827*8af74909SZhong Yang 					sel.TentativeSelection(range);
4828*8af74909SZhong Yang 					InvalidateSelection(range, true);
4829*8af74909SZhong Yang 				} else {
4830*8af74909SZhong Yang 					SetSelection(movePos, sel.RangeMain().anchor);
4831*8af74909SZhong Yang 				}
4832*8af74909SZhong Yang 			} else if (selectionUnit == TextUnit::word) {
4833*8af74909SZhong Yang 				// Continue selecting by word
4834*8af74909SZhong Yang 				if (movePos.Position() == wordSelectInitialCaretPos) {  // Didn't move
4835*8af74909SZhong Yang 					// No need to do anything. Previously this case was lumped
4836*8af74909SZhong Yang 					// in with "Moved forward", but that can be harmful in this
4837*8af74909SZhong Yang 					// case: a handler for the NotifyDoubleClick re-adjusts
4838*8af74909SZhong Yang 					// the selection for a fancier definition of "word" (for
4839*8af74909SZhong Yang 					// example, in Perl it is useful to include the leading
4840*8af74909SZhong Yang 					// '$', '%' or '@' on variables for word selection). In this
4841*8af74909SZhong Yang 					// the ButtonMove() called via TickFor() for auto-scrolling
4842*8af74909SZhong Yang 					// could result in the fancier word selection adjustment
4843*8af74909SZhong Yang 					// being unmade.
4844*8af74909SZhong Yang 				} else {
4845*8af74909SZhong Yang 					wordSelectInitialCaretPos = -1;
4846*8af74909SZhong Yang 					WordSelection(movePos.Position());
4847*8af74909SZhong Yang 				}
4848*8af74909SZhong Yang 			} else {
4849*8af74909SZhong Yang 				// Continue selecting by line
4850*8af74909SZhong Yang 				LineSelection(movePos.Position(), lineAnchorPos, selectionUnit == TextUnit::wholeLine);
4851*8af74909SZhong Yang 			}
4852*8af74909SZhong Yang 		}
4853*8af74909SZhong Yang 
4854*8af74909SZhong Yang 		// Autoscroll
4855*8af74909SZhong Yang 		const Sci::Line lineMove = DisplayFromPosition(movePos.Position());
4856*8af74909SZhong Yang 		if (pt.y >= rcClient.bottom) {
4857*8af74909SZhong Yang 			ScrollTo(lineMove - LinesOnScreen() + 1);
4858*8af74909SZhong Yang 			Redraw();
4859*8af74909SZhong Yang 		} else if (pt.y < rcClient.top) {
4860*8af74909SZhong Yang 			ScrollTo(lineMove);
4861*8af74909SZhong Yang 			Redraw();
4862*8af74909SZhong Yang 		}
4863*8af74909SZhong Yang 		EnsureCaretVisible(false, false, true);
4864*8af74909SZhong Yang 
4865*8af74909SZhong Yang 		if (hotspot.Valid() && !PointIsHotspot(pt))
4866*8af74909SZhong Yang 			SetHotSpotRange(nullptr);
4867*8af74909SZhong Yang 
4868*8af74909SZhong Yang 		if (hotSpotClickPos != INVALID_POSITION && PositionFromLocation(pt, true, true) != hotSpotClickPos) {
4869*8af74909SZhong Yang 			if (inDragDrop == ddNone) {
4870*8af74909SZhong Yang 				DisplayCursor(Window::cursorText);
4871*8af74909SZhong Yang 			}
4872*8af74909SZhong Yang 			hotSpotClickPos = INVALID_POSITION;
4873*8af74909SZhong Yang 		}
4874*8af74909SZhong Yang 
4875*8af74909SZhong Yang 	} else {
4876*8af74909SZhong Yang 		if (vs.fixedColumnWidth > 0) {	// There is a margin
4877*8af74909SZhong Yang 			if (PointInSelMargin(pt)) {
4878*8af74909SZhong Yang 				DisplayCursor(GetMarginCursor(pt));
4879*8af74909SZhong Yang 				SetHotSpotRange(nullptr);
4880*8af74909SZhong Yang 				SetHoverIndicatorPosition(Sci::invalidPosition);
4881*8af74909SZhong Yang 				return; 	// No need to test for selection
4882*8af74909SZhong Yang 			}
4883*8af74909SZhong Yang 		}
4884*8af74909SZhong Yang 		// Display regular (drag) cursor over selection
4885*8af74909SZhong Yang 		if (PointInSelection(pt) && !SelectionEmpty()) {
4886*8af74909SZhong Yang 			DisplayCursor(Window::cursorArrow);
4887*8af74909SZhong Yang 			SetHoverIndicatorPosition(Sci::invalidPosition);
4888*8af74909SZhong Yang 		} else {
4889*8af74909SZhong Yang 			SetHoverIndicatorPoint(pt);
4890*8af74909SZhong Yang 			if (PointIsHotspot(pt)) {
4891*8af74909SZhong Yang 				DisplayCursor(Window::cursorHand);
4892*8af74909SZhong Yang 				SetHotSpotRange(&pt);
4893*8af74909SZhong Yang 			} else {
4894*8af74909SZhong Yang 				if (hoverIndicatorPos != Sci::invalidPosition)
4895*8af74909SZhong Yang 					DisplayCursor(Window::cursorHand);
4896*8af74909SZhong Yang 				else
4897*8af74909SZhong Yang 					DisplayCursor(Window::cursorText);
4898*8af74909SZhong Yang 				SetHotSpotRange(nullptr);
4899*8af74909SZhong Yang 			}
4900*8af74909SZhong Yang 		}
4901*8af74909SZhong Yang 	}
4902*8af74909SZhong Yang }
4903*8af74909SZhong Yang 
ButtonUpWithModifiers(Point pt,unsigned int curTime,int modifiers)4904*8af74909SZhong Yang void Editor::ButtonUpWithModifiers(Point pt, unsigned int curTime, int modifiers) {
4905*8af74909SZhong Yang 	//Platform::DebugPrintf("ButtonUp %d %d\n", HaveMouseCapture(), inDragDrop);
4906*8af74909SZhong Yang 	SelectionPosition newPos = SPositionFromLocation(pt, false, false,
4907*8af74909SZhong Yang 		AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular()));
4908*8af74909SZhong Yang 	if (hoverIndicatorPos != INVALID_POSITION)
4909*8af74909SZhong Yang 		InvalidateRange(newPos.Position(), newPos.Position() + 1);
4910*8af74909SZhong Yang 	newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position());
4911*8af74909SZhong Yang 	if (inDragDrop == ddInitial) {
4912*8af74909SZhong Yang 		inDragDrop = ddNone;
4913*8af74909SZhong Yang 		SetEmptySelection(newPos);
4914*8af74909SZhong Yang 		selectionUnit = TextUnit::character;
4915*8af74909SZhong Yang 		originalAnchorPos = sel.MainCaret();
4916*8af74909SZhong Yang 	}
4917*8af74909SZhong Yang 	if (hotSpotClickPos != INVALID_POSITION && PointIsHotspot(pt)) {
4918*8af74909SZhong Yang 		hotSpotClickPos = INVALID_POSITION;
4919*8af74909SZhong Yang 		SelectionPosition newCharPos = SPositionFromLocation(pt, false, true, false);
4920*8af74909SZhong Yang 		newCharPos = MovePositionOutsideChar(newCharPos, -1);
4921*8af74909SZhong Yang 		NotifyHotSpotReleaseClick(newCharPos.Position(), modifiers & SCI_CTRL);
4922*8af74909SZhong Yang 	}
4923*8af74909SZhong Yang 	if (HaveMouseCapture()) {
4924*8af74909SZhong Yang 		if (PointInSelMargin(pt)) {
4925*8af74909SZhong Yang 			DisplayCursor(GetMarginCursor(pt));
4926*8af74909SZhong Yang 		} else {
4927*8af74909SZhong Yang 			DisplayCursor(Window::cursorText);
4928*8af74909SZhong Yang 			SetHotSpotRange(nullptr);
4929*8af74909SZhong Yang 		}
4930*8af74909SZhong Yang 		ptMouseLast = pt;
4931*8af74909SZhong Yang 		SetMouseCapture(false);
4932*8af74909SZhong Yang 		FineTickerCancel(tickScroll);
4933*8af74909SZhong Yang 		NotifyIndicatorClick(false, newPos.Position(), 0);
4934*8af74909SZhong Yang 		if (inDragDrop == ddDragging) {
4935*8af74909SZhong Yang 			const SelectionPosition selStart = SelectionStart();
4936*8af74909SZhong Yang 			const SelectionPosition selEnd = SelectionEnd();
4937*8af74909SZhong Yang 			if (selStart < selEnd) {
4938*8af74909SZhong Yang 				if (drag.Length()) {
4939*8af74909SZhong Yang 					const Sci::Position length = drag.Length();
4940*8af74909SZhong Yang 					if (modifiers & SCI_CTRL) {
4941*8af74909SZhong Yang 						const Sci::Position lengthInserted = pdoc->InsertString(
4942*8af74909SZhong Yang 							newPos.Position(), drag.Data(), length);
4943*8af74909SZhong Yang 						if (lengthInserted > 0) {
4944*8af74909SZhong Yang 							SetSelection(newPos.Position(), newPos.Position() + lengthInserted);
4945*8af74909SZhong Yang 						}
4946*8af74909SZhong Yang 					} else if (newPos < selStart) {
4947*8af74909SZhong Yang 						pdoc->DeleteChars(selStart.Position(), drag.Length());
4948*8af74909SZhong Yang 						const Sci::Position lengthInserted = pdoc->InsertString(
4949*8af74909SZhong Yang 							newPos.Position(), drag.Data(), length);
4950*8af74909SZhong Yang 						if (lengthInserted > 0) {
4951*8af74909SZhong Yang 							SetSelection(newPos.Position(), newPos.Position() + lengthInserted);
4952*8af74909SZhong Yang 						}
4953*8af74909SZhong Yang 					} else if (newPos > selEnd) {
4954*8af74909SZhong Yang 						pdoc->DeleteChars(selStart.Position(), drag.Length());
4955*8af74909SZhong Yang 						newPos.Add(-static_cast<Sci::Position>(drag.Length()));
4956*8af74909SZhong Yang 						const Sci::Position lengthInserted = pdoc->InsertString(
4957*8af74909SZhong Yang 							newPos.Position(), drag.Data(), length);
4958*8af74909SZhong Yang 						if (lengthInserted > 0) {
4959*8af74909SZhong Yang 							SetSelection(newPos.Position(), newPos.Position() + lengthInserted);
4960*8af74909SZhong Yang 						}
4961*8af74909SZhong Yang 					} else {
4962*8af74909SZhong Yang 						SetEmptySelection(newPos.Position());
4963*8af74909SZhong Yang 					}
4964*8af74909SZhong Yang 					drag.Clear();
4965*8af74909SZhong Yang 				}
4966*8af74909SZhong Yang 				selectionUnit = TextUnit::character;
4967*8af74909SZhong Yang 			}
4968*8af74909SZhong Yang 		} else {
4969*8af74909SZhong Yang 			if (selectionUnit == TextUnit::character) {
4970*8af74909SZhong Yang 				if (sel.Count() > 1) {
4971*8af74909SZhong Yang 					sel.RangeMain() =
4972*8af74909SZhong Yang 						SelectionRange(newPos, sel.Range(sel.Count() - 1).anchor);
4973*8af74909SZhong Yang 					InvalidateWholeSelection();
4974*8af74909SZhong Yang 				} else {
4975*8af74909SZhong Yang 					SetSelection(newPos, sel.RangeMain().anchor);
4976*8af74909SZhong Yang 				}
4977*8af74909SZhong Yang 			}
4978*8af74909SZhong Yang 			sel.CommitTentative();
4979*8af74909SZhong Yang 		}
4980*8af74909SZhong Yang 		SetRectangularRange();
4981*8af74909SZhong Yang 		lastClickTime = curTime;
4982*8af74909SZhong Yang 		lastClick = pt;
4983*8af74909SZhong Yang 		lastXChosen = static_cast<int>(pt.x) + xOffset;
4984*8af74909SZhong Yang 		if (sel.selType == Selection::selStream) {
4985*8af74909SZhong Yang 			SetLastXChosen();
4986*8af74909SZhong Yang 		}
4987*8af74909SZhong Yang 		inDragDrop = ddNone;
4988*8af74909SZhong Yang 		EnsureCaretVisible(false);
4989*8af74909SZhong Yang 	}
4990*8af74909SZhong Yang }
4991*8af74909SZhong Yang 
Idle()4992*8af74909SZhong Yang bool Editor::Idle() {
4993*8af74909SZhong Yang 	NotifyUpdateUI();
4994*8af74909SZhong Yang 
4995*8af74909SZhong Yang 	bool needWrap = Wrapping() && wrapPending.NeedsWrap();
4996*8af74909SZhong Yang 
4997*8af74909SZhong Yang 	if (needWrap) {
4998*8af74909SZhong Yang 		// Wrap lines during idle.
4999*8af74909SZhong Yang 		WrapLines(WrapScope::wsIdle);
5000*8af74909SZhong Yang 		// No more wrapping
5001*8af74909SZhong Yang 		needWrap = wrapPending.NeedsWrap();
5002*8af74909SZhong Yang 	} else if (needIdleStyling) {
5003*8af74909SZhong Yang 		IdleStyling();
5004*8af74909SZhong Yang 	}
5005*8af74909SZhong Yang 
5006*8af74909SZhong Yang 	// Add more idle things to do here, but make sure idleDone is
5007*8af74909SZhong Yang 	// set correctly before the function returns. returning
5008*8af74909SZhong Yang 	// false will stop calling this idle function until SetIdle() is
5009*8af74909SZhong Yang 	// called again.
5010*8af74909SZhong Yang 
5011*8af74909SZhong Yang 	const bool idleDone = !needWrap && !needIdleStyling; // && thatDone && theOtherThingDone...
5012*8af74909SZhong Yang 
5013*8af74909SZhong Yang 	return !idleDone;
5014*8af74909SZhong Yang }
5015*8af74909SZhong Yang 
TickFor(TickReason reason)5016*8af74909SZhong Yang void Editor::TickFor(TickReason reason) {
5017*8af74909SZhong Yang 	switch (reason) {
5018*8af74909SZhong Yang 		case tickCaret:
5019*8af74909SZhong Yang 			caret.on = !caret.on;
5020*8af74909SZhong Yang 			if (caret.active) {
5021*8af74909SZhong Yang 				InvalidateCaret();
5022*8af74909SZhong Yang 			}
5023*8af74909SZhong Yang 			break;
5024*8af74909SZhong Yang 		case tickScroll:
5025*8af74909SZhong Yang 			// Auto scroll
5026*8af74909SZhong Yang 			ButtonMoveWithModifiers(ptMouseLast, 0, 0);
5027*8af74909SZhong Yang 			break;
5028*8af74909SZhong Yang 		case tickWiden:
5029*8af74909SZhong Yang 			SetScrollBars();
5030*8af74909SZhong Yang 			FineTickerCancel(tickWiden);
5031*8af74909SZhong Yang 			break;
5032*8af74909SZhong Yang 		case tickDwell:
5033*8af74909SZhong Yang 			if ((!HaveMouseCapture()) &&
5034*8af74909SZhong Yang 				(ptMouseLast.y >= 0)) {
5035*8af74909SZhong Yang 				dwelling = true;
5036*8af74909SZhong Yang 				NotifyDwelling(ptMouseLast, dwelling);
5037*8af74909SZhong Yang 			}
5038*8af74909SZhong Yang 			FineTickerCancel(tickDwell);
5039*8af74909SZhong Yang 			break;
5040*8af74909SZhong Yang 		default:
5041*8af74909SZhong Yang 			// tickPlatform handled by subclass
5042*8af74909SZhong Yang 			break;
5043*8af74909SZhong Yang 	}
5044*8af74909SZhong Yang }
5045*8af74909SZhong Yang 
5046*8af74909SZhong Yang // FineTickerStart is be overridden by subclasses that support fine ticking so
5047*8af74909SZhong Yang // this method should never be called.
FineTickerRunning(TickReason)5048*8af74909SZhong Yang bool Editor::FineTickerRunning(TickReason) {
5049*8af74909SZhong Yang 	assert(false);
5050*8af74909SZhong Yang 	return false;
5051*8af74909SZhong Yang }
5052*8af74909SZhong Yang 
5053*8af74909SZhong Yang // FineTickerStart is be overridden by subclasses that support fine ticking so
5054*8af74909SZhong Yang // this method should never be called.
FineTickerStart(TickReason,int,int)5055*8af74909SZhong Yang void Editor::FineTickerStart(TickReason, int, int) {
5056*8af74909SZhong Yang 	assert(false);
5057*8af74909SZhong Yang }
5058*8af74909SZhong Yang 
5059*8af74909SZhong Yang // FineTickerCancel is be overridden by subclasses that support fine ticking so
5060*8af74909SZhong Yang // this method should never be called.
FineTickerCancel(TickReason)5061*8af74909SZhong Yang void Editor::FineTickerCancel(TickReason) {
5062*8af74909SZhong Yang 	assert(false);
5063*8af74909SZhong Yang }
5064*8af74909SZhong Yang 
SetFocusState(bool focusState)5065*8af74909SZhong Yang void Editor::SetFocusState(bool focusState) {
5066*8af74909SZhong Yang 	hasFocus = focusState;
5067*8af74909SZhong Yang 	NotifyFocus(hasFocus);
5068*8af74909SZhong Yang 	if (!hasFocus) {
5069*8af74909SZhong Yang 		CancelModes();
5070*8af74909SZhong Yang 	}
5071*8af74909SZhong Yang 	ShowCaretAtCurrentPosition();
5072*8af74909SZhong Yang }
5073*8af74909SZhong Yang 
PositionAfterArea(PRectangle rcArea) const5074*8af74909SZhong Yang Sci::Position Editor::PositionAfterArea(PRectangle rcArea) const {
5075*8af74909SZhong Yang 	// The start of the document line after the display line after the area
5076*8af74909SZhong Yang 	// This often means that the line after a modification is restyled which helps
5077*8af74909SZhong Yang 	// detect multiline comment additions and heals single line comments
5078*8af74909SZhong Yang 	const Sci::Line lineAfter = TopLineOfMain() + static_cast<Sci::Line>(rcArea.bottom - 1) / vs.lineHeight + 1;
5079*8af74909SZhong Yang 	if (lineAfter < pcs->LinesDisplayed())
5080*8af74909SZhong Yang 		return pdoc->LineStart(pcs->DocFromDisplay(lineAfter) + 1);
5081*8af74909SZhong Yang 	else
5082*8af74909SZhong Yang 		return pdoc->Length();
5083*8af74909SZhong Yang }
5084*8af74909SZhong Yang 
5085*8af74909SZhong Yang // Style to a position within the view. If this causes a change at end of last line then
5086*8af74909SZhong Yang // affects later lines so style all the viewed text.
StyleToPositionInView(Sci::Position pos)5087*8af74909SZhong Yang void Editor::StyleToPositionInView(Sci::Position pos) {
5088*8af74909SZhong Yang 	Sci::Position endWindow = PositionAfterArea(GetClientDrawingRectangle());
5089*8af74909SZhong Yang 	if (pos > endWindow)
5090*8af74909SZhong Yang 		pos = endWindow;
5091*8af74909SZhong Yang 	const int styleAtEnd = pdoc->StyleIndexAt(pos-1);
5092*8af74909SZhong Yang 	pdoc->EnsureStyledTo(pos);
5093*8af74909SZhong Yang 	if ((endWindow > pos) && (styleAtEnd != pdoc->StyleIndexAt(pos-1))) {
5094*8af74909SZhong Yang 		// Style at end of line changed so is multi-line change like starting a comment
5095*8af74909SZhong Yang 		// so require rest of window to be styled.
5096*8af74909SZhong Yang 		DiscardOverdraw();	// Prepared bitmaps may be invalid
5097*8af74909SZhong Yang 		// DiscardOverdraw may have truncated client drawing area so recalculate endWindow
5098*8af74909SZhong Yang 		endWindow = PositionAfterArea(GetClientDrawingRectangle());
5099*8af74909SZhong Yang 		pdoc->EnsureStyledTo(endWindow);
5100*8af74909SZhong Yang 	}
5101*8af74909SZhong Yang }
5102*8af74909SZhong Yang 
PositionAfterMaxStyling(Sci::Position posMax,bool scrolling) const5103*8af74909SZhong Yang Sci::Position Editor::PositionAfterMaxStyling(Sci::Position posMax, bool scrolling) const {
5104*8af74909SZhong Yang 	if (SynchronousStylingToVisible()) {
5105*8af74909SZhong Yang 		// Both states do not limit styling
5106*8af74909SZhong Yang 		return posMax;
5107*8af74909SZhong Yang 	}
5108*8af74909SZhong Yang 
5109*8af74909SZhong Yang 	// Try to keep time taken by styling reasonable so interaction remains smooth.
5110*8af74909SZhong Yang 	// When scrolling, allow less time to ensure responsive
5111*8af74909SZhong Yang 	const double secondsAllowed = scrolling ? 0.005 : 0.02;
5112*8af74909SZhong Yang 
5113*8af74909SZhong Yang 	const Sci::Line linesToStyle = std::clamp(
5114*8af74909SZhong Yang 		static_cast<int>(secondsAllowed / pdoc->durationStyleOneLine.Duration()),
5115*8af74909SZhong Yang 		10, 0x10000);
5116*8af74909SZhong Yang 	const Sci::Line stylingMaxLine = std::min(
5117*8af74909SZhong Yang 		pdoc->SciLineFromPosition(pdoc->GetEndStyled()) + linesToStyle,
5118*8af74909SZhong Yang 		pdoc->LinesTotal());
5119*8af74909SZhong Yang 	return std::min(pdoc->LineStart(stylingMaxLine), posMax);
5120*8af74909SZhong Yang }
5121*8af74909SZhong Yang 
StartIdleStyling(bool truncatedLastStyling)5122*8af74909SZhong Yang void Editor::StartIdleStyling(bool truncatedLastStyling) {
5123*8af74909SZhong Yang 	if ((idleStyling == SC_IDLESTYLING_ALL) || (idleStyling == SC_IDLESTYLING_AFTERVISIBLE)) {
5124*8af74909SZhong Yang 		if (pdoc->GetEndStyled() < pdoc->Length()) {
5125*8af74909SZhong Yang 			// Style remainder of document in idle time
5126*8af74909SZhong Yang 			needIdleStyling = true;
5127*8af74909SZhong Yang 		}
5128*8af74909SZhong Yang 	} else if (truncatedLastStyling) {
5129*8af74909SZhong Yang 		needIdleStyling = true;
5130*8af74909SZhong Yang 	}
5131*8af74909SZhong Yang 
5132*8af74909SZhong Yang 	if (needIdleStyling) {
5133*8af74909SZhong Yang 		SetIdle(true);
5134*8af74909SZhong Yang 	}
5135*8af74909SZhong Yang }
5136*8af74909SZhong Yang 
5137*8af74909SZhong Yang // Style for an area but bound the amount of styling to remain responsive
StyleAreaBounded(PRectangle rcArea,bool scrolling)5138*8af74909SZhong Yang void Editor::StyleAreaBounded(PRectangle rcArea, bool scrolling) {
5139*8af74909SZhong Yang 	const Sci::Position posAfterArea = PositionAfterArea(rcArea);
5140*8af74909SZhong Yang 	const Sci::Position posAfterMax = PositionAfterMaxStyling(posAfterArea, scrolling);
5141*8af74909SZhong Yang 	if (posAfterMax < posAfterArea) {
5142*8af74909SZhong Yang 		// Idle styling may be performed before current visible area
5143*8af74909SZhong Yang 		// Style a bit now then style further in idle time
5144*8af74909SZhong Yang 		pdoc->StyleToAdjustingLineDuration(posAfterMax);
5145*8af74909SZhong Yang 	} else {
5146*8af74909SZhong Yang 		// Can style all wanted now.
5147*8af74909SZhong Yang 		StyleToPositionInView(posAfterArea);
5148*8af74909SZhong Yang 	}
5149*8af74909SZhong Yang 	StartIdleStyling(posAfterMax < posAfterArea);
5150*8af74909SZhong Yang }
5151*8af74909SZhong Yang 
IdleStyling()5152*8af74909SZhong Yang void Editor::IdleStyling() {
5153*8af74909SZhong Yang 	const Sci::Position posAfterArea = PositionAfterArea(GetClientRectangle());
5154*8af74909SZhong Yang 	const Sci::Position endGoal = (idleStyling >= SC_IDLESTYLING_AFTERVISIBLE) ?
5155*8af74909SZhong Yang 		pdoc->Length() : posAfterArea;
5156*8af74909SZhong Yang 	const Sci::Position posAfterMax = PositionAfterMaxStyling(endGoal, false);
5157*8af74909SZhong Yang 	pdoc->StyleToAdjustingLineDuration(posAfterMax);
5158*8af74909SZhong Yang 	if (pdoc->GetEndStyled() >= endGoal) {
5159*8af74909SZhong Yang 		needIdleStyling = false;
5160*8af74909SZhong Yang 	}
5161*8af74909SZhong Yang }
5162*8af74909SZhong Yang 
IdleWork()5163*8af74909SZhong Yang void Editor::IdleWork() {
5164*8af74909SZhong Yang 	// Style the line after the modification as this allows modifications that change just the
5165*8af74909SZhong Yang 	// line of the modification to heal instead of propagating to the rest of the window.
5166*8af74909SZhong Yang 	if (workNeeded.items & WorkNeeded::workStyle) {
5167*8af74909SZhong Yang 		StyleToPositionInView(pdoc->LineStart(pdoc->LineFromPosition(workNeeded.upTo) + 2));
5168*8af74909SZhong Yang 	}
5169*8af74909SZhong Yang 	NotifyUpdateUI();
5170*8af74909SZhong Yang 	workNeeded.Reset();
5171*8af74909SZhong Yang }
5172*8af74909SZhong Yang 
QueueIdleWork(WorkNeeded::workItems items,Sci::Position upTo)5173*8af74909SZhong Yang void Editor::QueueIdleWork(WorkNeeded::workItems items, Sci::Position upTo) {
5174*8af74909SZhong Yang 	workNeeded.Need(items, upTo);
5175*8af74909SZhong Yang }
5176*8af74909SZhong Yang 
PaintContains(PRectangle rc)5177*8af74909SZhong Yang bool Editor::PaintContains(PRectangle rc) {
5178*8af74909SZhong Yang 	if (rc.Empty()) {
5179*8af74909SZhong Yang 		return true;
5180*8af74909SZhong Yang 	} else {
5181*8af74909SZhong Yang 		return rcPaint.Contains(rc);
5182*8af74909SZhong Yang 	}
5183*8af74909SZhong Yang }
5184*8af74909SZhong Yang 
PaintContainsMargin()5185*8af74909SZhong Yang bool Editor::PaintContainsMargin() {
5186*8af74909SZhong Yang 	if (wMargin.GetID()) {
5187*8af74909SZhong Yang 		// With separate margin view, paint of text view
5188*8af74909SZhong Yang 		// never contains margin.
5189*8af74909SZhong Yang 		return false;
5190*8af74909SZhong Yang 	}
5191*8af74909SZhong Yang 	PRectangle rcSelMargin = GetClientRectangle();
5192*8af74909SZhong Yang 	rcSelMargin.right = static_cast<XYPOSITION>(vs.textStart);
5193*8af74909SZhong Yang 	return PaintContains(rcSelMargin);
5194*8af74909SZhong Yang }
5195*8af74909SZhong Yang 
CheckForChangeOutsidePaint(Range r)5196*8af74909SZhong Yang void Editor::CheckForChangeOutsidePaint(Range r) {
5197*8af74909SZhong Yang 	if (paintState == painting && !paintingAllText) {
5198*8af74909SZhong Yang 		//Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end);
5199*8af74909SZhong Yang 		if (!r.Valid())
5200*8af74909SZhong Yang 			return;
5201*8af74909SZhong Yang 
5202*8af74909SZhong Yang 		PRectangle rcRange = RectangleFromRange(r, 0);
5203*8af74909SZhong Yang 		const PRectangle rcText = GetTextRectangle();
5204*8af74909SZhong Yang 		if (rcRange.top < rcText.top) {
5205*8af74909SZhong Yang 			rcRange.top = rcText.top;
5206*8af74909SZhong Yang 		}
5207*8af74909SZhong Yang 		if (rcRange.bottom > rcText.bottom) {
5208*8af74909SZhong Yang 			rcRange.bottom = rcText.bottom;
5209*8af74909SZhong Yang 		}
5210*8af74909SZhong Yang 
5211*8af74909SZhong Yang 		if (!PaintContains(rcRange)) {
5212*8af74909SZhong Yang 			AbandonPaint();
5213*8af74909SZhong Yang 			paintAbandonedByStyling = true;
5214*8af74909SZhong Yang 		}
5215*8af74909SZhong Yang 	}
5216*8af74909SZhong Yang }
5217*8af74909SZhong Yang 
SetBraceHighlight(Sci::Position pos0,Sci::Position pos1,int matchStyle)5218*8af74909SZhong Yang void Editor::SetBraceHighlight(Sci::Position pos0, Sci::Position pos1, int matchStyle) {
5219*8af74909SZhong Yang 	if ((pos0 != braces[0]) || (pos1 != braces[1]) || (matchStyle != bracesMatchStyle)) {
5220*8af74909SZhong Yang 		if ((braces[0] != pos0) || (matchStyle != bracesMatchStyle)) {
5221*8af74909SZhong Yang 			CheckForChangeOutsidePaint(Range(braces[0]));
5222*8af74909SZhong Yang 			CheckForChangeOutsidePaint(Range(pos0));
5223*8af74909SZhong Yang 			braces[0] = pos0;
5224*8af74909SZhong Yang 		}
5225*8af74909SZhong Yang 		if ((braces[1] != pos1) || (matchStyle != bracesMatchStyle)) {
5226*8af74909SZhong Yang 			CheckForChangeOutsidePaint(Range(braces[1]));
5227*8af74909SZhong Yang 			CheckForChangeOutsidePaint(Range(pos1));
5228*8af74909SZhong Yang 			braces[1] = pos1;
5229*8af74909SZhong Yang 		}
5230*8af74909SZhong Yang 		bracesMatchStyle = matchStyle;
5231*8af74909SZhong Yang 		if (paintState == notPainting) {
5232*8af74909SZhong Yang 			Redraw();
5233*8af74909SZhong Yang 		}
5234*8af74909SZhong Yang 	}
5235*8af74909SZhong Yang }
5236*8af74909SZhong Yang 
SetAnnotationHeights(Sci::Line start,Sci::Line end)5237*8af74909SZhong Yang void Editor::SetAnnotationHeights(Sci::Line start, Sci::Line end) {
5238*8af74909SZhong Yang 	if (vs.annotationVisible) {
5239*8af74909SZhong Yang 		RefreshStyleData();
5240*8af74909SZhong Yang 		bool changedHeight = false;
5241*8af74909SZhong Yang 		for (Sci::Line line=start; line<end && line<pdoc->LinesTotal(); line++) {
5242*8af74909SZhong Yang 			int linesWrapped = 1;
5243*8af74909SZhong Yang 			if (Wrapping()) {
5244*8af74909SZhong Yang 				AutoSurface surface(this);
5245*8af74909SZhong Yang 				AutoLineLayout ll(view.llc, view.RetrieveLineLayout(line, *this));
5246*8af74909SZhong Yang 				if (surface && ll) {
5247*8af74909SZhong Yang 					view.LayoutLine(*this, line, surface, vs, ll, wrapWidth);
5248*8af74909SZhong Yang 					linesWrapped = ll->lines;
5249*8af74909SZhong Yang 				}
5250*8af74909SZhong Yang 			}
5251*8af74909SZhong Yang 			if (pcs->SetHeight(line, pdoc->AnnotationLines(line) + linesWrapped))
5252*8af74909SZhong Yang 				changedHeight = true;
5253*8af74909SZhong Yang 		}
5254*8af74909SZhong Yang 		if (changedHeight) {
5255*8af74909SZhong Yang 			Redraw();
5256*8af74909SZhong Yang 		}
5257*8af74909SZhong Yang 	}
5258*8af74909SZhong Yang }
5259*8af74909SZhong Yang 
SetDocPointer(Document * document)5260*8af74909SZhong Yang void Editor::SetDocPointer(Document *document) {
5261*8af74909SZhong Yang 	//Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document);
5262*8af74909SZhong Yang 	pdoc->RemoveWatcher(this, 0);
5263*8af74909SZhong Yang 	pdoc->Release();
5264*8af74909SZhong Yang 	if (!document) {
5265*8af74909SZhong Yang 		pdoc = new Document(SC_DOCUMENTOPTION_DEFAULT);
5266*8af74909SZhong Yang 	} else {
5267*8af74909SZhong Yang 		pdoc = document;
5268*8af74909SZhong Yang 	}
5269*8af74909SZhong Yang 	pdoc->AddRef();
5270*8af74909SZhong Yang 	pcs = ContractionStateCreate(pdoc->IsLarge());
5271*8af74909SZhong Yang 
5272*8af74909SZhong Yang 	// Ensure all positions within document
5273*8af74909SZhong Yang 	sel.Clear();
5274*8af74909SZhong Yang 	targetRange = SelectionSegment();
5275*8af74909SZhong Yang 
5276*8af74909SZhong Yang 	braces[0] = Sci::invalidPosition;
5277*8af74909SZhong Yang 	braces[1] = Sci::invalidPosition;
5278*8af74909SZhong Yang 
5279*8af74909SZhong Yang 	vs.ReleaseAllExtendedStyles();
5280*8af74909SZhong Yang 
5281*8af74909SZhong Yang 	SetRepresentations();
5282*8af74909SZhong Yang 
5283*8af74909SZhong Yang 	// Reset the contraction state to fully shown.
5284*8af74909SZhong Yang 	pcs->Clear();
5285*8af74909SZhong Yang 	pcs->InsertLines(0, pdoc->LinesTotal() - 1);
5286*8af74909SZhong Yang 	SetAnnotationHeights(0, pdoc->LinesTotal());
5287*8af74909SZhong Yang 	view.llc.Deallocate();
5288*8af74909SZhong Yang 	NeedWrapping();
5289*8af74909SZhong Yang 
5290*8af74909SZhong Yang 	hotspot = Range(Sci::invalidPosition);
5291*8af74909SZhong Yang 	hoverIndicatorPos = Sci::invalidPosition;
5292*8af74909SZhong Yang 
5293*8af74909SZhong Yang 	view.ClearAllTabstops();
5294*8af74909SZhong Yang 
5295*8af74909SZhong Yang 	pdoc->AddWatcher(this, 0);
5296*8af74909SZhong Yang 	SetScrollBars();
5297*8af74909SZhong Yang 	Redraw();
5298*8af74909SZhong Yang }
5299*8af74909SZhong Yang 
SetAnnotationVisible(int visible)5300*8af74909SZhong Yang void Editor::SetAnnotationVisible(int visible) {
5301*8af74909SZhong Yang 	if (vs.annotationVisible != visible) {
5302*8af74909SZhong Yang 		const bool changedFromOrToHidden = ((vs.annotationVisible != 0) != (visible != 0));
5303*8af74909SZhong Yang 		vs.annotationVisible = visible;
5304*8af74909SZhong Yang 		if (changedFromOrToHidden) {
5305*8af74909SZhong Yang 			const int dir = vs.annotationVisible ? 1 : -1;
5306*8af74909SZhong Yang 			for (Sci::Line line=0; line<pdoc->LinesTotal(); line++) {
5307*8af74909SZhong Yang 				const int annotationLines = pdoc->AnnotationLines(line);
5308*8af74909SZhong Yang 				if (annotationLines > 0) {
5309*8af74909SZhong Yang 					pcs->SetHeight(line, pcs->GetHeight(line) + annotationLines * dir);
5310*8af74909SZhong Yang 				}
5311*8af74909SZhong Yang 			}
5312*8af74909SZhong Yang 			SetScrollBars();
5313*8af74909SZhong Yang 		}
5314*8af74909SZhong Yang 		Redraw();
5315*8af74909SZhong Yang 	}
5316*8af74909SZhong Yang }
5317*8af74909SZhong Yang 
SetEOLAnnotationVisible(int visible)5318*8af74909SZhong Yang void Editor::SetEOLAnnotationVisible(int visible) {
5319*8af74909SZhong Yang 	if (vs.eolAnnotationVisible != visible) {
5320*8af74909SZhong Yang 		vs.eolAnnotationVisible = visible;
5321*8af74909SZhong Yang 		Redraw();
5322*8af74909SZhong Yang 	}
5323*8af74909SZhong Yang }
5324*8af74909SZhong Yang 
5325*8af74909SZhong Yang /**
5326*8af74909SZhong Yang  * Recursively expand a fold, making lines visible except where they have an unexpanded parent.
5327*8af74909SZhong Yang  */
ExpandLine(Sci::Line line)5328*8af74909SZhong Yang Sci::Line Editor::ExpandLine(Sci::Line line) {
5329*8af74909SZhong Yang 	const Sci::Line lineMaxSubord = pdoc->GetLastChild(line);
5330*8af74909SZhong Yang 	line++;
5331*8af74909SZhong Yang 	while (line <= lineMaxSubord) {
5332*8af74909SZhong Yang 		pcs->SetVisible(line, line, true);
5333*8af74909SZhong Yang 		const int level = pdoc->GetLevel(line);
5334*8af74909SZhong Yang 		if (level & SC_FOLDLEVELHEADERFLAG) {
5335*8af74909SZhong Yang 			if (pcs->GetExpanded(line)) {
5336*8af74909SZhong Yang 				line = ExpandLine(line);
5337*8af74909SZhong Yang 			} else {
5338*8af74909SZhong Yang 				line = pdoc->GetLastChild(line);
5339*8af74909SZhong Yang 			}
5340*8af74909SZhong Yang 		}
5341*8af74909SZhong Yang 		line++;
5342*8af74909SZhong Yang 	}
5343*8af74909SZhong Yang 	return lineMaxSubord;
5344*8af74909SZhong Yang }
5345*8af74909SZhong Yang 
SetFoldExpanded(Sci::Line lineDoc,bool expanded)5346*8af74909SZhong Yang void Editor::SetFoldExpanded(Sci::Line lineDoc, bool expanded) {
5347*8af74909SZhong Yang 	if (pcs->SetExpanded(lineDoc, expanded)) {
5348*8af74909SZhong Yang 		RedrawSelMargin();
5349*8af74909SZhong Yang 	}
5350*8af74909SZhong Yang }
5351*8af74909SZhong Yang 
FoldLine(Sci::Line line,int action)5352*8af74909SZhong Yang void Editor::FoldLine(Sci::Line line, int action) {
5353*8af74909SZhong Yang 	if (line >= 0) {
5354*8af74909SZhong Yang 		if (action == SC_FOLDACTION_TOGGLE) {
5355*8af74909SZhong Yang 			if ((pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) == 0) {
5356*8af74909SZhong Yang 				line = pdoc->GetFoldParent(line);
5357*8af74909SZhong Yang 				if (line < 0)
5358*8af74909SZhong Yang 					return;
5359*8af74909SZhong Yang 			}
5360*8af74909SZhong Yang 			action = (pcs->GetExpanded(line)) ? SC_FOLDACTION_CONTRACT : SC_FOLDACTION_EXPAND;
5361*8af74909SZhong Yang 		}
5362*8af74909SZhong Yang 
5363*8af74909SZhong Yang 		if (action == SC_FOLDACTION_CONTRACT) {
5364*8af74909SZhong Yang 			const Sci::Line lineMaxSubord = pdoc->GetLastChild(line);
5365*8af74909SZhong Yang 			if (lineMaxSubord > line) {
5366*8af74909SZhong Yang 				pcs->SetExpanded(line, false);
5367*8af74909SZhong Yang 				pcs->SetVisible(line + 1, lineMaxSubord, false);
5368*8af74909SZhong Yang 
5369*8af74909SZhong Yang 				const Sci::Line lineCurrent =
5370*8af74909SZhong Yang 					pdoc->SciLineFromPosition(sel.MainCaret());
5371*8af74909SZhong Yang 				if (lineCurrent > line && lineCurrent <= lineMaxSubord) {
5372*8af74909SZhong Yang 					// This does not re-expand the fold
5373*8af74909SZhong Yang 					EnsureCaretVisible();
5374*8af74909SZhong Yang 				}
5375*8af74909SZhong Yang 			}
5376*8af74909SZhong Yang 
5377*8af74909SZhong Yang 		} else {
5378*8af74909SZhong Yang 			if (!(pcs->GetVisible(line))) {
5379*8af74909SZhong Yang 				EnsureLineVisible(line, false);
5380*8af74909SZhong Yang 				GoToLine(line);
5381*8af74909SZhong Yang 			}
5382*8af74909SZhong Yang 			pcs->SetExpanded(line, true);
5383*8af74909SZhong Yang 			ExpandLine(line);
5384*8af74909SZhong Yang 		}
5385*8af74909SZhong Yang 
5386*8af74909SZhong Yang 		SetScrollBars();
5387*8af74909SZhong Yang 		Redraw();
5388*8af74909SZhong Yang 	}
5389*8af74909SZhong Yang }
5390*8af74909SZhong Yang 
FoldExpand(Sci::Line line,int action,int level)5391*8af74909SZhong Yang void Editor::FoldExpand(Sci::Line line, int action, int level) {
5392*8af74909SZhong Yang 	bool expanding = action == SC_FOLDACTION_EXPAND;
5393*8af74909SZhong Yang 	if (action == SC_FOLDACTION_TOGGLE) {
5394*8af74909SZhong Yang 		expanding = !pcs->GetExpanded(line);
5395*8af74909SZhong Yang 	}
5396*8af74909SZhong Yang 	// Ensure child lines lexed and fold information extracted before
5397*8af74909SZhong Yang 	// flipping the state.
5398*8af74909SZhong Yang 	pdoc->GetLastChild(line, LevelNumber(level));
5399*8af74909SZhong Yang 	SetFoldExpanded(line, expanding);
5400*8af74909SZhong Yang 	if (expanding && (pcs->HiddenLines() == 0))
5401*8af74909SZhong Yang 		// Nothing to do
5402*8af74909SZhong Yang 		return;
5403*8af74909SZhong Yang 	const Sci::Line lineMaxSubord = pdoc->GetLastChild(line, LevelNumber(level));
5404*8af74909SZhong Yang 	line++;
5405*8af74909SZhong Yang 	pcs->SetVisible(line, lineMaxSubord, expanding);
5406*8af74909SZhong Yang 	while (line <= lineMaxSubord) {
5407*8af74909SZhong Yang 		const int levelLine = pdoc->GetLevel(line);
5408*8af74909SZhong Yang 		if (levelLine & SC_FOLDLEVELHEADERFLAG) {
5409*8af74909SZhong Yang 			SetFoldExpanded(line, expanding);
5410*8af74909SZhong Yang 		}
5411*8af74909SZhong Yang 		line++;
5412*8af74909SZhong Yang 	}
5413*8af74909SZhong Yang 	SetScrollBars();
5414*8af74909SZhong Yang 	Redraw();
5415*8af74909SZhong Yang }
5416*8af74909SZhong Yang 
ContractedFoldNext(Sci::Line lineStart) const5417*8af74909SZhong Yang Sci::Line Editor::ContractedFoldNext(Sci::Line lineStart) const {
5418*8af74909SZhong Yang 	for (Sci::Line line = lineStart; line<pdoc->LinesTotal();) {
5419*8af74909SZhong Yang 		if (!pcs->GetExpanded(line) && (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG))
5420*8af74909SZhong Yang 			return line;
5421*8af74909SZhong Yang 		line = pcs->ContractedNext(line+1);
5422*8af74909SZhong Yang 		if (line < 0)
5423*8af74909SZhong Yang 			return -1;
5424*8af74909SZhong Yang 	}
5425*8af74909SZhong Yang 
5426*8af74909SZhong Yang 	return -1;
5427*8af74909SZhong Yang }
5428*8af74909SZhong Yang 
5429*8af74909SZhong Yang /**
5430*8af74909SZhong Yang  * Recurse up from this line to find any folds that prevent this line from being visible
5431*8af74909SZhong Yang  * and unfold them all.
5432*8af74909SZhong Yang  */
EnsureLineVisible(Sci::Line lineDoc,bool enforcePolicy)5433*8af74909SZhong Yang void Editor::EnsureLineVisible(Sci::Line lineDoc, bool enforcePolicy) {
5434*8af74909SZhong Yang 
5435*8af74909SZhong Yang 	// In case in need of wrapping to ensure DisplayFromDoc works.
5436*8af74909SZhong Yang 	if (lineDoc >= wrapPending.start) {
5437*8af74909SZhong Yang 		if (WrapLines(WrapScope::wsAll)) {
5438*8af74909SZhong Yang 			Redraw();
5439*8af74909SZhong Yang 		}
5440*8af74909SZhong Yang 	}
5441*8af74909SZhong Yang 
5442*8af74909SZhong Yang 	if (!pcs->GetVisible(lineDoc)) {
5443*8af74909SZhong Yang 		// Back up to find a non-blank line
5444*8af74909SZhong Yang 		Sci::Line lookLine = lineDoc;
5445*8af74909SZhong Yang 		int lookLineLevel = pdoc->GetLevel(lookLine);
5446*8af74909SZhong Yang 		while ((lookLine > 0) && (lookLineLevel & SC_FOLDLEVELWHITEFLAG)) {
5447*8af74909SZhong Yang 			lookLineLevel = pdoc->GetLevel(--lookLine);
5448*8af74909SZhong Yang 		}
5449*8af74909SZhong Yang 		Sci::Line lineParent = pdoc->GetFoldParent(lookLine);
5450*8af74909SZhong Yang 		if (lineParent < 0) {
5451*8af74909SZhong Yang 			// Backed up to a top level line, so try to find parent of initial line
5452*8af74909SZhong Yang 			lineParent = pdoc->GetFoldParent(lineDoc);
5453*8af74909SZhong Yang 		}
5454*8af74909SZhong Yang 		if (lineParent >= 0) {
5455*8af74909SZhong Yang 			if (lineDoc != lineParent)
5456*8af74909SZhong Yang 				EnsureLineVisible(lineParent, enforcePolicy);
5457*8af74909SZhong Yang 			if (!pcs->GetExpanded(lineParent)) {
5458*8af74909SZhong Yang 				pcs->SetExpanded(lineParent, true);
5459*8af74909SZhong Yang 				ExpandLine(lineParent);
5460*8af74909SZhong Yang 			}
5461*8af74909SZhong Yang 		}
5462*8af74909SZhong Yang 		SetScrollBars();
5463*8af74909SZhong Yang 		Redraw();
5464*8af74909SZhong Yang 	}
5465*8af74909SZhong Yang 	if (enforcePolicy) {
5466*8af74909SZhong Yang 		const Sci::Line lineDisplay = pcs->DisplayFromDoc(lineDoc);
5467*8af74909SZhong Yang 		if (visiblePolicy.policy & VISIBLE_SLOP) {
5468*8af74909SZhong Yang 			if ((topLine > lineDisplay) || ((visiblePolicy.policy & VISIBLE_STRICT) && (topLine + visiblePolicy.slop > lineDisplay))) {
5469*8af74909SZhong Yang 				SetTopLine(std::clamp<Sci::Line>(lineDisplay - visiblePolicy.slop, 0, MaxScrollPos()));
5470*8af74909SZhong Yang 				SetVerticalScrollPos();
5471*8af74909SZhong Yang 				Redraw();
5472*8af74909SZhong Yang 			} else if ((lineDisplay > topLine + LinesOnScreen() - 1) ||
5473*8af74909SZhong Yang 			        ((visiblePolicy.policy & VISIBLE_STRICT) && (lineDisplay > topLine + LinesOnScreen() - 1 - visiblePolicy.slop))) {
5474*8af74909SZhong Yang 				SetTopLine(std::clamp<Sci::Line>(lineDisplay - LinesOnScreen() + 1 + visiblePolicy.slop, 0, MaxScrollPos()));
5475*8af74909SZhong Yang 				SetVerticalScrollPos();
5476*8af74909SZhong Yang 				Redraw();
5477*8af74909SZhong Yang 			}
5478*8af74909SZhong Yang 		} else {
5479*8af74909SZhong Yang 			if ((topLine > lineDisplay) || (lineDisplay > topLine + LinesOnScreen() - 1) || (visiblePolicy.policy & VISIBLE_STRICT)) {
5480*8af74909SZhong Yang 				SetTopLine(std::clamp<Sci::Line>(lineDisplay - LinesOnScreen() / 2 + 1, 0, MaxScrollPos()));
5481*8af74909SZhong Yang 				SetVerticalScrollPos();
5482*8af74909SZhong Yang 				Redraw();
5483*8af74909SZhong Yang 			}
5484*8af74909SZhong Yang 		}
5485*8af74909SZhong Yang 	}
5486*8af74909SZhong Yang }
5487*8af74909SZhong Yang 
FoldAll(int action)5488*8af74909SZhong Yang void Editor::FoldAll(int action) {
5489*8af74909SZhong Yang 	pdoc->EnsureStyledTo(pdoc->Length());
5490*8af74909SZhong Yang 	const Sci::Line maxLine = pdoc->LinesTotal();
5491*8af74909SZhong Yang 	bool expanding = action == SC_FOLDACTION_EXPAND;
5492*8af74909SZhong Yang 	if (action == SC_FOLDACTION_TOGGLE) {
5493*8af74909SZhong Yang 		// Discover current state
5494*8af74909SZhong Yang 		for (int lineSeek = 0; lineSeek < maxLine; lineSeek++) {
5495*8af74909SZhong Yang 			if (pdoc->GetLevel(lineSeek) & SC_FOLDLEVELHEADERFLAG) {
5496*8af74909SZhong Yang 				expanding = !pcs->GetExpanded(lineSeek);
5497*8af74909SZhong Yang 				break;
5498*8af74909SZhong Yang 			}
5499*8af74909SZhong Yang 		}
5500*8af74909SZhong Yang 	}
5501*8af74909SZhong Yang 	if (expanding) {
5502*8af74909SZhong Yang 		pcs->SetVisible(0, maxLine-1, true);
5503*8af74909SZhong Yang 		for (int line = 0; line < maxLine; line++) {
5504*8af74909SZhong Yang 			const int levelLine = pdoc->GetLevel(line);
5505*8af74909SZhong Yang 			if (levelLine & SC_FOLDLEVELHEADERFLAG) {
5506*8af74909SZhong Yang 				SetFoldExpanded(line, true);
5507*8af74909SZhong Yang 			}
5508*8af74909SZhong Yang 		}
5509*8af74909SZhong Yang 	} else {
5510*8af74909SZhong Yang 		for (Sci::Line line = 0; line < maxLine; line++) {
5511*8af74909SZhong Yang 			const int level = pdoc->GetLevel(line);
5512*8af74909SZhong Yang 			if ((level & SC_FOLDLEVELHEADERFLAG) &&
5513*8af74909SZhong Yang 					(SC_FOLDLEVELBASE == LevelNumber(level))) {
5514*8af74909SZhong Yang 				SetFoldExpanded(line, false);
5515*8af74909SZhong Yang 				const Sci::Line lineMaxSubord = pdoc->GetLastChild(line, -1);
5516*8af74909SZhong Yang 				if (lineMaxSubord > line) {
5517*8af74909SZhong Yang 					pcs->SetVisible(line + 1, lineMaxSubord, false);
5518*8af74909SZhong Yang 				}
5519*8af74909SZhong Yang 			}
5520*8af74909SZhong Yang 		}
5521*8af74909SZhong Yang 	}
5522*8af74909SZhong Yang 	SetScrollBars();
5523*8af74909SZhong Yang 	Redraw();
5524*8af74909SZhong Yang }
5525*8af74909SZhong Yang 
FoldChanged(Sci::Line line,int levelNow,int levelPrev)5526*8af74909SZhong Yang void Editor::FoldChanged(Sci::Line line, int levelNow, int levelPrev) {
5527*8af74909SZhong Yang 	if (levelNow & SC_FOLDLEVELHEADERFLAG) {
5528*8af74909SZhong Yang 		if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) {
5529*8af74909SZhong Yang 			// Adding a fold point.
5530*8af74909SZhong Yang 			if (pcs->SetExpanded(line, true)) {
5531*8af74909SZhong Yang 				RedrawSelMargin();
5532*8af74909SZhong Yang 			}
5533*8af74909SZhong Yang 			FoldExpand(line, SC_FOLDACTION_EXPAND, levelPrev);
5534*8af74909SZhong Yang 		}
5535*8af74909SZhong Yang 	} else if (levelPrev & SC_FOLDLEVELHEADERFLAG) {
5536*8af74909SZhong Yang 		const Sci::Line prevLine = line - 1;
5537*8af74909SZhong Yang 		const int prevLineLevel = pdoc->GetLevel(prevLine);
5538*8af74909SZhong Yang 
5539*8af74909SZhong Yang 		// Combining two blocks where the first block is collapsed (e.g. by deleting the line(s) which separate(s) the two blocks)
5540*8af74909SZhong Yang 		if ((LevelNumber(prevLineLevel) == LevelNumber(levelNow)) && !pcs->GetVisible(prevLine))
5541*8af74909SZhong Yang 			FoldLine(pdoc->GetFoldParent(prevLine), SC_FOLDACTION_EXPAND);
5542*8af74909SZhong Yang 
5543*8af74909SZhong Yang 		if (!pcs->GetExpanded(line)) {
5544*8af74909SZhong Yang 			// Removing the fold from one that has been contracted so should expand
5545*8af74909SZhong Yang 			// otherwise lines are left invisible with no way to make them visible
5546*8af74909SZhong Yang 			if (pcs->SetExpanded(line, true)) {
5547*8af74909SZhong Yang 				RedrawSelMargin();
5548*8af74909SZhong Yang 			}
5549*8af74909SZhong Yang 			// Combining two blocks where the second one is collapsed (e.g. by adding characters in the line which separates the two blocks)
5550*8af74909SZhong Yang 			FoldExpand(line, SC_FOLDACTION_EXPAND, levelPrev);
5551*8af74909SZhong Yang 		}
5552*8af74909SZhong Yang 	}
5553*8af74909SZhong Yang 	if (!(levelNow & SC_FOLDLEVELWHITEFLAG) &&
5554*8af74909SZhong Yang 	        (LevelNumber(levelPrev) > LevelNumber(levelNow))) {
5555*8af74909SZhong Yang 		if (pcs->HiddenLines()) {
5556*8af74909SZhong Yang 			// See if should still be hidden
5557*8af74909SZhong Yang 			const Sci::Line parentLine = pdoc->GetFoldParent(line);
5558*8af74909SZhong Yang 			if ((parentLine < 0) || (pcs->GetExpanded(parentLine) && pcs->GetVisible(parentLine))) {
5559*8af74909SZhong Yang 				pcs->SetVisible(line, line, true);
5560*8af74909SZhong Yang 				SetScrollBars();
5561*8af74909SZhong Yang 				Redraw();
5562*8af74909SZhong Yang 			}
5563*8af74909SZhong Yang 		}
5564*8af74909SZhong Yang 	}
5565*8af74909SZhong Yang 
5566*8af74909SZhong Yang 	// Combining two blocks where the first one is collapsed (e.g. by adding characters in the line which separates the two blocks)
5567*8af74909SZhong Yang 	if (!(levelNow & SC_FOLDLEVELWHITEFLAG) && (LevelNumber(levelPrev) < LevelNumber(levelNow))) {
5568*8af74909SZhong Yang 		if (pcs->HiddenLines()) {
5569*8af74909SZhong Yang 			const Sci::Line parentLine = pdoc->GetFoldParent(line);
5570*8af74909SZhong Yang 			if (!pcs->GetExpanded(parentLine) && pcs->GetVisible(line))
5571*8af74909SZhong Yang 				FoldLine(parentLine, SC_FOLDACTION_EXPAND);
5572*8af74909SZhong Yang 		}
5573*8af74909SZhong Yang 	}
5574*8af74909SZhong Yang }
5575*8af74909SZhong Yang 
NeedShown(Sci::Position pos,Sci::Position len)5576*8af74909SZhong Yang void Editor::NeedShown(Sci::Position pos, Sci::Position len) {
5577*8af74909SZhong Yang 	if (foldAutomatic & SC_AUTOMATICFOLD_SHOW) {
5578*8af74909SZhong Yang 		const Sci::Line lineStart = pdoc->SciLineFromPosition(pos);
5579*8af74909SZhong Yang 		const Sci::Line lineEnd = pdoc->SciLineFromPosition(pos+len);
5580*8af74909SZhong Yang 		for (Sci::Line line = lineStart; line <= lineEnd; line++) {
5581*8af74909SZhong Yang 			EnsureLineVisible(line, false);
5582*8af74909SZhong Yang 		}
5583*8af74909SZhong Yang 	} else {
5584*8af74909SZhong Yang 		NotifyNeedShown(pos, len);
5585*8af74909SZhong Yang 	}
5586*8af74909SZhong Yang }
5587*8af74909SZhong Yang 
GetTag(char * tagValue,int tagNumber)5588*8af74909SZhong Yang Sci::Position Editor::GetTag(char *tagValue, int tagNumber) {
5589*8af74909SZhong Yang 	const char *text = nullptr;
5590*8af74909SZhong Yang 	Sci::Position length = 0;
5591*8af74909SZhong Yang 	if ((tagNumber >= 1) && (tagNumber <= 9)) {
5592*8af74909SZhong Yang 		char name[3] = "\\?";
5593*8af74909SZhong Yang 		name[1] = static_cast<char>(tagNumber + '0');
5594*8af74909SZhong Yang 		length = 2;
5595*8af74909SZhong Yang 		text = pdoc->SubstituteByPosition(name, &length);
5596*8af74909SZhong Yang 	}
5597*8af74909SZhong Yang 	if (tagValue) {
5598*8af74909SZhong Yang 		if (text)
5599*8af74909SZhong Yang 			memcpy(tagValue, text, length + 1);
5600*8af74909SZhong Yang 		else
5601*8af74909SZhong Yang 			*tagValue = '\0';
5602*8af74909SZhong Yang 	}
5603*8af74909SZhong Yang 	return length;
5604*8af74909SZhong Yang }
5605*8af74909SZhong Yang 
ReplaceTarget(bool replacePatterns,const char * text,Sci::Position length)5606*8af74909SZhong Yang Sci::Position Editor::ReplaceTarget(bool replacePatterns, const char *text, Sci::Position length) {
5607*8af74909SZhong Yang 	UndoGroup ug(pdoc);
5608*8af74909SZhong Yang 	if (length == -1)
5609*8af74909SZhong Yang 		length = strlen(text);
5610*8af74909SZhong Yang 	if (replacePatterns) {
5611*8af74909SZhong Yang 		text = pdoc->SubstituteByPosition(text, &length);
5612*8af74909SZhong Yang 		if (!text) {
5613*8af74909SZhong Yang 			return 0;
5614*8af74909SZhong Yang 		}
5615*8af74909SZhong Yang 	}
5616*8af74909SZhong Yang 
5617*8af74909SZhong Yang 	// Remove the text inside the range
5618*8af74909SZhong Yang 	if (targetRange.Length() > 0)
5619*8af74909SZhong Yang 		pdoc->DeleteChars(targetRange.start.Position(), targetRange.Length());
5620*8af74909SZhong Yang 	targetRange.end = targetRange.start;
5621*8af74909SZhong Yang 
5622*8af74909SZhong Yang 	// Realize virtual space of target start
5623*8af74909SZhong Yang 	const Sci::Position startAfterSpaceInsertion = RealizeVirtualSpace(targetRange.start.Position(), targetRange.start.VirtualSpace());
5624*8af74909SZhong Yang 	targetRange.start.SetPosition(startAfterSpaceInsertion);
5625*8af74909SZhong Yang 	targetRange.end = targetRange.start;
5626*8af74909SZhong Yang 
5627*8af74909SZhong Yang 	// Insert the new text
5628*8af74909SZhong Yang 	const Sci::Position lengthInserted = pdoc->InsertString(targetRange.start.Position(), text, length);
5629*8af74909SZhong Yang 	targetRange.end.SetPosition(targetRange.start.Position() + lengthInserted);
5630*8af74909SZhong Yang 	return length;
5631*8af74909SZhong Yang }
5632*8af74909SZhong Yang 
IsUnicodeMode() const5633*8af74909SZhong Yang bool Editor::IsUnicodeMode() const noexcept {
5634*8af74909SZhong Yang 	return pdoc && (SC_CP_UTF8 == pdoc->dbcsCodePage);
5635*8af74909SZhong Yang }
5636*8af74909SZhong Yang 
CodePage() const5637*8af74909SZhong Yang int Editor::CodePage() const noexcept {
5638*8af74909SZhong Yang 	if (pdoc)
5639*8af74909SZhong Yang 		return pdoc->dbcsCodePage;
5640*8af74909SZhong Yang 	else
5641*8af74909SZhong Yang 		return 0;
5642*8af74909SZhong Yang }
5643*8af74909SZhong Yang 
WrapCount(Sci::Line line)5644*8af74909SZhong Yang Sci::Line Editor::WrapCount(Sci::Line line) {
5645*8af74909SZhong Yang 	AutoSurface surface(this);
5646*8af74909SZhong Yang 	AutoLineLayout ll(view.llc, view.RetrieveLineLayout(line, *this));
5647*8af74909SZhong Yang 
5648*8af74909SZhong Yang 	if (surface && ll) {
5649*8af74909SZhong Yang 		view.LayoutLine(*this, line, surface, vs, ll, wrapWidth);
5650*8af74909SZhong Yang 		return ll->lines;
5651*8af74909SZhong Yang 	} else {
5652*8af74909SZhong Yang 		return 1;
5653*8af74909SZhong Yang 	}
5654*8af74909SZhong Yang }
5655*8af74909SZhong Yang 
AddStyledText(const char * buffer,Sci::Position appendLength)5656*8af74909SZhong Yang void Editor::AddStyledText(const char *buffer, Sci::Position appendLength) {
5657*8af74909SZhong Yang 	// The buffer consists of alternating character bytes and style bytes
5658*8af74909SZhong Yang 	const Sci::Position textLength = appendLength / 2;
5659*8af74909SZhong Yang 	std::string text(textLength, '\0');
5660*8af74909SZhong Yang 	Sci::Position i;
5661*8af74909SZhong Yang 	for (i = 0; i < textLength; i++) {
5662*8af74909SZhong Yang 		text[i] = buffer[i*2];
5663*8af74909SZhong Yang 	}
5664*8af74909SZhong Yang 	const Sci::Position lengthInserted = pdoc->InsertString(CurrentPosition(), text.c_str(), textLength);
5665*8af74909SZhong Yang 	for (i = 0; i < textLength; i++) {
5666*8af74909SZhong Yang 		text[i] = buffer[i*2+1];
5667*8af74909SZhong Yang 	}
5668*8af74909SZhong Yang 	pdoc->StartStyling(CurrentPosition());
5669*8af74909SZhong Yang 	pdoc->SetStyles(textLength, text.c_str());
5670*8af74909SZhong Yang 	SetEmptySelection(sel.MainCaret() + lengthInserted);
5671*8af74909SZhong Yang }
5672*8af74909SZhong Yang 
ValidMargin(uptr_t wParam) const5673*8af74909SZhong Yang bool Editor::ValidMargin(uptr_t wParam) const noexcept {
5674*8af74909SZhong Yang 	return wParam < vs.ms.size();
5675*8af74909SZhong Yang }
5676*8af74909SZhong Yang 
StyleSetMessage(unsigned int iMessage,uptr_t wParam,sptr_t lParam)5677*8af74909SZhong Yang void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
5678*8af74909SZhong Yang 	vs.EnsureStyle(wParam);
5679*8af74909SZhong Yang 	switch (iMessage) {
5680*8af74909SZhong Yang 	case SCI_STYLESETFORE:
5681*8af74909SZhong Yang 		vs.styles[wParam].fore = ColourDesired(static_cast<int>(lParam));
5682*8af74909SZhong Yang 		break;
5683*8af74909SZhong Yang 	case SCI_STYLESETBACK:
5684*8af74909SZhong Yang 		vs.styles[wParam].back = ColourDesired(static_cast<int>(lParam));
5685*8af74909SZhong Yang 		break;
5686*8af74909SZhong Yang 	case SCI_STYLESETBOLD:
5687*8af74909SZhong Yang 		vs.styles[wParam].weight = lParam != 0 ? SC_WEIGHT_BOLD : SC_WEIGHT_NORMAL;
5688*8af74909SZhong Yang 		break;
5689*8af74909SZhong Yang 	case SCI_STYLESETWEIGHT:
5690*8af74909SZhong Yang 		vs.styles[wParam].weight = static_cast<int>(lParam);
5691*8af74909SZhong Yang 		break;
5692*8af74909SZhong Yang 	case SCI_STYLESETITALIC:
5693*8af74909SZhong Yang 		vs.styles[wParam].italic = lParam != 0;
5694*8af74909SZhong Yang 		break;
5695*8af74909SZhong Yang 	case SCI_STYLESETEOLFILLED:
5696*8af74909SZhong Yang 		vs.styles[wParam].eolFilled = lParam != 0;
5697*8af74909SZhong Yang 		break;
5698*8af74909SZhong Yang 	case SCI_STYLESETSIZE:
5699*8af74909SZhong Yang 		vs.styles[wParam].size = static_cast<int>(lParam * SC_FONT_SIZE_MULTIPLIER);
5700*8af74909SZhong Yang 		break;
5701*8af74909SZhong Yang 	case SCI_STYLESETSIZEFRACTIONAL:
5702*8af74909SZhong Yang 		vs.styles[wParam].size = static_cast<int>(lParam);
5703*8af74909SZhong Yang 		break;
5704*8af74909SZhong Yang 	case SCI_STYLESETFONT:
5705*8af74909SZhong Yang 		if (lParam != 0) {
5706*8af74909SZhong Yang 			vs.SetStyleFontName(static_cast<int>(wParam), CharPtrFromSPtr(lParam));
5707*8af74909SZhong Yang 		}
5708*8af74909SZhong Yang 		break;
5709*8af74909SZhong Yang 	case SCI_STYLESETUNDERLINE:
5710*8af74909SZhong Yang 		vs.styles[wParam].underline = lParam != 0;
5711*8af74909SZhong Yang 		break;
5712*8af74909SZhong Yang 	case SCI_STYLESETCASE:
5713*8af74909SZhong Yang 		vs.styles[wParam].caseForce = static_cast<Style::ecaseForced>(lParam);
5714*8af74909SZhong Yang 		break;
5715*8af74909SZhong Yang 	case SCI_STYLESETCHARACTERSET:
5716*8af74909SZhong Yang 		vs.styles[wParam].characterSet = static_cast<int>(lParam);
5717*8af74909SZhong Yang 		pdoc->SetCaseFolder(nullptr);
5718*8af74909SZhong Yang 		break;
5719*8af74909SZhong Yang 	case SCI_STYLESETVISIBLE:
5720*8af74909SZhong Yang 		vs.styles[wParam].visible = lParam != 0;
5721*8af74909SZhong Yang 		break;
5722*8af74909SZhong Yang 	case SCI_STYLESETCHANGEABLE:
5723*8af74909SZhong Yang 		vs.styles[wParam].changeable = lParam != 0;
5724*8af74909SZhong Yang 		break;
5725*8af74909SZhong Yang 	case SCI_STYLESETHOTSPOT:
5726*8af74909SZhong Yang 		vs.styles[wParam].hotspot = lParam != 0;
5727*8af74909SZhong Yang 		break;
5728*8af74909SZhong Yang 	}
5729*8af74909SZhong Yang 	InvalidateStyleRedraw();
5730*8af74909SZhong Yang }
5731*8af74909SZhong Yang 
StyleGetMessage(unsigned int iMessage,uptr_t wParam,sptr_t lParam)5732*8af74909SZhong Yang sptr_t Editor::StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
5733*8af74909SZhong Yang 	vs.EnsureStyle(wParam);
5734*8af74909SZhong Yang 	switch (iMessage) {
5735*8af74909SZhong Yang 	case SCI_STYLEGETFORE:
5736*8af74909SZhong Yang 		return vs.styles[wParam].fore.AsInteger();
5737*8af74909SZhong Yang 	case SCI_STYLEGETBACK:
5738*8af74909SZhong Yang 		return vs.styles[wParam].back.AsInteger();
5739*8af74909SZhong Yang 	case SCI_STYLEGETBOLD:
5740*8af74909SZhong Yang 		return vs.styles[wParam].weight > SC_WEIGHT_NORMAL;
5741*8af74909SZhong Yang 	case SCI_STYLEGETWEIGHT:
5742*8af74909SZhong Yang 		return vs.styles[wParam].weight;
5743*8af74909SZhong Yang 	case SCI_STYLEGETITALIC:
5744*8af74909SZhong Yang 		return vs.styles[wParam].italic ? 1 : 0;
5745*8af74909SZhong Yang 	case SCI_STYLEGETEOLFILLED:
5746*8af74909SZhong Yang 		return vs.styles[wParam].eolFilled ? 1 : 0;
5747*8af74909SZhong Yang 	case SCI_STYLEGETSIZE:
5748*8af74909SZhong Yang 		return vs.styles[wParam].size / SC_FONT_SIZE_MULTIPLIER;
5749*8af74909SZhong Yang 	case SCI_STYLEGETSIZEFRACTIONAL:
5750*8af74909SZhong Yang 		return vs.styles[wParam].size;
5751*8af74909SZhong Yang 	case SCI_STYLEGETFONT:
5752*8af74909SZhong Yang 		return StringResult(lParam, vs.styles[wParam].fontName);
5753*8af74909SZhong Yang 	case SCI_STYLEGETUNDERLINE:
5754*8af74909SZhong Yang 		return vs.styles[wParam].underline ? 1 : 0;
5755*8af74909SZhong Yang 	case SCI_STYLEGETCASE:
5756*8af74909SZhong Yang 		return static_cast<int>(vs.styles[wParam].caseForce);
5757*8af74909SZhong Yang 	case SCI_STYLEGETCHARACTERSET:
5758*8af74909SZhong Yang 		return vs.styles[wParam].characterSet;
5759*8af74909SZhong Yang 	case SCI_STYLEGETVISIBLE:
5760*8af74909SZhong Yang 		return vs.styles[wParam].visible ? 1 : 0;
5761*8af74909SZhong Yang 	case SCI_STYLEGETCHANGEABLE:
5762*8af74909SZhong Yang 		return vs.styles[wParam].changeable ? 1 : 0;
5763*8af74909SZhong Yang 	case SCI_STYLEGETHOTSPOT:
5764*8af74909SZhong Yang 		return vs.styles[wParam].hotspot ? 1 : 0;
5765*8af74909SZhong Yang 	}
5766*8af74909SZhong Yang 	return 0;
5767*8af74909SZhong Yang }
5768*8af74909SZhong Yang 
SetSelectionNMessage(unsigned int iMessage,uptr_t wParam,sptr_t lParam)5769*8af74909SZhong Yang void Editor::SetSelectionNMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
5770*8af74909SZhong Yang 	if (wParam >= sel.Count()) {
5771*8af74909SZhong Yang 		return;
5772*8af74909SZhong Yang 	}
5773*8af74909SZhong Yang 	InvalidateRange(sel.Range(wParam).Start().Position(), sel.Range(wParam).End().Position());
5774*8af74909SZhong Yang 
5775*8af74909SZhong Yang 	switch (iMessage) {
5776*8af74909SZhong Yang 	case SCI_SETSELECTIONNCARET:
5777*8af74909SZhong Yang 		sel.Range(wParam).caret.SetPosition(lParam);
5778*8af74909SZhong Yang 		break;
5779*8af74909SZhong Yang 
5780*8af74909SZhong Yang 	case SCI_SETSELECTIONNANCHOR:
5781*8af74909SZhong Yang 		sel.Range(wParam).anchor.SetPosition(lParam);
5782*8af74909SZhong Yang 		break;
5783*8af74909SZhong Yang 
5784*8af74909SZhong Yang 	case SCI_SETSELECTIONNCARETVIRTUALSPACE:
5785*8af74909SZhong Yang 		sel.Range(wParam).caret.SetVirtualSpace(lParam);
5786*8af74909SZhong Yang 		break;
5787*8af74909SZhong Yang 
5788*8af74909SZhong Yang 	case SCI_SETSELECTIONNANCHORVIRTUALSPACE:
5789*8af74909SZhong Yang 		sel.Range(wParam).anchor.SetVirtualSpace(lParam);
5790*8af74909SZhong Yang 		break;
5791*8af74909SZhong Yang 
5792*8af74909SZhong Yang 	case SCI_SETSELECTIONNSTART:
5793*8af74909SZhong Yang 		sel.Range(wParam).anchor.SetPosition(lParam);
5794*8af74909SZhong Yang 		break;
5795*8af74909SZhong Yang 
5796*8af74909SZhong Yang 	case SCI_SETSELECTIONNEND:
5797*8af74909SZhong Yang 		sel.Range(wParam).caret.SetPosition(lParam);
5798*8af74909SZhong Yang 		break;
5799*8af74909SZhong Yang 	}
5800*8af74909SZhong Yang 
5801*8af74909SZhong Yang 	InvalidateRange(sel.Range(wParam).Start().Position(), sel.Range(wParam).End().Position());
5802*8af74909SZhong Yang 	ContainerNeedsUpdate(SC_UPDATE_SELECTION);
5803*8af74909SZhong Yang }
5804*8af74909SZhong Yang 
StringResult(sptr_t lParam,const char * val)5805*8af74909SZhong Yang sptr_t Editor::StringResult(sptr_t lParam, const char *val) noexcept {
5806*8af74909SZhong Yang 	const size_t len = val ? strlen(val) : 0;
5807*8af74909SZhong Yang 	if (lParam) {
5808*8af74909SZhong Yang 		char *ptr = CharPtrFromSPtr(lParam);
5809*8af74909SZhong Yang 		if (val)
5810*8af74909SZhong Yang 			memcpy(ptr, val, len+1);
5811*8af74909SZhong Yang 		else
5812*8af74909SZhong Yang 			*ptr = 0;
5813*8af74909SZhong Yang 	}
5814*8af74909SZhong Yang 	return len;	// Not including NUL
5815*8af74909SZhong Yang }
5816*8af74909SZhong Yang 
BytesResult(sptr_t lParam,const unsigned char * val,size_t len)5817*8af74909SZhong Yang sptr_t Editor::BytesResult(sptr_t lParam, const unsigned char *val, size_t len) noexcept {
5818*8af74909SZhong Yang 	// No NUL termination: len is number of valid/displayed bytes
5819*8af74909SZhong Yang 	if ((lParam) && (len > 0)) {
5820*8af74909SZhong Yang 		char *ptr = CharPtrFromSPtr(lParam);
5821*8af74909SZhong Yang 		if (val)
5822*8af74909SZhong Yang 			memcpy(ptr, val, len);
5823*8af74909SZhong Yang 		else
5824*8af74909SZhong Yang 			*ptr = 0;
5825*8af74909SZhong Yang 	}
5826*8af74909SZhong Yang 	return val ? len : 0;
5827*8af74909SZhong Yang }
5828*8af74909SZhong Yang 
WndProc(unsigned int iMessage,uptr_t wParam,sptr_t lParam)5829*8af74909SZhong Yang sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
5830*8af74909SZhong Yang 	//Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);
5831*8af74909SZhong Yang 
5832*8af74909SZhong Yang 	// Optional macro recording hook
5833*8af74909SZhong Yang 	if (recordingMacro)
5834*8af74909SZhong Yang 		NotifyMacroRecord(iMessage, wParam, lParam);
5835*8af74909SZhong Yang 
5836*8af74909SZhong Yang 	switch (iMessage) {
5837*8af74909SZhong Yang 
5838*8af74909SZhong Yang 	case SCI_GETTEXT: {
5839*8af74909SZhong Yang 			if (lParam == 0)
5840*8af74909SZhong Yang 				return pdoc->Length() + 1;
5841*8af74909SZhong Yang 			if (wParam == 0)
5842*8af74909SZhong Yang 				return 0;
5843*8af74909SZhong Yang 			char *ptr = CharPtrFromSPtr(lParam);
5844*8af74909SZhong Yang 			const Sci_Position len = std::min<Sci_Position>(wParam - 1, pdoc->Length());
5845*8af74909SZhong Yang 			pdoc->GetCharRange(ptr, 0, len);
5846*8af74909SZhong Yang 			ptr[len] = '\0';
5847*8af74909SZhong Yang 			return len;
5848*8af74909SZhong Yang 		}
5849*8af74909SZhong Yang 
5850*8af74909SZhong Yang 	case SCI_SETTEXT: {
5851*8af74909SZhong Yang 			if (lParam == 0)
5852*8af74909SZhong Yang 				return 0;
5853*8af74909SZhong Yang 			UndoGroup ug(pdoc);
5854*8af74909SZhong Yang 			pdoc->DeleteChars(0, pdoc->Length());
5855*8af74909SZhong Yang 			SetEmptySelection(0);
5856*8af74909SZhong Yang 			const char *text = CharPtrFromSPtr(lParam);
5857*8af74909SZhong Yang             size_t length = wParam;
5858*8af74909SZhong Yang             if (length <= 0)
5859*8af74909SZhong Yang                 length = strlen(text);
5860*8af74909SZhong Yang 			pdoc->InsertString(0, text, length);
5861*8af74909SZhong Yang 			return 1;
5862*8af74909SZhong Yang 		}
5863*8af74909SZhong Yang 
5864*8af74909SZhong Yang 	case SCI_GETTEXTLENGTH:
5865*8af74909SZhong Yang 		return pdoc->Length();
5866*8af74909SZhong Yang 
5867*8af74909SZhong Yang 	case SCI_CUT:
5868*8af74909SZhong Yang 		Cut();
5869*8af74909SZhong Yang 		SetLastXChosen();
5870*8af74909SZhong Yang 		break;
5871*8af74909SZhong Yang 
5872*8af74909SZhong Yang 	case SCI_COPY:
5873*8af74909SZhong Yang 		Copy();
5874*8af74909SZhong Yang 		break;
5875*8af74909SZhong Yang 
5876*8af74909SZhong Yang 	case SCI_COPYALLOWLINE:
5877*8af74909SZhong Yang 		CopyAllowLine();
5878*8af74909SZhong Yang 		break;
5879*8af74909SZhong Yang 
5880*8af74909SZhong Yang 	case SCI_VERTICALCENTRECARET:
5881*8af74909SZhong Yang 		VerticalCentreCaret();
5882*8af74909SZhong Yang 		break;
5883*8af74909SZhong Yang 
5884*8af74909SZhong Yang 	case SCI_MOVESELECTEDLINESUP:
5885*8af74909SZhong Yang 		MoveSelectedLinesUp();
5886*8af74909SZhong Yang 		break;
5887*8af74909SZhong Yang 
5888*8af74909SZhong Yang 	case SCI_MOVESELECTEDLINESDOWN:
5889*8af74909SZhong Yang 		MoveSelectedLinesDown();
5890*8af74909SZhong Yang 		break;
5891*8af74909SZhong Yang 
5892*8af74909SZhong Yang 	case SCI_COPYRANGE:
5893*8af74909SZhong Yang 		CopyRangeToClipboard(static_cast<Sci::Position>(wParam), lParam);
5894*8af74909SZhong Yang 		break;
5895*8af74909SZhong Yang 
5896*8af74909SZhong Yang 	case SCI_COPYTEXT:
5897*8af74909SZhong Yang 		CopyText(wParam, CharPtrFromSPtr(lParam));
5898*8af74909SZhong Yang 		break;
5899*8af74909SZhong Yang 
5900*8af74909SZhong Yang 	case SCI_PASTE:
5901*8af74909SZhong Yang 		Paste();
5902*8af74909SZhong Yang 		if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
5903*8af74909SZhong Yang 			SetLastXChosen();
5904*8af74909SZhong Yang 		}
5905*8af74909SZhong Yang 		EnsureCaretVisible();
5906*8af74909SZhong Yang 		break;
5907*8af74909SZhong Yang 
5908*8af74909SZhong Yang 	case SCI_CLEAR:
5909*8af74909SZhong Yang 		Clear();
5910*8af74909SZhong Yang 		SetLastXChosen();
5911*8af74909SZhong Yang 		EnsureCaretVisible();
5912*8af74909SZhong Yang 		break;
5913*8af74909SZhong Yang 
5914*8af74909SZhong Yang 	case SCI_UNDO:
5915*8af74909SZhong Yang 		Undo();
5916*8af74909SZhong Yang 		SetLastXChosen();
5917*8af74909SZhong Yang 		break;
5918*8af74909SZhong Yang 
5919*8af74909SZhong Yang 	case SCI_CANUNDO:
5920*8af74909SZhong Yang 		return (pdoc->CanUndo() && !pdoc->IsReadOnly()) ? 1 : 0;
5921*8af74909SZhong Yang 
5922*8af74909SZhong Yang 	case SCI_EMPTYUNDOBUFFER:
5923*8af74909SZhong Yang 		pdoc->DeleteUndoHistory();
5924*8af74909SZhong Yang 		return 0;
5925*8af74909SZhong Yang 
5926*8af74909SZhong Yang 	case SCI_GETFIRSTVISIBLELINE:
5927*8af74909SZhong Yang 		return topLine;
5928*8af74909SZhong Yang 
5929*8af74909SZhong Yang 	case SCI_SETFIRSTVISIBLELINE:
5930*8af74909SZhong Yang 		ScrollTo(static_cast<Sci::Line>(wParam));
5931*8af74909SZhong Yang 		break;
5932*8af74909SZhong Yang 
5933*8af74909SZhong Yang 	case SCI_GETLINE: {	// Risk of overwriting the end of the buffer
5934*8af74909SZhong Yang 			const Sci::Position lineStart =
5935*8af74909SZhong Yang 				pdoc->LineStart(static_cast<Sci::Line>(wParam));
5936*8af74909SZhong Yang 			const Sci::Position lineEnd =
5937*8af74909SZhong Yang 				pdoc->LineStart(static_cast<Sci::Line>(wParam + 1));
5938*8af74909SZhong Yang 			// not NUL terminated
5939*8af74909SZhong Yang 			const Sci::Position len = lineEnd - lineStart;
5940*8af74909SZhong Yang 			if (lParam == 0) {
5941*8af74909SZhong Yang 				return len;
5942*8af74909SZhong Yang 			}
5943*8af74909SZhong Yang 			char *ptr = CharPtrFromSPtr(lParam);
5944*8af74909SZhong Yang 			pdoc->GetCharRange(ptr, lineStart, len);
5945*8af74909SZhong Yang 			return len;
5946*8af74909SZhong Yang 		}
5947*8af74909SZhong Yang 
5948*8af74909SZhong Yang 	case SCI_GETLINECOUNT:
5949*8af74909SZhong Yang 		if (pdoc->LinesTotal() == 0)
5950*8af74909SZhong Yang 			return 1;
5951*8af74909SZhong Yang 		else
5952*8af74909SZhong Yang 			return pdoc->LinesTotal();
5953*8af74909SZhong Yang 
5954*8af74909SZhong Yang 	case SCI_GETMODIFY:
5955*8af74909SZhong Yang 		return !pdoc->IsSavePoint();
5956*8af74909SZhong Yang 
5957*8af74909SZhong Yang 	case SCI_SETSEL: {
5958*8af74909SZhong Yang 			Sci::Position nStart = static_cast<Sci::Position>(wParam);
5959*8af74909SZhong Yang 			Sci::Position nEnd = lParam;
5960*8af74909SZhong Yang 			if (nEnd < 0)
5961*8af74909SZhong Yang 				nEnd = pdoc->Length();
5962*8af74909SZhong Yang 			if (nStart < 0)
5963*8af74909SZhong Yang 				nStart = nEnd; 	// Remove selection
5964*8af74909SZhong Yang 			InvalidateSelection(SelectionRange(nStart, nEnd));
5965*8af74909SZhong Yang 			sel.Clear();
5966*8af74909SZhong Yang 			sel.selType = Selection::selStream;
5967*8af74909SZhong Yang 			SetSelection(nEnd, nStart);
5968*8af74909SZhong Yang 			EnsureCaretVisible();
5969*8af74909SZhong Yang 		}
5970*8af74909SZhong Yang 		break;
5971*8af74909SZhong Yang 
5972*8af74909SZhong Yang 	case SCI_GETSELTEXT: {
5973*8af74909SZhong Yang 			SelectionText selectedText;
5974*8af74909SZhong Yang 			CopySelectionRange(&selectedText);
5975*8af74909SZhong Yang 			if (lParam == 0) {
5976*8af74909SZhong Yang 				return selectedText.LengthWithTerminator();
5977*8af74909SZhong Yang 			} else {
5978*8af74909SZhong Yang 				char *ptr = CharPtrFromSPtr(lParam);
5979*8af74909SZhong Yang 				size_t iChar = selectedText.Length();
5980*8af74909SZhong Yang 				if (iChar) {
5981*8af74909SZhong Yang 					memcpy(ptr, selectedText.Data(), iChar);
5982*8af74909SZhong Yang 					ptr[iChar++] = '\0';
5983*8af74909SZhong Yang 				} else {
5984*8af74909SZhong Yang 					ptr[0] = '\0';
5985*8af74909SZhong Yang 				}
5986*8af74909SZhong Yang 				return iChar;
5987*8af74909SZhong Yang 			}
5988*8af74909SZhong Yang 		}
5989*8af74909SZhong Yang 
5990*8af74909SZhong Yang 	case SCI_LINEFROMPOSITION:
5991*8af74909SZhong Yang 		if (static_cast<Sci::Position>(wParam) < 0)
5992*8af74909SZhong Yang 			return 0;
5993*8af74909SZhong Yang 		return pdoc->LineFromPosition(static_cast<Sci::Position>(wParam));
5994*8af74909SZhong Yang 
5995*8af74909SZhong Yang 	case SCI_POSITIONFROMLINE:
5996*8af74909SZhong Yang 		if (static_cast<Sci::Position>(wParam) < 0)
5997*8af74909SZhong Yang 			wParam = pdoc->LineFromPosition(SelectionStart().Position());
5998*8af74909SZhong Yang 		if (wParam == 0)
5999*8af74909SZhong Yang 			return 0; 	// Even if there is no text, there is a first line that starts at 0
6000*8af74909SZhong Yang 		if (static_cast<Sci::Line>(wParam) > pdoc->LinesTotal())
6001*8af74909SZhong Yang 			return -1;
6002*8af74909SZhong Yang 		//if (wParam > pdoc->LineFromPosition(pdoc->Length()))	// Useful test, anyway...
6003*8af74909SZhong Yang 		//	return -1;
6004*8af74909SZhong Yang 		return pdoc->LineStart(static_cast<Sci::Position>(wParam));
6005*8af74909SZhong Yang 
6006*8af74909SZhong Yang 		// Replacement of the old Scintilla interpretation of EM_LINELENGTH
6007*8af74909SZhong Yang 	case SCI_LINELENGTH:
6008*8af74909SZhong Yang 		if ((static_cast<Sci::Position>(wParam) < 0) ||
6009*8af74909SZhong Yang 		        (static_cast<Sci::Position>(wParam) > pdoc->LineFromPosition(pdoc->Length())))
6010*8af74909SZhong Yang 			return 0;
6011*8af74909SZhong Yang 		return pdoc->LineStart(static_cast<Sci::Position>(wParam) + 1) - pdoc->LineStart(static_cast<Sci::Position>(wParam));
6012*8af74909SZhong Yang 
6013*8af74909SZhong Yang 	case SCI_REPLACESEL: {
6014*8af74909SZhong Yang 			if (lParam == 0)
6015*8af74909SZhong Yang 				return 0;
6016*8af74909SZhong Yang 			UndoGroup ug(pdoc);
6017*8af74909SZhong Yang 			ClearSelection();
6018*8af74909SZhong Yang 			const char *replacement = CharPtrFromSPtr(lParam);
6019*8af74909SZhong Yang 			const Sci::Position lengthInserted = pdoc->InsertString(
6020*8af74909SZhong Yang 				sel.MainCaret(), replacement, strlen(replacement));
6021*8af74909SZhong Yang 			SetEmptySelection(sel.MainCaret() + lengthInserted);
6022*8af74909SZhong Yang 			SetLastXChosen();
6023*8af74909SZhong Yang 			EnsureCaretVisible();
6024*8af74909SZhong Yang 		}
6025*8af74909SZhong Yang 		break;
6026*8af74909SZhong Yang 
6027*8af74909SZhong Yang 	case SCI_SETTARGETSTART:
6028*8af74909SZhong Yang 		targetRange.start.SetPosition(static_cast<Sci::Position>(wParam));
6029*8af74909SZhong Yang 		break;
6030*8af74909SZhong Yang 
6031*8af74909SZhong Yang 	case SCI_GETTARGETSTART:
6032*8af74909SZhong Yang 		return targetRange.start.Position();
6033*8af74909SZhong Yang 
6034*8af74909SZhong Yang 	case SCI_SETTARGETSTARTVIRTUALSPACE:
6035*8af74909SZhong Yang 		targetRange.start.SetVirtualSpace(static_cast<Sci::Position>(wParam));
6036*8af74909SZhong Yang 		break;
6037*8af74909SZhong Yang 
6038*8af74909SZhong Yang 	case SCI_GETTARGETSTARTVIRTUALSPACE:
6039*8af74909SZhong Yang 		return targetRange.start.VirtualSpace();
6040*8af74909SZhong Yang 
6041*8af74909SZhong Yang 	case SCI_SETTARGETEND:
6042*8af74909SZhong Yang 		targetRange.end.SetPosition(static_cast<Sci::Position>(wParam));
6043*8af74909SZhong Yang 		break;
6044*8af74909SZhong Yang 
6045*8af74909SZhong Yang 	case SCI_GETTARGETEND:
6046*8af74909SZhong Yang 		return targetRange.end.Position();
6047*8af74909SZhong Yang 
6048*8af74909SZhong Yang 	case SCI_SETTARGETENDVIRTUALSPACE:
6049*8af74909SZhong Yang 		targetRange.end.SetVirtualSpace(static_cast<Sci::Position>(wParam));
6050*8af74909SZhong Yang 		break;
6051*8af74909SZhong Yang 
6052*8af74909SZhong Yang 	case SCI_GETTARGETENDVIRTUALSPACE:
6053*8af74909SZhong Yang 		return targetRange.end.VirtualSpace();
6054*8af74909SZhong Yang 
6055*8af74909SZhong Yang 	case SCI_SETTARGETRANGE:
6056*8af74909SZhong Yang 		targetRange.start.SetPosition(static_cast<Sci::Position>(wParam));
6057*8af74909SZhong Yang 		targetRange.end.SetPosition(lParam);
6058*8af74909SZhong Yang 		break;
6059*8af74909SZhong Yang 
6060*8af74909SZhong Yang 	case SCI_TARGETWHOLEDOCUMENT:
6061*8af74909SZhong Yang 		targetRange.start.SetPosition(0);
6062*8af74909SZhong Yang 		targetRange.end.SetPosition(pdoc->Length());
6063*8af74909SZhong Yang 		break;
6064*8af74909SZhong Yang 
6065*8af74909SZhong Yang 	case SCI_TARGETFROMSELECTION:
6066*8af74909SZhong Yang 		targetRange.start = sel.RangeMain().Start();
6067*8af74909SZhong Yang 		targetRange.end = sel.RangeMain().End();
6068*8af74909SZhong Yang 		break;
6069*8af74909SZhong Yang 
6070*8af74909SZhong Yang 	case SCI_GETTARGETTEXT: {
6071*8af74909SZhong Yang 			std::string text = RangeText(targetRange.start.Position(), targetRange.end.Position());
6072*8af74909SZhong Yang 			return BytesResult(lParam, reinterpret_cast<const unsigned char *>(text.c_str()), text.length());
6073*8af74909SZhong Yang 		}
6074*8af74909SZhong Yang 
6075*8af74909SZhong Yang 	case SCI_REPLACETARGET:
6076*8af74909SZhong Yang 		PLATFORM_ASSERT(lParam);
6077*8af74909SZhong Yang 		return ReplaceTarget(false, CharPtrFromSPtr(lParam), static_cast<Sci::Position>(wParam));
6078*8af74909SZhong Yang 
6079*8af74909SZhong Yang 	case SCI_REPLACETARGETRE:
6080*8af74909SZhong Yang 		PLATFORM_ASSERT(lParam);
6081*8af74909SZhong Yang 		return ReplaceTarget(true, CharPtrFromSPtr(lParam), static_cast<Sci::Position>(wParam));
6082*8af74909SZhong Yang 
6083*8af74909SZhong Yang 	case SCI_SEARCHINTARGET:
6084*8af74909SZhong Yang 		PLATFORM_ASSERT(lParam);
6085*8af74909SZhong Yang 		return SearchInTarget(CharPtrFromSPtr(lParam), static_cast<Sci::Position>(wParam));
6086*8af74909SZhong Yang 
6087*8af74909SZhong Yang 	case SCI_SETSEARCHFLAGS:
6088*8af74909SZhong Yang 		searchFlags = static_cast<int>(wParam);
6089*8af74909SZhong Yang 		break;
6090*8af74909SZhong Yang 
6091*8af74909SZhong Yang 	case SCI_GETSEARCHFLAGS:
6092*8af74909SZhong Yang 		return searchFlags;
6093*8af74909SZhong Yang 
6094*8af74909SZhong Yang 	case SCI_GETTAG:
6095*8af74909SZhong Yang 		return GetTag(CharPtrFromSPtr(lParam), static_cast<int>(wParam));
6096*8af74909SZhong Yang 
6097*8af74909SZhong Yang 	case SCI_POSITIONBEFORE:
6098*8af74909SZhong Yang 		return pdoc->MovePositionOutsideChar(static_cast<Sci::Position>(wParam) - 1, -1, true);
6099*8af74909SZhong Yang 
6100*8af74909SZhong Yang 	case SCI_POSITIONAFTER:
6101*8af74909SZhong Yang 		return pdoc->MovePositionOutsideChar(static_cast<Sci::Position>(wParam) + 1, 1, true);
6102*8af74909SZhong Yang 
6103*8af74909SZhong Yang 	case SCI_POSITIONRELATIVE:
6104*8af74909SZhong Yang 		return std::clamp<Sci::Position>(pdoc->GetRelativePosition(
6105*8af74909SZhong Yang 			static_cast<Sci::Position>(wParam), lParam),
6106*8af74909SZhong Yang 			0, pdoc->Length());
6107*8af74909SZhong Yang 
6108*8af74909SZhong Yang 	case SCI_POSITIONRELATIVECODEUNITS:
6109*8af74909SZhong Yang 		return std::clamp<Sci::Position>(pdoc->GetRelativePositionUTF16(
6110*8af74909SZhong Yang 			static_cast<Sci::Position>(wParam), lParam),
6111*8af74909SZhong Yang 			0, pdoc->Length());
6112*8af74909SZhong Yang 
6113*8af74909SZhong Yang 	case SCI_LINESCROLL:
6114*8af74909SZhong Yang 		ScrollTo(topLine + static_cast<Sci::Line>(lParam));
6115*8af74909SZhong Yang 		HorizontalScrollTo(xOffset + static_cast<int>(wParam) * static_cast<int>(vs.spaceWidth));
6116*8af74909SZhong Yang 		return 1;
6117*8af74909SZhong Yang 
6118*8af74909SZhong Yang 	case SCI_SETXOFFSET:
6119*8af74909SZhong Yang 		xOffset = static_cast<int>(wParam);
6120*8af74909SZhong Yang 		ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
6121*8af74909SZhong Yang 		SetHorizontalScrollPos();
6122*8af74909SZhong Yang 		Redraw();
6123*8af74909SZhong Yang 		break;
6124*8af74909SZhong Yang 
6125*8af74909SZhong Yang 	case SCI_GETXOFFSET:
6126*8af74909SZhong Yang 		return xOffset;
6127*8af74909SZhong Yang 
6128*8af74909SZhong Yang 	case SCI_CHOOSECARETX:
6129*8af74909SZhong Yang 		SetLastXChosen();
6130*8af74909SZhong Yang 		break;
6131*8af74909SZhong Yang 
6132*8af74909SZhong Yang 	case SCI_SCROLLCARET:
6133*8af74909SZhong Yang 		EnsureCaretVisible();
6134*8af74909SZhong Yang 		break;
6135*8af74909SZhong Yang 
6136*8af74909SZhong Yang 	case SCI_SETREADONLY:
6137*8af74909SZhong Yang 		pdoc->SetReadOnly(wParam != 0);
6138*8af74909SZhong Yang 		return 1;
6139*8af74909SZhong Yang 
6140*8af74909SZhong Yang 	case SCI_GETREADONLY:
6141*8af74909SZhong Yang 		return pdoc->IsReadOnly();
6142*8af74909SZhong Yang 
6143*8af74909SZhong Yang 	case SCI_CANPASTE:
6144*8af74909SZhong Yang 		return CanPaste();
6145*8af74909SZhong Yang 
6146*8af74909SZhong Yang 	case SCI_POINTXFROMPOSITION:
6147*8af74909SZhong Yang 		if (lParam < 0) {
6148*8af74909SZhong Yang 			return 0;
6149*8af74909SZhong Yang 		} else {
6150*8af74909SZhong Yang 			const Point pt = LocationFromPosition(lParam);
6151*8af74909SZhong Yang 			// Convert to view-relative
6152*8af74909SZhong Yang 			return static_cast<int>(pt.x) - vs.textStart + vs.fixedColumnWidth;
6153*8af74909SZhong Yang 		}
6154*8af74909SZhong Yang 
6155*8af74909SZhong Yang 	case SCI_POINTYFROMPOSITION:
6156*8af74909SZhong Yang 		if (lParam < 0) {
6157*8af74909SZhong Yang 			return 0;
6158*8af74909SZhong Yang 		} else {
6159*8af74909SZhong Yang 			const Point pt = LocationFromPosition(lParam);
6160*8af74909SZhong Yang 			return static_cast<int>(pt.y);
6161*8af74909SZhong Yang 		}
6162*8af74909SZhong Yang 
6163*8af74909SZhong Yang 	case SCI_FINDTEXT:
6164*8af74909SZhong Yang 		return FindText(wParam, lParam);
6165*8af74909SZhong Yang 
6166*8af74909SZhong Yang 	case SCI_GETTEXTRANGE: {
6167*8af74909SZhong Yang 			if (lParam == 0)
6168*8af74909SZhong Yang 				return 0;
6169*8af74909SZhong Yang 			Sci_TextRange *tr = static_cast<Sci_TextRange *>(PtrFromSPtr(lParam));
6170*8af74909SZhong Yang 			Sci::Position cpMax = static_cast<Sci::Position>(tr->chrg.cpMax);
6171*8af74909SZhong Yang 			if (cpMax == -1)
6172*8af74909SZhong Yang 				cpMax = pdoc->Length();
6173*8af74909SZhong Yang 			PLATFORM_ASSERT(cpMax <= pdoc->Length());
6174*8af74909SZhong Yang 			Sci::Position len = cpMax - tr->chrg.cpMin; 	// No -1 as cpMin and cpMax are referring to inter character positions
6175*8af74909SZhong Yang 			pdoc->GetCharRange(tr->lpstrText, tr->chrg.cpMin, len);
6176*8af74909SZhong Yang 			// Spec says copied text is terminated with a NUL
6177*8af74909SZhong Yang 			tr->lpstrText[len] = '\0';
6178*8af74909SZhong Yang 			return len; 	// Not including NUL
6179*8af74909SZhong Yang 		}
6180*8af74909SZhong Yang 
6181*8af74909SZhong Yang 	case SCI_HIDESELECTION:
6182*8af74909SZhong Yang 		view.hideSelection = wParam != 0;
6183*8af74909SZhong Yang 		Redraw();
6184*8af74909SZhong Yang 		break;
6185*8af74909SZhong Yang 
6186*8af74909SZhong Yang 	case SCI_FORMATRANGE:
6187*8af74909SZhong Yang 		return FormatRange(wParam != 0, static_cast<Sci_RangeToFormat *>(PtrFromSPtr(lParam)));
6188*8af74909SZhong Yang 
6189*8af74909SZhong Yang 	case SCI_GETMARGINLEFT:
6190*8af74909SZhong Yang 		return vs.leftMarginWidth;
6191*8af74909SZhong Yang 
6192*8af74909SZhong Yang 	case SCI_GETMARGINRIGHT:
6193*8af74909SZhong Yang 		return vs.rightMarginWidth;
6194*8af74909SZhong Yang 
6195*8af74909SZhong Yang 	case SCI_SETMARGINLEFT:
6196*8af74909SZhong Yang 		lastXChosen += static_cast<int>(lParam) - vs.leftMarginWidth;
6197*8af74909SZhong Yang 		vs.leftMarginWidth = static_cast<int>(lParam);
6198*8af74909SZhong Yang 		InvalidateStyleRedraw();
6199*8af74909SZhong Yang 		break;
6200*8af74909SZhong Yang 
6201*8af74909SZhong Yang 	case SCI_SETMARGINRIGHT:
6202*8af74909SZhong Yang 		vs.rightMarginWidth = static_cast<int>(lParam);
6203*8af74909SZhong Yang 		InvalidateStyleRedraw();
6204*8af74909SZhong Yang 		break;
6205*8af74909SZhong Yang 
6206*8af74909SZhong Yang 		// Control specific messages
6207*8af74909SZhong Yang 
6208*8af74909SZhong Yang 	case SCI_ADDTEXT: {
6209*8af74909SZhong Yang 			if (lParam == 0)
6210*8af74909SZhong Yang 				return 0;
6211*8af74909SZhong Yang 			const Sci::Position lengthInserted = pdoc->InsertString(
6212*8af74909SZhong Yang 				CurrentPosition(), CharPtrFromSPtr(lParam), static_cast<Sci::Position>(wParam));
6213*8af74909SZhong Yang 			SetEmptySelection(sel.MainCaret() + lengthInserted);
6214*8af74909SZhong Yang 			return 0;
6215*8af74909SZhong Yang 		}
6216*8af74909SZhong Yang 
6217*8af74909SZhong Yang 	case SCI_ADDSTYLEDTEXT:
6218*8af74909SZhong Yang 		if (lParam)
6219*8af74909SZhong Yang 			AddStyledText(CharPtrFromSPtr(lParam), static_cast<Sci::Position>(wParam));
6220*8af74909SZhong Yang 		return 0;
6221*8af74909SZhong Yang 
6222*8af74909SZhong Yang 	case SCI_INSERTTEXT: {
6223*8af74909SZhong Yang 			if (lParam == 0)
6224*8af74909SZhong Yang 				return 0;
6225*8af74909SZhong Yang 			Sci::Position insertPos = static_cast<Sci::Position>(wParam);
6226*8af74909SZhong Yang 			if (insertPos == -1)
6227*8af74909SZhong Yang 				insertPos = CurrentPosition();
6228*8af74909SZhong Yang 			Sci::Position newCurrent = CurrentPosition();
6229*8af74909SZhong Yang 			const char *sz = CharPtrFromSPtr(lParam);
6230*8af74909SZhong Yang 			const Sci::Position lengthInserted = pdoc->InsertString(insertPos, sz, strlen(sz));
6231*8af74909SZhong Yang 			if (newCurrent > insertPos)
6232*8af74909SZhong Yang 				newCurrent += lengthInserted;
6233*8af74909SZhong Yang 			SetEmptySelection(newCurrent);
6234*8af74909SZhong Yang 			return 0;
6235*8af74909SZhong Yang 		}
6236*8af74909SZhong Yang 
6237*8af74909SZhong Yang 	case SCI_CHANGEINSERTION:
6238*8af74909SZhong Yang 		PLATFORM_ASSERT(lParam);
6239*8af74909SZhong Yang 		pdoc->ChangeInsertion(CharPtrFromSPtr(lParam), static_cast<Sci::Position>(wParam));
6240*8af74909SZhong Yang 		return 0;
6241*8af74909SZhong Yang 
6242*8af74909SZhong Yang 	case SCI_APPENDTEXT:
6243*8af74909SZhong Yang 		pdoc->InsertString(pdoc->Length(),
6244*8af74909SZhong Yang 			CharPtrFromSPtr(lParam), static_cast<Sci::Position>(wParam));
6245*8af74909SZhong Yang 		return 0;
6246*8af74909SZhong Yang 
6247*8af74909SZhong Yang 	case SCI_CLEARALL:
6248*8af74909SZhong Yang 		ClearAll();
6249*8af74909SZhong Yang 		return 0;
6250*8af74909SZhong Yang 
6251*8af74909SZhong Yang 	case SCI_DELETERANGE:
6252*8af74909SZhong Yang 		pdoc->DeleteChars(static_cast<Sci::Position>(wParam), lParam);
6253*8af74909SZhong Yang 		return 0;
6254*8af74909SZhong Yang 
6255*8af74909SZhong Yang 	case SCI_CLEARDOCUMENTSTYLE:
6256*8af74909SZhong Yang 		ClearDocumentStyle();
6257*8af74909SZhong Yang 		return 0;
6258*8af74909SZhong Yang 
6259*8af74909SZhong Yang 	case SCI_SETUNDOCOLLECTION:
6260*8af74909SZhong Yang 		pdoc->SetUndoCollection(wParam != 0);
6261*8af74909SZhong Yang 		return 0;
6262*8af74909SZhong Yang 
6263*8af74909SZhong Yang 	case SCI_GETUNDOCOLLECTION:
6264*8af74909SZhong Yang 		return pdoc->IsCollectingUndo();
6265*8af74909SZhong Yang 
6266*8af74909SZhong Yang 	case SCI_BEGINUNDOACTION:
6267*8af74909SZhong Yang 		pdoc->BeginUndoAction();
6268*8af74909SZhong Yang 		return 0;
6269*8af74909SZhong Yang 
6270*8af74909SZhong Yang 	case SCI_ENDUNDOACTION:
6271*8af74909SZhong Yang 		pdoc->EndUndoAction();
6272*8af74909SZhong Yang 		return 0;
6273*8af74909SZhong Yang 
6274*8af74909SZhong Yang 	case SCI_GETCARETPERIOD:
6275*8af74909SZhong Yang 		return caret.period;
6276*8af74909SZhong Yang 
6277*8af74909SZhong Yang 	case SCI_SETCARETPERIOD:
6278*8af74909SZhong Yang 		CaretSetPeriod(static_cast<int>(wParam));
6279*8af74909SZhong Yang 		break;
6280*8af74909SZhong Yang 
6281*8af74909SZhong Yang 	case SCI_GETWORDCHARS:
6282*8af74909SZhong Yang 		return pdoc->GetCharsOfClass(CharClassify::ccWord, UCharPtrFromSPtr(lParam));
6283*8af74909SZhong Yang 
6284*8af74909SZhong Yang 	case SCI_SETWORDCHARS: {
6285*8af74909SZhong Yang 			pdoc->SetDefaultCharClasses(false);
6286*8af74909SZhong Yang 			if (lParam == 0)
6287*8af74909SZhong Yang 				return 0;
6288*8af74909SZhong Yang 			pdoc->SetCharClasses(ConstUCharPtrFromSPtr(lParam), CharClassify::ccWord);
6289*8af74909SZhong Yang 		}
6290*8af74909SZhong Yang 		break;
6291*8af74909SZhong Yang 
6292*8af74909SZhong Yang 	case SCI_GETWHITESPACECHARS:
6293*8af74909SZhong Yang 		return pdoc->GetCharsOfClass(CharClassify::ccSpace, UCharPtrFromSPtr(lParam));
6294*8af74909SZhong Yang 
6295*8af74909SZhong Yang 	case SCI_SETWHITESPACECHARS: {
6296*8af74909SZhong Yang 			if (lParam == 0)
6297*8af74909SZhong Yang 				return 0;
6298*8af74909SZhong Yang 			pdoc->SetCharClasses(ConstUCharPtrFromSPtr(lParam), CharClassify::ccSpace);
6299*8af74909SZhong Yang 		}
6300*8af74909SZhong Yang 		break;
6301*8af74909SZhong Yang 
6302*8af74909SZhong Yang 	case SCI_GETPUNCTUATIONCHARS:
6303*8af74909SZhong Yang 		return pdoc->GetCharsOfClass(CharClassify::ccPunctuation, UCharPtrFromSPtr(lParam));
6304*8af74909SZhong Yang 
6305*8af74909SZhong Yang 	case SCI_SETPUNCTUATIONCHARS: {
6306*8af74909SZhong Yang 			if (lParam == 0)
6307*8af74909SZhong Yang 				return 0;
6308*8af74909SZhong Yang 			pdoc->SetCharClasses(ConstUCharPtrFromSPtr(lParam), CharClassify::ccPunctuation);
6309*8af74909SZhong Yang 		}
6310*8af74909SZhong Yang 		break;
6311*8af74909SZhong Yang 
6312*8af74909SZhong Yang 	case SCI_SETCHARSDEFAULT:
6313*8af74909SZhong Yang 		pdoc->SetDefaultCharClasses(true);
6314*8af74909SZhong Yang 		break;
6315*8af74909SZhong Yang 
6316*8af74909SZhong Yang 	case SCI_SETCHARACTERCATEGORYOPTIMIZATION:
6317*8af74909SZhong Yang 		pdoc->SetCharacterCategoryOptimization(static_cast<int>(wParam));
6318*8af74909SZhong Yang 		break;
6319*8af74909SZhong Yang 
6320*8af74909SZhong Yang 	case SCI_GETCHARACTERCATEGORYOPTIMIZATION:
6321*8af74909SZhong Yang 		return pdoc->CharacterCategoryOptimization();
6322*8af74909SZhong Yang 
6323*8af74909SZhong Yang 	case SCI_GETLENGTH:
6324*8af74909SZhong Yang 		return pdoc->Length();
6325*8af74909SZhong Yang 
6326*8af74909SZhong Yang 	case SCI_ALLOCATE:
6327*8af74909SZhong Yang 		pdoc->Allocate(static_cast<Sci::Position>(wParam));
6328*8af74909SZhong Yang 		break;
6329*8af74909SZhong Yang 
6330*8af74909SZhong Yang 	case SCI_GETCHARAT:
6331*8af74909SZhong Yang 		return pdoc->CharAt(static_cast<Sci::Position>(wParam));
6332*8af74909SZhong Yang 
6333*8af74909SZhong Yang 	case SCI_SETCURRENTPOS:
6334*8af74909SZhong Yang 		if (sel.IsRectangular()) {
6335*8af74909SZhong Yang 			sel.Rectangular().caret.SetPosition(static_cast<Sci::Position>(wParam));
6336*8af74909SZhong Yang 			SetRectangularRange();
6337*8af74909SZhong Yang 			Redraw();
6338*8af74909SZhong Yang 		} else {
6339*8af74909SZhong Yang 			SetSelection(static_cast<Sci::Position>(wParam), sel.MainAnchor());
6340*8af74909SZhong Yang 		}
6341*8af74909SZhong Yang 		break;
6342*8af74909SZhong Yang 
6343*8af74909SZhong Yang 	case SCI_GETCURRENTPOS:
6344*8af74909SZhong Yang 		return sel.IsRectangular() ? sel.Rectangular().caret.Position() : sel.MainCaret();
6345*8af74909SZhong Yang 
6346*8af74909SZhong Yang 	case SCI_SETANCHOR:
6347*8af74909SZhong Yang 		if (sel.IsRectangular()) {
6348*8af74909SZhong Yang 			sel.Rectangular().anchor.SetPosition(static_cast<Sci::Position>(wParam));
6349*8af74909SZhong Yang 			SetRectangularRange();
6350*8af74909SZhong Yang 			Redraw();
6351*8af74909SZhong Yang 		} else {
6352*8af74909SZhong Yang 			SetSelection(sel.MainCaret(), static_cast<Sci::Position>(wParam));
6353*8af74909SZhong Yang 		}
6354*8af74909SZhong Yang 		break;
6355*8af74909SZhong Yang 
6356*8af74909SZhong Yang 	case SCI_GETANCHOR:
6357*8af74909SZhong Yang 		return sel.IsRectangular() ? sel.Rectangular().anchor.Position() : sel.MainAnchor();
6358*8af74909SZhong Yang 
6359*8af74909SZhong Yang 	case SCI_SETSELECTIONSTART:
6360*8af74909SZhong Yang 		SetSelection(std::max(sel.MainCaret(), static_cast<Sci::Position>(wParam)), static_cast<Sci::Position>(wParam));
6361*8af74909SZhong Yang 		break;
6362*8af74909SZhong Yang 
6363*8af74909SZhong Yang 	case SCI_GETSELECTIONSTART:
6364*8af74909SZhong Yang 		return sel.LimitsForRectangularElseMain().start.Position();
6365*8af74909SZhong Yang 
6366*8af74909SZhong Yang 	case SCI_SETSELECTIONEND:
6367*8af74909SZhong Yang 		SetSelection(static_cast<Sci::Position>(wParam), std::min(sel.MainAnchor(), static_cast<Sci::Position>(wParam)));
6368*8af74909SZhong Yang 		break;
6369*8af74909SZhong Yang 
6370*8af74909SZhong Yang 	case SCI_GETSELECTIONEND:
6371*8af74909SZhong Yang 		return sel.LimitsForRectangularElseMain().end.Position();
6372*8af74909SZhong Yang 
6373*8af74909SZhong Yang 	case SCI_SETEMPTYSELECTION:
6374*8af74909SZhong Yang 		SetEmptySelection(static_cast<Sci::Position>(wParam));
6375*8af74909SZhong Yang 		break;
6376*8af74909SZhong Yang 
6377*8af74909SZhong Yang 	case SCI_SETPRINTMAGNIFICATION:
6378*8af74909SZhong Yang 		view.printParameters.magnification = static_cast<int>(wParam);
6379*8af74909SZhong Yang 		break;
6380*8af74909SZhong Yang 
6381*8af74909SZhong Yang 	case SCI_GETPRINTMAGNIFICATION:
6382*8af74909SZhong Yang 		return view.printParameters.magnification;
6383*8af74909SZhong Yang 
6384*8af74909SZhong Yang 	case SCI_SETPRINTCOLOURMODE:
6385*8af74909SZhong Yang 		view.printParameters.colourMode = static_cast<int>(wParam);
6386*8af74909SZhong Yang 		break;
6387*8af74909SZhong Yang 
6388*8af74909SZhong Yang 	case SCI_GETPRINTCOLOURMODE:
6389*8af74909SZhong Yang 		return view.printParameters.colourMode;
6390*8af74909SZhong Yang 
6391*8af74909SZhong Yang 	case SCI_SETPRINTWRAPMODE:
6392*8af74909SZhong Yang 		view.printParameters.wrapState = (wParam == SC_WRAP_WORD) ? WrapMode::word : WrapMode::none;
6393*8af74909SZhong Yang 		break;
6394*8af74909SZhong Yang 
6395*8af74909SZhong Yang 	case SCI_GETPRINTWRAPMODE:
6396*8af74909SZhong Yang 		return static_cast<sptr_t>(view.printParameters.wrapState);
6397*8af74909SZhong Yang 
6398*8af74909SZhong Yang 	case SCI_GETSTYLEAT:
6399*8af74909SZhong Yang 		if (static_cast<Sci::Position>(wParam) >= pdoc->Length())
6400*8af74909SZhong Yang 			return 0;
6401*8af74909SZhong Yang 		else
6402*8af74909SZhong Yang 			return pdoc->StyleAt(static_cast<Sci::Position>(wParam));
6403*8af74909SZhong Yang 
6404*8af74909SZhong Yang 	case SCI_REDO:
6405*8af74909SZhong Yang 		Redo();
6406*8af74909SZhong Yang 		break;
6407*8af74909SZhong Yang 
6408*8af74909SZhong Yang 	case SCI_SELECTALL:
6409*8af74909SZhong Yang 		SelectAll();
6410*8af74909SZhong Yang 		break;
6411*8af74909SZhong Yang 
6412*8af74909SZhong Yang 	case SCI_SETSAVEPOINT:
6413*8af74909SZhong Yang 		pdoc->SetSavePoint();
6414*8af74909SZhong Yang 		break;
6415*8af74909SZhong Yang 
6416*8af74909SZhong Yang 	case SCI_GETSTYLEDTEXT: {
6417*8af74909SZhong Yang 			if (lParam == 0)
6418*8af74909SZhong Yang 				return 0;
6419*8af74909SZhong Yang 			Sci_TextRange *tr = static_cast<Sci_TextRange *>(PtrFromSPtr(lParam));
6420*8af74909SZhong Yang 			Sci::Position iPlace = 0;
6421*8af74909SZhong Yang 			for (Sci::Position iChar = tr->chrg.cpMin; iChar < tr->chrg.cpMax; iChar++) {
6422*8af74909SZhong Yang 				tr->lpstrText[iPlace++] = pdoc->CharAt(iChar);
6423*8af74909SZhong Yang 				tr->lpstrText[iPlace++] = pdoc->StyleAt(iChar);
6424*8af74909SZhong Yang 			}
6425*8af74909SZhong Yang 			tr->lpstrText[iPlace] = '\0';
6426*8af74909SZhong Yang 			tr->lpstrText[iPlace + 1] = '\0';
6427*8af74909SZhong Yang 			return iPlace;
6428*8af74909SZhong Yang 		}
6429*8af74909SZhong Yang 
6430*8af74909SZhong Yang 	case SCI_CANREDO:
6431*8af74909SZhong Yang 		return (pdoc->CanRedo() && !pdoc->IsReadOnly()) ? 1 : 0;
6432*8af74909SZhong Yang 
6433*8af74909SZhong Yang 	case SCI_MARKERLINEFROMHANDLE:
6434*8af74909SZhong Yang 		return pdoc->LineFromHandle(static_cast<int>(wParam));
6435*8af74909SZhong Yang 
6436*8af74909SZhong Yang 	case SCI_MARKERDELETEHANDLE:
6437*8af74909SZhong Yang 		pdoc->DeleteMarkFromHandle(static_cast<int>(wParam));
6438*8af74909SZhong Yang 		break;
6439*8af74909SZhong Yang 
6440*8af74909SZhong Yang 	case SCI_MARKERHANDLEFROMLINE:
6441*8af74909SZhong Yang 		return pdoc->MarkerHandleFromLine(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
6442*8af74909SZhong Yang 
6443*8af74909SZhong Yang 	case SCI_MARKERNUMBERFROMLINE:
6444*8af74909SZhong Yang 		return pdoc->MarkerNumberFromLine(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
6445*8af74909SZhong Yang 
6446*8af74909SZhong Yang 	case SCI_GETVIEWWS:
6447*8af74909SZhong Yang 		return vs.viewWhitespace;
6448*8af74909SZhong Yang 
6449*8af74909SZhong Yang 	case SCI_SETVIEWWS:
6450*8af74909SZhong Yang 		vs.viewWhitespace = static_cast<WhiteSpaceVisibility>(wParam);
6451*8af74909SZhong Yang 		Redraw();
6452*8af74909SZhong Yang 		break;
6453*8af74909SZhong Yang 
6454*8af74909SZhong Yang 	case SCI_GETTABDRAWMODE:
6455*8af74909SZhong Yang 		return vs.tabDrawMode;
6456*8af74909SZhong Yang 
6457*8af74909SZhong Yang 	case SCI_SETTABDRAWMODE:
6458*8af74909SZhong Yang 		vs.tabDrawMode = static_cast<TabDrawMode>(wParam);
6459*8af74909SZhong Yang 		Redraw();
6460*8af74909SZhong Yang 		break;
6461*8af74909SZhong Yang 
6462*8af74909SZhong Yang 	case SCI_GETWHITESPACESIZE:
6463*8af74909SZhong Yang 		return vs.whitespaceSize;
6464*8af74909SZhong Yang 
6465*8af74909SZhong Yang 	case SCI_SETWHITESPACESIZE:
6466*8af74909SZhong Yang 		vs.whitespaceSize = static_cast<int>(wParam);
6467*8af74909SZhong Yang 		Redraw();
6468*8af74909SZhong Yang 		break;
6469*8af74909SZhong Yang 
6470*8af74909SZhong Yang 	case SCI_POSITIONFROMPOINT:
6471*8af74909SZhong Yang 		return PositionFromLocation(Point::FromInts(static_cast<int>(wParam) - vs.ExternalMarginWidth(), static_cast<int>(lParam)),
6472*8af74909SZhong Yang 					    false, false);
6473*8af74909SZhong Yang 
6474*8af74909SZhong Yang 	case SCI_POSITIONFROMPOINTCLOSE:
6475*8af74909SZhong Yang 		return PositionFromLocation(Point::FromInts(static_cast<int>(wParam) - vs.ExternalMarginWidth(), static_cast<int>(lParam)),
6476*8af74909SZhong Yang 					    true, false);
6477*8af74909SZhong Yang 
6478*8af74909SZhong Yang 	case SCI_CHARPOSITIONFROMPOINT:
6479*8af74909SZhong Yang 		return PositionFromLocation(Point::FromInts(static_cast<int>(wParam) - vs.ExternalMarginWidth(), static_cast<int>(lParam)),
6480*8af74909SZhong Yang 					    false, true);
6481*8af74909SZhong Yang 
6482*8af74909SZhong Yang 	case SCI_CHARPOSITIONFROMPOINTCLOSE:
6483*8af74909SZhong Yang 		return PositionFromLocation(Point::FromInts(static_cast<int>(wParam) - vs.ExternalMarginWidth(), static_cast<int>(lParam)),
6484*8af74909SZhong Yang 					    true, true);
6485*8af74909SZhong Yang 
6486*8af74909SZhong Yang 	case SCI_GOTOLINE:
6487*8af74909SZhong Yang 		GoToLine(static_cast<Sci::Line>(wParam));
6488*8af74909SZhong Yang 		break;
6489*8af74909SZhong Yang 
6490*8af74909SZhong Yang 	case SCI_GOTOPOS:
6491*8af74909SZhong Yang 		SetEmptySelection(static_cast<Sci::Position>(wParam));
6492*8af74909SZhong Yang 		EnsureCaretVisible();
6493*8af74909SZhong Yang 		break;
6494*8af74909SZhong Yang 
6495*8af74909SZhong Yang 	case SCI_GETCURLINE: {
6496*8af74909SZhong Yang 			const Sci::Line lineCurrentPos = pdoc->SciLineFromPosition(sel.MainCaret());
6497*8af74909SZhong Yang 			const Sci::Position lineStart = pdoc->LineStart(lineCurrentPos);
6498*8af74909SZhong Yang 			const Sci::Position lineEnd = pdoc->LineStart(lineCurrentPos + 1);
6499*8af74909SZhong Yang 			if (lParam == 0) {
6500*8af74909SZhong Yang 				return 1 + lineEnd - lineStart;
6501*8af74909SZhong Yang 			}
6502*8af74909SZhong Yang 			PLATFORM_ASSERT(wParam > 0);
6503*8af74909SZhong Yang 			char *ptr = CharPtrFromSPtr(lParam);
6504*8af74909SZhong Yang 			const Sci::Position len = std::min<uptr_t>(lineEnd - lineStart, wParam - 1);
6505*8af74909SZhong Yang 			pdoc->GetCharRange(ptr, lineStart, len);
6506*8af74909SZhong Yang 			ptr[len] = '\0';
6507*8af74909SZhong Yang 			return sel.MainCaret() - lineStart;
6508*8af74909SZhong Yang 		}
6509*8af74909SZhong Yang 
6510*8af74909SZhong Yang 	case SCI_GETENDSTYLED:
6511*8af74909SZhong Yang 		return pdoc->GetEndStyled();
6512*8af74909SZhong Yang 
6513*8af74909SZhong Yang 	case SCI_GETEOLMODE:
6514*8af74909SZhong Yang 		return pdoc->eolMode;
6515*8af74909SZhong Yang 
6516*8af74909SZhong Yang 	case SCI_SETEOLMODE:
6517*8af74909SZhong Yang 		pdoc->eolMode = static_cast<int>(wParam);
6518*8af74909SZhong Yang 		break;
6519*8af74909SZhong Yang 
6520*8af74909SZhong Yang 	case SCI_SETLINEENDTYPESALLOWED:
6521*8af74909SZhong Yang 		if (pdoc->SetLineEndTypesAllowed(static_cast<int>(wParam))) {
6522*8af74909SZhong Yang 			pcs->Clear();
6523*8af74909SZhong Yang 			pcs->InsertLines(0, pdoc->LinesTotal() - 1);
6524*8af74909SZhong Yang 			SetAnnotationHeights(0, pdoc->LinesTotal());
6525*8af74909SZhong Yang 			InvalidateStyleRedraw();
6526*8af74909SZhong Yang 		}
6527*8af74909SZhong Yang 		break;
6528*8af74909SZhong Yang 
6529*8af74909SZhong Yang 	case SCI_GETLINEENDTYPESALLOWED:
6530*8af74909SZhong Yang 		return pdoc->GetLineEndTypesAllowed();
6531*8af74909SZhong Yang 
6532*8af74909SZhong Yang 	case SCI_GETLINEENDTYPESACTIVE:
6533*8af74909SZhong Yang 		return pdoc->GetLineEndTypesActive();
6534*8af74909SZhong Yang 
6535*8af74909SZhong Yang 	case SCI_STARTSTYLING:
6536*8af74909SZhong Yang 		pdoc->StartStyling(static_cast<Sci::Position>(wParam));
6537*8af74909SZhong Yang 		break;
6538*8af74909SZhong Yang 
6539*8af74909SZhong Yang 	case SCI_SETSTYLING:
6540*8af74909SZhong Yang 		if (static_cast<Sci::Position>(wParam) < 0)
6541*8af74909SZhong Yang 			errorStatus = SC_STATUS_FAILURE;
6542*8af74909SZhong Yang 		else
6543*8af74909SZhong Yang 			pdoc->SetStyleFor(static_cast<Sci::Position>(wParam), static_cast<char>(lParam));
6544*8af74909SZhong Yang 		break;
6545*8af74909SZhong Yang 
6546*8af74909SZhong Yang 	case SCI_SETSTYLINGEX:             // Specify a complete styling buffer
6547*8af74909SZhong Yang 		if (lParam == 0)
6548*8af74909SZhong Yang 			return 0;
6549*8af74909SZhong Yang 		pdoc->SetStyles(static_cast<Sci::Position>(wParam), CharPtrFromSPtr(lParam));
6550*8af74909SZhong Yang 		break;
6551*8af74909SZhong Yang 
6552*8af74909SZhong Yang 	case SCI_SETBUFFEREDDRAW:
6553*8af74909SZhong Yang 		view.bufferedDraw = wParam != 0;
6554*8af74909SZhong Yang 		break;
6555*8af74909SZhong Yang 
6556*8af74909SZhong Yang 	case SCI_GETBUFFEREDDRAW:
6557*8af74909SZhong Yang 		return view.bufferedDraw;
6558*8af74909SZhong Yang 
6559*8af74909SZhong Yang #ifdef INCLUDE_DEPRECATED_FEATURES
6560*8af74909SZhong Yang 	case SCI_GETTWOPHASEDRAW:
6561*8af74909SZhong Yang 		return view.phasesDraw == EditView::phasesTwo;
6562*8af74909SZhong Yang 
6563*8af74909SZhong Yang 	case SCI_SETTWOPHASEDRAW:
6564*8af74909SZhong Yang 		if (view.SetTwoPhaseDraw(wParam != 0))
6565*8af74909SZhong Yang 			InvalidateStyleRedraw();
6566*8af74909SZhong Yang 		break;
6567*8af74909SZhong Yang #endif
6568*8af74909SZhong Yang 
6569*8af74909SZhong Yang 	case SCI_GETPHASESDRAW:
6570*8af74909SZhong Yang 		return view.phasesDraw;
6571*8af74909SZhong Yang 
6572*8af74909SZhong Yang 	case SCI_SETPHASESDRAW:
6573*8af74909SZhong Yang 		if (view.SetPhasesDraw(static_cast<int>(wParam)))
6574*8af74909SZhong Yang 			InvalidateStyleRedraw();
6575*8af74909SZhong Yang 		break;
6576*8af74909SZhong Yang 
6577*8af74909SZhong Yang 	case SCI_SETFONTQUALITY:
6578*8af74909SZhong Yang 		vs.extraFontFlag &= ~SC_EFF_QUALITY_MASK;
6579*8af74909SZhong Yang 		vs.extraFontFlag |= (wParam & SC_EFF_QUALITY_MASK);
6580*8af74909SZhong Yang 		InvalidateStyleRedraw();
6581*8af74909SZhong Yang 		break;
6582*8af74909SZhong Yang 
6583*8af74909SZhong Yang 	case SCI_GETFONTQUALITY:
6584*8af74909SZhong Yang 		return (vs.extraFontFlag & SC_EFF_QUALITY_MASK);
6585*8af74909SZhong Yang 
6586*8af74909SZhong Yang 	case SCI_SETTABWIDTH:
6587*8af74909SZhong Yang 		if (wParam > 0) {
6588*8af74909SZhong Yang 			pdoc->tabInChars = static_cast<int>(wParam);
6589*8af74909SZhong Yang 			if (pdoc->indentInChars == 0)
6590*8af74909SZhong Yang 				pdoc->actualIndentInChars = pdoc->tabInChars;
6591*8af74909SZhong Yang 		}
6592*8af74909SZhong Yang 		InvalidateStyleRedraw();
6593*8af74909SZhong Yang 		break;
6594*8af74909SZhong Yang 
6595*8af74909SZhong Yang 	case SCI_GETTABWIDTH:
6596*8af74909SZhong Yang 		return pdoc->tabInChars;
6597*8af74909SZhong Yang 
6598*8af74909SZhong Yang 	case SCI_SETTABMINIMUMWIDTH:
6599*8af74909SZhong Yang 		SetAppearance(view.tabWidthMinimumPixels, static_cast<int>(wParam));
6600*8af74909SZhong Yang 		break;
6601*8af74909SZhong Yang 
6602*8af74909SZhong Yang 	case SCI_GETTABMINIMUMWIDTH:
6603*8af74909SZhong Yang 		return view.tabWidthMinimumPixels;
6604*8af74909SZhong Yang 
6605*8af74909SZhong Yang 	case SCI_CLEARTABSTOPS:
6606*8af74909SZhong Yang 		if (view.ClearTabstops(static_cast<Sci::Line>(wParam))) {
6607*8af74909SZhong Yang 			const DocModification mh(SC_MOD_CHANGETABSTOPS, 0, 0, 0, nullptr, static_cast<Sci::Line>(wParam));
6608*8af74909SZhong Yang 			NotifyModified(pdoc, mh, nullptr);
6609*8af74909SZhong Yang 		}
6610*8af74909SZhong Yang 		break;
6611*8af74909SZhong Yang 
6612*8af74909SZhong Yang 	case SCI_ADDTABSTOP:
6613*8af74909SZhong Yang 		if (view.AddTabstop(static_cast<Sci::Line>(wParam), static_cast<int>(lParam))) {
6614*8af74909SZhong Yang 			const DocModification mh(SC_MOD_CHANGETABSTOPS, 0, 0, 0, nullptr, static_cast<Sci::Line>(wParam));
6615*8af74909SZhong Yang 			NotifyModified(pdoc, mh, nullptr);
6616*8af74909SZhong Yang 		}
6617*8af74909SZhong Yang 		break;
6618*8af74909SZhong Yang 
6619*8af74909SZhong Yang 	case SCI_GETNEXTTABSTOP:
6620*8af74909SZhong Yang 		return view.GetNextTabstop(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
6621*8af74909SZhong Yang 
6622*8af74909SZhong Yang 	case SCI_SETINDENT:
6623*8af74909SZhong Yang 		pdoc->indentInChars = static_cast<int>(wParam);
6624*8af74909SZhong Yang 		if (pdoc->indentInChars != 0)
6625*8af74909SZhong Yang 			pdoc->actualIndentInChars = pdoc->indentInChars;
6626*8af74909SZhong Yang 		else
6627*8af74909SZhong Yang 			pdoc->actualIndentInChars = pdoc->tabInChars;
6628*8af74909SZhong Yang 		InvalidateStyleRedraw();
6629*8af74909SZhong Yang 		break;
6630*8af74909SZhong Yang 
6631*8af74909SZhong Yang 	case SCI_GETINDENT:
6632*8af74909SZhong Yang 		return pdoc->indentInChars;
6633*8af74909SZhong Yang 
6634*8af74909SZhong Yang 	case SCI_SETUSETABS:
6635*8af74909SZhong Yang 		pdoc->useTabs = wParam != 0;
6636*8af74909SZhong Yang 		InvalidateStyleRedraw();
6637*8af74909SZhong Yang 		break;
6638*8af74909SZhong Yang 
6639*8af74909SZhong Yang 	case SCI_GETUSETABS:
6640*8af74909SZhong Yang 		return pdoc->useTabs;
6641*8af74909SZhong Yang 
6642*8af74909SZhong Yang 	case SCI_SETLINEINDENTATION:
6643*8af74909SZhong Yang 		pdoc->SetLineIndentation(static_cast<Sci::Line>(wParam), lParam);
6644*8af74909SZhong Yang 		break;
6645*8af74909SZhong Yang 
6646*8af74909SZhong Yang 	case SCI_GETLINEINDENTATION:
6647*8af74909SZhong Yang 		return pdoc->GetLineIndentation(static_cast<Sci::Line>(wParam));
6648*8af74909SZhong Yang 
6649*8af74909SZhong Yang 	case SCI_GETLINEINDENTPOSITION:
6650*8af74909SZhong Yang 		return pdoc->GetLineIndentPosition(static_cast<Sci::Line>(wParam));
6651*8af74909SZhong Yang 
6652*8af74909SZhong Yang 	case SCI_SETTABINDENTS:
6653*8af74909SZhong Yang 		pdoc->tabIndents = wParam != 0;
6654*8af74909SZhong Yang 		break;
6655*8af74909SZhong Yang 
6656*8af74909SZhong Yang 	case SCI_GETTABINDENTS:
6657*8af74909SZhong Yang 		return pdoc->tabIndents;
6658*8af74909SZhong Yang 
6659*8af74909SZhong Yang 	case SCI_SETBACKSPACEUNINDENTS:
6660*8af74909SZhong Yang 		pdoc->backspaceUnindents = wParam != 0;
6661*8af74909SZhong Yang 		break;
6662*8af74909SZhong Yang 
6663*8af74909SZhong Yang 	case SCI_GETBACKSPACEUNINDENTS:
6664*8af74909SZhong Yang 		return pdoc->backspaceUnindents;
6665*8af74909SZhong Yang 
6666*8af74909SZhong Yang 	case SCI_SETMOUSEDWELLTIME:
6667*8af74909SZhong Yang 		dwellDelay = static_cast<int>(wParam);
6668*8af74909SZhong Yang 		ticksToDwell = dwellDelay;
6669*8af74909SZhong Yang 		break;
6670*8af74909SZhong Yang 
6671*8af74909SZhong Yang 	case SCI_GETMOUSEDWELLTIME:
6672*8af74909SZhong Yang 		return dwellDelay;
6673*8af74909SZhong Yang 
6674*8af74909SZhong Yang 	case SCI_WORDSTARTPOSITION:
6675*8af74909SZhong Yang 		return pdoc->ExtendWordSelect(static_cast<Sci::Position>(wParam), -1, lParam != 0);
6676*8af74909SZhong Yang 
6677*8af74909SZhong Yang 	case SCI_WORDENDPOSITION:
6678*8af74909SZhong Yang 		return pdoc->ExtendWordSelect(static_cast<Sci::Position>(wParam), 1, lParam != 0);
6679*8af74909SZhong Yang 
6680*8af74909SZhong Yang 	case SCI_ISRANGEWORD:
6681*8af74909SZhong Yang 		return pdoc->IsWordAt(static_cast<Sci::Position>(wParam), lParam);
6682*8af74909SZhong Yang 
6683*8af74909SZhong Yang 	case SCI_SETIDLESTYLING:
6684*8af74909SZhong Yang 		idleStyling = static_cast<int>(wParam);
6685*8af74909SZhong Yang 		break;
6686*8af74909SZhong Yang 
6687*8af74909SZhong Yang 	case SCI_GETIDLESTYLING:
6688*8af74909SZhong Yang 		return idleStyling;
6689*8af74909SZhong Yang 
6690*8af74909SZhong Yang 	case SCI_SETWRAPMODE:
6691*8af74909SZhong Yang 		if (vs.SetWrapState(static_cast<int>(wParam))) {
6692*8af74909SZhong Yang 			xOffset = 0;
6693*8af74909SZhong Yang 			ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
6694*8af74909SZhong Yang 			InvalidateStyleRedraw();
6695*8af74909SZhong Yang 			ReconfigureScrollBars();
6696*8af74909SZhong Yang 		}
6697*8af74909SZhong Yang 		break;
6698*8af74909SZhong Yang 
6699*8af74909SZhong Yang 	case SCI_GETWRAPMODE:
6700*8af74909SZhong Yang 		return static_cast<sptr_t>(vs.wrapState);
6701*8af74909SZhong Yang 
6702*8af74909SZhong Yang 	case SCI_SETWRAPVISUALFLAGS:
6703*8af74909SZhong Yang 		if (vs.SetWrapVisualFlags(static_cast<int>(wParam))) {
6704*8af74909SZhong Yang 			InvalidateStyleRedraw();
6705*8af74909SZhong Yang 			ReconfigureScrollBars();
6706*8af74909SZhong Yang 		}
6707*8af74909SZhong Yang 		break;
6708*8af74909SZhong Yang 
6709*8af74909SZhong Yang 	case SCI_GETWRAPVISUALFLAGS:
6710*8af74909SZhong Yang 		return vs.wrapVisualFlags;
6711*8af74909SZhong Yang 
6712*8af74909SZhong Yang 	case SCI_SETWRAPVISUALFLAGSLOCATION:
6713*8af74909SZhong Yang 		if (vs.SetWrapVisualFlagsLocation(static_cast<int>(wParam))) {
6714*8af74909SZhong Yang 			InvalidateStyleRedraw();
6715*8af74909SZhong Yang 		}
6716*8af74909SZhong Yang 		break;
6717*8af74909SZhong Yang 
6718*8af74909SZhong Yang 	case SCI_GETWRAPVISUALFLAGSLOCATION:
6719*8af74909SZhong Yang 		return vs.wrapVisualFlagsLocation;
6720*8af74909SZhong Yang 
6721*8af74909SZhong Yang 	case SCI_SETWRAPSTARTINDENT:
6722*8af74909SZhong Yang 		if (vs.SetWrapVisualStartIndent(static_cast<int>(wParam))) {
6723*8af74909SZhong Yang 			InvalidateStyleRedraw();
6724*8af74909SZhong Yang 			ReconfigureScrollBars();
6725*8af74909SZhong Yang 		}
6726*8af74909SZhong Yang 		break;
6727*8af74909SZhong Yang 
6728*8af74909SZhong Yang 	case SCI_GETWRAPSTARTINDENT:
6729*8af74909SZhong Yang 		return vs.wrapVisualStartIndent;
6730*8af74909SZhong Yang 
6731*8af74909SZhong Yang 	case SCI_SETWRAPINDENTMODE:
6732*8af74909SZhong Yang 		if (vs.SetWrapIndentMode(static_cast<int>(wParam))) {
6733*8af74909SZhong Yang 			InvalidateStyleRedraw();
6734*8af74909SZhong Yang 			ReconfigureScrollBars();
6735*8af74909SZhong Yang 		}
6736*8af74909SZhong Yang 		break;
6737*8af74909SZhong Yang 
6738*8af74909SZhong Yang 	case SCI_GETWRAPINDENTMODE:
6739*8af74909SZhong Yang 		return vs.wrapIndentMode;
6740*8af74909SZhong Yang 
6741*8af74909SZhong Yang 	case SCI_SETLAYOUTCACHE:
6742*8af74909SZhong Yang 		view.llc.SetLevel(static_cast<int>(wParam));
6743*8af74909SZhong Yang 		break;
6744*8af74909SZhong Yang 
6745*8af74909SZhong Yang 	case SCI_GETLAYOUTCACHE:
6746*8af74909SZhong Yang 		return view.llc.GetLevel();
6747*8af74909SZhong Yang 
6748*8af74909SZhong Yang 	case SCI_SETPOSITIONCACHE:
6749*8af74909SZhong Yang 		view.posCache.SetSize(wParam);
6750*8af74909SZhong Yang 		break;
6751*8af74909SZhong Yang 
6752*8af74909SZhong Yang 	case SCI_GETPOSITIONCACHE:
6753*8af74909SZhong Yang 		return view.posCache.GetSize();
6754*8af74909SZhong Yang 
6755*8af74909SZhong Yang 	case SCI_SETSCROLLWIDTH:
6756*8af74909SZhong Yang 		PLATFORM_ASSERT(wParam > 0);
6757*8af74909SZhong Yang 		if ((wParam > 0) && (wParam != static_cast<unsigned int>(scrollWidth))) {
6758*8af74909SZhong Yang 			view.lineWidthMaxSeen = 0;
6759*8af74909SZhong Yang 			scrollWidth = static_cast<int>(wParam);
6760*8af74909SZhong Yang 			SetScrollBars();
6761*8af74909SZhong Yang 		}
6762*8af74909SZhong Yang 		break;
6763*8af74909SZhong Yang 
6764*8af74909SZhong Yang 	case SCI_GETSCROLLWIDTH:
6765*8af74909SZhong Yang 		return scrollWidth;
6766*8af74909SZhong Yang 
6767*8af74909SZhong Yang 	case SCI_SETSCROLLWIDTHTRACKING:
6768*8af74909SZhong Yang 		trackLineWidth = wParam != 0;
6769*8af74909SZhong Yang 		break;
6770*8af74909SZhong Yang 
6771*8af74909SZhong Yang 	case SCI_GETSCROLLWIDTHTRACKING:
6772*8af74909SZhong Yang 		return trackLineWidth;
6773*8af74909SZhong Yang 
6774*8af74909SZhong Yang 	case SCI_LINESJOIN:
6775*8af74909SZhong Yang 		LinesJoin();
6776*8af74909SZhong Yang 		break;
6777*8af74909SZhong Yang 
6778*8af74909SZhong Yang 	case SCI_LINESSPLIT:
6779*8af74909SZhong Yang 		LinesSplit(static_cast<int>(wParam));
6780*8af74909SZhong Yang 		break;
6781*8af74909SZhong Yang 
6782*8af74909SZhong Yang 	case SCI_TEXTWIDTH:
6783*8af74909SZhong Yang 		PLATFORM_ASSERT(wParam < vs.styles.size());
6784*8af74909SZhong Yang 		PLATFORM_ASSERT(lParam);
6785*8af74909SZhong Yang 		return TextWidth(wParam, CharPtrFromSPtr(lParam));
6786*8af74909SZhong Yang 
6787*8af74909SZhong Yang 	case SCI_TEXTHEIGHT:
6788*8af74909SZhong Yang 		RefreshStyleData();
6789*8af74909SZhong Yang 		return vs.lineHeight;
6790*8af74909SZhong Yang 
6791*8af74909SZhong Yang 	case SCI_SETENDATLASTLINE:
6792*8af74909SZhong Yang 		PLATFORM_ASSERT((wParam == 0) || (wParam == 1));
6793*8af74909SZhong Yang 		if (endAtLastLine != (wParam != 0)) {
6794*8af74909SZhong Yang 			endAtLastLine = wParam != 0;
6795*8af74909SZhong Yang 			SetScrollBars();
6796*8af74909SZhong Yang 		}
6797*8af74909SZhong Yang 		break;
6798*8af74909SZhong Yang 
6799*8af74909SZhong Yang 	case SCI_GETENDATLASTLINE:
6800*8af74909SZhong Yang 		return endAtLastLine;
6801*8af74909SZhong Yang 
6802*8af74909SZhong Yang 	case SCI_SETCARETSTICKY:
6803*8af74909SZhong Yang 		PLATFORM_ASSERT(wParam <= SC_CARETSTICKY_WHITESPACE);
6804*8af74909SZhong Yang 		if (wParam <= SC_CARETSTICKY_WHITESPACE) {
6805*8af74909SZhong Yang 			caretSticky = static_cast<int>(wParam);
6806*8af74909SZhong Yang 		}
6807*8af74909SZhong Yang 		break;
6808*8af74909SZhong Yang 
6809*8af74909SZhong Yang 	case SCI_GETCARETSTICKY:
6810*8af74909SZhong Yang 		return caretSticky;
6811*8af74909SZhong Yang 
6812*8af74909SZhong Yang 	case SCI_TOGGLECARETSTICKY:
6813*8af74909SZhong Yang 		caretSticky = !caretSticky;
6814*8af74909SZhong Yang 		break;
6815*8af74909SZhong Yang 
6816*8af74909SZhong Yang 	case SCI_GETCOLUMN:
6817*8af74909SZhong Yang 		return pdoc->GetColumn(static_cast<Sci::Position>(wParam));
6818*8af74909SZhong Yang 
6819*8af74909SZhong Yang 	case SCI_FINDCOLUMN:
6820*8af74909SZhong Yang 		return pdoc->FindColumn(static_cast<Sci::Line>(wParam), lParam);
6821*8af74909SZhong Yang 
6822*8af74909SZhong Yang 	case SCI_SETHSCROLLBAR :
6823*8af74909SZhong Yang 		if (horizontalScrollBarVisible != (wParam != 0)) {
6824*8af74909SZhong Yang 			horizontalScrollBarVisible = wParam != 0;
6825*8af74909SZhong Yang 			SetScrollBars();
6826*8af74909SZhong Yang 			ReconfigureScrollBars();
6827*8af74909SZhong Yang 		}
6828*8af74909SZhong Yang 		break;
6829*8af74909SZhong Yang 
6830*8af74909SZhong Yang 	case SCI_GETHSCROLLBAR:
6831*8af74909SZhong Yang 		return horizontalScrollBarVisible;
6832*8af74909SZhong Yang 
6833*8af74909SZhong Yang 	case SCI_SETVSCROLLBAR:
6834*8af74909SZhong Yang 		if (verticalScrollBarVisible != (wParam != 0)) {
6835*8af74909SZhong Yang 			verticalScrollBarVisible = wParam != 0;
6836*8af74909SZhong Yang 			SetScrollBars();
6837*8af74909SZhong Yang 			ReconfigureScrollBars();
6838*8af74909SZhong Yang 			if (verticalScrollBarVisible)
6839*8af74909SZhong Yang 				SetVerticalScrollPos();
6840*8af74909SZhong Yang 		}
6841*8af74909SZhong Yang 		break;
6842*8af74909SZhong Yang 
6843*8af74909SZhong Yang 	case SCI_GETVSCROLLBAR:
6844*8af74909SZhong Yang 		return verticalScrollBarVisible;
6845*8af74909SZhong Yang 
6846*8af74909SZhong Yang 	case SCI_SETINDENTATIONGUIDES:
6847*8af74909SZhong Yang 		vs.viewIndentationGuides = static_cast<IndentView>(wParam);
6848*8af74909SZhong Yang 		Redraw();
6849*8af74909SZhong Yang 		break;
6850*8af74909SZhong Yang 
6851*8af74909SZhong Yang 	case SCI_GETINDENTATIONGUIDES:
6852*8af74909SZhong Yang 		return vs.viewIndentationGuides;
6853*8af74909SZhong Yang 
6854*8af74909SZhong Yang 	case SCI_SETHIGHLIGHTGUIDE:
6855*8af74909SZhong Yang 		if ((highlightGuideColumn != static_cast<int>(wParam)) || (wParam > 0)) {
6856*8af74909SZhong Yang 			highlightGuideColumn = static_cast<int>(wParam);
6857*8af74909SZhong Yang 			Redraw();
6858*8af74909SZhong Yang 		}
6859*8af74909SZhong Yang 		break;
6860*8af74909SZhong Yang 
6861*8af74909SZhong Yang 	case SCI_GETHIGHLIGHTGUIDE:
6862*8af74909SZhong Yang 		return highlightGuideColumn;
6863*8af74909SZhong Yang 
6864*8af74909SZhong Yang 	case SCI_GETLINEENDPOSITION:
6865*8af74909SZhong Yang 		return pdoc->LineEnd(static_cast<Sci::Line>(wParam));
6866*8af74909SZhong Yang 
6867*8af74909SZhong Yang 	case SCI_SETCODEPAGE:
6868*8af74909SZhong Yang 		if (ValidCodePage(static_cast<int>(wParam))) {
6869*8af74909SZhong Yang 			if (pdoc->SetDBCSCodePage(static_cast<int>(wParam))) {
6870*8af74909SZhong Yang 				pcs->Clear();
6871*8af74909SZhong Yang 				pcs->InsertLines(0, pdoc->LinesTotal() - 1);
6872*8af74909SZhong Yang 				SetAnnotationHeights(0, pdoc->LinesTotal());
6873*8af74909SZhong Yang 				InvalidateStyleRedraw();
6874*8af74909SZhong Yang 				SetRepresentations();
6875*8af74909SZhong Yang 			}
6876*8af74909SZhong Yang 		}
6877*8af74909SZhong Yang 		break;
6878*8af74909SZhong Yang 
6879*8af74909SZhong Yang 	case SCI_GETCODEPAGE:
6880*8af74909SZhong Yang 		return pdoc->dbcsCodePage;
6881*8af74909SZhong Yang 
6882*8af74909SZhong Yang 	case SCI_SETIMEINTERACTION:
6883*8af74909SZhong Yang 		imeInteraction = static_cast<EditModel::IMEInteraction>(wParam);
6884*8af74909SZhong Yang 		break;
6885*8af74909SZhong Yang 
6886*8af74909SZhong Yang 	case SCI_GETIMEINTERACTION:
6887*8af74909SZhong Yang 		return imeInteraction;
6888*8af74909SZhong Yang 
6889*8af74909SZhong Yang 	case SCI_SETBIDIRECTIONAL:
6890*8af74909SZhong Yang 		// SCI_SETBIDIRECTIONAL is implemented on platform subclasses if they support bidirectional text.
6891*8af74909SZhong Yang 		break;
6892*8af74909SZhong Yang 
6893*8af74909SZhong Yang 	case SCI_GETBIDIRECTIONAL:
6894*8af74909SZhong Yang 		return static_cast<sptr_t>(bidirectional);
6895*8af74909SZhong Yang 
6896*8af74909SZhong Yang 	case SCI_GETLINECHARACTERINDEX:
6897*8af74909SZhong Yang 		return pdoc->LineCharacterIndex();
6898*8af74909SZhong Yang 
6899*8af74909SZhong Yang 	case SCI_ALLOCATELINECHARACTERINDEX:
6900*8af74909SZhong Yang 		pdoc->AllocateLineCharacterIndex(static_cast<int>(wParam));
6901*8af74909SZhong Yang 		break;
6902*8af74909SZhong Yang 
6903*8af74909SZhong Yang 	case SCI_RELEASELINECHARACTERINDEX:
6904*8af74909SZhong Yang 		pdoc->ReleaseLineCharacterIndex(static_cast<int>(wParam));
6905*8af74909SZhong Yang 		break;
6906*8af74909SZhong Yang 
6907*8af74909SZhong Yang 	case SCI_LINEFROMINDEXPOSITION:
6908*8af74909SZhong Yang 		return pdoc->LineFromPositionIndex(static_cast<Sci::Position>(wParam), static_cast<int>(lParam));
6909*8af74909SZhong Yang 
6910*8af74909SZhong Yang 	case SCI_INDEXPOSITIONFROMLINE:
6911*8af74909SZhong Yang 		return pdoc->IndexLineStart(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
6912*8af74909SZhong Yang 
6913*8af74909SZhong Yang 		// Marker definition and setting
6914*8af74909SZhong Yang 	case SCI_MARKERDEFINE:
6915*8af74909SZhong Yang 		if (wParam <= MARKER_MAX) {
6916*8af74909SZhong Yang 			vs.markers[wParam].markType = static_cast<int>(lParam);
6917*8af74909SZhong Yang 			vs.CalcLargestMarkerHeight();
6918*8af74909SZhong Yang 		}
6919*8af74909SZhong Yang 		InvalidateStyleData();
6920*8af74909SZhong Yang 		RedrawSelMargin();
6921*8af74909SZhong Yang 		break;
6922*8af74909SZhong Yang 
6923*8af74909SZhong Yang 	case SCI_MARKERSYMBOLDEFINED:
6924*8af74909SZhong Yang 		if (wParam <= MARKER_MAX)
6925*8af74909SZhong Yang 			return vs.markers[wParam].markType;
6926*8af74909SZhong Yang 		else
6927*8af74909SZhong Yang 			return 0;
6928*8af74909SZhong Yang 
6929*8af74909SZhong Yang 	case SCI_MARKERSETFORE:
6930*8af74909SZhong Yang 		if (wParam <= MARKER_MAX)
6931*8af74909SZhong Yang 			vs.markers[wParam].fore = ColourDesired(static_cast<int>(lParam));
6932*8af74909SZhong Yang 		InvalidateStyleData();
6933*8af74909SZhong Yang 		RedrawSelMargin();
6934*8af74909SZhong Yang 		break;
6935*8af74909SZhong Yang 	case SCI_MARKERSETBACKSELECTED:
6936*8af74909SZhong Yang 		if (wParam <= MARKER_MAX)
6937*8af74909SZhong Yang 			vs.markers[wParam].backSelected = ColourDesired(static_cast<int>(lParam));
6938*8af74909SZhong Yang 		InvalidateStyleData();
6939*8af74909SZhong Yang 		RedrawSelMargin();
6940*8af74909SZhong Yang 		break;
6941*8af74909SZhong Yang 	case SCI_MARKERENABLEHIGHLIGHT:
6942*8af74909SZhong Yang 		marginView.highlightDelimiter.isEnabled = wParam == 1;
6943*8af74909SZhong Yang 		RedrawSelMargin();
6944*8af74909SZhong Yang 		break;
6945*8af74909SZhong Yang 	case SCI_MARKERSETBACK:
6946*8af74909SZhong Yang 		if (wParam <= MARKER_MAX)
6947*8af74909SZhong Yang 			vs.markers[wParam].back = ColourDesired(static_cast<int>(lParam));
6948*8af74909SZhong Yang 		InvalidateStyleData();
6949*8af74909SZhong Yang 		RedrawSelMargin();
6950*8af74909SZhong Yang 		break;
6951*8af74909SZhong Yang 	case SCI_MARKERSETALPHA:
6952*8af74909SZhong Yang 		if (wParam <= MARKER_MAX)
6953*8af74909SZhong Yang 			vs.markers[wParam].alpha = static_cast<int>(lParam);
6954*8af74909SZhong Yang 		InvalidateStyleRedraw();
6955*8af74909SZhong Yang 		break;
6956*8af74909SZhong Yang 	case SCI_MARKERADD: {
6957*8af74909SZhong Yang 			const int markerID = pdoc->AddMark(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
6958*8af74909SZhong Yang 			return markerID;
6959*8af74909SZhong Yang 		}
6960*8af74909SZhong Yang 	case SCI_MARKERADDSET:
6961*8af74909SZhong Yang 		if (lParam != 0)
6962*8af74909SZhong Yang 			pdoc->AddMarkSet(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
6963*8af74909SZhong Yang 		break;
6964*8af74909SZhong Yang 
6965*8af74909SZhong Yang 	case SCI_MARKERDELETE:
6966*8af74909SZhong Yang 		pdoc->DeleteMark(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
6967*8af74909SZhong Yang 		break;
6968*8af74909SZhong Yang 
6969*8af74909SZhong Yang 	case SCI_MARKERDELETEALL:
6970*8af74909SZhong Yang 		pdoc->DeleteAllMarks(static_cast<int>(wParam));
6971*8af74909SZhong Yang 		break;
6972*8af74909SZhong Yang 
6973*8af74909SZhong Yang 	case SCI_MARKERGET:
6974*8af74909SZhong Yang 		return pdoc->GetMark(static_cast<Sci::Line>(wParam));
6975*8af74909SZhong Yang 
6976*8af74909SZhong Yang 	case SCI_MARKERNEXT:
6977*8af74909SZhong Yang 		return pdoc->MarkerNext(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
6978*8af74909SZhong Yang 
6979*8af74909SZhong Yang 	case SCI_MARKERPREVIOUS: {
6980*8af74909SZhong Yang 			for (Sci::Line iLine = static_cast<Sci::Line>(wParam); iLine >= 0; iLine--) {
6981*8af74909SZhong Yang 				if ((pdoc->GetMark(iLine) & lParam) != 0)
6982*8af74909SZhong Yang 					return iLine;
6983*8af74909SZhong Yang 			}
6984*8af74909SZhong Yang 		}
6985*8af74909SZhong Yang 		return -1;
6986*8af74909SZhong Yang 
6987*8af74909SZhong Yang 	case SCI_MARKERDEFINEPIXMAP:
6988*8af74909SZhong Yang 		if (wParam <= MARKER_MAX) {
6989*8af74909SZhong Yang 			vs.markers[wParam].SetXPM(CharPtrFromSPtr(lParam));
6990*8af74909SZhong Yang 			vs.CalcLargestMarkerHeight();
6991*8af74909SZhong Yang 		}
6992*8af74909SZhong Yang 		InvalidateStyleData();
6993*8af74909SZhong Yang 		RedrawSelMargin();
6994*8af74909SZhong Yang 		break;
6995*8af74909SZhong Yang 
6996*8af74909SZhong Yang 	case SCI_RGBAIMAGESETWIDTH:
6997*8af74909SZhong Yang 		sizeRGBAImage.x = static_cast<XYPOSITION>(wParam);
6998*8af74909SZhong Yang 		break;
6999*8af74909SZhong Yang 
7000*8af74909SZhong Yang 	case SCI_RGBAIMAGESETHEIGHT:
7001*8af74909SZhong Yang 		sizeRGBAImage.y = static_cast<XYPOSITION>(wParam);
7002*8af74909SZhong Yang 		break;
7003*8af74909SZhong Yang 
7004*8af74909SZhong Yang 	case SCI_RGBAIMAGESETSCALE:
7005*8af74909SZhong Yang 		scaleRGBAImage = static_cast<float>(wParam);
7006*8af74909SZhong Yang 		break;
7007*8af74909SZhong Yang 
7008*8af74909SZhong Yang 	case SCI_MARKERDEFINERGBAIMAGE:
7009*8af74909SZhong Yang 		if (wParam <= MARKER_MAX) {
7010*8af74909SZhong Yang 			vs.markers[wParam].SetRGBAImage(sizeRGBAImage, scaleRGBAImage / 100.0f, ConstUCharPtrFromSPtr(lParam));
7011*8af74909SZhong Yang 			vs.CalcLargestMarkerHeight();
7012*8af74909SZhong Yang 		}
7013*8af74909SZhong Yang 		InvalidateStyleData();
7014*8af74909SZhong Yang 		RedrawSelMargin();
7015*8af74909SZhong Yang 		break;
7016*8af74909SZhong Yang 
7017*8af74909SZhong Yang 	case SCI_SETMARGINTYPEN:
7018*8af74909SZhong Yang 		if (ValidMargin(wParam)) {
7019*8af74909SZhong Yang 			vs.ms[wParam].style = static_cast<int>(lParam);
7020*8af74909SZhong Yang 			InvalidateStyleRedraw();
7021*8af74909SZhong Yang 		}
7022*8af74909SZhong Yang 		break;
7023*8af74909SZhong Yang 
7024*8af74909SZhong Yang 	case SCI_GETMARGINTYPEN:
7025*8af74909SZhong Yang 		if (ValidMargin(wParam))
7026*8af74909SZhong Yang 			return vs.ms[wParam].style;
7027*8af74909SZhong Yang 		else
7028*8af74909SZhong Yang 			return 0;
7029*8af74909SZhong Yang 
7030*8af74909SZhong Yang 	case SCI_SETMARGINWIDTHN:
7031*8af74909SZhong Yang 		if (ValidMargin(wParam)) {
7032*8af74909SZhong Yang 			// Short-circuit if the width is unchanged, to avoid unnecessary redraw.
7033*8af74909SZhong Yang 			if (vs.ms[wParam].width != lParam) {
7034*8af74909SZhong Yang 				lastXChosen += static_cast<int>(lParam) - vs.ms[wParam].width;
7035*8af74909SZhong Yang 				vs.ms[wParam].width = static_cast<int>(lParam);
7036*8af74909SZhong Yang 				InvalidateStyleRedraw();
7037*8af74909SZhong Yang 			}
7038*8af74909SZhong Yang 		}
7039*8af74909SZhong Yang 		break;
7040*8af74909SZhong Yang 
7041*8af74909SZhong Yang 	case SCI_GETMARGINWIDTHN:
7042*8af74909SZhong Yang 		if (ValidMargin(wParam))
7043*8af74909SZhong Yang 			return vs.ms[wParam].width;
7044*8af74909SZhong Yang 		else
7045*8af74909SZhong Yang 			return 0;
7046*8af74909SZhong Yang 
7047*8af74909SZhong Yang 	case SCI_SETMARGINMASKN:
7048*8af74909SZhong Yang 		if (ValidMargin(wParam)) {
7049*8af74909SZhong Yang 			vs.ms[wParam].mask = static_cast<int>(lParam);
7050*8af74909SZhong Yang 			InvalidateStyleRedraw();
7051*8af74909SZhong Yang 		}
7052*8af74909SZhong Yang 		break;
7053*8af74909SZhong Yang 
7054*8af74909SZhong Yang 	case SCI_GETMARGINMASKN:
7055*8af74909SZhong Yang 		if (ValidMargin(wParam))
7056*8af74909SZhong Yang 			return vs.ms[wParam].mask;
7057*8af74909SZhong Yang 		else
7058*8af74909SZhong Yang 			return 0;
7059*8af74909SZhong Yang 
7060*8af74909SZhong Yang 	case SCI_SETMARGINSENSITIVEN:
7061*8af74909SZhong Yang 		if (ValidMargin(wParam)) {
7062*8af74909SZhong Yang 			vs.ms[wParam].sensitive = lParam != 0;
7063*8af74909SZhong Yang 			InvalidateStyleRedraw();
7064*8af74909SZhong Yang 		}
7065*8af74909SZhong Yang 		break;
7066*8af74909SZhong Yang 
7067*8af74909SZhong Yang 	case SCI_GETMARGINSENSITIVEN:
7068*8af74909SZhong Yang 		if (ValidMargin(wParam))
7069*8af74909SZhong Yang 			return vs.ms[wParam].sensitive ? 1 : 0;
7070*8af74909SZhong Yang 		else
7071*8af74909SZhong Yang 			return 0;
7072*8af74909SZhong Yang 
7073*8af74909SZhong Yang 	case SCI_SETMARGINCURSORN:
7074*8af74909SZhong Yang 		if (ValidMargin(wParam))
7075*8af74909SZhong Yang 			vs.ms[wParam].cursor = static_cast<int>(lParam);
7076*8af74909SZhong Yang 		break;
7077*8af74909SZhong Yang 
7078*8af74909SZhong Yang 	case SCI_GETMARGINCURSORN:
7079*8af74909SZhong Yang 		if (ValidMargin(wParam))
7080*8af74909SZhong Yang 			return vs.ms[wParam].cursor;
7081*8af74909SZhong Yang 		else
7082*8af74909SZhong Yang 			return 0;
7083*8af74909SZhong Yang 
7084*8af74909SZhong Yang 	case SCI_SETMARGINBACKN:
7085*8af74909SZhong Yang 		if (ValidMargin(wParam)) {
7086*8af74909SZhong Yang 			vs.ms[wParam].back = ColourDesired(static_cast<int>(lParam));
7087*8af74909SZhong Yang 			InvalidateStyleRedraw();
7088*8af74909SZhong Yang 		}
7089*8af74909SZhong Yang 		break;
7090*8af74909SZhong Yang 
7091*8af74909SZhong Yang 	case SCI_GETMARGINBACKN:
7092*8af74909SZhong Yang 		if (ValidMargin(wParam))
7093*8af74909SZhong Yang 			return vs.ms[wParam].back.AsInteger();
7094*8af74909SZhong Yang 		else
7095*8af74909SZhong Yang 			return 0;
7096*8af74909SZhong Yang 
7097*8af74909SZhong Yang 	case SCI_SETMARGINS:
7098*8af74909SZhong Yang 		if (wParam < 1000)
7099*8af74909SZhong Yang 			vs.ms.resize(wParam);
7100*8af74909SZhong Yang 		break;
7101*8af74909SZhong Yang 
7102*8af74909SZhong Yang 	case SCI_GETMARGINS:
7103*8af74909SZhong Yang 		return vs.ms.size();
7104*8af74909SZhong Yang 
7105*8af74909SZhong Yang 	case SCI_STYLECLEARALL:
7106*8af74909SZhong Yang 		vs.ClearStyles();
7107*8af74909SZhong Yang 		InvalidateStyleRedraw();
7108*8af74909SZhong Yang 		break;
7109*8af74909SZhong Yang 
7110*8af74909SZhong Yang 	case SCI_STYLESETFORE:
7111*8af74909SZhong Yang 	case SCI_STYLESETBACK:
7112*8af74909SZhong Yang 	case SCI_STYLESETBOLD:
7113*8af74909SZhong Yang 	case SCI_STYLESETWEIGHT:
7114*8af74909SZhong Yang 	case SCI_STYLESETITALIC:
7115*8af74909SZhong Yang 	case SCI_STYLESETEOLFILLED:
7116*8af74909SZhong Yang 	case SCI_STYLESETSIZE:
7117*8af74909SZhong Yang 	case SCI_STYLESETSIZEFRACTIONAL:
7118*8af74909SZhong Yang 	case SCI_STYLESETFONT:
7119*8af74909SZhong Yang 	case SCI_STYLESETUNDERLINE:
7120*8af74909SZhong Yang 	case SCI_STYLESETCASE:
7121*8af74909SZhong Yang 	case SCI_STYLESETCHARACTERSET:
7122*8af74909SZhong Yang 	case SCI_STYLESETVISIBLE:
7123*8af74909SZhong Yang 	case SCI_STYLESETCHANGEABLE:
7124*8af74909SZhong Yang 	case SCI_STYLESETHOTSPOT:
7125*8af74909SZhong Yang 		StyleSetMessage(iMessage, wParam, lParam);
7126*8af74909SZhong Yang 		break;
7127*8af74909SZhong Yang 
7128*8af74909SZhong Yang 	case SCI_STYLEGETFORE:
7129*8af74909SZhong Yang 	case SCI_STYLEGETBACK:
7130*8af74909SZhong Yang 	case SCI_STYLEGETBOLD:
7131*8af74909SZhong Yang 	case SCI_STYLEGETWEIGHT:
7132*8af74909SZhong Yang 	case SCI_STYLEGETITALIC:
7133*8af74909SZhong Yang 	case SCI_STYLEGETEOLFILLED:
7134*8af74909SZhong Yang 	case SCI_STYLEGETSIZE:
7135*8af74909SZhong Yang 	case SCI_STYLEGETSIZEFRACTIONAL:
7136*8af74909SZhong Yang 	case SCI_STYLEGETFONT:
7137*8af74909SZhong Yang 	case SCI_STYLEGETUNDERLINE:
7138*8af74909SZhong Yang 	case SCI_STYLEGETCASE:
7139*8af74909SZhong Yang 	case SCI_STYLEGETCHARACTERSET:
7140*8af74909SZhong Yang 	case SCI_STYLEGETVISIBLE:
7141*8af74909SZhong Yang 	case SCI_STYLEGETCHANGEABLE:
7142*8af74909SZhong Yang 	case SCI_STYLEGETHOTSPOT:
7143*8af74909SZhong Yang 		return StyleGetMessage(iMessage, wParam, lParam);
7144*8af74909SZhong Yang 
7145*8af74909SZhong Yang 	case SCI_STYLERESETDEFAULT:
7146*8af74909SZhong Yang 		vs.ResetDefaultStyle();
7147*8af74909SZhong Yang 		InvalidateStyleRedraw();
7148*8af74909SZhong Yang 		break;
7149*8af74909SZhong Yang 
7150*8af74909SZhong Yang #ifdef INCLUDE_DEPRECATED_FEATURES
7151*8af74909SZhong Yang 	case SCI_SETSTYLEBITS:
7152*8af74909SZhong Yang 		vs.EnsureStyle(0xff);
7153*8af74909SZhong Yang 		break;
7154*8af74909SZhong Yang 
7155*8af74909SZhong Yang 	case SCI_GETSTYLEBITS:
7156*8af74909SZhong Yang 		return 8;
7157*8af74909SZhong Yang #endif
7158*8af74909SZhong Yang 
7159*8af74909SZhong Yang 	case SCI_SETLINESTATE:
7160*8af74909SZhong Yang 		return pdoc->SetLineState(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
7161*8af74909SZhong Yang 
7162*8af74909SZhong Yang 	case SCI_GETLINESTATE:
7163*8af74909SZhong Yang 		return pdoc->GetLineState(static_cast<Sci::Line>(wParam));
7164*8af74909SZhong Yang 
7165*8af74909SZhong Yang 	case SCI_GETMAXLINESTATE:
7166*8af74909SZhong Yang 		return pdoc->GetMaxLineState();
7167*8af74909SZhong Yang 
7168*8af74909SZhong Yang 	case SCI_GETCARETLINEVISIBLE:
7169*8af74909SZhong Yang 		return vs.showCaretLineBackground;
7170*8af74909SZhong Yang 	case SCI_SETCARETLINEVISIBLE:
7171*8af74909SZhong Yang 		vs.showCaretLineBackground = wParam != 0;
7172*8af74909SZhong Yang 		InvalidateStyleRedraw();
7173*8af74909SZhong Yang 		break;
7174*8af74909SZhong Yang 	case SCI_GETCARETLINEVISIBLEALWAYS:
7175*8af74909SZhong Yang 		return vs.alwaysShowCaretLineBackground;
7176*8af74909SZhong Yang 	case SCI_SETCARETLINEVISIBLEALWAYS:
7177*8af74909SZhong Yang 		vs.alwaysShowCaretLineBackground = wParam != 0;
7178*8af74909SZhong Yang 		InvalidateStyleRedraw();
7179*8af74909SZhong Yang 		break;
7180*8af74909SZhong Yang 
7181*8af74909SZhong Yang 	case SCI_GETCARETLINEFRAME:
7182*8af74909SZhong Yang 		return vs.caretLineFrame;
7183*8af74909SZhong Yang 	case SCI_SETCARETLINEFRAME:
7184*8af74909SZhong Yang 		vs.caretLineFrame = static_cast<int>(wParam);
7185*8af74909SZhong Yang 		InvalidateStyleRedraw();
7186*8af74909SZhong Yang 		break;
7187*8af74909SZhong Yang 	case SCI_GETCARETLINEBACK:
7188*8af74909SZhong Yang 		return vs.caretLineBackground.AsInteger();
7189*8af74909SZhong Yang 	case SCI_SETCARETLINEBACK:
7190*8af74909SZhong Yang 		vs.caretLineBackground = ColourDesired(static_cast<int>(wParam));
7191*8af74909SZhong Yang 		InvalidateStyleRedraw();
7192*8af74909SZhong Yang 		break;
7193*8af74909SZhong Yang 	case SCI_GETCARETLINEBACKALPHA:
7194*8af74909SZhong Yang 		return vs.caretLineAlpha;
7195*8af74909SZhong Yang 	case SCI_SETCARETLINEBACKALPHA:
7196*8af74909SZhong Yang 		vs.caretLineAlpha = static_cast<int>(wParam);
7197*8af74909SZhong Yang 		InvalidateStyleRedraw();
7198*8af74909SZhong Yang 		break;
7199*8af74909SZhong Yang 
7200*8af74909SZhong Yang 		// Folding messages
7201*8af74909SZhong Yang 
7202*8af74909SZhong Yang 	case SCI_VISIBLEFROMDOCLINE:
7203*8af74909SZhong Yang 		return pcs->DisplayFromDoc(static_cast<Sci::Line>(wParam));
7204*8af74909SZhong Yang 
7205*8af74909SZhong Yang 	case SCI_DOCLINEFROMVISIBLE:
7206*8af74909SZhong Yang 		return pcs->DocFromDisplay(static_cast<Sci::Line>(wParam));
7207*8af74909SZhong Yang 
7208*8af74909SZhong Yang 	case SCI_WRAPCOUNT:
7209*8af74909SZhong Yang 		return WrapCount(static_cast<Sci::Line>(wParam));
7210*8af74909SZhong Yang 
7211*8af74909SZhong Yang 	case SCI_SETFOLDLEVEL: {
7212*8af74909SZhong Yang 			const int prev = pdoc->SetLevel(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
7213*8af74909SZhong Yang 			if (prev != static_cast<int>(lParam))
7214*8af74909SZhong Yang 				RedrawSelMargin();
7215*8af74909SZhong Yang 			return prev;
7216*8af74909SZhong Yang 		}
7217*8af74909SZhong Yang 
7218*8af74909SZhong Yang 	case SCI_GETFOLDLEVEL:
7219*8af74909SZhong Yang 		return pdoc->GetLevel(static_cast<Sci::Line>(wParam));
7220*8af74909SZhong Yang 
7221*8af74909SZhong Yang 	case SCI_GETLASTCHILD:
7222*8af74909SZhong Yang 		return pdoc->GetLastChild(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
7223*8af74909SZhong Yang 
7224*8af74909SZhong Yang 	case SCI_GETFOLDPARENT:
7225*8af74909SZhong Yang 		return pdoc->GetFoldParent(static_cast<Sci::Line>(wParam));
7226*8af74909SZhong Yang 
7227*8af74909SZhong Yang 	case SCI_SHOWLINES:
7228*8af74909SZhong Yang 		pcs->SetVisible(static_cast<Sci::Line>(wParam), static_cast<Sci::Line>(lParam), true);
7229*8af74909SZhong Yang 		SetScrollBars();
7230*8af74909SZhong Yang 		Redraw();
7231*8af74909SZhong Yang 		break;
7232*8af74909SZhong Yang 
7233*8af74909SZhong Yang 	case SCI_HIDELINES:
7234*8af74909SZhong Yang 		if (wParam > 0)
7235*8af74909SZhong Yang 			pcs->SetVisible(static_cast<Sci::Line>(wParam), static_cast<Sci::Line>(lParam), false);
7236*8af74909SZhong Yang 		SetScrollBars();
7237*8af74909SZhong Yang 		Redraw();
7238*8af74909SZhong Yang 		break;
7239*8af74909SZhong Yang 
7240*8af74909SZhong Yang 	case SCI_GETLINEVISIBLE:
7241*8af74909SZhong Yang 		return pcs->GetVisible(static_cast<Sci::Line>(wParam));
7242*8af74909SZhong Yang 
7243*8af74909SZhong Yang 	case SCI_GETALLLINESVISIBLE:
7244*8af74909SZhong Yang 		return pcs->HiddenLines() ? 0 : 1;
7245*8af74909SZhong Yang 
7246*8af74909SZhong Yang 	case SCI_SETFOLDEXPANDED:
7247*8af74909SZhong Yang 		SetFoldExpanded(static_cast<Sci::Line>(wParam), lParam != 0);
7248*8af74909SZhong Yang 		break;
7249*8af74909SZhong Yang 
7250*8af74909SZhong Yang 	case SCI_GETFOLDEXPANDED:
7251*8af74909SZhong Yang 		return pcs->GetExpanded(static_cast<Sci::Line>(wParam));
7252*8af74909SZhong Yang 
7253*8af74909SZhong Yang 	case SCI_SETAUTOMATICFOLD:
7254*8af74909SZhong Yang 		foldAutomatic = static_cast<int>(wParam);
7255*8af74909SZhong Yang 		break;
7256*8af74909SZhong Yang 
7257*8af74909SZhong Yang 	case SCI_GETAUTOMATICFOLD:
7258*8af74909SZhong Yang 		return foldAutomatic;
7259*8af74909SZhong Yang 
7260*8af74909SZhong Yang 	case SCI_SETFOLDFLAGS:
7261*8af74909SZhong Yang 		foldFlags = static_cast<int>(wParam);
7262*8af74909SZhong Yang 		Redraw();
7263*8af74909SZhong Yang 		break;
7264*8af74909SZhong Yang 
7265*8af74909SZhong Yang 	case SCI_TOGGLEFOLDSHOWTEXT:
7266*8af74909SZhong Yang 		pcs->SetFoldDisplayText(static_cast<Sci::Line>(wParam), CharPtrFromSPtr(lParam));
7267*8af74909SZhong Yang 		FoldLine(static_cast<Sci::Line>(wParam), SC_FOLDACTION_TOGGLE);
7268*8af74909SZhong Yang 		break;
7269*8af74909SZhong Yang 
7270*8af74909SZhong Yang 	case SCI_FOLDDISPLAYTEXTSETSTYLE:
7271*8af74909SZhong Yang 		foldDisplayTextStyle = static_cast<int>(wParam);
7272*8af74909SZhong Yang 		Redraw();
7273*8af74909SZhong Yang 		break;
7274*8af74909SZhong Yang 
7275*8af74909SZhong Yang 	case SCI_FOLDDISPLAYTEXTGETSTYLE:
7276*8af74909SZhong Yang 		return foldDisplayTextStyle;
7277*8af74909SZhong Yang 
7278*8af74909SZhong Yang 	case SCI_SETDEFAULTFOLDDISPLAYTEXT:
7279*8af74909SZhong Yang 		SetDefaultFoldDisplayText(CharPtrFromSPtr(lParam));
7280*8af74909SZhong Yang 		Redraw();
7281*8af74909SZhong Yang 		break;
7282*8af74909SZhong Yang 
7283*8af74909SZhong Yang 	case SCI_GETDEFAULTFOLDDISPLAYTEXT:
7284*8af74909SZhong Yang 		return StringResult(lParam, GetDefaultFoldDisplayText());
7285*8af74909SZhong Yang 
7286*8af74909SZhong Yang 	case SCI_TOGGLEFOLD:
7287*8af74909SZhong Yang 		FoldLine(static_cast<Sci::Line>(wParam), SC_FOLDACTION_TOGGLE);
7288*8af74909SZhong Yang 		break;
7289*8af74909SZhong Yang 
7290*8af74909SZhong Yang 	case SCI_FOLDLINE:
7291*8af74909SZhong Yang 		FoldLine(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
7292*8af74909SZhong Yang 		break;
7293*8af74909SZhong Yang 
7294*8af74909SZhong Yang 	case SCI_FOLDCHILDREN:
7295*8af74909SZhong Yang 		FoldExpand(static_cast<Sci::Line>(wParam), static_cast<int>(lParam), pdoc->GetLevel(static_cast<int>(wParam)));
7296*8af74909SZhong Yang 		break;
7297*8af74909SZhong Yang 
7298*8af74909SZhong Yang 	case SCI_FOLDALL:
7299*8af74909SZhong Yang 		FoldAll(static_cast<int>(wParam));
7300*8af74909SZhong Yang 		break;
7301*8af74909SZhong Yang 
7302*8af74909SZhong Yang 	case SCI_EXPANDCHILDREN:
7303*8af74909SZhong Yang 		FoldExpand(static_cast<Sci::Line>(wParam), SC_FOLDACTION_EXPAND, static_cast<int>(lParam));
7304*8af74909SZhong Yang 		break;
7305*8af74909SZhong Yang 
7306*8af74909SZhong Yang 	case SCI_CONTRACTEDFOLDNEXT:
7307*8af74909SZhong Yang 		return ContractedFoldNext(static_cast<Sci::Line>(wParam));
7308*8af74909SZhong Yang 
7309*8af74909SZhong Yang 	case SCI_ENSUREVISIBLE:
7310*8af74909SZhong Yang 		EnsureLineVisible(static_cast<Sci::Line>(wParam), false);
7311*8af74909SZhong Yang 		break;
7312*8af74909SZhong Yang 
7313*8af74909SZhong Yang 	case SCI_ENSUREVISIBLEENFORCEPOLICY:
7314*8af74909SZhong Yang 		EnsureLineVisible(static_cast<Sci::Line>(wParam), true);
7315*8af74909SZhong Yang 		break;
7316*8af74909SZhong Yang 
7317*8af74909SZhong Yang 	case SCI_SCROLLRANGE:
7318*8af74909SZhong Yang 		ScrollRange(SelectionRange(static_cast<Sci::Position>(wParam), lParam));
7319*8af74909SZhong Yang 		break;
7320*8af74909SZhong Yang 
7321*8af74909SZhong Yang 	case SCI_SEARCHANCHOR:
7322*8af74909SZhong Yang 		SearchAnchor();
7323*8af74909SZhong Yang 		break;
7324*8af74909SZhong Yang 
7325*8af74909SZhong Yang 	case SCI_SEARCHNEXT:
7326*8af74909SZhong Yang 	case SCI_SEARCHPREV:
7327*8af74909SZhong Yang 		return SearchText(iMessage, wParam, lParam);
7328*8af74909SZhong Yang 
7329*8af74909SZhong Yang 	case SCI_SETXCARETPOLICY:
7330*8af74909SZhong Yang 		caretPolicies.x = CaretPolicy(wParam, lParam);
7331*8af74909SZhong Yang 		break;
7332*8af74909SZhong Yang 
7333*8af74909SZhong Yang 	case SCI_SETYCARETPOLICY:
7334*8af74909SZhong Yang 		caretPolicies.y = CaretPolicy(wParam, lParam);
7335*8af74909SZhong Yang 		break;
7336*8af74909SZhong Yang 
7337*8af74909SZhong Yang 	case SCI_SETVISIBLEPOLICY:
7338*8af74909SZhong Yang 		visiblePolicy = CaretPolicy(wParam, lParam);
7339*8af74909SZhong Yang 		break;
7340*8af74909SZhong Yang 
7341*8af74909SZhong Yang 	case SCI_LINESONSCREEN:
7342*8af74909SZhong Yang 		return LinesOnScreen();
7343*8af74909SZhong Yang 
7344*8af74909SZhong Yang 	case SCI_SETSELFORE:
7345*8af74909SZhong Yang 		vs.selColours.fore = ColourOptional(wParam, lParam);
7346*8af74909SZhong Yang 		vs.selAdditionalForeground = ColourDesired(static_cast<int>(lParam));
7347*8af74909SZhong Yang 		InvalidateStyleRedraw();
7348*8af74909SZhong Yang 		break;
7349*8af74909SZhong Yang 
7350*8af74909SZhong Yang 	case SCI_SETSELBACK:
7351*8af74909SZhong Yang 		vs.selColours.back = ColourOptional(wParam, lParam);
7352*8af74909SZhong Yang 		vs.selAdditionalBackground = ColourDesired(static_cast<int>(lParam));
7353*8af74909SZhong Yang 		InvalidateStyleRedraw();
7354*8af74909SZhong Yang 		break;
7355*8af74909SZhong Yang 
7356*8af74909SZhong Yang 	case SCI_SETSELALPHA:
7357*8af74909SZhong Yang 		vs.selAlpha = static_cast<int>(wParam);
7358*8af74909SZhong Yang 		vs.selAdditionalAlpha = static_cast<int>(wParam);
7359*8af74909SZhong Yang 		InvalidateStyleRedraw();
7360*8af74909SZhong Yang 		break;
7361*8af74909SZhong Yang 
7362*8af74909SZhong Yang 	case SCI_GETSELALPHA:
7363*8af74909SZhong Yang 		return vs.selAlpha;
7364*8af74909SZhong Yang 
7365*8af74909SZhong Yang 	case SCI_GETSELEOLFILLED:
7366*8af74909SZhong Yang 		return vs.selEOLFilled;
7367*8af74909SZhong Yang 
7368*8af74909SZhong Yang 	case SCI_SETSELEOLFILLED:
7369*8af74909SZhong Yang 		vs.selEOLFilled = wParam != 0;
7370*8af74909SZhong Yang 		InvalidateStyleRedraw();
7371*8af74909SZhong Yang 		break;
7372*8af74909SZhong Yang 
7373*8af74909SZhong Yang 	case SCI_SETWHITESPACEFORE:
7374*8af74909SZhong Yang 		vs.whitespaceColours.fore = ColourOptional(wParam, lParam);
7375*8af74909SZhong Yang 		InvalidateStyleRedraw();
7376*8af74909SZhong Yang 		break;
7377*8af74909SZhong Yang 
7378*8af74909SZhong Yang 	case SCI_SETWHITESPACEBACK:
7379*8af74909SZhong Yang 		vs.whitespaceColours.back = ColourOptional(wParam, lParam);
7380*8af74909SZhong Yang 		InvalidateStyleRedraw();
7381*8af74909SZhong Yang 		break;
7382*8af74909SZhong Yang 
7383*8af74909SZhong Yang 	case SCI_SETCARETFORE:
7384*8af74909SZhong Yang 		vs.caretcolour = ColourDesired(static_cast<int>(wParam));
7385*8af74909SZhong Yang 		InvalidateStyleRedraw();
7386*8af74909SZhong Yang 		break;
7387*8af74909SZhong Yang 
7388*8af74909SZhong Yang 	case SCI_GETCARETFORE:
7389*8af74909SZhong Yang 		return vs.caretcolour.AsInteger();
7390*8af74909SZhong Yang 
7391*8af74909SZhong Yang 	case SCI_SETCARETSTYLE:
7392*8af74909SZhong Yang 		if (wParam <= (CARETSTYLE_BLOCK | CARETSTYLE_OVERSTRIKE_BLOCK | CARETSTYLE_BLOCK_AFTER))
7393*8af74909SZhong Yang 			vs.caretStyle = static_cast<int>(wParam);
7394*8af74909SZhong Yang 		else
7395*8af74909SZhong Yang 			/* Default to the line caret */
7396*8af74909SZhong Yang 			vs.caretStyle = CARETSTYLE_LINE;
7397*8af74909SZhong Yang 		InvalidateStyleRedraw();
7398*8af74909SZhong Yang 		break;
7399*8af74909SZhong Yang 
7400*8af74909SZhong Yang 	case SCI_GETCARETSTYLE:
7401*8af74909SZhong Yang 		return vs.caretStyle;
7402*8af74909SZhong Yang 
7403*8af74909SZhong Yang 	case SCI_SETCARETWIDTH:
7404*8af74909SZhong Yang 		vs.caretWidth = std::clamp(static_cast<int>(wParam), 0, 20);
7405*8af74909SZhong Yang 		InvalidateStyleRedraw();
7406*8af74909SZhong Yang 		break;
7407*8af74909SZhong Yang 
7408*8af74909SZhong Yang 	case SCI_GETCARETWIDTH:
7409*8af74909SZhong Yang 		return vs.caretWidth;
7410*8af74909SZhong Yang 
7411*8af74909SZhong Yang 	case SCI_ASSIGNCMDKEY:
7412*8af74909SZhong Yang 		kmap.AssignCmdKey(LowShortFromWParam(wParam),
7413*8af74909SZhong Yang 			HighShortFromWParam(wParam), static_cast<unsigned int>(lParam));
7414*8af74909SZhong Yang 		break;
7415*8af74909SZhong Yang 
7416*8af74909SZhong Yang 	case SCI_CLEARCMDKEY:
7417*8af74909SZhong Yang 		kmap.AssignCmdKey(LowShortFromWParam(wParam),
7418*8af74909SZhong Yang 			HighShortFromWParam(wParam), SCI_NULL);
7419*8af74909SZhong Yang 		break;
7420*8af74909SZhong Yang 
7421*8af74909SZhong Yang 	case SCI_CLEARALLCMDKEYS:
7422*8af74909SZhong Yang 		kmap.Clear();
7423*8af74909SZhong Yang 		break;
7424*8af74909SZhong Yang 
7425*8af74909SZhong Yang 	case SCI_INDICSETSTYLE:
7426*8af74909SZhong Yang 		if (wParam <= INDICATOR_MAX) {
7427*8af74909SZhong Yang 			vs.indicators[wParam].sacNormal.style = static_cast<int>(lParam);
7428*8af74909SZhong Yang 			vs.indicators[wParam].sacHover.style = static_cast<int>(lParam);
7429*8af74909SZhong Yang 			InvalidateStyleRedraw();
7430*8af74909SZhong Yang 		}
7431*8af74909SZhong Yang 		break;
7432*8af74909SZhong Yang 
7433*8af74909SZhong Yang 	case SCI_INDICGETSTYLE:
7434*8af74909SZhong Yang 		return (wParam <= INDICATOR_MAX) ? vs.indicators[wParam].sacNormal.style : 0;
7435*8af74909SZhong Yang 
7436*8af74909SZhong Yang 	case SCI_INDICSETFORE:
7437*8af74909SZhong Yang 		if (wParam <= INDICATOR_MAX) {
7438*8af74909SZhong Yang 			vs.indicators[wParam].sacNormal.fore = ColourDesired(static_cast<int>(lParam));
7439*8af74909SZhong Yang 			vs.indicators[wParam].sacHover.fore = ColourDesired(static_cast<int>(lParam));
7440*8af74909SZhong Yang 			InvalidateStyleRedraw();
7441*8af74909SZhong Yang 		}
7442*8af74909SZhong Yang 		break;
7443*8af74909SZhong Yang 
7444*8af74909SZhong Yang 	case SCI_INDICGETFORE:
7445*8af74909SZhong Yang 		return (wParam <= INDICATOR_MAX) ? vs.indicators[wParam].sacNormal.fore.AsInteger() : 0;
7446*8af74909SZhong Yang 
7447*8af74909SZhong Yang 	case SCI_INDICSETHOVERSTYLE:
7448*8af74909SZhong Yang 		if (wParam <= INDICATOR_MAX) {
7449*8af74909SZhong Yang 			vs.indicators[wParam].sacHover.style = static_cast<int>(lParam);
7450*8af74909SZhong Yang 			InvalidateStyleRedraw();
7451*8af74909SZhong Yang 		}
7452*8af74909SZhong Yang 		break;
7453*8af74909SZhong Yang 
7454*8af74909SZhong Yang 	case SCI_INDICGETHOVERSTYLE:
7455*8af74909SZhong Yang 		return (wParam <= INDICATOR_MAX) ? vs.indicators[wParam].sacHover.style : 0;
7456*8af74909SZhong Yang 
7457*8af74909SZhong Yang 	case SCI_INDICSETHOVERFORE:
7458*8af74909SZhong Yang 		if (wParam <= INDICATOR_MAX) {
7459*8af74909SZhong Yang 			vs.indicators[wParam].sacHover.fore = ColourDesired(static_cast<int>(lParam));
7460*8af74909SZhong Yang 			InvalidateStyleRedraw();
7461*8af74909SZhong Yang 		}
7462*8af74909SZhong Yang 		break;
7463*8af74909SZhong Yang 
7464*8af74909SZhong Yang 	case SCI_INDICGETHOVERFORE:
7465*8af74909SZhong Yang 		return (wParam <= INDICATOR_MAX) ? vs.indicators[wParam].sacHover.fore.AsInteger() : 0;
7466*8af74909SZhong Yang 
7467*8af74909SZhong Yang 	case SCI_INDICSETFLAGS:
7468*8af74909SZhong Yang 		if (wParam <= INDICATOR_MAX) {
7469*8af74909SZhong Yang 			vs.indicators[wParam].SetFlags(static_cast<int>(lParam));
7470*8af74909SZhong Yang 			InvalidateStyleRedraw();
7471*8af74909SZhong Yang 		}
7472*8af74909SZhong Yang 		break;
7473*8af74909SZhong Yang 
7474*8af74909SZhong Yang 	case SCI_INDICGETFLAGS:
7475*8af74909SZhong Yang 		return (wParam <= INDICATOR_MAX) ? vs.indicators[wParam].Flags() : 0;
7476*8af74909SZhong Yang 
7477*8af74909SZhong Yang 	case SCI_INDICSETUNDER:
7478*8af74909SZhong Yang 		if (wParam <= INDICATOR_MAX) {
7479*8af74909SZhong Yang 			vs.indicators[wParam].under = lParam != 0;
7480*8af74909SZhong Yang 			InvalidateStyleRedraw();
7481*8af74909SZhong Yang 		}
7482*8af74909SZhong Yang 		break;
7483*8af74909SZhong Yang 
7484*8af74909SZhong Yang 	case SCI_INDICGETUNDER:
7485*8af74909SZhong Yang 		return (wParam <= INDICATOR_MAX) ? vs.indicators[wParam].under : 0;
7486*8af74909SZhong Yang 
7487*8af74909SZhong Yang 	case SCI_INDICSETALPHA:
7488*8af74909SZhong Yang 		if (wParam <= INDICATOR_MAX && lParam >=0 && lParam <= 255) {
7489*8af74909SZhong Yang 			vs.indicators[wParam].fillAlpha = static_cast<int>(lParam);
7490*8af74909SZhong Yang 			InvalidateStyleRedraw();
7491*8af74909SZhong Yang 		}
7492*8af74909SZhong Yang 		break;
7493*8af74909SZhong Yang 
7494*8af74909SZhong Yang 	case SCI_INDICGETALPHA:
7495*8af74909SZhong Yang 		return (wParam <= INDICATOR_MAX) ? vs.indicators[wParam].fillAlpha : 0;
7496*8af74909SZhong Yang 
7497*8af74909SZhong Yang 	case SCI_INDICSETOUTLINEALPHA:
7498*8af74909SZhong Yang 		if (wParam <= INDICATOR_MAX && lParam >=0 && lParam <= 255) {
7499*8af74909SZhong Yang 			vs.indicators[wParam].outlineAlpha = static_cast<int>(lParam);
7500*8af74909SZhong Yang 			InvalidateStyleRedraw();
7501*8af74909SZhong Yang 		}
7502*8af74909SZhong Yang 		break;
7503*8af74909SZhong Yang 
7504*8af74909SZhong Yang 	case SCI_INDICGETOUTLINEALPHA:
7505*8af74909SZhong Yang 		return (wParam <= INDICATOR_MAX) ? vs.indicators[wParam].outlineAlpha : 0;
7506*8af74909SZhong Yang 
7507*8af74909SZhong Yang 	case SCI_SETINDICATORCURRENT:
7508*8af74909SZhong Yang 		pdoc->DecorationSetCurrentIndicator(static_cast<int>(wParam));
7509*8af74909SZhong Yang 		break;
7510*8af74909SZhong Yang 	case SCI_GETINDICATORCURRENT:
7511*8af74909SZhong Yang 		return pdoc->decorations->GetCurrentIndicator();
7512*8af74909SZhong Yang 	case SCI_SETINDICATORVALUE:
7513*8af74909SZhong Yang 		pdoc->decorations->SetCurrentValue(static_cast<int>(wParam));
7514*8af74909SZhong Yang 		break;
7515*8af74909SZhong Yang 	case SCI_GETINDICATORVALUE:
7516*8af74909SZhong Yang 		return pdoc->decorations->GetCurrentValue();
7517*8af74909SZhong Yang 
7518*8af74909SZhong Yang 	case SCI_INDICATORFILLRANGE:
7519*8af74909SZhong Yang 		pdoc->DecorationFillRange(static_cast<Sci::Position>(wParam),
7520*8af74909SZhong Yang 			pdoc->decorations->GetCurrentValue(), lParam);
7521*8af74909SZhong Yang 		break;
7522*8af74909SZhong Yang 
7523*8af74909SZhong Yang 	case SCI_INDICATORCLEARRANGE:
7524*8af74909SZhong Yang 		pdoc->DecorationFillRange(static_cast<Sci::Position>(wParam), 0,
7525*8af74909SZhong Yang 			lParam);
7526*8af74909SZhong Yang 		break;
7527*8af74909SZhong Yang 
7528*8af74909SZhong Yang 	case SCI_INDICATORALLONFOR:
7529*8af74909SZhong Yang 		return pdoc->decorations->AllOnFor(static_cast<Sci::Position>(wParam));
7530*8af74909SZhong Yang 
7531*8af74909SZhong Yang 	case SCI_INDICATORVALUEAT:
7532*8af74909SZhong Yang 		return pdoc->decorations->ValueAt(static_cast<int>(wParam), lParam);
7533*8af74909SZhong Yang 
7534*8af74909SZhong Yang 	case SCI_INDICATORSTART:
7535*8af74909SZhong Yang 		return pdoc->decorations->Start(static_cast<int>(wParam), lParam);
7536*8af74909SZhong Yang 
7537*8af74909SZhong Yang 	case SCI_INDICATOREND:
7538*8af74909SZhong Yang 		return pdoc->decorations->End(static_cast<int>(wParam), lParam);
7539*8af74909SZhong Yang 
7540*8af74909SZhong Yang 	case SCI_LINEDOWN:
7541*8af74909SZhong Yang 	case SCI_LINEDOWNEXTEND:
7542*8af74909SZhong Yang 	case SCI_PARADOWN:
7543*8af74909SZhong Yang 	case SCI_PARADOWNEXTEND:
7544*8af74909SZhong Yang 	case SCI_LINEUP:
7545*8af74909SZhong Yang 	case SCI_LINEUPEXTEND:
7546*8af74909SZhong Yang 	case SCI_PARAUP:
7547*8af74909SZhong Yang 	case SCI_PARAUPEXTEND:
7548*8af74909SZhong Yang 	case SCI_CHARLEFT:
7549*8af74909SZhong Yang 	case SCI_CHARLEFTEXTEND:
7550*8af74909SZhong Yang 	case SCI_CHARRIGHT:
7551*8af74909SZhong Yang 	case SCI_CHARRIGHTEXTEND:
7552*8af74909SZhong Yang 	case SCI_WORDLEFT:
7553*8af74909SZhong Yang 	case SCI_WORDLEFTEXTEND:
7554*8af74909SZhong Yang 	case SCI_WORDRIGHT:
7555*8af74909SZhong Yang 	case SCI_WORDRIGHTEXTEND:
7556*8af74909SZhong Yang 	case SCI_WORDLEFTEND:
7557*8af74909SZhong Yang 	case SCI_WORDLEFTENDEXTEND:
7558*8af74909SZhong Yang 	case SCI_WORDRIGHTEND:
7559*8af74909SZhong Yang 	case SCI_WORDRIGHTENDEXTEND:
7560*8af74909SZhong Yang 	case SCI_HOME:
7561*8af74909SZhong Yang 	case SCI_HOMEEXTEND:
7562*8af74909SZhong Yang 	case SCI_LINEEND:
7563*8af74909SZhong Yang 	case SCI_LINEENDEXTEND:
7564*8af74909SZhong Yang 	case SCI_HOMEWRAP:
7565*8af74909SZhong Yang 	case SCI_HOMEWRAPEXTEND:
7566*8af74909SZhong Yang 	case SCI_LINEENDWRAP:
7567*8af74909SZhong Yang 	case SCI_LINEENDWRAPEXTEND:
7568*8af74909SZhong Yang 	case SCI_DOCUMENTSTART:
7569*8af74909SZhong Yang 	case SCI_DOCUMENTSTARTEXTEND:
7570*8af74909SZhong Yang 	case SCI_DOCUMENTEND:
7571*8af74909SZhong Yang 	case SCI_DOCUMENTENDEXTEND:
7572*8af74909SZhong Yang 	case SCI_SCROLLTOSTART:
7573*8af74909SZhong Yang 	case SCI_SCROLLTOEND:
7574*8af74909SZhong Yang 
7575*8af74909SZhong Yang 	case SCI_STUTTEREDPAGEUP:
7576*8af74909SZhong Yang 	case SCI_STUTTEREDPAGEUPEXTEND:
7577*8af74909SZhong Yang 	case SCI_STUTTEREDPAGEDOWN:
7578*8af74909SZhong Yang 	case SCI_STUTTEREDPAGEDOWNEXTEND:
7579*8af74909SZhong Yang 
7580*8af74909SZhong Yang 	case SCI_PAGEUP:
7581*8af74909SZhong Yang 	case SCI_PAGEUPEXTEND:
7582*8af74909SZhong Yang 	case SCI_PAGEDOWN:
7583*8af74909SZhong Yang 	case SCI_PAGEDOWNEXTEND:
7584*8af74909SZhong Yang 	case SCI_EDITTOGGLEOVERTYPE:
7585*8af74909SZhong Yang 	case SCI_CANCEL:
7586*8af74909SZhong Yang 	case SCI_DELETEBACK:
7587*8af74909SZhong Yang 	case SCI_TAB:
7588*8af74909SZhong Yang 	case SCI_BACKTAB:
7589*8af74909SZhong Yang 	case SCI_NEWLINE:
7590*8af74909SZhong Yang 	case SCI_FORMFEED:
7591*8af74909SZhong Yang 	case SCI_VCHOME:
7592*8af74909SZhong Yang 	case SCI_VCHOMEEXTEND:
7593*8af74909SZhong Yang 	case SCI_VCHOMEWRAP:
7594*8af74909SZhong Yang 	case SCI_VCHOMEWRAPEXTEND:
7595*8af74909SZhong Yang 	case SCI_VCHOMEDISPLAY:
7596*8af74909SZhong Yang 	case SCI_VCHOMEDISPLAYEXTEND:
7597*8af74909SZhong Yang 	case SCI_ZOOMIN:
7598*8af74909SZhong Yang 	case SCI_ZOOMOUT:
7599*8af74909SZhong Yang 	case SCI_DELWORDLEFT:
7600*8af74909SZhong Yang 	case SCI_DELWORDRIGHT:
7601*8af74909SZhong Yang 	case SCI_DELWORDRIGHTEND:
7602*8af74909SZhong Yang 	case SCI_DELLINELEFT:
7603*8af74909SZhong Yang 	case SCI_DELLINERIGHT:
7604*8af74909SZhong Yang 	case SCI_LINECOPY:
7605*8af74909SZhong Yang 	case SCI_LINECUT:
7606*8af74909SZhong Yang 	case SCI_LINEDELETE:
7607*8af74909SZhong Yang 	case SCI_LINETRANSPOSE:
7608*8af74909SZhong Yang 	case SCI_LINEREVERSE:
7609*8af74909SZhong Yang 	case SCI_LINEDUPLICATE:
7610*8af74909SZhong Yang 	case SCI_LOWERCASE:
7611*8af74909SZhong Yang 	case SCI_UPPERCASE:
7612*8af74909SZhong Yang 	case SCI_LINESCROLLDOWN:
7613*8af74909SZhong Yang 	case SCI_LINESCROLLUP:
7614*8af74909SZhong Yang 	case SCI_WORDPARTLEFT:
7615*8af74909SZhong Yang 	case SCI_WORDPARTLEFTEXTEND:
7616*8af74909SZhong Yang 	case SCI_WORDPARTRIGHT:
7617*8af74909SZhong Yang 	case SCI_WORDPARTRIGHTEXTEND:
7618*8af74909SZhong Yang 	case SCI_DELETEBACKNOTLINE:
7619*8af74909SZhong Yang 	case SCI_HOMEDISPLAY:
7620*8af74909SZhong Yang 	case SCI_HOMEDISPLAYEXTEND:
7621*8af74909SZhong Yang 	case SCI_LINEENDDISPLAY:
7622*8af74909SZhong Yang 	case SCI_LINEENDDISPLAYEXTEND:
7623*8af74909SZhong Yang 	case SCI_LINEDOWNRECTEXTEND:
7624*8af74909SZhong Yang 	case SCI_LINEUPRECTEXTEND:
7625*8af74909SZhong Yang 	case SCI_CHARLEFTRECTEXTEND:
7626*8af74909SZhong Yang 	case SCI_CHARRIGHTRECTEXTEND:
7627*8af74909SZhong Yang 	case SCI_HOMERECTEXTEND:
7628*8af74909SZhong Yang 	case SCI_VCHOMERECTEXTEND:
7629*8af74909SZhong Yang 	case SCI_LINEENDRECTEXTEND:
7630*8af74909SZhong Yang 	case SCI_PAGEUPRECTEXTEND:
7631*8af74909SZhong Yang 	case SCI_PAGEDOWNRECTEXTEND:
7632*8af74909SZhong Yang 	case SCI_SELECTIONDUPLICATE:
7633*8af74909SZhong Yang 		return KeyCommand(iMessage);
7634*8af74909SZhong Yang 
7635*8af74909SZhong Yang 	case SCI_BRACEHIGHLIGHT:
7636*8af74909SZhong Yang 		SetBraceHighlight(static_cast<Sci::Position>(wParam), lParam, STYLE_BRACELIGHT);
7637*8af74909SZhong Yang 		break;
7638*8af74909SZhong Yang 
7639*8af74909SZhong Yang 	case SCI_BRACEHIGHLIGHTINDICATOR:
7640*8af74909SZhong Yang 		if (lParam >= 0 && lParam <= INDICATOR_MAX) {
7641*8af74909SZhong Yang 			vs.braceHighlightIndicatorSet = wParam != 0;
7642*8af74909SZhong Yang 			vs.braceHighlightIndicator = static_cast<int>(lParam);
7643*8af74909SZhong Yang 		}
7644*8af74909SZhong Yang 		break;
7645*8af74909SZhong Yang 
7646*8af74909SZhong Yang 	case SCI_BRACEBADLIGHT:
7647*8af74909SZhong Yang 		SetBraceHighlight(static_cast<Sci::Position>(wParam), -1, STYLE_BRACEBAD);
7648*8af74909SZhong Yang 		break;
7649*8af74909SZhong Yang 
7650*8af74909SZhong Yang 	case SCI_BRACEBADLIGHTINDICATOR:
7651*8af74909SZhong Yang 		if (lParam >= 0 && lParam <= INDICATOR_MAX) {
7652*8af74909SZhong Yang 			vs.braceBadLightIndicatorSet = wParam != 0;
7653*8af74909SZhong Yang 			vs.braceBadLightIndicator = static_cast<int>(lParam);
7654*8af74909SZhong Yang 		}
7655*8af74909SZhong Yang 		break;
7656*8af74909SZhong Yang 
7657*8af74909SZhong Yang 	case SCI_BRACEMATCH:
7658*8af74909SZhong Yang 		// wParam is position of char to find brace for,
7659*8af74909SZhong Yang 		// lParam is maximum amount of text to restyle to find it
7660*8af74909SZhong Yang 		return pdoc->BraceMatch(static_cast<Sci::Position>(wParam), lParam, 0, false);
7661*8af74909SZhong Yang 
7662*8af74909SZhong Yang 	case SCI_BRACEMATCHNEXT:
7663*8af74909SZhong Yang 		return pdoc->BraceMatch(static_cast<Sci::Position>(wParam), 0, lParam, true);
7664*8af74909SZhong Yang 
7665*8af74909SZhong Yang 	case SCI_GETVIEWEOL:
7666*8af74909SZhong Yang 		return vs.viewEOL;
7667*8af74909SZhong Yang 
7668*8af74909SZhong Yang 	case SCI_SETVIEWEOL:
7669*8af74909SZhong Yang 		vs.viewEOL = wParam != 0;
7670*8af74909SZhong Yang 		InvalidateStyleRedraw();
7671*8af74909SZhong Yang 		break;
7672*8af74909SZhong Yang 
7673*8af74909SZhong Yang 	case SCI_SETZOOM: {
7674*8af74909SZhong Yang 			const int zoomLevel = static_cast<int>(wParam);
7675*8af74909SZhong Yang 			if (zoomLevel != vs.zoomLevel) {
7676*8af74909SZhong Yang 				vs.zoomLevel = zoomLevel;
7677*8af74909SZhong Yang 				InvalidateStyleRedraw();
7678*8af74909SZhong Yang 				NotifyZoom();
7679*8af74909SZhong Yang 			}
7680*8af74909SZhong Yang 			break;
7681*8af74909SZhong Yang 		}
7682*8af74909SZhong Yang 
7683*8af74909SZhong Yang 	case SCI_GETZOOM:
7684*8af74909SZhong Yang 		return vs.zoomLevel;
7685*8af74909SZhong Yang 
7686*8af74909SZhong Yang 	case SCI_GETEDGECOLUMN:
7687*8af74909SZhong Yang 		return vs.theEdge.column;
7688*8af74909SZhong Yang 
7689*8af74909SZhong Yang 	case SCI_SETEDGECOLUMN:
7690*8af74909SZhong Yang 		vs.theEdge.column = static_cast<int>(wParam);
7691*8af74909SZhong Yang 		InvalidateStyleRedraw();
7692*8af74909SZhong Yang 		break;
7693*8af74909SZhong Yang 
7694*8af74909SZhong Yang 	case SCI_GETEDGEMODE:
7695*8af74909SZhong Yang 		return vs.edgeState;
7696*8af74909SZhong Yang 
7697*8af74909SZhong Yang 	case SCI_SETEDGEMODE:
7698*8af74909SZhong Yang 		vs.edgeState = static_cast<int>(wParam);
7699*8af74909SZhong Yang 		InvalidateStyleRedraw();
7700*8af74909SZhong Yang 		break;
7701*8af74909SZhong Yang 
7702*8af74909SZhong Yang 	case SCI_GETEDGECOLOUR:
7703*8af74909SZhong Yang 		return vs.theEdge.colour.AsInteger();
7704*8af74909SZhong Yang 
7705*8af74909SZhong Yang 	case SCI_SETEDGECOLOUR:
7706*8af74909SZhong Yang 		vs.theEdge.colour = ColourDesired(static_cast<int>(wParam));
7707*8af74909SZhong Yang 		InvalidateStyleRedraw();
7708*8af74909SZhong Yang 		break;
7709*8af74909SZhong Yang 
7710*8af74909SZhong Yang 	case SCI_MULTIEDGEADDLINE:
7711*8af74909SZhong Yang 		vs.AddMultiEdge(wParam, lParam);
7712*8af74909SZhong Yang 		InvalidateStyleRedraw();
7713*8af74909SZhong Yang 		break;
7714*8af74909SZhong Yang 
7715*8af74909SZhong Yang 	case SCI_MULTIEDGECLEARALL:
7716*8af74909SZhong Yang 		std::vector<EdgeProperties>().swap(vs.theMultiEdge); // Free vector and memory, C++03 compatible
7717*8af74909SZhong Yang 		InvalidateStyleRedraw();
7718*8af74909SZhong Yang 		break;
7719*8af74909SZhong Yang 
7720*8af74909SZhong Yang 	case SCI_GETMULTIEDGECOLUMN: {
7721*8af74909SZhong Yang 			const size_t which = wParam;
7722*8af74909SZhong Yang 			// size_t is unsigned so this also handles negative inputs.
7723*8af74909SZhong Yang 			if (which >= vs.theMultiEdge.size()) {
7724*8af74909SZhong Yang 				return -1;
7725*8af74909SZhong Yang 			}
7726*8af74909SZhong Yang 			return vs.theMultiEdge[which].column;
7727*8af74909SZhong Yang 		}
7728*8af74909SZhong Yang 
7729*8af74909SZhong Yang 	case SCI_GETACCESSIBILITY:
7730*8af74909SZhong Yang 		return SC_ACCESSIBILITY_DISABLED;
7731*8af74909SZhong Yang 
7732*8af74909SZhong Yang 	case SCI_SETACCESSIBILITY:
7733*8af74909SZhong Yang 		// May be implemented by platform code.
7734*8af74909SZhong Yang 		break;
7735*8af74909SZhong Yang 
7736*8af74909SZhong Yang 	case SCI_GETDOCPOINTER:
7737*8af74909SZhong Yang 		return reinterpret_cast<sptr_t>(pdoc);
7738*8af74909SZhong Yang 
7739*8af74909SZhong Yang 	case SCI_SETDOCPOINTER:
7740*8af74909SZhong Yang 		CancelModes();
7741*8af74909SZhong Yang 		SetDocPointer(static_cast<Document *>(PtrFromSPtr(lParam)));
7742*8af74909SZhong Yang 		return 0;
7743*8af74909SZhong Yang 
7744*8af74909SZhong Yang 	case SCI_CREATEDOCUMENT: {
7745*8af74909SZhong Yang 			Document *doc = new Document(static_cast<int>(lParam));
7746*8af74909SZhong Yang 			doc->AddRef();
7747*8af74909SZhong Yang 			doc->Allocate(static_cast<Sci::Position>(wParam));
7748*8af74909SZhong Yang 			pcs = ContractionStateCreate(pdoc->IsLarge());
7749*8af74909SZhong Yang 			return reinterpret_cast<sptr_t>(doc);
7750*8af74909SZhong Yang 		}
7751*8af74909SZhong Yang 
7752*8af74909SZhong Yang 	case SCI_ADDREFDOCUMENT:
7753*8af74909SZhong Yang 		(static_cast<Document *>(PtrFromSPtr(lParam)))->AddRef();
7754*8af74909SZhong Yang 		break;
7755*8af74909SZhong Yang 
7756*8af74909SZhong Yang 	case SCI_RELEASEDOCUMENT:
7757*8af74909SZhong Yang 		(static_cast<Document *>(PtrFromSPtr(lParam)))->Release();
7758*8af74909SZhong Yang 		break;
7759*8af74909SZhong Yang 
7760*8af74909SZhong Yang 	case SCI_GETDOCUMENTOPTIONS:
7761*8af74909SZhong Yang 		return pdoc->Options();
7762*8af74909SZhong Yang 
7763*8af74909SZhong Yang 	case SCI_CREATELOADER: {
7764*8af74909SZhong Yang 			Document *doc = new Document(static_cast<int>(lParam));
7765*8af74909SZhong Yang 			doc->AddRef();
7766*8af74909SZhong Yang 			doc->Allocate(static_cast<Sci::Position>(wParam));
7767*8af74909SZhong Yang 			doc->SetUndoCollection(false);
7768*8af74909SZhong Yang 			pcs = ContractionStateCreate(pdoc->IsLarge());
7769*8af74909SZhong Yang 			return reinterpret_cast<sptr_t>(static_cast<ILoader *>(doc));
7770*8af74909SZhong Yang 		}
7771*8af74909SZhong Yang 
7772*8af74909SZhong Yang 	case SCI_SETMODEVENTMASK:
7773*8af74909SZhong Yang 		modEventMask = static_cast<int>(wParam);
7774*8af74909SZhong Yang 		return 0;
7775*8af74909SZhong Yang 
7776*8af74909SZhong Yang 	case SCI_GETMODEVENTMASK:
7777*8af74909SZhong Yang 		return modEventMask;
7778*8af74909SZhong Yang 
7779*8af74909SZhong Yang 	case SCI_SETCOMMANDEVENTS:
7780*8af74909SZhong Yang 		commandEvents = static_cast<bool>(wParam);
7781*8af74909SZhong Yang 		return 0;
7782*8af74909SZhong Yang 
7783*8af74909SZhong Yang 	case SCI_GETCOMMANDEVENTS:
7784*8af74909SZhong Yang 		return commandEvents;
7785*8af74909SZhong Yang 
7786*8af74909SZhong Yang 	case SCI_CONVERTEOLS:
7787*8af74909SZhong Yang 		pdoc->ConvertLineEnds(static_cast<int>(wParam));
7788*8af74909SZhong Yang 		SetSelection(sel.MainCaret(), sel.MainAnchor());	// Ensure selection inside document
7789*8af74909SZhong Yang 		return 0;
7790*8af74909SZhong Yang 
7791*8af74909SZhong Yang 	case SCI_SETLENGTHFORENCODE:
7792*8af74909SZhong Yang 		lengthForEncode = static_cast<Sci::Position>(wParam);
7793*8af74909SZhong Yang 		return 0;
7794*8af74909SZhong Yang 
7795*8af74909SZhong Yang 	case SCI_SELECTIONISRECTANGLE:
7796*8af74909SZhong Yang 		return sel.selType == Selection::selRectangle ? 1 : 0;
7797*8af74909SZhong Yang 
7798*8af74909SZhong Yang 	case SCI_SETSELECTIONMODE: {
7799*8af74909SZhong Yang 			switch (wParam) {
7800*8af74909SZhong Yang 			case SC_SEL_STREAM:
7801*8af74909SZhong Yang 				sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selStream));
7802*8af74909SZhong Yang 				sel.selType = Selection::selStream;
7803*8af74909SZhong Yang 				break;
7804*8af74909SZhong Yang 			case SC_SEL_RECTANGLE:
7805*8af74909SZhong Yang 				sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selRectangle));
7806*8af74909SZhong Yang 				sel.selType = Selection::selRectangle;
7807*8af74909SZhong Yang 				sel.Rectangular() = sel.RangeMain(); // adjust current selection
7808*8af74909SZhong Yang 				break;
7809*8af74909SZhong Yang 			case SC_SEL_LINES:
7810*8af74909SZhong Yang 				sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selLines));
7811*8af74909SZhong Yang 				sel.selType = Selection::selLines;
7812*8af74909SZhong Yang 				SetSelection(sel.RangeMain().caret, sel.RangeMain().anchor); // adjust current selection
7813*8af74909SZhong Yang 				break;
7814*8af74909SZhong Yang 			case SC_SEL_THIN:
7815*8af74909SZhong Yang 				sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selThin));
7816*8af74909SZhong Yang 				sel.selType = Selection::selThin;
7817*8af74909SZhong Yang 				break;
7818*8af74909SZhong Yang 			default:
7819*8af74909SZhong Yang 				sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selStream));
7820*8af74909SZhong Yang 				sel.selType = Selection::selStream;
7821*8af74909SZhong Yang 			}
7822*8af74909SZhong Yang 			InvalidateWholeSelection();
7823*8af74909SZhong Yang 			break;
7824*8af74909SZhong Yang 		}
7825*8af74909SZhong Yang 	case SCI_GETSELECTIONMODE:
7826*8af74909SZhong Yang 		switch (sel.selType) {
7827*8af74909SZhong Yang 		case Selection::selStream:
7828*8af74909SZhong Yang 			return SC_SEL_STREAM;
7829*8af74909SZhong Yang 		case Selection::selRectangle:
7830*8af74909SZhong Yang 			return SC_SEL_RECTANGLE;
7831*8af74909SZhong Yang 		case Selection::selLines:
7832*8af74909SZhong Yang 			return SC_SEL_LINES;
7833*8af74909SZhong Yang 		case Selection::selThin:
7834*8af74909SZhong Yang 			return SC_SEL_THIN;
7835*8af74909SZhong Yang 		default:	// ?!
7836*8af74909SZhong Yang 			return SC_SEL_STREAM;
7837*8af74909SZhong Yang 		}
7838*8af74909SZhong Yang 	case SCI_GETMOVEEXTENDSSELECTION:
7839*8af74909SZhong Yang 		return sel.MoveExtends();
7840*8af74909SZhong Yang 	case SCI_GETLINESELSTARTPOSITION:
7841*8af74909SZhong Yang 	case SCI_GETLINESELENDPOSITION: {
7842*8af74909SZhong Yang 			const SelectionSegment segmentLine(
7843*8af74909SZhong Yang 				SelectionPosition(pdoc->LineStart(static_cast<Sci::Position>(wParam))),
7844*8af74909SZhong Yang 				SelectionPosition(pdoc->LineEnd(static_cast<Sci::Position>(wParam))));
7845*8af74909SZhong Yang 			for (size_t r=0; r<sel.Count(); r++) {
7846*8af74909SZhong Yang 				const SelectionSegment portion = sel.Range(r).Intersect(segmentLine);
7847*8af74909SZhong Yang 				if (portion.start.IsValid()) {
7848*8af74909SZhong Yang 					return (iMessage == SCI_GETLINESELSTARTPOSITION) ? portion.start.Position() : portion.end.Position();
7849*8af74909SZhong Yang 				}
7850*8af74909SZhong Yang 			}
7851*8af74909SZhong Yang 			return INVALID_POSITION;
7852*8af74909SZhong Yang 		}
7853*8af74909SZhong Yang 
7854*8af74909SZhong Yang 	case SCI_SETOVERTYPE:
7855*8af74909SZhong Yang 		if (inOverstrike != (wParam != 0)) {
7856*8af74909SZhong Yang 			inOverstrike = wParam != 0;
7857*8af74909SZhong Yang 			ContainerNeedsUpdate(SC_UPDATE_SELECTION);
7858*8af74909SZhong Yang 			ShowCaretAtCurrentPosition();
7859*8af74909SZhong Yang 			SetIdle(true);
7860*8af74909SZhong Yang 		}
7861*8af74909SZhong Yang 		break;
7862*8af74909SZhong Yang 
7863*8af74909SZhong Yang 	case SCI_GETOVERTYPE:
7864*8af74909SZhong Yang 		return inOverstrike ? 1 : 0;
7865*8af74909SZhong Yang 
7866*8af74909SZhong Yang 	case SCI_SETFOCUS:
7867*8af74909SZhong Yang 		SetFocusState(wParam != 0);
7868*8af74909SZhong Yang 		break;
7869*8af74909SZhong Yang 
7870*8af74909SZhong Yang 	case SCI_GETFOCUS:
7871*8af74909SZhong Yang 		return hasFocus;
7872*8af74909SZhong Yang 
7873*8af74909SZhong Yang 	case SCI_SETSTATUS:
7874*8af74909SZhong Yang 		errorStatus = static_cast<int>(wParam);
7875*8af74909SZhong Yang 		break;
7876*8af74909SZhong Yang 
7877*8af74909SZhong Yang 	case SCI_GETSTATUS:
7878*8af74909SZhong Yang 		return errorStatus;
7879*8af74909SZhong Yang 
7880*8af74909SZhong Yang 	case SCI_SETMOUSEDOWNCAPTURES:
7881*8af74909SZhong Yang 		mouseDownCaptures = wParam != 0;
7882*8af74909SZhong Yang 		break;
7883*8af74909SZhong Yang 
7884*8af74909SZhong Yang 	case SCI_GETMOUSEDOWNCAPTURES:
7885*8af74909SZhong Yang 		return mouseDownCaptures;
7886*8af74909SZhong Yang 
7887*8af74909SZhong Yang 	case SCI_SETMOUSEWHEELCAPTURES:
7888*8af74909SZhong Yang 		mouseWheelCaptures = wParam != 0;
7889*8af74909SZhong Yang 		break;
7890*8af74909SZhong Yang 
7891*8af74909SZhong Yang 	case SCI_GETMOUSEWHEELCAPTURES:
7892*8af74909SZhong Yang 		return mouseWheelCaptures;
7893*8af74909SZhong Yang 
7894*8af74909SZhong Yang 	case SCI_SETCURSOR:
7895*8af74909SZhong Yang 		cursorMode = static_cast<int>(wParam);
7896*8af74909SZhong Yang 		DisplayCursor(Window::cursorText);
7897*8af74909SZhong Yang 		break;
7898*8af74909SZhong Yang 
7899*8af74909SZhong Yang 	case SCI_GETCURSOR:
7900*8af74909SZhong Yang 		return cursorMode;
7901*8af74909SZhong Yang 
7902*8af74909SZhong Yang 	case SCI_SETCONTROLCHARSYMBOL:
7903*8af74909SZhong Yang 		vs.controlCharSymbol = static_cast<int>(wParam);
7904*8af74909SZhong Yang 		InvalidateStyleRedraw();
7905*8af74909SZhong Yang 		break;
7906*8af74909SZhong Yang 
7907*8af74909SZhong Yang 	case SCI_GETCONTROLCHARSYMBOL:
7908*8af74909SZhong Yang 		return vs.controlCharSymbol;
7909*8af74909SZhong Yang 
7910*8af74909SZhong Yang 	case SCI_SETREPRESENTATION:
7911*8af74909SZhong Yang 		reprs.SetRepresentation(ConstCharPtrFromUPtr(wParam), ConstCharPtrFromSPtr(lParam));
7912*8af74909SZhong Yang 		break;
7913*8af74909SZhong Yang 
7914*8af74909SZhong Yang 	case SCI_GETREPRESENTATION: {
7915*8af74909SZhong Yang 			const Representation *repr = reprs.RepresentationFromCharacter(
7916*8af74909SZhong Yang 				ConstCharPtrFromUPtr(wParam), UTF8MaxBytes);
7917*8af74909SZhong Yang 			if (repr) {
7918*8af74909SZhong Yang 				return StringResult(lParam, repr->stringRep.c_str());
7919*8af74909SZhong Yang 			}
7920*8af74909SZhong Yang 			return 0;
7921*8af74909SZhong Yang 		}
7922*8af74909SZhong Yang 
7923*8af74909SZhong Yang 	case SCI_CLEARREPRESENTATION:
7924*8af74909SZhong Yang 		reprs.ClearRepresentation(ConstCharPtrFromUPtr(wParam));
7925*8af74909SZhong Yang 		break;
7926*8af74909SZhong Yang 
7927*8af74909SZhong Yang 	case SCI_STARTRECORD:
7928*8af74909SZhong Yang 		recordingMacro = true;
7929*8af74909SZhong Yang 		return 0;
7930*8af74909SZhong Yang 
7931*8af74909SZhong Yang 	case SCI_STOPRECORD:
7932*8af74909SZhong Yang 		recordingMacro = false;
7933*8af74909SZhong Yang 		return 0;
7934*8af74909SZhong Yang 
7935*8af74909SZhong Yang 	case SCI_MOVECARETINSIDEVIEW:
7936*8af74909SZhong Yang 		MoveCaretInsideView();
7937*8af74909SZhong Yang 		break;
7938*8af74909SZhong Yang 
7939*8af74909SZhong Yang 	case SCI_SETFOLDMARGINCOLOUR:
7940*8af74909SZhong Yang 		vs.foldmarginColour = ColourOptional(wParam, lParam);
7941*8af74909SZhong Yang 		InvalidateStyleRedraw();
7942*8af74909SZhong Yang 		break;
7943*8af74909SZhong Yang 
7944*8af74909SZhong Yang 	case SCI_SETFOLDMARGINHICOLOUR:
7945*8af74909SZhong Yang 		vs.foldmarginHighlightColour = ColourOptional(wParam, lParam);
7946*8af74909SZhong Yang 		InvalidateStyleRedraw();
7947*8af74909SZhong Yang 		break;
7948*8af74909SZhong Yang 
7949*8af74909SZhong Yang 	case SCI_SETHOTSPOTACTIVEFORE:
7950*8af74909SZhong Yang 		vs.hotspotColours.fore = ColourOptional(wParam, lParam);
7951*8af74909SZhong Yang 		InvalidateStyleRedraw();
7952*8af74909SZhong Yang 		break;
7953*8af74909SZhong Yang 
7954*8af74909SZhong Yang 	case SCI_GETHOTSPOTACTIVEFORE:
7955*8af74909SZhong Yang 		return vs.hotspotColours.fore.AsInteger();
7956*8af74909SZhong Yang 
7957*8af74909SZhong Yang 	case SCI_SETHOTSPOTACTIVEBACK:
7958*8af74909SZhong Yang 		vs.hotspotColours.back = ColourOptional(wParam, lParam);
7959*8af74909SZhong Yang 		InvalidateStyleRedraw();
7960*8af74909SZhong Yang 		break;
7961*8af74909SZhong Yang 
7962*8af74909SZhong Yang 	case SCI_GETHOTSPOTACTIVEBACK:
7963*8af74909SZhong Yang 		return vs.hotspotColours.back.AsInteger();
7964*8af74909SZhong Yang 
7965*8af74909SZhong Yang 	case SCI_SETHOTSPOTACTIVEUNDERLINE:
7966*8af74909SZhong Yang 		vs.hotspotUnderline = wParam != 0;
7967*8af74909SZhong Yang 		InvalidateStyleRedraw();
7968*8af74909SZhong Yang 		break;
7969*8af74909SZhong Yang 
7970*8af74909SZhong Yang 	case SCI_GETHOTSPOTACTIVEUNDERLINE:
7971*8af74909SZhong Yang 		return vs.hotspotUnderline ? 1 : 0;
7972*8af74909SZhong Yang 
7973*8af74909SZhong Yang 	case SCI_SETHOTSPOTSINGLELINE:
7974*8af74909SZhong Yang 		vs.hotspotSingleLine = wParam != 0;
7975*8af74909SZhong Yang 		InvalidateStyleRedraw();
7976*8af74909SZhong Yang 		break;
7977*8af74909SZhong Yang 
7978*8af74909SZhong Yang 	case SCI_GETHOTSPOTSINGLELINE:
7979*8af74909SZhong Yang 		return vs.hotspotSingleLine ? 1 : 0;
7980*8af74909SZhong Yang 
7981*8af74909SZhong Yang 	case SCI_SETPASTECONVERTENDINGS:
7982*8af74909SZhong Yang 		convertPastes = wParam != 0;
7983*8af74909SZhong Yang 		break;
7984*8af74909SZhong Yang 
7985*8af74909SZhong Yang 	case SCI_GETPASTECONVERTENDINGS:
7986*8af74909SZhong Yang 		return convertPastes ? 1 : 0;
7987*8af74909SZhong Yang 
7988*8af74909SZhong Yang 	case SCI_GETCHARACTERPOINTER:
7989*8af74909SZhong Yang 		return reinterpret_cast<sptr_t>(pdoc->BufferPointer());
7990*8af74909SZhong Yang 
7991*8af74909SZhong Yang 	case SCI_GETRANGEPOINTER:
7992*8af74909SZhong Yang 		return reinterpret_cast<sptr_t>(pdoc->RangePointer(
7993*8af74909SZhong Yang 			static_cast<Sci::Position>(wParam), lParam));
7994*8af74909SZhong Yang 
7995*8af74909SZhong Yang 	case SCI_GETGAPPOSITION:
7996*8af74909SZhong Yang 		return pdoc->GapPosition();
7997*8af74909SZhong Yang 
7998*8af74909SZhong Yang 	case SCI_SETEXTRAASCENT:
7999*8af74909SZhong Yang 		vs.extraAscent = static_cast<int>(wParam);
8000*8af74909SZhong Yang 		InvalidateStyleRedraw();
8001*8af74909SZhong Yang 		break;
8002*8af74909SZhong Yang 
8003*8af74909SZhong Yang 	case SCI_GETEXTRAASCENT:
8004*8af74909SZhong Yang 		return vs.extraAscent;
8005*8af74909SZhong Yang 
8006*8af74909SZhong Yang 	case SCI_SETEXTRADESCENT:
8007*8af74909SZhong Yang 		vs.extraDescent = static_cast<int>(wParam);
8008*8af74909SZhong Yang 		InvalidateStyleRedraw();
8009*8af74909SZhong Yang 		break;
8010*8af74909SZhong Yang 
8011*8af74909SZhong Yang 	case SCI_GETEXTRADESCENT:
8012*8af74909SZhong Yang 		return vs.extraDescent;
8013*8af74909SZhong Yang 
8014*8af74909SZhong Yang 	case SCI_MARGINSETSTYLEOFFSET:
8015*8af74909SZhong Yang 		vs.marginStyleOffset = static_cast<int>(wParam);
8016*8af74909SZhong Yang 		InvalidateStyleRedraw();
8017*8af74909SZhong Yang 		break;
8018*8af74909SZhong Yang 
8019*8af74909SZhong Yang 	case SCI_MARGINGETSTYLEOFFSET:
8020*8af74909SZhong Yang 		return vs.marginStyleOffset;
8021*8af74909SZhong Yang 
8022*8af74909SZhong Yang 	case SCI_SETMARGINOPTIONS:
8023*8af74909SZhong Yang 		marginOptions = static_cast<int>(wParam);
8024*8af74909SZhong Yang 		break;
8025*8af74909SZhong Yang 
8026*8af74909SZhong Yang 	case SCI_GETMARGINOPTIONS:
8027*8af74909SZhong Yang 		return marginOptions;
8028*8af74909SZhong Yang 
8029*8af74909SZhong Yang 	case SCI_MARGINSETTEXT:
8030*8af74909SZhong Yang 		pdoc->MarginSetText(static_cast<Sci::Line>(wParam), CharPtrFromSPtr(lParam));
8031*8af74909SZhong Yang 		break;
8032*8af74909SZhong Yang 
8033*8af74909SZhong Yang 	case SCI_MARGINGETTEXT: {
8034*8af74909SZhong Yang 			const StyledText st = pdoc->MarginStyledText(static_cast<Sci::Line>(wParam));
8035*8af74909SZhong Yang 			return BytesResult(lParam, reinterpret_cast<const unsigned char *>(st.text), st.length);
8036*8af74909SZhong Yang 		}
8037*8af74909SZhong Yang 
8038*8af74909SZhong Yang 	case SCI_MARGINSETSTYLE:
8039*8af74909SZhong Yang 		pdoc->MarginSetStyle(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
8040*8af74909SZhong Yang 		break;
8041*8af74909SZhong Yang 
8042*8af74909SZhong Yang 	case SCI_MARGINGETSTYLE: {
8043*8af74909SZhong Yang 			const StyledText st = pdoc->MarginStyledText(static_cast<Sci::Line>(wParam));
8044*8af74909SZhong Yang 			return st.style;
8045*8af74909SZhong Yang 		}
8046*8af74909SZhong Yang 
8047*8af74909SZhong Yang 	case SCI_MARGINSETSTYLES:
8048*8af74909SZhong Yang 		pdoc->MarginSetStyles(static_cast<Sci::Line>(wParam), ConstUCharPtrFromSPtr(lParam));
8049*8af74909SZhong Yang 		break;
8050*8af74909SZhong Yang 
8051*8af74909SZhong Yang 	case SCI_MARGINGETSTYLES: {
8052*8af74909SZhong Yang 			const StyledText st = pdoc->MarginStyledText(static_cast<Sci::Line>(wParam));
8053*8af74909SZhong Yang 			return BytesResult(lParam, st.styles, st.length);
8054*8af74909SZhong Yang 		}
8055*8af74909SZhong Yang 
8056*8af74909SZhong Yang 	case SCI_MARGINTEXTCLEARALL:
8057*8af74909SZhong Yang 		pdoc->MarginClearAll();
8058*8af74909SZhong Yang 		break;
8059*8af74909SZhong Yang 
8060*8af74909SZhong Yang 	case SCI_ANNOTATIONSETTEXT:
8061*8af74909SZhong Yang 		pdoc->AnnotationSetText(static_cast<Sci::Line>(wParam), CharPtrFromSPtr(lParam));
8062*8af74909SZhong Yang 		break;
8063*8af74909SZhong Yang 
8064*8af74909SZhong Yang 	case SCI_ANNOTATIONGETTEXT: {
8065*8af74909SZhong Yang 			const StyledText st = pdoc->AnnotationStyledText(static_cast<Sci::Line>(wParam));
8066*8af74909SZhong Yang 			return BytesResult(lParam, reinterpret_cast<const unsigned char *>(st.text), st.length);
8067*8af74909SZhong Yang 		}
8068*8af74909SZhong Yang 
8069*8af74909SZhong Yang 	case SCI_ANNOTATIONGETSTYLE: {
8070*8af74909SZhong Yang 			const StyledText st = pdoc->AnnotationStyledText(static_cast<Sci::Line>(wParam));
8071*8af74909SZhong Yang 			return st.style;
8072*8af74909SZhong Yang 		}
8073*8af74909SZhong Yang 
8074*8af74909SZhong Yang 	case SCI_ANNOTATIONSETSTYLE:
8075*8af74909SZhong Yang 		pdoc->AnnotationSetStyle(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
8076*8af74909SZhong Yang 		break;
8077*8af74909SZhong Yang 
8078*8af74909SZhong Yang 	case SCI_ANNOTATIONSETSTYLES:
8079*8af74909SZhong Yang 		pdoc->AnnotationSetStyles(static_cast<Sci::Line>(wParam), ConstUCharPtrFromSPtr(lParam));
8080*8af74909SZhong Yang 		break;
8081*8af74909SZhong Yang 
8082*8af74909SZhong Yang 	case SCI_ANNOTATIONGETSTYLES: {
8083*8af74909SZhong Yang 			const StyledText st = pdoc->AnnotationStyledText(static_cast<Sci::Line>(wParam));
8084*8af74909SZhong Yang 			return BytesResult(lParam, st.styles, st.length);
8085*8af74909SZhong Yang 		}
8086*8af74909SZhong Yang 
8087*8af74909SZhong Yang 	case SCI_ANNOTATIONGETLINES:
8088*8af74909SZhong Yang 		return pdoc->AnnotationLines(static_cast<Sci::Line>(wParam));
8089*8af74909SZhong Yang 
8090*8af74909SZhong Yang 	case SCI_ANNOTATIONCLEARALL:
8091*8af74909SZhong Yang 		pdoc->AnnotationClearAll();
8092*8af74909SZhong Yang 		break;
8093*8af74909SZhong Yang 
8094*8af74909SZhong Yang 	case SCI_ANNOTATIONSETVISIBLE:
8095*8af74909SZhong Yang 		SetAnnotationVisible(static_cast<int>(wParam));
8096*8af74909SZhong Yang 		break;
8097*8af74909SZhong Yang 
8098*8af74909SZhong Yang 	case SCI_ANNOTATIONGETVISIBLE:
8099*8af74909SZhong Yang 		return vs.annotationVisible;
8100*8af74909SZhong Yang 
8101*8af74909SZhong Yang 	case SCI_ANNOTATIONSETSTYLEOFFSET:
8102*8af74909SZhong Yang 		vs.annotationStyleOffset = static_cast<int>(wParam);
8103*8af74909SZhong Yang 		InvalidateStyleRedraw();
8104*8af74909SZhong Yang 		break;
8105*8af74909SZhong Yang 
8106*8af74909SZhong Yang 	case SCI_ANNOTATIONGETSTYLEOFFSET:
8107*8af74909SZhong Yang 		return vs.annotationStyleOffset;
8108*8af74909SZhong Yang 
8109*8af74909SZhong Yang 	case SCI_EOLANNOTATIONSETTEXT:
8110*8af74909SZhong Yang 		pdoc->EOLAnnotationSetText(static_cast<Sci::Line>(wParam), CharPtrFromSPtr(lParam));
8111*8af74909SZhong Yang 		break;
8112*8af74909SZhong Yang 
8113*8af74909SZhong Yang 	case SCI_EOLANNOTATIONGETTEXT: {
8114*8af74909SZhong Yang 			const StyledText st = pdoc->EOLAnnotationStyledText(static_cast<Sci::Line>(wParam));
8115*8af74909SZhong Yang 			return BytesResult(lParam, reinterpret_cast<const unsigned char *>(st.text), st.length);
8116*8af74909SZhong Yang 		}
8117*8af74909SZhong Yang 
8118*8af74909SZhong Yang 	case SCI_EOLANNOTATIONGETSTYLE: {
8119*8af74909SZhong Yang 			const StyledText st = pdoc->EOLAnnotationStyledText(static_cast<Sci::Line>(wParam));
8120*8af74909SZhong Yang 			return st.style;
8121*8af74909SZhong Yang 		}
8122*8af74909SZhong Yang 
8123*8af74909SZhong Yang 	case SCI_EOLANNOTATIONSETSTYLE:
8124*8af74909SZhong Yang 		pdoc->EOLAnnotationSetStyle(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
8125*8af74909SZhong Yang 		break;
8126*8af74909SZhong Yang 
8127*8af74909SZhong Yang 	case SCI_EOLANNOTATIONCLEARALL:
8128*8af74909SZhong Yang 		pdoc->EOLAnnotationClearAll();
8129*8af74909SZhong Yang 		break;
8130*8af74909SZhong Yang 
8131*8af74909SZhong Yang 	case SCI_EOLANNOTATIONSETVISIBLE:
8132*8af74909SZhong Yang 		SetEOLAnnotationVisible(static_cast<int>(wParam));
8133*8af74909SZhong Yang 		break;
8134*8af74909SZhong Yang 
8135*8af74909SZhong Yang 	case SCI_EOLANNOTATIONGETVISIBLE:
8136*8af74909SZhong Yang 		return vs.eolAnnotationVisible;
8137*8af74909SZhong Yang 
8138*8af74909SZhong Yang 	case SCI_EOLANNOTATIONSETSTYLEOFFSET:
8139*8af74909SZhong Yang 		vs.eolAnnotationStyleOffset = static_cast<int>(wParam);
8140*8af74909SZhong Yang 		InvalidateStyleRedraw();
8141*8af74909SZhong Yang 		break;
8142*8af74909SZhong Yang 
8143*8af74909SZhong Yang 	case SCI_EOLANNOTATIONGETSTYLEOFFSET:
8144*8af74909SZhong Yang 		return vs.eolAnnotationStyleOffset;
8145*8af74909SZhong Yang 
8146*8af74909SZhong Yang 	case SCI_RELEASEALLEXTENDEDSTYLES:
8147*8af74909SZhong Yang 		vs.ReleaseAllExtendedStyles();
8148*8af74909SZhong Yang 		break;
8149*8af74909SZhong Yang 
8150*8af74909SZhong Yang 	case SCI_ALLOCATEEXTENDEDSTYLES:
8151*8af74909SZhong Yang 		return vs.AllocateExtendedStyles(static_cast<int>(wParam));
8152*8af74909SZhong Yang 
8153*8af74909SZhong Yang 	case SCI_ADDUNDOACTION:
8154*8af74909SZhong Yang 		pdoc->AddUndoAction(static_cast<Sci::Position>(wParam), lParam & UNDO_MAY_COALESCE);
8155*8af74909SZhong Yang 		break;
8156*8af74909SZhong Yang 
8157*8af74909SZhong Yang 	case SCI_SETMOUSESELECTIONRECTANGULARSWITCH:
8158*8af74909SZhong Yang 		mouseSelectionRectangularSwitch = wParam != 0;
8159*8af74909SZhong Yang 		break;
8160*8af74909SZhong Yang 
8161*8af74909SZhong Yang 	case SCI_GETMOUSESELECTIONRECTANGULARSWITCH:
8162*8af74909SZhong Yang 		return mouseSelectionRectangularSwitch;
8163*8af74909SZhong Yang 
8164*8af74909SZhong Yang 	case SCI_SETMULTIPLESELECTION:
8165*8af74909SZhong Yang 		multipleSelection = wParam != 0;
8166*8af74909SZhong Yang 		InvalidateCaret();
8167*8af74909SZhong Yang 		break;
8168*8af74909SZhong Yang 
8169*8af74909SZhong Yang 	case SCI_GETMULTIPLESELECTION:
8170*8af74909SZhong Yang 		return multipleSelection;
8171*8af74909SZhong Yang 
8172*8af74909SZhong Yang 	case SCI_SETADDITIONALSELECTIONTYPING:
8173*8af74909SZhong Yang 		additionalSelectionTyping = wParam != 0;
8174*8af74909SZhong Yang 		InvalidateCaret();
8175*8af74909SZhong Yang 		break;
8176*8af74909SZhong Yang 
8177*8af74909SZhong Yang 	case SCI_GETADDITIONALSELECTIONTYPING:
8178*8af74909SZhong Yang 		return additionalSelectionTyping;
8179*8af74909SZhong Yang 
8180*8af74909SZhong Yang 	case SCI_SETMULTIPASTE:
8181*8af74909SZhong Yang 		multiPasteMode = static_cast<int>(wParam);
8182*8af74909SZhong Yang 		break;
8183*8af74909SZhong Yang 
8184*8af74909SZhong Yang 	case SCI_GETMULTIPASTE:
8185*8af74909SZhong Yang 		return multiPasteMode;
8186*8af74909SZhong Yang 
8187*8af74909SZhong Yang 	case SCI_SETADDITIONALCARETSBLINK:
8188*8af74909SZhong Yang 		view.additionalCaretsBlink = wParam != 0;
8189*8af74909SZhong Yang 		InvalidateCaret();
8190*8af74909SZhong Yang 		break;
8191*8af74909SZhong Yang 
8192*8af74909SZhong Yang 	case SCI_GETADDITIONALCARETSBLINK:
8193*8af74909SZhong Yang 		return view.additionalCaretsBlink;
8194*8af74909SZhong Yang 
8195*8af74909SZhong Yang 	case SCI_SETADDITIONALCARETSVISIBLE:
8196*8af74909SZhong Yang 		view.additionalCaretsVisible = wParam != 0;
8197*8af74909SZhong Yang 		InvalidateCaret();
8198*8af74909SZhong Yang 		break;
8199*8af74909SZhong Yang 
8200*8af74909SZhong Yang 	case SCI_GETADDITIONALCARETSVISIBLE:
8201*8af74909SZhong Yang 		return view.additionalCaretsVisible;
8202*8af74909SZhong Yang 
8203*8af74909SZhong Yang 	case SCI_GETSELECTIONS:
8204*8af74909SZhong Yang 		return sel.Count();
8205*8af74909SZhong Yang 
8206*8af74909SZhong Yang 	case SCI_GETSELECTIONEMPTY:
8207*8af74909SZhong Yang 		return sel.Empty();
8208*8af74909SZhong Yang 
8209*8af74909SZhong Yang 	case SCI_CLEARSELECTIONS:
8210*8af74909SZhong Yang 		sel.Clear();
8211*8af74909SZhong Yang 		ContainerNeedsUpdate(SC_UPDATE_SELECTION);
8212*8af74909SZhong Yang 		Redraw();
8213*8af74909SZhong Yang 		break;
8214*8af74909SZhong Yang 
8215*8af74909SZhong Yang 	case SCI_SETSELECTION:
8216*8af74909SZhong Yang 		sel.SetSelection(SelectionRange(static_cast<Sci::Position>(wParam), lParam));
8217*8af74909SZhong Yang 		Redraw();
8218*8af74909SZhong Yang 		break;
8219*8af74909SZhong Yang 
8220*8af74909SZhong Yang 	case SCI_ADDSELECTION:
8221*8af74909SZhong Yang 		sel.AddSelection(SelectionRange(static_cast<Sci::Position>(wParam), lParam));
8222*8af74909SZhong Yang 		ContainerNeedsUpdate(SC_UPDATE_SELECTION);
8223*8af74909SZhong Yang 		Redraw();
8224*8af74909SZhong Yang 		break;
8225*8af74909SZhong Yang 
8226*8af74909SZhong Yang 	case SCI_DROPSELECTIONN:
8227*8af74909SZhong Yang 		sel.DropSelection(static_cast<size_t>(wParam));
8228*8af74909SZhong Yang 		ContainerNeedsUpdate(SC_UPDATE_SELECTION);
8229*8af74909SZhong Yang 		Redraw();
8230*8af74909SZhong Yang 		break;
8231*8af74909SZhong Yang 
8232*8af74909SZhong Yang 	case SCI_SETMAINSELECTION:
8233*8af74909SZhong Yang 		sel.SetMain(static_cast<size_t>(wParam));
8234*8af74909SZhong Yang 		ContainerNeedsUpdate(SC_UPDATE_SELECTION);
8235*8af74909SZhong Yang 		Redraw();
8236*8af74909SZhong Yang 		break;
8237*8af74909SZhong Yang 
8238*8af74909SZhong Yang 	case SCI_GETMAINSELECTION:
8239*8af74909SZhong Yang 		return sel.Main();
8240*8af74909SZhong Yang 
8241*8af74909SZhong Yang 	case SCI_SETSELECTIONNCARET:
8242*8af74909SZhong Yang 	case SCI_SETSELECTIONNANCHOR:
8243*8af74909SZhong Yang 	case SCI_SETSELECTIONNCARETVIRTUALSPACE:
8244*8af74909SZhong Yang 	case SCI_SETSELECTIONNANCHORVIRTUALSPACE:
8245*8af74909SZhong Yang 	case SCI_SETSELECTIONNSTART:
8246*8af74909SZhong Yang 	case SCI_SETSELECTIONNEND:
8247*8af74909SZhong Yang 		SetSelectionNMessage(iMessage, wParam, lParam);
8248*8af74909SZhong Yang 		break;
8249*8af74909SZhong Yang 
8250*8af74909SZhong Yang 	case SCI_GETSELECTIONNCARET:
8251*8af74909SZhong Yang 		return sel.Range(wParam).caret.Position();
8252*8af74909SZhong Yang 
8253*8af74909SZhong Yang 	case SCI_GETSELECTIONNANCHOR:
8254*8af74909SZhong Yang 		return sel.Range(wParam).anchor.Position();
8255*8af74909SZhong Yang 
8256*8af74909SZhong Yang 	case SCI_GETSELECTIONNCARETVIRTUALSPACE:
8257*8af74909SZhong Yang 		return sel.Range(wParam).caret.VirtualSpace();
8258*8af74909SZhong Yang 
8259*8af74909SZhong Yang 	case SCI_GETSELECTIONNANCHORVIRTUALSPACE:
8260*8af74909SZhong Yang 		return sel.Range(wParam).anchor.VirtualSpace();
8261*8af74909SZhong Yang 
8262*8af74909SZhong Yang 	case SCI_GETSELECTIONNSTART:
8263*8af74909SZhong Yang 		return sel.Range(wParam).Start().Position();
8264*8af74909SZhong Yang 
8265*8af74909SZhong Yang 	case SCI_GETSELECTIONNSTARTVIRTUALSPACE:
8266*8af74909SZhong Yang 		return sel.Range(wParam).Start().VirtualSpace();
8267*8af74909SZhong Yang 
8268*8af74909SZhong Yang 	case SCI_GETSELECTIONNEND:
8269*8af74909SZhong Yang 		return sel.Range(wParam).End().Position();
8270*8af74909SZhong Yang 
8271*8af74909SZhong Yang 	case SCI_GETSELECTIONNENDVIRTUALSPACE:
8272*8af74909SZhong Yang 		return sel.Range(wParam).End().VirtualSpace();
8273*8af74909SZhong Yang 
8274*8af74909SZhong Yang 	case SCI_SETRECTANGULARSELECTIONCARET:
8275*8af74909SZhong Yang 		if (!sel.IsRectangular())
8276*8af74909SZhong Yang 			sel.Clear();
8277*8af74909SZhong Yang 		sel.selType = Selection::selRectangle;
8278*8af74909SZhong Yang 		sel.Rectangular().caret.SetPosition(static_cast<Sci::Position>(wParam));
8279*8af74909SZhong Yang 		SetRectangularRange();
8280*8af74909SZhong Yang 		Redraw();
8281*8af74909SZhong Yang 		break;
8282*8af74909SZhong Yang 
8283*8af74909SZhong Yang 	case SCI_GETRECTANGULARSELECTIONCARET:
8284*8af74909SZhong Yang 		return sel.Rectangular().caret.Position();
8285*8af74909SZhong Yang 
8286*8af74909SZhong Yang 	case SCI_SETRECTANGULARSELECTIONANCHOR:
8287*8af74909SZhong Yang 		if (!sel.IsRectangular())
8288*8af74909SZhong Yang 			sel.Clear();
8289*8af74909SZhong Yang 		sel.selType = Selection::selRectangle;
8290*8af74909SZhong Yang 		sel.Rectangular().anchor.SetPosition(static_cast<Sci::Position>(wParam));
8291*8af74909SZhong Yang 		SetRectangularRange();
8292*8af74909SZhong Yang 		Redraw();
8293*8af74909SZhong Yang 		break;
8294*8af74909SZhong Yang 
8295*8af74909SZhong Yang 	case SCI_GETRECTANGULARSELECTIONANCHOR:
8296*8af74909SZhong Yang 		return sel.Rectangular().anchor.Position();
8297*8af74909SZhong Yang 
8298*8af74909SZhong Yang 	case SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE:
8299*8af74909SZhong Yang 		if (!sel.IsRectangular())
8300*8af74909SZhong Yang 			sel.Clear();
8301*8af74909SZhong Yang 		sel.selType = Selection::selRectangle;
8302*8af74909SZhong Yang 		sel.Rectangular().caret.SetVirtualSpace(static_cast<Sci::Position>(wParam));
8303*8af74909SZhong Yang 		SetRectangularRange();
8304*8af74909SZhong Yang 		Redraw();
8305*8af74909SZhong Yang 		break;
8306*8af74909SZhong Yang 
8307*8af74909SZhong Yang 	case SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE:
8308*8af74909SZhong Yang 		return sel.Rectangular().caret.VirtualSpace();
8309*8af74909SZhong Yang 
8310*8af74909SZhong Yang 	case SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE:
8311*8af74909SZhong Yang 		if (!sel.IsRectangular())
8312*8af74909SZhong Yang 			sel.Clear();
8313*8af74909SZhong Yang 		sel.selType = Selection::selRectangle;
8314*8af74909SZhong Yang 		sel.Rectangular().anchor.SetVirtualSpace(static_cast<Sci::Position>(wParam));
8315*8af74909SZhong Yang 		SetRectangularRange();
8316*8af74909SZhong Yang 		Redraw();
8317*8af74909SZhong Yang 		break;
8318*8af74909SZhong Yang 
8319*8af74909SZhong Yang 	case SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE:
8320*8af74909SZhong Yang 		return sel.Rectangular().anchor.VirtualSpace();
8321*8af74909SZhong Yang 
8322*8af74909SZhong Yang 	case SCI_SETVIRTUALSPACEOPTIONS:
8323*8af74909SZhong Yang 		virtualSpaceOptions = static_cast<int>(wParam);
8324*8af74909SZhong Yang 		break;
8325*8af74909SZhong Yang 
8326*8af74909SZhong Yang 	case SCI_GETVIRTUALSPACEOPTIONS:
8327*8af74909SZhong Yang 		return virtualSpaceOptions;
8328*8af74909SZhong Yang 
8329*8af74909SZhong Yang 	case SCI_SETADDITIONALSELFORE:
8330*8af74909SZhong Yang 		vs.selAdditionalForeground = ColourDesired(static_cast<int>(wParam));
8331*8af74909SZhong Yang 		InvalidateStyleRedraw();
8332*8af74909SZhong Yang 		break;
8333*8af74909SZhong Yang 
8334*8af74909SZhong Yang 	case SCI_SETADDITIONALSELBACK:
8335*8af74909SZhong Yang 		vs.selAdditionalBackground = ColourDesired(static_cast<int>(wParam));
8336*8af74909SZhong Yang 		InvalidateStyleRedraw();
8337*8af74909SZhong Yang 		break;
8338*8af74909SZhong Yang 
8339*8af74909SZhong Yang 	case SCI_SETADDITIONALSELALPHA:
8340*8af74909SZhong Yang 		vs.selAdditionalAlpha = static_cast<int>(wParam);
8341*8af74909SZhong Yang 		InvalidateStyleRedraw();
8342*8af74909SZhong Yang 		break;
8343*8af74909SZhong Yang 
8344*8af74909SZhong Yang 	case SCI_GETADDITIONALSELALPHA:
8345*8af74909SZhong Yang 		return vs.selAdditionalAlpha;
8346*8af74909SZhong Yang 
8347*8af74909SZhong Yang 	case SCI_SETADDITIONALCARETFORE:
8348*8af74909SZhong Yang 		vs.additionalCaretColour = ColourDesired(static_cast<int>(wParam));
8349*8af74909SZhong Yang 		InvalidateStyleRedraw();
8350*8af74909SZhong Yang 		break;
8351*8af74909SZhong Yang 
8352*8af74909SZhong Yang 	case SCI_GETADDITIONALCARETFORE:
8353*8af74909SZhong Yang 		return vs.additionalCaretColour.AsInteger();
8354*8af74909SZhong Yang 
8355*8af74909SZhong Yang 	case SCI_ROTATESELECTION:
8356*8af74909SZhong Yang 		sel.RotateMain();
8357*8af74909SZhong Yang 		InvalidateWholeSelection();
8358*8af74909SZhong Yang 		break;
8359*8af74909SZhong Yang 
8360*8af74909SZhong Yang 	case SCI_SWAPMAINANCHORCARET:
8361*8af74909SZhong Yang 		InvalidateSelection(sel.RangeMain());
8362*8af74909SZhong Yang 		sel.RangeMain().Swap();
8363*8af74909SZhong Yang 		break;
8364*8af74909SZhong Yang 
8365*8af74909SZhong Yang 	case SCI_MULTIPLESELECTADDNEXT:
8366*8af74909SZhong Yang 		MultipleSelectAdd(AddNumber::one);
8367*8af74909SZhong Yang 		break;
8368*8af74909SZhong Yang 
8369*8af74909SZhong Yang 	case SCI_MULTIPLESELECTADDEACH:
8370*8af74909SZhong Yang 		MultipleSelectAdd(AddNumber::each);
8371*8af74909SZhong Yang 		break;
8372*8af74909SZhong Yang 
8373*8af74909SZhong Yang 	case SCI_CHANGELEXERSTATE:
8374*8af74909SZhong Yang 		pdoc->ChangeLexerState(static_cast<Sci::Position>(wParam), lParam);
8375*8af74909SZhong Yang 		break;
8376*8af74909SZhong Yang 
8377*8af74909SZhong Yang 	case SCI_SETIDENTIFIER:
8378*8af74909SZhong Yang 		SetCtrlID(static_cast<int>(wParam));
8379*8af74909SZhong Yang 		break;
8380*8af74909SZhong Yang 
8381*8af74909SZhong Yang 	case SCI_GETIDENTIFIER:
8382*8af74909SZhong Yang 		return GetCtrlID();
8383*8af74909SZhong Yang 
8384*8af74909SZhong Yang 	case SCI_SETTECHNOLOGY:
8385*8af74909SZhong Yang 		// No action by default
8386*8af74909SZhong Yang 		break;
8387*8af74909SZhong Yang 
8388*8af74909SZhong Yang 	case SCI_GETTECHNOLOGY:
8389*8af74909SZhong Yang 		return technology;
8390*8af74909SZhong Yang 
8391*8af74909SZhong Yang 	case SCI_COUNTCHARACTERS:
8392*8af74909SZhong Yang 		return pdoc->CountCharacters(static_cast<Sci::Position>(wParam), lParam);
8393*8af74909SZhong Yang 
8394*8af74909SZhong Yang 	case SCI_COUNTCODEUNITS:
8395*8af74909SZhong Yang 		return pdoc->CountUTF16(static_cast<Sci::Position>(wParam), lParam);
8396*8af74909SZhong Yang 
8397*8af74909SZhong Yang 	default:
8398*8af74909SZhong Yang 		return DefWndProc(iMessage, wParam, lParam);
8399*8af74909SZhong Yang 	}
8400*8af74909SZhong Yang 	//Platform::DebugPrintf("end wnd proc\n");
8401*8af74909SZhong Yang 	return 0;
8402*8af74909SZhong Yang }
8403