diff options
| -rw-r--r-- | src/Editor.cxx | 112 | ||||
| -rw-r--r-- | src/Editor.h | 27 | 
2 files changed, 68 insertions, 71 deletions
| diff --git a/src/Editor.cxx b/src/Editor.cxx index 8f80ef716..d8d231911 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -143,14 +143,10 @@ Editor::Editor() : durationWrapOneLine(0.00001, 0.000001, 0.0001) {  	wordSelectAnchorEndPos = 0;  	wordSelectInitialCaretPos = -1; -	caretXPolicy = CARET_SLOP | CARET_EVEN; -	caretXSlop = 50; +	caretPolicies.x = { CARET_SLOP | CARET_EVEN, 50 }; +	caretPolicies.y = { CARET_EVEN, 0 }; -	caretYPolicy = CARET_EVEN; -	caretYSlop = 0; - -	visiblePolicy = 0; -	visibleSlop = 0; +	visiblePolicy = { 0, 0 };  	searchAnchor = 0; @@ -847,7 +843,8 @@ SelectionPosition Editor::MovePositionOutsideChar(SelectionPosition pos, Sci::Po  	return pos;  } -void Editor::MovedCaret(SelectionPosition newPos, SelectionPosition previousPos, bool ensureVisible) { +void Editor::MovedCaret(SelectionPosition newPos, SelectionPosition previousPos, +	bool ensureVisible, CaretPolicies policies) {  	const Sci::Line currentLine = pdoc->SciLineFromPosition(newPos.Position());  	if (ensureVisible) {  		// In case in need of wrapping to ensure DisplayFromDoc works. @@ -857,7 +854,7 @@ void Editor::MovedCaret(SelectionPosition newPos, SelectionPosition previousPos,  			}  		}  		const XYScrollPosition newXY = XYScrollToMakeVisible( -			SelectionRange(posDrag.IsValid() ? posDrag : newPos), xysDefault); +			SelectionRange(posDrag.IsValid() ? posDrag : newPos), xysDefault, policies);  		if (previousPos.IsValid() && (newXY.xOffset == xOffset)) {  			// simple vertical scroll then invalidate  			ScrollTo(newXY.topLine); @@ -907,7 +904,7 @@ void Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt,  		SetEmptySelection(newPos);  	} -	MovedCaret(newPos, spCaret, ensureVisible); +	MovedCaret(newPos, spCaret, ensureVisible, caretPolicies);  }  void Editor::MovePositionTo(Sci::Position newPos, Selection::selTypes selt, bool ensureVisible) { @@ -1108,7 +1105,7 @@ Sci::Line Editor::DisplayFromPosition(Sci::Position pos) {  /**   * Ensure the caret is reasonably visible in context.   * -Caret policy in SciTE +Caret policy in Scintilla  If slop is set, we can define a slop value.  This value defines an unwanted zone (UZ) where the caret is... unwanted. @@ -1151,7 +1148,8 @@ slop | strict | jumps | even | Caret can go to the margin                 | When    1  |   1    |   1   |   1  | No, kept out of UZ                         | moved to put caret at 3UZ of the margin  */ -Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &range, const XYScrollOptions options) { +Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &range, +	const XYScrollOptions options, CaretPolicies policies) {  	const PRectangle rcClient = GetTextRectangle();  	const Point ptOrigin = GetVisibleOriginInMain();  	const Point pt = LocationFromPosition(range.caret) + ptOrigin; @@ -1164,14 +1162,14 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &ran  	}  	// Vertical positioning -	if ((options & xysVertical) && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) { +	if ((options & xysVertical) && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (policies.y.policy & CARET_STRICT) != 0)) {  		const Sci::Line lineCaret = DisplayFromPosition(range.caret.Position());  		const Sci::Line linesOnScreen = LinesOnScreen();  		const Sci::Line halfScreen = std::max(linesOnScreen - 1, static_cast<Sci::Line>(2)) / 2; -		const bool bSlop = (caretYPolicy & CARET_SLOP) != 0; -		const bool bStrict = (caretYPolicy & CARET_STRICT) != 0; -		const bool bJump = (caretYPolicy & CARET_JUMPS) != 0; -		const bool bEven = (caretYPolicy & CARET_EVEN) != 0; +		const bool bSlop = (policies.y.policy & CARET_SLOP) != 0; +		const bool bStrict = (policies.y.policy & CARET_STRICT) != 0; +		const bool bJump = (policies.y.policy & CARET_JUMPS) != 0; +		const bool bEven = (policies.y.policy & CARET_EVEN) != 0;  		// It should be possible to scroll the window to show the caret,  		// but this fails to remove the caret on GTK+ @@ -1186,7 +1184,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &ran  				} else {  					// yMarginT must equal to caretYSlop, with a minimum of 1 and  					// a maximum of slightly less than half the heigth of the text area. -					yMarginT = std::clamp<Sci::Line>(caretYSlop, 1, halfScreen); +					yMarginT = std::clamp<Sci::Line>(policies.y.slop, 1, halfScreen);  					if (bEven) {  						yMarginB = yMarginT;  					} else { @@ -1196,7 +1194,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &ran  				yMoveT = yMarginT;  				if (bEven) {  					if (bJump) { -						yMoveT = std::clamp<Sci::Line>(caretYSlop * 3, 1, halfScreen); +						yMoveT = std::clamp<Sci::Line>(policies.y.slop * 3, 1, halfScreen);  					}  					yMoveB = yMoveT;  				} else { @@ -1210,7 +1208,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &ran  					newXY.topLine = lineCaret - linesOnScreen + 1 + yMoveB;  				}  			} else {	// Not strict -				yMoveT = bJump ? caretYSlop * 3 : caretYSlop; +				yMoveT = bJump ? policies.y.slop * 3 : policies.y.slop;  				yMoveT = std::clamp<Sci::Line>(yMoveT, 1, halfScreen);  				if (bEven) {  					yMoveB = yMoveT; @@ -1267,10 +1265,10 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &ran  	// Horizontal positioning  	if ((options & xysHorizontal) && !Wrapping()) {  		const int halfScreen = std::max(static_cast<int>(rcClient.Width()) - 4, 4) / 2; -		const bool bSlop = (caretXPolicy & CARET_SLOP) != 0; -		const bool bStrict = (caretXPolicy & CARET_STRICT) != 0; -		const bool bJump = (caretXPolicy & CARET_JUMPS) != 0; -		const bool bEven = (caretXPolicy & CARET_EVEN) != 0; +		const bool bSlop = (policies.x.policy & CARET_SLOP) != 0; +		const bool bStrict = (policies.x.policy & CARET_STRICT) != 0; +		const bool bJump = (policies.x.policy & CARET_JUMPS) != 0; +		const bool bEven = (policies.x.policy & CARET_EVEN) != 0;  		if (bSlop) {	// A margin is defined  			int xMoveL, xMoveR; @@ -1283,7 +1281,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &ran  				} else {  					// xMargin must equal to caretXSlop, with a minimum of 2 and  					// a maximum of slightly less than half the width of the text area. -					xMarginR = std::clamp(caretXSlop, 2, halfScreen); +					xMarginR = std::clamp(policies.x.slop, 2, halfScreen);  					if (bEven) {  						xMarginL = xMarginR;  					} else { @@ -1292,7 +1290,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &ran  				}  				if (bJump && bEven) {  					// Jump is used only in even mode -					xMoveL = xMoveR = std::clamp(caretXSlop * 3, 1, halfScreen); +					xMoveL = xMoveR = std::clamp(policies.x.slop * 3, 1, halfScreen);  				} else {  					xMoveL = xMoveR = 0;	// Not used, avoid a warning  				} @@ -1314,7 +1312,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &ran  					}  				}  			} else {	// Not strict -				xMoveR = bJump ? caretXSlop * 3 : caretXSlop; +				xMoveR = bJump ? policies.x.slop * 3 : policies.x.slop;  				xMoveR = std::clamp(xMoveR, 1, halfScreen);  				if (bEven) {  					xMoveL = xMoveR; @@ -1413,12 +1411,13 @@ void Editor::SetXYScroll(XYScrollPosition newXY) {  }  void Editor::ScrollRange(SelectionRange range) { -	SetXYScroll(XYScrollToMakeVisible(range, xysDefault)); +	SetXYScroll(XYScrollToMakeVisible(range, xysDefault, caretPolicies));  }  void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) {  	SetXYScroll(XYScrollToMakeVisible(SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret), -		static_cast<XYScrollOptions>((useMargin?xysUseMargin:0)|(vert?xysVertical:0)|(horiz?xysHorizontal:0)))); +		static_cast<XYScrollOptions>((useMargin?xysUseMargin:0)|(vert?xysVertical:0)|(horiz?xysHorizontal:0)), +		caretPolicies));  }  void Editor::ShowCaretAtCurrentPosition() { @@ -2889,20 +2888,20 @@ void Editor::PageMove(int direction, Selection::selTypes selt, bool stuttered) {  	SelectionPosition newPos;  	const Sci::Line currentLine = pdoc->SciLineFromPosition(sel.MainCaret()); -	const Sci::Line topStutterLine = topLine + caretYSlop; +	const Sci::Line topStutterLine = topLine + caretPolicies.y.slop;  	const Sci::Line bottomStutterLine =  	    pdoc->SciLineFromPosition(PositionFromLocation(  	                Point::FromInts(lastXChosen - xOffset, direction * vs.lineHeight * static_cast<int>(LinesToScroll())))) -	    - caretYSlop - 1; +	    - caretPolicies.y.slop - 1;  	if (stuttered && (direction < 0 && currentLine > topStutterLine)) {  		topLineNew = topLine; -		newPos = SPositionFromLocation(Point::FromInts(lastXChosen - xOffset, vs.lineHeight * caretYSlop), +		newPos = SPositionFromLocation(Point::FromInts(lastXChosen - xOffset, vs.lineHeight * caretPolicies.y.slop),  			false, false, UserVirtualSpace());  	} else if (stuttered && (direction > 0 && currentLine < bottomStutterLine)) {  		topLineNew = topLine; -		newPos = SPositionFromLocation(Point::FromInts(lastXChosen - xOffset, vs.lineHeight * static_cast<int>(LinesToScroll() - caretYSlop)), +		newPos = SPositionFromLocation(Point::FromInts(lastXChosen - xOffset, vs.lineHeight * static_cast<int>(LinesToScroll() - caretPolicies.y.slop)),  			false, false, UserVirtualSpace());  	} else { @@ -3189,7 +3188,7 @@ void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) {  		sel.selType = Selection::selRectangle;  		sel.Rectangular() = SelectionRange(posNew, rangeBase.anchor);  		SetRectangularRange(); -		MovedCaret(posNew, caretToUse, true); +		MovedCaret(posNew, caretToUse, true, caretPolicies);  	} else if (sel.selType == Selection::selLines && sel.MoveExtends()) {  		// Calculate new caret position and call SetSelection(), which will ensure whole lines are selected.  		const SelectionPosition posNew = MovePositionSoVisible( @@ -3210,7 +3209,7 @@ void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) {  				SelectionRange(posNew, sel.Range(r).anchor) : SelectionRange(posNew);  		}  		sel.RemoveDuplicates(); -		MovedCaret(sel.RangeMain().caret, caretToUse, true); +		MovedCaret(sel.RangeMain().caret, caretToUse, true, caretPolicies);  	}  } @@ -3607,7 +3606,7 @@ int Editor::HorizontalMove(unsigned int iMessage) {  	sel.RemoveDuplicates(); -	MovedCaret(sel.RangeMain().caret, SelectionPosition(INVALID_POSITION), true); +	MovedCaret(sel.RangeMain().caret, SelectionPosition(INVALID_POSITION), true, caretPolicies);  	// Invalidate the new state of the selection  	InvalidateWholeSelection(); @@ -3678,7 +3677,7 @@ int Editor::DelWordOrLine(unsigned int iMessage) {  	// May need something stronger here: can selections overlap at this point?  	sel.RemoveDuplicates(); -	MovedCaret(sel.RangeMain().caret, SelectionPosition(INVALID_POSITION), true); +	MovedCaret(sel.RangeMain().caret, SelectionPosition(INVALID_POSITION), true, caretPolicies);  	// Invalidate the new state of the selection  	InvalidateWholeSelection(); @@ -4261,19 +4260,11 @@ void Editor::SetDragPosition(SelectionPosition newPos) {  		posDrop = newPos;  	}  	if (!(posDrag == newPos)) { -		const int oldCaretYPolicy = caretYPolicy; -		const int oldCaretYSlop = caretYSlop; -		const int oldCaretXPolicy = caretXPolicy; -		const int oldCaretXSlop = caretXSlop; -		caretYPolicy = CARET_SLOP | CARET_STRICT | CARET_EVEN; -		caretYSlop = 2; -		caretXPolicy = CARET_SLOP | CARET_STRICT | CARET_EVEN; -		caretXSlop = 50; -		MovedCaret(newPos, posDrag, true); -		caretYPolicy = oldCaretYPolicy; -		caretYSlop = oldCaretYSlop; -		caretXPolicy = oldCaretXPolicy; -		caretXSlop = oldCaretXSlop; +		const CaretPolicies dragCaretPolicies = { +			CaretPolicy(CARET_SLOP | CARET_STRICT | CARET_EVEN, 50), +			CaretPolicy(CARET_SLOP | CARET_STRICT | CARET_EVEN, 2) +		}; +		MovedCaret(newPos, posDrag, true, dragCaretPolicies);  		caret.on = true;  		FineTickerCancel(tickCaret); @@ -5454,19 +5445,19 @@ void Editor::EnsureLineVisible(Sci::Line lineDoc, bool enforcePolicy) {  	}  	if (enforcePolicy) {  		const Sci::Line lineDisplay = pcs->DisplayFromDoc(lineDoc); -		if (visiblePolicy & VISIBLE_SLOP) { -			if ((topLine > lineDisplay) || ((visiblePolicy & VISIBLE_STRICT) && (topLine + visibleSlop > lineDisplay))) { -				SetTopLine(std::clamp<Sci::Line>(lineDisplay - visibleSlop, 0, MaxScrollPos())); +		if (visiblePolicy.policy & VISIBLE_SLOP) { +			if ((topLine > lineDisplay) || ((visiblePolicy.policy & VISIBLE_STRICT) && (topLine + visiblePolicy.slop > lineDisplay))) { +				SetTopLine(std::clamp<Sci::Line>(lineDisplay - visiblePolicy.slop, 0, MaxScrollPos()));  				SetVerticalScrollPos();  				Redraw();  			} else if ((lineDisplay > topLine + LinesOnScreen() - 1) || -			        ((visiblePolicy & VISIBLE_STRICT) && (lineDisplay > topLine + LinesOnScreen() - 1 - visibleSlop))) { -				SetTopLine(std::clamp<Sci::Line>(lineDisplay - LinesOnScreen() + 1 + visibleSlop, 0, MaxScrollPos())); +			        ((visiblePolicy.policy & VISIBLE_STRICT) && (lineDisplay > topLine + LinesOnScreen() - 1 - visiblePolicy.slop))) { +				SetTopLine(std::clamp<Sci::Line>(lineDisplay - LinesOnScreen() + 1 + visiblePolicy.slop, 0, MaxScrollPos()));  				SetVerticalScrollPos();  				Redraw();  			}  		} else { -			if ((topLine > lineDisplay) || (lineDisplay > topLine + LinesOnScreen() - 1) || (visiblePolicy & VISIBLE_STRICT)) { +			if ((topLine > lineDisplay) || (lineDisplay > topLine + LinesOnScreen() - 1) || (visiblePolicy.policy & VISIBLE_STRICT)) {  				SetTopLine(std::clamp<Sci::Line>(lineDisplay - LinesOnScreen() / 2 + 1, 0, MaxScrollPos()));  				SetVerticalScrollPos();  				Redraw(); @@ -7305,18 +7296,15 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {  		return SearchText(iMessage, wParam, lParam);  	case SCI_SETXCARETPOLICY: -		caretXPolicy = static_cast<int>(wParam); -		caretXSlop = static_cast<int>(lParam); +		caretPolicies.x = CaretPolicy(wParam, lParam);  		break;  	case SCI_SETYCARETPOLICY: -		caretYPolicy = static_cast<int>(wParam); -		caretYSlop = static_cast<int>(lParam); +		caretPolicies.y = CaretPolicy(wParam, lParam);  		break;  	case SCI_SETVISIBLEPOLICY: -		visiblePolicy = static_cast<int>(wParam); -		visibleSlop = static_cast<int>(lParam); +		visiblePolicy = CaretPolicy(wParam, lParam);  		break;  	case SCI_LINESONSCREEN: diff --git a/src/Editor.h b/src/Editor.h index 69f8ef4ca..374639d4c 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -143,6 +143,18 @@ struct WrapPending {  	}  }; +struct CaretPolicy { +	int policy;	// Combination from CARET_SLOP, CARET_STRICT, CARET_JUMPS, CARET_EVEN +	int slop;	// Pixels for X, lines for Y +	CaretPolicy(uptr_t policy_=0, sptr_t slop_=0) noexcept : +		policy(static_cast<int>(policy_)), slop(static_cast<int>(slop_)) {} +}; + +struct CaretPolicies { +	CaretPolicy x; +	CaretPolicy y; +}; +  /**   */  class Editor : public EditModel, public DocWatcher { @@ -232,14 +244,9 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	SelectionText drag; -	int caretXPolicy; -	int caretXSlop;	///< Ensure this many pixels visible on both sides of caret - -	int caretYPolicy; -	int caretYSlop;	///< Ensure this many lines visible on both sides of caret +	CaretPolicies caretPolicies; -	int visiblePolicy; -	int visibleSlop; +	CaretPolicy visiblePolicy;  	Sci::Position searchAnchor; @@ -325,7 +332,8 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	bool SelectionContainsProtected();  	Sci::Position MovePositionOutsideChar(Sci::Position pos, Sci::Position moveDir, bool checkLineEnd=true) const;  	SelectionPosition MovePositionOutsideChar(SelectionPosition pos, Sci::Position moveDir, bool checkLineEnd=true) const; -	void MovedCaret(SelectionPosition newPos, SelectionPosition previousPos, bool ensureVisible); +	void MovedCaret(SelectionPosition newPos, SelectionPosition previousPos, +		bool ensureVisible, CaretPolicies policies);  	void MovePositionTo(SelectionPosition newPos, Selection::selTypes selt=Selection::noSel, bool ensureVisible=true);  	void MovePositionTo(Sci::Position newPos, Selection::selTypes selt=Selection::noSel, bool ensureVisible=true);  	SelectionPosition MovePositionSoVisible(SelectionPosition pos, int moveDir); @@ -356,7 +364,8 @@ protected:	// ScintillaBase subclass needs access to much of Editor  		xysVertical=0x2,  		xysHorizontal=0x4,  		xysDefault=xysUseMargin|xysVertical|xysHorizontal}; -	XYScrollPosition XYScrollToMakeVisible(const SelectionRange &range, const XYScrollOptions options); +	XYScrollPosition XYScrollToMakeVisible(const SelectionRange &range, +		const XYScrollOptions options, CaretPolicies policies);  	void SetXYScroll(XYScrollPosition newXY);  	void EnsureCaretVisible(bool useMargin=true, bool vert=true, bool horiz=true);  	void ScrollRange(SelectionRange range); | 
