diff options
Diffstat (limited to 'src')
-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); |