aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/EditView.cxx31
-rw-r--r--src/Editor.cxx2
-rw-r--r--src/PositionCache.cxx36
-rw-r--r--src/ViewStyle.cxx22
-rw-r--r--src/ViewStyle.h5
5 files changed, 79 insertions, 17 deletions
diff --git a/src/EditView.cxx b/src/EditView.cxx
index 3ab4c17a5..e0f52f501 100644
--- a/src/EditView.cxx
+++ b/src/EditView.cxx
@@ -1636,7 +1636,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;
@@ -1660,7 +1660,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);
@@ -1733,6 +1734,22 @@ 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 PositionCache
+// has broken up the line 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 {
@@ -1743,7 +1760,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;
@@ -1766,7 +1783,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 (vsDraw.IsMainCursesCaret(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);
@@ -2010,7 +2029,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 (vsDraw.IsMainCursesCaret(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 06d96134f..dc3cf6caf 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 6eee26113..07507a7fa 100644
--- a/src/PositionCache.cxx
+++ b/src/PositionCache.cxx
@@ -690,10 +690,38 @@ BreakFinder::BreakFinder(const LineLayout *ll_, const Selection *psel, Range lin
for (size_t r=0; r<psel->Count(); r++) {
const SelectionSegment portion = psel->Range(r).Intersect(segmentLine);
if (!(portion.start == portion.end)) {
- if (portion.start.IsValid())
- Insert(portion.start.Position() - posLineStart);
- if (portion.end.IsValid())
- Insert(portion.end.Position() - posLineStart);
+ if (portion.start.IsValid()) {
+ const bool skipFirstSelectedCharacter = pvsDraw && pvsDraw->IsMainCursesCaret(r == 0) &&
+ psel->Range(r).caret < psel->Range(r).anchor;
+ if (!skipFirstSelectedCharacter) {
+ Insert(portion.start.Position() - posLineStart);
+ } else {
+ // On the curses platform, the terminal is drawing its own caret, so
+ // make sure the main selection is not drawn on its first character
+ // if the caret is currently on it.
+ // While the caret is still inside the selection, it will be at the
+ // end of this text segment (instead of the beginning of the next
+ // one), so testing against this condition allows it to be drawn
+ // as not selected.
+ const Sci::Position next = pdoc->MovePositionOutsideChar(portion.start.Position()+1, 1);
+ Insert(next - posLineStart);
+ }
+ }
+ if (portion.end.IsValid()) {
+ const bool skipLastSelectedCharacter = pvsDraw && pvsDraw->IsMainCursesCaret(r == 0) &&
+ psel->Range(r).caret > psel->Range(r).anchor && pvsDraw->DrawCaretInsideSelection(false, false);
+ if (!skipLastSelectedCharacter) {
+ Insert(portion.end.Position() - posLineStart);
+ } else {
+ // On the curses platform, the terminal is drawing its own caret, so
+ // make sure the main selection is not drawn on its last character
+ // if the caret is currently on it. The caret will be its own text
+ // segment and at the end of said segment, so testing against this
+ // condition allows it to be drawn as not selected.
+ const Sci::Position prev = pdoc->MovePositionOutsideChar(portion.end.Position()-1, -1);
+ Insert(prev - posLineStart);
+ }
+ }
}
}
}
diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx
index 5273841ed..92e2613bb 100644
--- a/src/ViewStyle.cxx
+++ b/src/ViewStyle.cxx
@@ -661,11 +661,18 @@ 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::IsMainCursesCaret(bool isMainSelection) const noexcept {
+ return isMainSelection && FlagSet(caret.style, CaretStyle::Curses);
}
bool ViewStyle::DrawCaretInsideSelection(bool inOverstrike, bool imeCaretBlockOverride) const noexcept {
@@ -673,14 +680,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..704da635a 100644
--- a/src/ViewStyle.h
+++ b/src/ViewStyle.h
@@ -235,9 +235,10 @@ public:
enum class CaretShape { invisible, line, block, bar };
bool IsBlockCaretStyle() const noexcept;
- bool IsCaretVisible() const noexcept;
+ bool IsCaretVisible(bool isMainSelection) const noexcept;
+ bool IsMainCursesCaret(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);