diff options
author | Mitchell Foral <unknown> | 2021-10-22 15:58:17 +1100 |
---|---|---|
committer | Mitchell Foral <unknown> | 2021-10-22 15:58:17 +1100 |
commit | 1c2f3fb6ce528add154abce1791d56ce7a94271c (patch) | |
tree | 113769c983cb307b9ba44873b0f9d4fdcaff76ab /src | |
parent | 67759806434b36d47d5f08810854a661f2e992d1 (diff) | |
download | scintilla-mirror-1c2f3fb6ce528add154abce1791d56ce7a94271c.tar.gz |
Add CARETSTYLE_CURSES to draw more than 1 caret on curses terminal.
Diffstat (limited to 'src')
-rw-r--r-- | src/EditView.cxx | 30 | ||||
-rw-r--r-- | src/Editor.cxx | 2 | ||||
-rw-r--r-- | src/PositionCache.cxx | 15 | ||||
-rw-r--r-- | src/ViewStyle.cxx | 18 | ||||
-rw-r--r-- | src/ViewStyle.h | 4 |
5 files changed, 56 insertions, 13 deletions
diff --git a/src/EditView.cxx b/src/EditView.cxx index 762aa8187..30db6fb0d 100644 --- a/src/EditView.cxx +++ b/src/EditView.cxx @@ -1639,7 +1639,7 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt } const bool caretBlinkState = (model.caret.active && model.caret.on) || (!additionalCaretsBlink && !mainCaret); const bool caretVisibleState = additionalCaretsVisible || mainCaret; - if ((xposCaret >= 0) && vsDraw.IsCaretVisible() && + if ((xposCaret >= 0) && vsDraw.IsCaretVisible(mainCaret) && (drawDrag || (caretBlinkState && caretVisibleState))) { bool canDrawBlockCaret = true; bool drawBlockCaret = false; @@ -1663,7 +1663,8 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt if (xposCaret > 0) caretWidthOffset = 0.51f; // Move back so overlaps both character cells. xposCaret += xStart; - const ViewStyle::CaretShape caretShape = drawDrag ? ViewStyle::CaretShape::line : vsDraw.CaretShapeForMode(model.inOverstrike); + const ViewStyle::CaretShape caretShape = drawDrag ? ViewStyle::CaretShape::line : + vsDraw.CaretShapeForMode(model.inOverstrike, mainCaret); if (drawDrag) { /* Dragging text, use a line caret */ rcCaret.left = std::round(xposCaret - caretWidthOffset); @@ -1736,6 +1737,21 @@ static void DrawWrapIndentAndMarker(Surface *surface, const ViewStyle &vsDraw, c } } +// On the curses platform, the terminal is drawing its own caret, so if the caret is within +// the main selection, do not draw the selection at that position. +// Use iDoc from DrawBackground and DrawForeground here because TextSegment has been adjusted +// such that, if the caret is inside the main selection, the beginning or end of that selection +// is at the end of a text segment. +// This function should only be called if iDoc is within the main selection. +static InSelection CharacterInCursesSelection(Sci::Position iDoc, const EditModel &model, const ViewStyle &vsDraw) { + const SelectionPosition &posCaret = model.sel.RangeMain().caret; + const bool caretAtStart = posCaret < model.sel.RangeMain().anchor && posCaret.Position() == iDoc; + const bool caretAtEnd = posCaret > model.sel.RangeMain().anchor && + vsDraw.DrawCaretInsideSelection(false, false) && + model.pdoc->MovePositionOutsideChar(posCaret.Position() - 1, -1) == iDoc; + return (caretAtStart || caretAtEnd) ? InSelection::inNone : InSelection::inMain; +} + void EditView::DrawBackground(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, PRectangle rcLine, Range lineRange, Sci::Position posLineStart, int xStart, int subLine, std::optional<ColourRGBA> background) const { @@ -1746,7 +1762,7 @@ void EditView::DrawBackground(Surface *surface, const EditModel &model, const Vi // Does not take margin into account but not significant const XYPOSITION xStartVisible = static_cast<XYPOSITION>(subLineStart-xStart); - BreakFinder bfBack(ll, &model.sel, lineRange, posLineStart, xStartVisible, selBackDrawn, model.pdoc, &model.reprs, nullptr); + BreakFinder bfBack(ll, &model.sel, lineRange, posLineStart, xStartVisible, selBackDrawn, model.pdoc, &model.reprs, &vsDraw); const bool drawWhitespaceBackground = vsDraw.WhitespaceBackgroundDrawn() && !background; @@ -1769,7 +1785,9 @@ void EditView::DrawBackground(Surface *surface, const EditModel &model, const Vi if (rcSegment.right > rcLine.right) rcSegment.right = rcLine.right; - const InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc); + InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc); + if (FlagSet(vsDraw.caret.style, CaretStyle::Curses) && (inSelection == InSelection::inMain)) + inSelection = CharacterInCursesSelection(iDoc, model, vsDraw); const bool inHotspot = model.hotspot.Valid() && model.hotspot.ContainsCharacter(iDoc); ColourRGBA textBack = TextBackground(model, vsDraw, ll, background, inSelection, inHotspot, ll->styles[i], i); @@ -2013,7 +2031,9 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi } } } - const InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc); + InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc); + if (FlagSet(vsDraw.caret.style, CaretStyle::Curses) && (inSelection == InSelection::inMain)) + inSelection = CharacterInCursesSelection(iDoc, model, vsDraw); const std::optional<ColourRGBA> selectionFore = SelectionForeground(model, vsDraw, inSelection); if (selectionFore) { textFore = *selectionFore; diff --git a/src/Editor.cxx b/src/Editor.cxx index 485eaef87..ce5a70ce5 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -7592,7 +7592,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { return vs.ElementColour(Element::Caret)->OpaqueRGB(); case Message::SetCaretStyle: - if (static_cast<CaretStyle>(wParam) <= (CaretStyle::Block | CaretStyle::OverstrikeBlock | CaretStyle::BlockAfter)) + if (static_cast<CaretStyle>(wParam) <= (CaretStyle::Block | CaretStyle::OverstrikeBlock | CaretStyle::Curses | CaretStyle::BlockAfter)) vs.caret.style = static_cast<CaretStyle>(wParam); else /* Default to the line caret */ diff --git a/src/PositionCache.cxx b/src/PositionCache.cxx index 13e4ab2b2..587ffdd3b 100644 --- a/src/PositionCache.cxx +++ b/src/PositionCache.cxx @@ -696,6 +696,21 @@ BreakFinder::BreakFinder(const LineLayout *ll_, const Selection *psel, Range lin Insert(portion.end.Position() - posLineStart); } } + // On the curses platform, the terminal is drawing its own caret, so add breaks around the + // caret in the main selection in order to help prevent the selection from being drawn in + // the caret's cell. + if (pvsDraw && FlagSet(pvsDraw->caret.style, CaretStyle::Curses) && !psel->RangeMain().Empty()) { + const Sci::Position caretPos = psel->RangeMain().caret.Position(); + const Sci::Position anchorPos = psel->RangeMain().anchor.Position(); + if (caretPos < anchorPos) { + const Sci::Position nextPos = pdoc->MovePositionOutsideChar(caretPos + 1, 1); + Insert(nextPos - posLineStart); + } else if (caretPos > anchorPos && pvsDraw->DrawCaretInsideSelection(false, false)) { + const Sci::Position prevPos = pdoc->MovePositionOutsideChar(caretPos - 1, -1); + if (prevPos > anchorPos) + Insert(prevPos - posLineStart); + } + } } if (pvsDraw && pvsDraw->indicatorsSetFore) { for (const IDecoration *deco : pdoc->decorations->View()) { diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx index 5273841ed..1458ea96f 100644 --- a/src/ViewStyle.cxx +++ b/src/ViewStyle.cxx @@ -661,11 +661,14 @@ bool ViewStyle::SetWrapIndentMode(WrapIndentMode wrapIndentMode_) noexcept { bool ViewStyle::IsBlockCaretStyle() const noexcept { return ((caret.style & CaretStyle::InsMask) == CaretStyle::Block) || - FlagSet(caret.style, CaretStyle::OverstrikeBlock); + FlagSet(caret.style, CaretStyle::OverstrikeBlock) || + FlagSet(caret.style, CaretStyle::Curses); } -bool ViewStyle::IsCaretVisible() const noexcept { - return caret.width > 0 && caret.style != CaretStyle::Invisible; +bool ViewStyle::IsCaretVisible(bool isMainSelection) const noexcept { + return caret.width > 0 && + ((caret.style & CaretStyle::InsMask) != CaretStyle::Invisible || + (FlagSet(caret.style, CaretStyle::Curses) && !isMainSelection)); // only draw additional selections in curses mode } bool ViewStyle::DrawCaretInsideSelection(bool inOverstrike, bool imeCaretBlockOverride) const noexcept { @@ -673,14 +676,19 @@ bool ViewStyle::DrawCaretInsideSelection(bool inOverstrike, bool imeCaretBlockOv return false; return ((caret.style & CaretStyle::InsMask) == CaretStyle::Block) || (inOverstrike && FlagSet(caret.style, CaretStyle::OverstrikeBlock)) || - imeCaretBlockOverride; + imeCaretBlockOverride || + FlagSet(caret.style, CaretStyle::Curses); } -ViewStyle::CaretShape ViewStyle::CaretShapeForMode(bool inOverstrike) const noexcept { +ViewStyle::CaretShape ViewStyle::CaretShapeForMode(bool inOverstrike, bool isMainSelection) const noexcept { if (inOverstrike) { return (FlagSet(caret.style, CaretStyle::OverstrikeBlock)) ? CaretShape::block : CaretShape::bar; } + if (FlagSet(caret.style, CaretStyle::Curses) && !isMainSelection) { + return CaretShape::block; + } + const CaretStyle caretStyle = caret.style & CaretStyle::InsMask; return (caretStyle <= CaretStyle::Block) ? static_cast<CaretShape>(caretStyle) : CaretShape::line; } diff --git a/src/ViewStyle.h b/src/ViewStyle.h index de56c0895..f799c4943 100644 --- a/src/ViewStyle.h +++ b/src/ViewStyle.h @@ -235,9 +235,9 @@ public: enum class CaretShape { invisible, line, block, bar }; bool IsBlockCaretStyle() const noexcept; - bool IsCaretVisible() const noexcept; + bool IsCaretVisible(bool isMainSelection) const noexcept; bool DrawCaretInsideSelection(bool inOverstrike, bool imeCaretBlockOverride) const noexcept; - CaretShape CaretShapeForMode(bool inOverstrike) const noexcept; + CaretShape CaretShapeForMode(bool inOverstrike, bool isMainSelection) const noexcept; private: void AllocStyles(size_t sizeNew); |