diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Editor.cxx | 58 | ||||
| -rw-r--r-- | src/Editor.h | 11 | 
2 files changed, 58 insertions, 11 deletions
| diff --git a/src/Editor.cxx b/src/Editor.cxx index 98d98d38f..d02f095cb 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -962,7 +962,8 @@ int Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt, b  		// In case in need of wrapping to ensure DisplayFromDoc works.  		if (currentLine >= wrapStart)  			WrapLines(true, -1); -		XYScrollPosition newXY = XYScrollToMakeVisible(true, true, true); +		XYScrollPosition newXY = XYScrollToMakeVisible( +			SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret), xysDefault);  		if (simpleCaret && (newXY.xOffset == xOffset)) {  			// simple vertical scroll then invalidate  			ScrollTo(newXY.topLine); @@ -1233,19 +1234,20 @@ 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 bool useMargin, const bool vert, const bool horiz) { +Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange range, const XYScrollOptions options) {  	PRectangle rcClient = GetTextRectangle(); -	const SelectionPosition posCaret = posDrag.IsValid() ? posDrag : sel.RangeMain().caret; -	Point pt = LocationFromPosition(posCaret); +	Point pt = LocationFromPosition(range.caret); +	Point ptAnchor = LocationFromPosition(range.anchor);  	const Point ptOrigin = GetVisibleOriginInMain();  	pt.x += ptOrigin.x; +	ptAnchor.x += ptOrigin.x;  	const Point ptBottomCaret(pt.x, pt.y + vs.lineHeight - 1); -	const int lineCaret = DisplayFromPosition(posCaret.Position());  	XYScrollPosition newXY(xOffset, topLine);  	// Vertical positioning -	if (vert && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) { +	if ((options & xysVertical) && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) { +		const int lineCaret = DisplayFromPosition(range.caret.Position());  		const int linesOnScreen = LinesOnScreen();  		const int halfScreen = Platform::Maximum(linesOnScreen - 1, 2) / 2;  		const bool bSlop = (caretYPolicy & CARET_SLOP) != 0; @@ -1259,7 +1261,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, con  			int yMoveT, yMoveB;  			if (bStrict) {  				int yMarginT, yMarginB; -				if (!useMargin) { +				if (!(options & xysUseMargin)) {  					// In drag mode, avoid moves  					// otherwise, a double click will select several lines.  					yMarginT = yMarginB = 0; @@ -1329,11 +1331,23 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, con  				}  			}  		} +		if (!(range.caret == range.anchor)) { +			const int lineAnchor = DisplayFromPosition(range.anchor.Position()); +			if (lineAnchor < lineCaret) { +				// Shift up to show anchor or as much of range as possible +				newXY.topLine = std::min(newXY.topLine, lineAnchor); +				newXY.topLine = std::max(newXY.topLine, lineCaret - LinesOnScreen()); +			} else { +				// Shift down to show anchor or as much of range as possible +				newXY.topLine = std::max(newXY.topLine, lineAnchor - LinesOnScreen()); +				newXY.topLine = std::min(newXY.topLine, lineCaret); +			} +		}  		newXY.topLine = Platform::Clamp(newXY.topLine, 0, MaxScrollPos());  	}  	// Horizontal positioning -	if (horiz && (wrapState == eWrapNone)) { +	if ((options & xysHorizontal) && (wrapState == eWrapNone)) {  		const int halfScreen = Platform::Maximum(rcClient.Width() - 4, 4) / 2;  		const bool bSlop = (caretXPolicy & CARET_SLOP) != 0;  		const bool bStrict = (caretXPolicy & CARET_STRICT) != 0; @@ -1344,7 +1358,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, con  			int xMoveL, xMoveR;  			if (bStrict) {  				int xMarginL, xMarginR; -				if (!useMargin) { +				if (!(options & xysUseMargin)) {  					// In drag mode, avoid moves unless very near of the margin  					// otherwise, a simple click will select text.  					xMarginL = xMarginR = 2; @@ -1433,6 +1447,21 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, con  				newXY.xOffset += static_cast<int>(vs.aveCharWidth);  			}  		} +		if (!(range.caret == range.anchor)) { +			if (ptAnchor.x < pt.x) { +				// Shift to left to show anchor or as much of range as possible +				int maxOffset = ptAnchor.x + xOffset - rcClient.left - 1; +				int minOffset = pt.x + xOffset - rcClient.right + 1; +				newXY.xOffset = std::min(newXY.xOffset, maxOffset); +				newXY.xOffset = std::max(newXY.xOffset, minOffset); +			} else { +				// Shift to right to show anchor or as much of range as possible +				int minOffset = ptAnchor.x + xOffset - rcClient.right + 1; +				int maxOffset = pt.x + xOffset - rcClient.left - 1; +				newXY.xOffset = std::max(newXY.xOffset, minOffset); +				newXY.xOffset = std::min(newXY.xOffset, maxOffset); +			} +		}  		if (newXY.xOffset < 0) {  			newXY.xOffset = 0;  		} @@ -1465,8 +1494,13 @@ void Editor::SetXYScroll(XYScrollPosition newXY) {  	}  } +void Editor::ScrollRange(SelectionRange range) { +	SetXYScroll(XYScrollToMakeVisible(range, xysDefault)); +} +  void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { -	SetXYScroll(XYScrollToMakeVisible(useMargin, vert, horiz)); +	SetXYScroll(XYScrollToMakeVisible(SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret), +		static_cast<XYScrollOptions>((useMargin?xysUseMargin:0)|(vert?xysVertical:0)|(horiz?xysHorizontal:0))));  }  void Editor::ShowCaretAtCurrentPosition() { @@ -8525,6 +8559,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {  		EnsureLineVisible(wParam, true);  		break; +	case SCI_SCROLLRANGE:  +		ScrollRange(SelectionRange(lParam, wParam)); +		break; +  	case SCI_SEARCHANCHOR:  		SearchAnchor();  		break; diff --git a/src/Editor.h b/src/Editor.h index 91cbd59a4..f2b452a77 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -381,10 +381,19 @@ protected:	// ScintillaBase subclass needs access to much of Editor  		int xOffset;  		int topLine;  		XYScrollPosition(int xOffset_, int topLine_) : xOffset(xOffset_), topLine(topLine_) {} +		bool operator==(const XYScrollPosition &other) const { +			return (xOffset == other.xOffset) && (topLine == other.topLine); +		}  	}; -	XYScrollPosition XYScrollToMakeVisible(const bool useMargin, const bool vert, const bool horiz); +	enum XYScrollOptions { +		xysUseMargin=0x1, +		xysVertical=0x2, +		xysHorizontal=0x4, +		xysDefault=xysUseMargin|xysVertical|xysHorizontal}; +	XYScrollPosition XYScrollToMakeVisible(const SelectionRange range, const XYScrollOptions options);  	void SetXYScroll(XYScrollPosition newXY);  	void EnsureCaretVisible(bool useMargin=true, bool vert=true, bool horiz=true); +	void ScrollRange(SelectionRange range);  	void ShowCaretAtCurrentPosition();  	void DropCaret();  	void InvalidateCaret(); | 
