aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--doc/ScintillaDoc.html9
-rw-r--r--include/Scintilla.h1
-rw-r--r--include/Scintilla.iface5
-rw-r--r--src/Editor.cxx58
-rw-r--r--src/Editor.h11
5 files changed, 73 insertions, 11 deletions
diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html
index 7e362ffb9..cfa13bfdc 100644
--- a/doc/ScintillaDoc.html
+++ b/doc/ScintillaDoc.html
@@ -1730,6 +1730,7 @@ struct Sci_TextToFind {
<h2 id="ScrollingAndAutomaticScrolling">Scrolling and automatic scrolling</h2>
<code><a class="message" href="#SCI_LINESCROLL">SCI_LINESCROLL(int column, int line)</a><br />
<a class="message" href="#SCI_SCROLLCARET">SCI_SCROLLCARET</a><br />
+ <a class="message" href="#SCI_SCROLLRANGE">SCI_SCROLLRANGE(int secondary, int primary)</a><br />
<a class="message" href="#SCI_SETXCARETPOLICY">SCI_SETXCARETPOLICY(int caretPolicy, int
caretSlop)</a><br />
<a class="message" href="#SCI_SETYCARETPOLICY">SCI_SETYCARETPOLICY(int caretPolicy, int
@@ -1766,6 +1767,14 @@ struct Sci_TextToFind {
If the current position (this is the caret if there is no selection) is not visible, the view
is scrolled to make it visible according to the current caret policy.</p>
+ <p><b id="SCI_SCROLLRANGE">SCI_SCROLLRANGE(int secondary, int primary)</b><br />
+ Scroll the argument positions and the range between them into view giving
+ priority to the primary position then the secondary position.
+ The behaviour is similar to <a class="message" href="#SCI_SCROLLCARET"><code>SCI_SCROLLCARET</code></a>
+ with the primary position used instead of the caret. An effort is then made to ensure that the secondary
+ position and range between are also visible.
+ This may be used to make a search match visible.</p>
+
<p><b id="SCI_SETXCARETPOLICY">SCI_SETXCARETPOLICY(int caretPolicy, int caretSlop)</b><br />
<b id="SCI_SETYCARETPOLICY">SCI_SETYCARETPOLICY(int caretPolicy, int caretSlop)</b><br />
These set the caret policy. The value of <code>caretPolicy</code> is a combination of
diff --git a/include/Scintilla.h b/include/Scintilla.h
index 15a86682e..48c7ff379 100644
--- a/include/Scintilla.h
+++ b/include/Scintilla.h
@@ -382,6 +382,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_POSITIONFROMLINE 2167
#define SCI_LINESCROLL 2168
#define SCI_SCROLLCARET 2169
+#define SCI_SCROLLRANGE 2569
#define SCI_REPLACESEL 2170
#define SCI_SETREADONLY 2171
#define SCI_NULL 2172
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index 670d3937f..496f472ae 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -924,6 +924,11 @@ fun void LineScroll=2168(int columns, int lines)
# Ensure the caret is visible.
fun void ScrollCaret=2169(,)
+# Scroll the argument positions and the range between them into view giving
+# priority to the primary position then the secondary position.
+# This may be used to make a search match visible.
+fun void ScrollRange=2569(position secondary, position primary)
+
# Replace the selected text with the argument text.
fun void ReplaceSel=2170(, string text)
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();