aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2020-02-27 11:14:46 +1100
committerNeil <nyamatongwe@gmail.com>2020-02-27 11:14:46 +1100
commit95ecd4d0e34290dbd054a8710a255a9e93347c5f (patch)
tree8ebfeb3283ffedcc199e0c1e70c1d2d24d741ce3
parent0a648064cf4d88f6252aa880a0832d39a5331148 (diff)
downloadscintilla-mirror-95ecd4d0e34290dbd054a8710a255a9e93347c5f.tar.gz
Feature [feature-requests:497] Structure caret policy data and pass policy for
dragging instead of manipulating global state..
-rw-r--r--src/Editor.cxx112
-rw-r--r--src/Editor.h27
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);