aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/EditView.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/EditView.cxx')
-rw-r--r--src/EditView.cxx417
1 files changed, 200 insertions, 217 deletions
diff --git a/src/EditView.cxx b/src/EditView.cxx
index 3bf0a1fbb..bec07fe95 100644
--- a/src/EditView.cxx
+++ b/src/EditView.cxx
@@ -17,6 +17,7 @@
#include <string>
#include <string_view>
#include <vector>
+#include <array>
#include <map>
#include <set>
#include <forward_list>
@@ -124,8 +125,7 @@ int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, cons
const std::string_view text(st.text + start, lenLine);
widthSubLine = static_cast<int>(surface->WidthText(fontText, text));
}
- if (widthSubLine > widthMax)
- widthMax = widthSubLine;
+ widthMax = std::max(widthMax, widthSubLine);
start += lenLine + 1;
}
return widthMax;
@@ -191,7 +191,7 @@ EditView::EditView() {
imeCaretBlockOverride = false;
llc.SetLevel(LineCache::Caret);
posCache = CreatePositionCache();
- posCache->SetSize(0x400);
+ posCache->SetSize(positionCacheDefaultSize);
maxLayoutThreads = 1;
tabArrowHeight = 4;
customDrawTabArrow = nullptr;
@@ -251,9 +251,8 @@ bool EditView::AddTabstop(Sci::Line line, int x) {
int EditView::GetNextTabstop(Sci::Line line, int x) const noexcept {
if (ldTabstops) {
return ldTabstops->GetNextTabstop(line, x);
- } else {
- return 0;
}
+ return 0;
}
void EditView::LinesAddedOrRemoved(Sci::Line lineOfPos, Sci::Line linesAdded) {
@@ -353,14 +352,14 @@ void LayoutSegments(IPositionCache *pCache,
XYPOSITION representationWidth = 0.0;
// Tab is a special case of representation, taking a variable amount of space
// which will be filled in later.
- if (ll->chars[ts.start] != '\t') {
+ if (ll->chars[ts.start] != '\t' || vstyle.tabDrawMode == TabDrawMode::ControlChar) {
representationWidth = vstyle.controlCharWidth;
if (representationWidth <= 0.0) {
assert(ts.representation->stringRep.length() <= Representation::maxLength);
- XYPOSITION positionsRepr[Representation::maxLength + 1];
+ std::array<XYPOSITION, Representation::maxLength + 1> positionsRepr;
// ts.representation->stringRep is UTF-8.
pCache->MeasureWidths(surface, vstyle, StyleControlChar, true, ts.representation->stringRep,
- positionsRepr, multiThreaded);
+ positionsRepr.data(), multiThreaded);
representationWidth = positionsRepr[ts.representation->stringRep.length() - 1];
if (FlagSet(ts.representation->appearance, RepresentationAppearance::Blob)) {
representationWidth += vstyle.ctrlCharPadding;
@@ -379,9 +378,9 @@ void LayoutSegments(IPositionCache *pCache,
}
} else if (vstyle.styles[styleSegment].invisibleRepresentation[0]) {
const std::string_view text = vstyle.styles[styleSegment].invisibleRepresentation;
- XYPOSITION positionsRepr[Representation::maxLength + 1];
+ std::array<XYPOSITION, Representation::maxLength + 1> positionsRepr;
// invisibleRepresentation is UTF-8.
- pCache->MeasureWidths(surface, vstyle, styleSegment, true, text, positionsRepr, multiThreaded);
+ pCache->MeasureWidths(surface, vstyle, styleSegment, true, text, positionsRepr.data(), multiThreaded);
const XYPOSITION representationWidth = positionsRepr[text.length() - 1];
std::fill(positions, positions + ts.length, representationWidth);
}
@@ -402,13 +401,10 @@ void EditView::LayoutLine(const EditModel &model, Surface *surface, const ViewSt
PLATFORM_ASSERT(line < model.pdoc->LinesTotal());
PLATFORM_ASSERT(ll->chars);
const Sci::Position posLineStart = model.pdoc->LineStart(line);
- Sci::Position posLineEnd = model.pdoc->LineStart(line + 1);
- // If the line is very long, limit the treatment to a length that should fit in the viewport
- if (posLineEnd >(posLineStart + ll->maxLineLength)) {
- posLineEnd = posLineStart + ll->maxLineLength;
- }
+ const Sci::Position posLineEnd = std::min(model.pdoc->LineStart(line + 1), posLineStart + ll->maxLineLength);
// Hard to cope when too narrow, so just assume there is space
- width = std::max(width, 20);
+ constexpr int minimumWidth = 20;
+ width = std::max(width, minimumWidth);
if (ll->validity == LineLayout::ValidLevel::checkTextAndStyle) {
Sci::Position lineLength = posLineEnd - posLineStart;
@@ -526,7 +522,7 @@ void EditView::LayoutLine(const EditModel &model, Surface *surface, const ViewSt
for (const TextSegment &ts : segments) {
if (vstyle.styles[ll->styles[ts.start]].visible &&
ts.representation &&
- (ll->chars[ts.start] == '\t')) {
+ ll->chars[ts.start] == '\t' && vstyle.tabDrawMode != TabDrawMode::ControlChar) {
// Simple visible tab, go to next tab stop
const XYPOSITION startTab = ll->positions[ts.start];
const XYPOSITION nextTab = NextTabstopPos(line, startTab, vstyle.tabWidth);
@@ -614,7 +610,7 @@ void EditView::UpdateBidiData(const EditModel &model, const ViewStyle &vstyle, L
const Representation *repr = model.reprs->RepresentationFromCharacter(std::string_view(&ll->chars[charsInLine], charWidth));
ll->bidiData->widthReprs[charsInLine] = 0.0f;
- if (repr && ll->chars[charsInLine] != '\t') {
+ if (repr && (ll->chars[charsInLine] != '\t' || vstyle.tabDrawMode == TabDrawMode::ControlChar)) {
ll->bidiData->widthReprs[charsInLine] = ll->positions[charsInLine + charWidth] - ll->positions[charsInLine];
}
if (charWidth > 1) {
@@ -745,7 +741,8 @@ SelectionPosition EditView::SPositionFromLocation(Surface *surface, const EditMo
const int spaceOffset = static_cast<int>(
(pt.x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth);
return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset);
- } else if (canReturnInvalid) {
+ }
+ if (canReturnInvalid) {
if (pt.x < (ll->positions[rangeSubLine.end] - subLineStart)) {
return SelectionPosition(model.pdoc->MovePositionOutsideChar(rangeSubLine.end + posLineStart, 1));
}
@@ -892,11 +889,11 @@ ColourRGBA TextBackground(const EditModel &model, const ViewStyle &vsDraw, const
}
if (background && (styleMain != StyleBraceLight) && (styleMain != StyleBraceBad)) {
return *background;
- } else {
- return vsDraw.styles[styleMain].back;
}
+ return vsDraw.styles[styleMain].back;
}
+// Draw inverted text in a filled rectangle but omit the 4 corner pixels so appears rounded.
void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle rcSegment,
std::string_view text, ColourRGBA textBack, ColourRGBA textFore, bool fillBackground) {
if (rcSegment.Empty())
@@ -910,42 +907,95 @@ void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle rcSegmen
rcCChar.left = rcCChar.left + 1;
rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight;
rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1;
- PRectangle rcCentral = rcCChar;
- rcCentral.top++;
- rcCentral.bottom--;
+
+ // Ensure pixels to left and right coloured for central part avoiding top and bottom
+ // pixels which will be drawn by DrawTextClippedUTF8.
+ const PRectangle rcCentral = rcCChar.Inset(Point(0, 1));
surface->FillRectangleAligned(rcCentral, Fill(textFore));
- PRectangle rcChar = rcCChar;
- rcChar.left++;
- rcChar.right--;
+
+ const PRectangle rcChar = rcCChar.Inset(Point(1, 0));
+ // NOLINTNEXTLINE(readability-suspicious-call-argument) Inverted text
surface->DrawTextClippedUTF8(rcChar, ctrlCharsFont,
rcSegment.top + vsDraw.maxAscent, text,
textBack, textFore);
}
void FillLineRemainder(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
- Sci::Line line, PRectangle rcArea, int subLine) {
+ Sci::Line line, PRectangle rcLine, XYPOSITION left, int subLine) {
+ if (rcLine.Empty()) {
+ return;
+ }
InSelection eolInSelection = InSelection::inNone;
if (vsDraw.selection.visible && (subLine == (ll->lines - 1))) {
eolInSelection = model.LineEndInSelection(line);
}
+ const bool drawEOLSelection = eolInSelection && vsDraw.selection.eolFilled && (line < model.pdoc->LinesTotal() - 1);
- if (eolInSelection && vsDraw.selection.eolFilled && (line < model.pdoc->LinesTotal() - 1) && (vsDraw.selection.layer == Layer::Base)) {
- surface->FillRectangleAligned(rcArea, Fill(SelectionBackground(model, vsDraw, eolInSelection).Opaque()));
+ const PRectangle rcArea = Clamp(rcLine, Edge::left, left); // Limit to right side of line from 'left'
+
+ const ColourRGBA selectionBack = drawEOLSelection ? SelectionBackground(model, vsDraw, eolInSelection) : ColourRGBA{};
+ ColourRGBA base = vsDraw.styles[StyleDefault].back;
+ if (drawEOLSelection && (vsDraw.selection.layer == Layer::Base)) {
+ base = selectionBack;
} else {
const ColourOptional background = vsDraw.Background(model.GetMark(line), model.caret.active, ll->containsCaret);
if (background) {
- surface->FillRectangleAligned(rcArea, Fill(*background));
- } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) {
- surface->FillRectangleAligned(rcArea, Fill(vsDraw.styles[ll->styles[ll->numCharsInLine]].back));
- } else {
- surface->FillRectangleAligned(rcArea, Fill(vsDraw.styles[StyleDefault].back));
+ base = *background;
+ } else if (vsDraw.styles[ll->LastStyle()].eolFilled) {
+ base = vsDraw.styles[ll->LastStyle()].back;
}
- if (eolInSelection && vsDraw.selection.eolFilled && (line < model.pdoc->LinesTotal() - 1) && (vsDraw.selection.layer != Layer::Base)) {
- surface->FillRectangleAligned(rcArea, SelectionBackground(model, vsDraw, eolInSelection));
+ }
+ surface->FillRectangleAligned(rcArea, Fill(base.Opaque()));
+ if (drawEOLSelection && (vsDraw.selection.layer != Layer::Base)) {
+ // This may be translucent
+ surface->FillRectangleAligned(rcArea, selectionBack);
+ }
+}
+
+// Stadium ends require different amounts of padding to look reasonable around text.
+constexpr XYPOSITION divisorAngle = 2.0; // <text>
+constexpr XYPOSITION divisorCircle = 3.0; // (text)
+constexpr XYPOSITION EndPadding(Surface::Ends side, XYPOSITION height) noexcept {
+ switch (side) {
+ case Surface::Ends::leftFlat:
+ case Surface::Ends::rightFlat:
+ return 1;
+ case Surface::Ends::leftAngle:
+ case Surface::Ends::rightAngle:
+ return height / divisorAngle;
+ default:
+ // semiCircles
+ return height / divisorCircle;
+ }
+}
+
+struct HorizontalPadding {
+ XYPOSITION left = 0;
+ XYPOSITION right = 0;
+};
+
+[[nodiscard]] constexpr PRectangle TextPart(const PRectangle &rc, const HorizontalPadding &padding) noexcept {
+ return PRectangle(rc.left + padding.left, rc.top, rc.right - padding.right, rc.bottom);
+}
+
+HorizontalPadding StadiumPadding(Scintilla::EOLAnnotationVisible eolAnnotationVisible, XYPOSITION height) noexcept {
+ if (eolAnnotationVisible >= EOLAnnotationVisible::Boxed) {
+ if (eolAnnotationVisible == EOLAnnotationVisible::Boxed) {
+ return { 1, 1 };
}
+ const Surface::Ends leftSide = static_cast<Surface::Ends>(static_cast<int>(eolAnnotationVisible) & 0xf);
+ const Surface::Ends rightSide = static_cast<Surface::Ends>(static_cast<int>(eolAnnotationVisible) & 0xf0);
+ const XYPOSITION leftSpace = EndPadding(leftSide, height);
+ const XYPOSITION rightSpace = EndPadding(rightSide, height);
+ return { leftSpace , rightSpace };
}
+ return {};
+}
+
}
+void EditView::UpdateMaxWidth(XYPOSITION width) noexcept {
+ lineWidthMaxSeen = std::max(lineWidthMaxSeen, static_cast<int>(width));
}
void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
@@ -955,27 +1005,23 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
PRectangle rcSegment = rcLine;
const bool lastSubLine = subLine == (ll->lines - 1);
- XYPOSITION virtualSpace = 0;
- if (lastSubLine) {
- const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
- virtualSpace = static_cast<XYPOSITION>(model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line))) * spaceWidth;
- }
+ const Sci::Position virtualSpaces = lastSubLine ? model.VirtualSpaceForLine(line) : 0;
+ const XYPOSITION spaceWidth = lastSubLine ? vsDraw.styles[ll->EndLineStyle()].spaceWidth : 0;
+ const XYPOSITION virtualSpace = static_cast<XYPOSITION>(virtualSpaces) * spaceWidth;
const XYPOSITION xEol = ll->positions[lineEnd] - subLineStart;
// Fill the virtual space and show selections within it
if (virtualSpace > 0.0f) {
rcSegment.left = xEol + xStart;
rcSegment.right = xEol + xStart + virtualSpace;
- const ColourRGBA backgroundFill = background.value_or(vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
+ const ColourRGBA backgroundFill = background.value_or(vsDraw.styles[ll->LastStyle()].back);
surface->FillRectangleAligned(rcSegment, backgroundFill);
if (vsDraw.selection.visible && (vsDraw.selection.layer == Layer::Base)) {
const SelectionSegment virtualSpaceRange(SelectionPosition(model.pdoc->LineEnd(line)),
- SelectionPosition(model.pdoc->LineEnd(line),
- model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line))));
+ SelectionPosition(model.pdoc->LineEnd(line), virtualSpaces));
for (size_t r = 0; r<model.sel.Count(); r++) {
const SelectionSegment portion = model.sel.Range(r).Intersect(virtualSpaceRange);
if (!portion.Empty()) {
- const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] -
subLineStart + portion.start.VirtualSpaceWidth(spaceWidth);
rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] -
@@ -989,30 +1035,29 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
}
}
- InSelection eolInSelection = InSelection::inNone;
- if (vsDraw.selection.visible && lastSubLine) {
- eolInSelection = model.LineEndInSelection(line);
- }
+ const InSelection eolInSelection = (vsDraw.selection.visible && lastSubLine) ?
+ model.LineEndInSelection(line) : InSelection::inNone;
+ const bool lastLine = line >= (model.pdoc->LinesTotal() - 1);
+ const bool drawEOLSelection = eolInSelection && !lastLine;
const ColourRGBA selectionBack = SelectionBackground(model, vsDraw, eolInSelection);
// Draw the [CR], [LF], or [CR][LF] blobs if visible line ends are on
XYPOSITION blobsWidth = 0;
if (lastSubLine) {
- for (Sci::Position eolPos = ll->numCharsBeforeEOL; eolPos<ll->numCharsInLine;) {
+ for (int eolPos = ll->numCharsBeforeEOL; eolPos<ll->numCharsInLine;) {
const int styleMain = ll->styles[eolPos];
const ColourOptional selectionFore = SelectionForeground(model, vsDraw, eolInSelection);
ColourRGBA textFore = selectionFore.value_or(vsDraw.styles[styleMain].fore);
char hexits[4] = "";
std::string_view ctrlChar;
- Sci::Position widthBytes = 1;
RepresentationAppearance appearance = RepresentationAppearance::Blob;
- const Representation *repr = model.reprs->RepresentationFromCharacter(std::string_view(&ll->chars[eolPos], ll->numCharsInLine - eolPos));
- if (repr) {
- // Representation of whole text
- widthBytes = ll->numCharsInLine - eolPos;
- } else {
- repr = model.reprs->RepresentationFromCharacter(std::string_view(&ll->chars[eolPos], 1));
+ const std::string_view rest(&ll->chars[eolPos], ll->numCharsInLine - eolPos);
+ const Representation *repr = model.reprs->RepresentationFromCharacter(rest);
+ const int widthBytes = repr ? static_cast<int>(rest.length()) : 1;
+ if (!repr) {
+ // No representation of whole line end so try first byte.
+ repr = model.reprs->RepresentationFromCharacter(rest.substr(0, 1));
}
if (repr) {
ctrlChar = repr->stringRep;
@@ -1021,7 +1066,7 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
textFore = repr->colour;
}
} else {
- const unsigned char chEOL = ll->chars[eolPos];
+ const unsigned char chEOL = rest.front();
if (UTF8IsAscii(chEOL)) {
ctrlChar = ControlCharacterString(chEOL);
} else {
@@ -1030,69 +1075,54 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
}
}
- rcSegment.left = xStart + ll->positions[eolPos] - subLineStart + virtualSpace;
- rcSegment.right = xStart + ll->positions[eolPos + widthBytes] - subLineStart + virtualSpace;
- blobsWidth += rcSegment.Width();
+ const PRectangle rcBlob = rcLine.WithHorizontalBounds(
+ ll->Span(eolPos, eolPos + widthBytes).Offset(xStart - subLineStart + virtualSpace));
+ blobsWidth += rcBlob.Width();
const ColourRGBA textBack = TextBackground(model, vsDraw, ll, background, eolInSelection, false, styleMain, eolPos);
- if (eolInSelection && (line < model.pdoc->LinesTotal() - 1)) {
- if (vsDraw.selection.layer == Layer::Base) {
- surface->FillRectangleAligned(rcSegment, Fill(selectionBack.Opaque()));
- } else {
- surface->FillRectangleAligned(rcSegment, Fill(textBack));
- }
+ if (drawEOLSelection && (vsDraw.selection.layer == Layer::Base)) {
+ surface->FillRectangleAligned(rcBlob, Fill(selectionBack.Opaque()));
} else {
- surface->FillRectangleAligned(rcSegment, Fill(textBack));
+ surface->FillRectangleAligned(rcBlob, Fill(textBack));
}
- const bool drawEOLSelection = eolInSelection && (line < model.pdoc->LinesTotal() - 1);
ColourRGBA blobText = textBack;
if (drawEOLSelection && (vsDraw.selection.layer == Layer::UnderText)) {
- surface->FillRectangleAligned(rcSegment, selectionBack);
+ surface->FillRectangleAligned(rcBlob, selectionBack);
blobText = textBack.MixedWith(selectionBack, selectionBack.GetAlphaComponent());
}
if (FlagSet(appearance, RepresentationAppearance::Blob)) {
- DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, blobText, textFore, phasesDraw == PhasesDraw::One);
+ DrawTextBlob(surface, vsDraw, rcBlob, ctrlChar, blobText, textFore, phasesDraw == PhasesDraw::One);
} else {
- surface->DrawTextTransparentUTF8(rcSegment, vsDraw.styles[StyleControlChar].font.get(),
- rcSegment.top + vsDraw.maxAscent, ctrlChar, textFore);
+ surface->DrawTextTransparentUTF8(rcBlob, vsDraw.styles[StyleControlChar].font.get(),
+ rcBlob.top + vsDraw.maxAscent, ctrlChar, textFore);
}
if (drawEOLSelection && (vsDraw.selection.layer == Layer::OverText)) {
- surface->FillRectangleAligned(rcSegment, selectionBack);
+ surface->FillRectangleAligned(rcBlob, selectionBack);
}
eolPos += widthBytes;
}
}
// Draw the eol-is-selected rectangle
- rcSegment.left = xEol + xStart + virtualSpace + blobsWidth;
- rcSegment.right = rcSegment.left + vsDraw.aveCharWidth;
-
- if (eolInSelection && (line < model.pdoc->LinesTotal() - 1) && (vsDraw.selection.layer == Layer::Base)) {
- surface->FillRectangleAligned(rcSegment, Fill(selectionBack.Opaque()));
- } else {
- if (background) {
- surface->FillRectangleAligned(rcSegment, Fill(*background));
- } else if (line < model.pdoc->LinesTotal() - 1) {
- surface->FillRectangleAligned(rcSegment, Fill(vsDraw.styles[ll->styles[ll->numCharsInLine]].back));
- } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) {
- surface->FillRectangleAligned(rcSegment, Fill(vsDraw.styles[ll->styles[ll->numCharsInLine]].back));
- } else {
- surface->FillRectangleAligned(rcSegment, Fill(vsDraw.styles[StyleDefault].back));
- }
- if (eolInSelection && (line < model.pdoc->LinesTotal() - 1) && (vsDraw.selection.layer != Layer::Base)) {
- surface->FillRectangleAligned(rcSegment, selectionBack);
- }
+ const PRectangle rcEOLIsSelected = rcLine.WithHorizontalBounds(
+ Interval::FromLeftAndWidth(xEol + xStart + virtualSpace + blobsWidth, vsDraw.aveCharWidth));
+ ColourRGBA base = vsDraw.styles[StyleDefault].back;
+ if (drawEOLSelection && (vsDraw.selection.layer == Layer::Base)) {
+ base = selectionBack;
+ } else if (background) {
+ base = *background;
+ } else if (const Style &styleLast = vsDraw.styles[ll->LastStyle()]; styleLast.eolFilled) {
+ base = styleLast.back;
+ }
+ surface->FillRectangleAligned(rcEOLIsSelected, Fill(base.Opaque()));
+ if (drawEOLSelection && (vsDraw.selection.layer != Layer::Base)) {
+ surface->FillRectangleAligned(rcEOLIsSelected, selectionBack);
}
-
- rcSegment.left = rcSegment.right;
- if (rcSegment.left < rcLine.left)
- rcSegment.left = rcLine.left;
- rcSegment.right = rcLine.right;
const bool drawEOLAnnotationStyledText = (vsDraw.eolAnnotationVisible != EOLAnnotationVisible::Hidden) && model.pdoc->EOLAnnotationStyledText(line).text;
const bool fillRemainder = (!lastSubLine || (!model.GetFoldDisplayText(line) && !drawEOLAnnotationStyledText));
if (fillRemainder) {
// Fill the remainder of the line
- FillLineRemainder(surface, model, vsDraw, ll, line, rcSegment, subLine);
+ FillLineRemainder(surface, model, vsDraw, ll, line, rcLine, rcEOLIsSelected.right, subLine);
}
bool drawWrapMarkEnd = false;
@@ -1109,8 +1139,8 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
}
if (drawWrapMarkEnd) {
- PRectangle rcPlace = rcSegment;
- const XYPOSITION maxLeft = rcPlace.right - vsDraw.aveCharWidth;
+ PRectangle rcPlace = rcLine;
+ const XYPOSITION maxLeft = rcLine.right - vsDraw.aveCharWidth;
if (FlagSet(vsDraw.wrap.visualFlagsLocation, WrapVisualLocation::EndByText)) {
rcPlace.left = std::min(xEol + xStart + virtualSpace, maxLeft);
@@ -1149,8 +1179,7 @@ void EditView::DrawFoldDisplayText(Surface *surface, const EditModel &model, con
}
const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
- const XYPOSITION virtualSpace = static_cast<XYPOSITION>(model.sel.VirtualSpaceFor(
- model.pdoc->LineEnd(line))) * spaceWidth;
+ const XYPOSITION virtualSpace = static_cast<XYPOSITION>(model.VirtualSpaceForLine(line)) * spaceWidth;
rcSegment.left = xStart + ll->positions[ll->numCharsInLine] - subLineStart + virtualSpace + vsDraw.aveCharWidth;
rcSegment.right = rcSegment.left + static_cast<XYPOSITION>(widthFoldDisplayText);
@@ -1161,22 +1190,15 @@ void EditView::DrawFoldDisplayText(Surface *surface, const EditModel &model, con
false, StyleFoldDisplayText, -1);
if (model.trackLineWidth) {
- if (rcSegment.right + 1> lineWidthMaxSeen) {
- // Fold display text border drawn on rcSegment.right with width 1 is the last visible object of the line
- lineWidthMaxSeen = static_cast<int>(rcSegment.right + 1);
- }
+ // Fold display text border drawn on rcSegment.right with width 1 is the last visible object of the line
+ UpdateMaxWidth(rcSegment.right + 1);
}
if (FlagSet(phase, DrawPhase::back)) {
surface->FillRectangleAligned(rcSegment, Fill(textBack));
// Fill Remainder of the line
- PRectangle rcRemainder = rcSegment;
- rcRemainder.left = rcRemainder.right;
- if (rcRemainder.left < rcLine.left)
- rcRemainder.left = rcLine.left;
- rcRemainder.right = rcLine.right;
- FillLineRemainder(surface, model, vsDraw, ll, line, rcRemainder, subLine);
+ FillLineRemainder(surface, model, vsDraw, ll, line, rcLine, rcSegment.right, subLine);
}
if (FlagSet(phase, DrawPhase::text)) {
@@ -1228,47 +1250,14 @@ void EditView::DrawEOLAnnotationText(Surface *surface, const EditModel &model, c
const Font *fontText = vsDraw.styles[style].font.get();
const Surface::Ends ends = static_cast<Surface::Ends>(static_cast<int>(vsDraw.eolAnnotationVisible) & 0xff);
- const Surface::Ends leftSide = static_cast<Surface::Ends>(static_cast<int>(ends) & 0xf);
- const Surface::Ends rightSide = static_cast<Surface::Ends>(static_cast<int>(ends) & 0xf0);
-
- XYPOSITION leftBoxSpace = 0;
- XYPOSITION rightBoxSpace = 0;
- if (vsDraw.eolAnnotationVisible >= EOLAnnotationVisible::Boxed) {
- leftBoxSpace = 1;
- rightBoxSpace = 1;
- if (vsDraw.eolAnnotationVisible != EOLAnnotationVisible::Boxed) {
- switch (leftSide) {
- case Surface::Ends::leftFlat:
- leftBoxSpace = 1;
- break;
- case Surface::Ends::leftAngle:
- leftBoxSpace = rcLine.Height() / 2.0;
- break;
- case Surface::Ends::semiCircles:
- default:
- leftBoxSpace = rcLine.Height() / 3.0;
- break;
- }
- switch (rightSide) {
- case Surface::Ends::rightFlat:
- rightBoxSpace = 1;
- break;
- case Surface::Ends::rightAngle:
- rightBoxSpace = rcLine.Height() / 2.0;
- break;
- case Surface::Ends::semiCircles:
- default:
- rightBoxSpace = rcLine.Height() / 3.0;
- break;
- }
- }
- }
+
+ const HorizontalPadding padding = StadiumPadding(vsDraw.eolAnnotationVisible, rcLine.Height());
+
const int widthEOLAnnotationText = static_cast<int>(surface->WidthTextUTF8(fontText, eolAnnotationText) +
- leftBoxSpace + rightBoxSpace);
+ padding.left + padding.right);
const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
- const XYPOSITION virtualSpace = static_cast<XYPOSITION>(model.sel.VirtualSpaceFor(
- model.pdoc->LineEnd(line))) * spaceWidth;
+ const XYPOSITION virtualSpace = static_cast<XYPOSITION>(model.VirtualSpaceForLine(line)) * spaceWidth;
rcSegment.left = xStart +
ll->positions[ll->numCharsInLine] - subLineStart
+ virtualSpace + vsDraw.aveCharWidth;
@@ -1288,10 +1277,8 @@ void EditView::DrawEOLAnnotationText(Surface *surface, const EditModel &model, c
false, static_cast<int>(style), -1);
if (model.trackLineWidth) {
- if (rcSegment.right + 1> lineWidthMaxSeen) {
- // EOL Annotation text border drawn on rcSegment.right with width 1 is the last visible object of the line
- lineWidthMaxSeen = static_cast<int>(rcSegment.right + 1);
- }
+ // EOL Annotation text border drawn on rcSegment.right with width 1 is the last visible object of the line
+ UpdateMaxWidth(rcSegment.right + 1);
}
if (FlagSet(phase, DrawPhase::back)) {
@@ -1299,14 +1286,10 @@ void EditView::DrawEOLAnnotationText(Surface *surface, const EditModel &model, c
// it may be double drawing. This is to allow stadiums with
// curved or angled ends to have the area outside in the correct
// background colour.
- PRectangle rcRemainder = rcSegment;
- rcRemainder.right = rcLine.right;
- FillLineRemainder(surface, model, vsDraw, ll, line, rcRemainder, subLine);
+ FillLineRemainder(surface, model, vsDraw, ll, line, rcLine, rcSegment.right, subLine);
}
- PRectangle rcText = rcSegment;
- rcText.left += leftBoxSpace;
- rcText.right -= rightBoxSpace;
+ const PRectangle rcText = TextPart(rcSegment, padding);
// For single phase drawing, draw the text then any box over it
if (FlagSet(phase, DrawPhase::text)) {
@@ -1369,7 +1352,7 @@ constexpr bool AnnotationBoxedOrIndented(AnnotationVisible annotationVisible) no
}
void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
- Sci::Line line, int xStart, PRectangle rcLine, int subLine, DrawPhase phase) {
+ Sci::Line line, int xOrigin, PRectangle rcLine, int subLine, DrawPhase phase) {
const int indent = static_cast<int>(model.pdoc->GetLineIndentation(line) * vsDraw.spaceWidth);
PRectangle rcSegment = rcLine;
const int annotationLine = subLine - ll->lines;
@@ -1378,17 +1361,16 @@ void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const Vi
if (FlagSet(phase, DrawPhase::back)) {
surface->FillRectangleAligned(rcSegment, Fill(vsDraw.styles[0].back));
}
- rcSegment.left = static_cast<XYPOSITION>(xStart);
+ rcSegment.left = static_cast<XYPOSITION>(xOrigin);
if (model.trackLineWidth || AnnotationBoxedOrIndented(vsDraw.annotationVisible)) {
// Only care about calculating width if tracking or need to draw indented box
int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation);
if (AnnotationBoxedOrIndented(vsDraw.annotationVisible)) {
widthAnnotation += static_cast<int>(vsDraw.spaceWidth * 2); // Margins
- rcSegment.left = static_cast<XYPOSITION>(xStart + indent);
+ rcSegment.left = static_cast<XYPOSITION>(xOrigin + indent);
rcSegment.right = rcSegment.left + widthAnnotation;
}
- if (widthAnnotation > lineWidthMaxSeen)
- lineWidthMaxSeen = widthAnnotation;
+ UpdateMaxWidth(widthAnnotation);
}
const int annotationLines = model.pdoc->AnnotationLines(line);
size_t start = 0;
@@ -1430,7 +1412,7 @@ void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const Vi
namespace {
void DrawBlockCaret(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
- int subLine, int xStart, Sci::Position offset, Sci::Position posCaret, PRectangle rcCaret, ColourRGBA caretColour) {
+ int subLine, int xOrigin, Sci::Position offset, Sci::Position posCaret, PRectangle rcCaret, ColourRGBA caretColour) {
const Sci::Position lineStart = ll->LineStart(subLine);
Sci::Position posBefore = posCaret;
@@ -1456,8 +1438,7 @@ void DrawBlockCaret(Surface *surface, const EditModel &model, const ViewStyle &v
// See if the next character shares horizontal space, if so we'll
// need to draw that too.
- if (offsetFirstChar < 0)
- offsetFirstChar = 0;
+ offsetFirstChar = std::max<Sci::Position>(offsetFirstChar, 0);
numCharsToDraw = offsetLastChar - offsetFirstChar;
while ((offsetLastChar < ll->LineStart(subLine + 1)) && (offsetLastChar <= ll->numCharsInLine)) {
// Update posAfter to point to the 2nd next char, this is where
@@ -1475,8 +1456,8 @@ void DrawBlockCaret(Surface *surface, const EditModel &model, const ViewStyle &v
}
// We now know what to draw, update the caret drawing rectangle
- rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xStart;
- rcCaret.right = ll->positions[offsetFirstChar + numCharsToDraw] - ll->positions[lineStart] + xStart;
+ rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xOrigin;
+ rcCaret.right = ll->positions[offsetFirstChar + numCharsToDraw] - ll->positions[lineStart] + xOrigin;
// Adjust caret position to take into account any word wrapping symbols.
if ((ll->wrapIndent != 0) && (lineStart != 0)) {
@@ -1498,7 +1479,7 @@ void DrawBlockCaret(Surface *surface, const EditModel &model, const ViewStyle &v
}
void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
- Sci::Line lineDoc, int xStart, PRectangle rcLine, int subLine) const {
+ Sci::Line lineDoc, int xOrigin, PRectangle rcLine, int subLine) const {
// When drag is active it is the only caret drawn
const bool drawDrag = model.posDrag.IsValid();
if (!vsDraw.selection.visible && !drawDrag)
@@ -1545,7 +1526,6 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
bool canDrawBlockCaret = true;
bool drawBlockCaret = false;
XYPOSITION widthOverstrikeCaret;
- XYPOSITION caretWidthOffset = 0;
PRectangle rcCaret = rcLine;
if (posCaret.Position() == model.pdoc->Length()) { // At end of document
@@ -1558,12 +1538,15 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
const int widthChar = model.pdoc->LenChar(posCaret.Position());
widthOverstrikeCaret = ll->positions[offset + widthChar] - ll->positions[offset];
}
- if (widthOverstrikeCaret < 3) // Make sure its visible
- widthOverstrikeCaret = 3;
+ // Make sure block caret visible
+ constexpr XYPOSITION minimumBlockCaretWidth = 3.0f;
+ widthOverstrikeCaret = std::max(widthOverstrikeCaret, minimumBlockCaretWidth);
- if (xposCaret > 0)
- caretWidthOffset = 0.51f; // Move back so overlaps both character cells.
- xposCaret += xStart;
+ // Move back slightly so line caret overlaps both character cells unless at start of text area.
+ constexpr XYPOSITION justOverHalf = 0.51f;
+ const XYPOSITION caretWidthOffset = (xposCaret > 0) ? justOverHalf : 0;
+
+ xposCaret += xOrigin;
const ViewStyle::CaretShape caretShape = drawDrag ? ViewStyle::CaretShape::line :
vsDraw.CaretShapeForMode(model.inOverstrike, mainCaret);
if (drawDrag) {
@@ -1593,7 +1576,7 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
const ColourRGBA caretColour = vsDraw.ElementColourForced(elementCaret);
//assert(caretColour.IsOpaque());
if (drawBlockCaret) {
- DrawBlockCaret(surface, model, vsDraw, ll, subLine, xStart, offset, posCaret.Position(), rcCaret, caretColour);
+ DrawBlockCaret(surface, model, vsDraw, ll, subLine, xOrigin, offset, posCaret.Position(), rcCaret, caretColour);
} else {
surface->FillRectangleAligned(rcCaret, Fill(caretColour));
}
@@ -1690,7 +1673,7 @@ void DrawBackground(Surface *surface, const EditModel &model, const ViewStyle &v
ColourRGBA textBack = TextBackground(model, vsDraw, ll, background, inSelection,
inHotspot, ll->styles[i], i);
if (ts.representation) {
- if (ll->chars[i] == '\t') {
+ if (ll->chars[i] == '\t' && vsDraw.tabDrawMode != TabDrawMode::ControlChar) {
// Tab display
if (drawWhitespaceBackground && vsDraw.WhiteSpaceVisible(inIndentation)) {
textBack = vsDraw.ElementColourForced(Element::WhiteSpaceBack).Opaque();
@@ -1771,10 +1754,8 @@ void DrawTranslucentSelection(Surface *surface, const EditModel &model, const Vi
const XYPOSITION subLineStart = ll->positions[lineRange.start];
const XYPOSITION horizontalOffset = xStart - subLineStart;
// For each selection draw
- Sci::Position virtualSpaces = 0;
- if (subLine == (ll->lines - 1)) {
- virtualSpaces = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line));
- }
+ const Sci::Position virtualSpaces = (subLine == (ll->lines - 1)) ?
+ model.VirtualSpaceForLine(line) : 0;
const SelectionPosition posStart(posLineStart + lineRange.start);
const SelectionPosition posEnd(posLineStart + lineRange.end, virtualSpaces);
const SelectionSegment virtualSpaceRange(posStart, posEnd);
@@ -1912,7 +1893,7 @@ void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid,
// Draw the arrow head if needed
if (vsDraw.tabDrawMode == TabDrawMode::LongArrow) {
- XYPOSITION ydiff = std::floor(rcTab.Height() / 2.0f);
+ XYPOSITION ydiff = std::floor(rcTab.Height() / 2);
XYPOSITION xhead = rightStroke - ydiff;
if (xhead <= rcTab.left) {
ydiff -= rcTab.left - xhead;
@@ -2031,7 +2012,7 @@ void DrawIndicators(Surface *surface, const EditModel &model, const ViewStyle &v
const Sci::Position endPos = std::min(rangeRun.end, posLineEnd);
const int edition = model.pdoc->EditionAt(startPos);
if (edition != 0) {
- const int indicator = (edition - 1) * 2 + indexHistory;
+ const int indicator = ((edition - 1) * 2) + indexHistory;
const Sci::Position posSecond = model.pdoc->MovePositionOutsideChar(rangeRun.First() + 1, 1);
DrawIndicator(indicator, startPos - posLineStart, endPos - posLineStart,
surface, vsDraw, ll, xStart, rcLine, posSecond - posLineStart, subLine, Indicator::State::normal,
@@ -2048,7 +2029,7 @@ void DrawIndicators(Surface *surface, const EditModel &model, const ViewStyle &v
const Sci::Position posSecond = model.pdoc->MovePositionOutsideChar(startPos + 1, 1);
for (unsigned int edition = 0; edition < 4; edition++) {
if (editions & (1 << edition)) {
- const int indicator = edition * 2 + indexHistory + 1;
+ const int indicator = (edition * 2) + indexHistory + 1;
DrawIndicator(indicator, startPos - posLineStart, posSecond - posLineStart,
surface, vsDraw, ll, xStart, rcLine, posSecond - posLineStart, subLine, Indicator::State::normal,
1, model.BidirectionalEnabled(), tabWidthMinimumPixels);
@@ -2102,12 +2083,12 @@ ColourRGBA InvertedLight(ColourRGBA orig) noexcept {
r = r * il / l;
g = g * il / l;
b = b * il / l;
- return ColourRGBA(std::min(r, 0xffu), std::min(g, 0xffu), std::min(b, 0xffu));
+ return ColourRGBA(std::min(r, maximumByte), std::min(g, maximumByte), std::min(b, maximumByte));
}
}
-void EditView::DrawIndentGuide(Surface *surface, XYPOSITION start, PRectangle rcSegment, bool highlight, bool offset) {
+void EditView::DrawIndentGuide(Surface *surface, XYPOSITION start, PRectangle rcSegment, bool highlight, bool offset) const {
const Point from = Point::FromInts(0, offset ? 1 : 0);
const PRectangle rcCopyArea(start + 1, rcSegment.top,
start + 2, rcSegment.bottom);
@@ -2197,7 +2178,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
}
ColourRGBA textBack = TextBackground(model, vsDraw, ll, background, inSelection, inHotspot, styleMain, i);
if (ts.representation) {
- if (ll->chars[i] == '\t') {
+ if (ll->chars[i] == '\t' && vsDraw.tabDrawMode != TabDrawMode::ControlChar) {
// Tab display
if (phasesDraw == PhasesDraw::One) {
if (drawWhitespaceBackground && vsDraw.WhiteSpaceVisible(inIndentation))
@@ -2219,7 +2200,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
if (vsDraw.WhiteSpaceVisible(inIndentation)) {
const PRectangle rcTab(rcSegment.left + 1, rcSegment.top + tabArrowHeight,
rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
- const int segmentTop = static_cast<int>(rcSegment.top) + vsDraw.lineHeight / 2;
+ const int segmentTop = static_cast<int>(rcSegment.top) + (vsDraw.lineHeight / 2);
const ColourRGBA whiteSpaceFore = vsDraw.ElementColour(Element::WhiteSpace).value_or(textFore);
if (!customDrawTabArrow)
DrawTabArrow(surface, rcTab, segmentTop, vsDraw, Stroke(whiteSpaceFore, 1.0f));
@@ -2229,12 +2210,13 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
}
} else {
inIndentation = false;
- if (vsDraw.controlCharSymbol >= 32) {
+ if (vsDraw.controlCharSymbol >= ' ') {
// Using one font for all control characters so it can be controlled independently to ensure
// the box goes around the characters tightly. Seems to be no way to work out what height
// is taken by an individual character - internal leading gives varying results.
const Font *ctrlCharsFont = vsDraw.styles[StyleControlChar].font.get();
const char cc[2] = { static_cast<char>(vsDraw.controlCharSymbol), '\0' };
+ // NOLINTNEXTLINE(readability-suspicious-call-argument) Inverted text
surface->DrawTextNoClip(rcSegment, ctrlCharsFont,
ybase, cc, textBack, textFore);
} else {
@@ -2286,7 +2268,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
}
const int halfDotWidth = vsDraw.whitespaceSize / 2;
PRectangle rcDot(xmid - halfDotWidth,
- rcSegment.top + vsDraw.lineHeight / 2, 0.0f, 0.0f);
+ rcSegment.top + (vsDraw.lineHeight / 2), 0.0f, 0.0f);
rcDot.right = rcDot.left + vsDraw.whitespaceSize;
rcDot.bottom = rcDot.top + vsDraw.whitespaceSize;
const ColourRGBA whiteSpaceFore = vsDraw.ElementColour(Element::WhiteSpace).value_or(textFore);
@@ -2336,12 +2318,16 @@ void EditView::DrawIndentGuidesOverEmpty(Surface *surface, const EditModel &mode
// Find the most recent line with some text
+ constexpr int largeIndent = 100000;
+
+ constexpr Sci::Line maxCheck = 20;
+
Sci::Line lineLastWithText = line;
- while (lineLastWithText > std::max(line - 20, static_cast<Sci::Line>(0)) && model.pdoc->IsWhiteLine(lineLastWithText)) {
+ while (lineLastWithText > std::max(line - maxCheck, static_cast<Sci::Line>(0)) && model.pdoc->IsWhiteLine(lineLastWithText)) {
lineLastWithText--;
}
if (lineLastWithText < line) {
- xStartText = 100000; // Don't limit to visible indentation on empty line
+ xStartText = largeIndent; // Don't limit to visible indentation on empty line
// This line is empty, so use indentation of last line with text
int indentLastWithText = model.pdoc->GetLineIndentation(lineLastWithText);
const int isFoldHeader = LevelIsHeader(model.pdoc->GetFoldLevel(lineLastWithText));
@@ -2350,21 +2336,21 @@ void EditView::DrawIndentGuidesOverEmpty(Surface *surface, const EditModel &mode
indentLastWithText += model.pdoc->IndentSize();
}
if (vsDraw.viewIndentationGuides == IndentView::LookForward) {
- // In viLookForward mode, previous line only used if it is a fold header
+ // In LookForward mode, previous line only used if it is a fold header
if (isFoldHeader) {
indentSpace = std::max(indentSpace, indentLastWithText);
}
- } else { // viLookBoth
+ } else { // LookBoth
indentSpace = std::max(indentSpace, indentLastWithText);
}
}
Sci::Line lineNextWithText = line;
- while (lineNextWithText < std::min(line + 20, model.pdoc->LinesTotal()) && model.pdoc->IsWhiteLine(lineNextWithText)) {
+ while (lineNextWithText < std::min(line + maxCheck, model.pdoc->LinesTotal()) && model.pdoc->IsWhiteLine(lineNextWithText)) {
lineNextWithText++;
}
if (lineNextWithText > line) {
- xStartText = 100000; // Don't limit to visible indentation on empty line
+ xStartText = largeIndent; // Don't limit to visible indentation on empty line
// This line is empty, so use indentation of first next line with text
indentSpace = std::max(indentSpace,
model.pdoc->GetLineIndentation(lineNextWithText));
@@ -2381,10 +2367,10 @@ void EditView::DrawIndentGuidesOverEmpty(Surface *surface, const EditModel &mode
}
void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
- Sci::Line line, Sci::Line lineVisible, int xStart, PRectangle rcLine, int subLine, DrawPhase phase) {
+ Sci::Line line, Sci::Line lineVisible, int xOrigin, PRectangle rcLine, int subLine, DrawPhase phase) {
if (subLine >= ll->lines) {
- DrawAnnotation(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, phase);
+ DrawAnnotation(surface, model, vsDraw, ll, line, xOrigin, rcLine, subLine, phase);
return; // No further drawing
}
@@ -2404,10 +2390,10 @@ void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyl
if ((ll->wrapIndent != 0) && (subLine > 0)) {
if (FlagSet(phase, DrawPhase::back)) {
- DrawWrapIndentAndMarker(surface, vsDraw, ll, xStart, rcLine, background, customDrawWrapMarker, model.caret.active);
+ DrawWrapIndentAndMarker(surface, vsDraw, ll, xOrigin, rcLine, background, customDrawWrapMarker, model.caret.active);
}
- xStart += static_cast<int>(ll->wrapIndent);
}
+ const int xStart = xOrigin + ((subLine > 0) ? static_cast<int>(ll->wrapIndent) : 0);
if (phasesDraw != PhasesDraw::One) {
if (FlagSet(phase, DrawPhase::back)) {
@@ -2497,7 +2483,7 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V
const Point ptOrigin = model.GetVisibleOriginInMain();
const int screenLinePaintFirst = static_cast<int>(rcArea.top) / vsDraw.lineHeight;
- const int xStart = vsDraw.textStart - model.xOffset + static_cast<int>(ptOrigin.x);
+ const int xOrigin = vsDraw.textStart - model.xOffset + static_cast<int>(ptOrigin.x);
const SelectionPosition posCaret = model.posDrag.IsValid() ? model.posDrag : model.sel.RangeMain().caret;
const Sci::Line lineCaret = model.pdoc->SciLineFromPosition(posCaret.Position());
@@ -2588,7 +2574,7 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V
surface->FillRectangleAligned(rcSpacer, Fill(vsDraw.styles[StyleDefault].back));
}
- DrawLine(surface, model, vsDraw, ll.get(), lineDoc, visibleLine, xStart, rcLine, subLine, phase);
+ DrawLine(surface, model, vsDraw, ll.get(), lineDoc, visibleLine, xOrigin, rcLine, subLine, phase);
#if defined(TIME_PAINTING)
durPaint += ep.Duration(true);
#endif
@@ -2600,7 +2586,7 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V
}
if (FlagSet(phase, DrawPhase::carets)) {
- DrawCarets(surface, model, vsDraw, ll.get(), lineDoc, xStart, rcLine, subLine);
+ DrawCarets(surface, model, vsDraw, ll.get(), lineDoc, xOrigin, rcLine, subLine);
}
if (bufferedDraw) {
@@ -2612,8 +2598,7 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V
surfaceWindow->Copy(rcCopyArea, from, *pixmapLine);
}
- lineWidthMaxSeen = std::max(
- lineWidthMaxSeen, static_cast<int>(ll->positions[ll->numCharsInLine]));
+ UpdateMaxWidth(ll->positions[ll->numCharsInLine]);
#if defined(TIME_PAINTING)
durCopy += ep.Duration(true);
#endif
@@ -2646,14 +2631,14 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V
surfaceWindow->FillRectangleAligned(rcBeyondEOF, Fill(vsDraw.styles[StyleDefault].back));
if (vsDraw.edgeState == EdgeVisualStyle::Line) {
const int edgeX = static_cast<int>(vsDraw.theEdge.column * vsDraw.spaceWidth);
- rcBeyondEOF.left = static_cast<XYPOSITION>(edgeX + xStart);
+ rcBeyondEOF.left = static_cast<XYPOSITION>(edgeX + xOrigin);
rcBeyondEOF.right = rcBeyondEOF.left + 1;
surfaceWindow->FillRectangleAligned(rcBeyondEOF, Fill(vsDraw.theEdge.colour));
} else if (vsDraw.edgeState == EdgeVisualStyle::MultiLine) {
for (size_t edge = 0; edge < vsDraw.theMultiEdge.size(); edge++) {
if (vsDraw.theMultiEdge[edge].column >= 0) {
const int edgeX = static_cast<int>(vsDraw.theMultiEdge[edge].column * vsDraw.spaceWidth);
- rcBeyondEOF.left = static_cast<XYPOSITION>(edgeX + xStart);
+ rcBeyondEOF.left = static_cast<XYPOSITION>(edgeX + xOrigin);
rcBeyondEOF.right = rcBeyondEOF.left + 1;
surfaceWindow->FillRectangleAligned(rcBeyondEOF, Fill(vsDraw.theMultiEdge[edge].colour));
}
@@ -2750,13 +2735,11 @@ Sci::Position EditView::FormatRange(bool draw, CharacterRangeFull chrg, Rectangl
1u << static_cast<unsigned int>(MarkerOutline::HistoryRevertedToModified);
vsPrint.maskInLine &= ~changeMarkers;
+ const int linesInArea = (rc.bottom - rc.top) / vsPrint.lineHeight;
const Sci::Line linePrintStart = model.pdoc->SciLineFromPosition(chrg.cpMin);
- Sci::Line linePrintLast = linePrintStart + (rc.bottom - rc.top) / vsPrint.lineHeight - 1;
- if (linePrintLast < linePrintStart)
- linePrintLast = linePrintStart;
const Sci::Line linePrintMax = model.pdoc->SciLineFromPosition(chrg.cpMax);
- if (linePrintLast > linePrintMax)
- linePrintLast = linePrintMax;
+ const Sci::Line linePrintLast = std::min(std::max(linePrintStart + linesInArea - 1, linePrintStart), linePrintMax);
+
//Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n",
// linePrintStart, linePrintLast, linePrintMax, rc.top, rc.bottom, vsPrint.lineHeight,
// surfaceMeasure->Height(vsPrint.styles[StyleLineNumber].font));
@@ -2767,7 +2750,7 @@ Sci::Position EditView::FormatRange(bool draw, CharacterRangeFull chrg, Rectangl
// Ensure we are styled to where we are formatting.
model.pdoc->EnsureStyledTo(endPosPrint);
- const int xStart = vsPrint.fixedColumnWidth + rc.left;
+ const int xOrigin = vsPrint.fixedColumnWidth + rc.left;
int ypos = rc.top;
Sci::Line lineDoc = linePrintStart;
@@ -2841,7 +2824,7 @@ Sci::Position EditView::FormatRange(bool draw, CharacterRangeFull chrg, Rectangl
if (draw) {
rcLine.top = static_cast<XYPOSITION>(ypos);
rcLine.bottom = static_cast<XYPOSITION>(ypos + vsPrint.lineHeight);
- DrawLine(surface, model, vsPrint, &ll, lineDoc, visibleLine, xStart, rcLine, iwl, DrawPhase::all);
+ DrawLine(surface, model, vsPrint, &ll, lineDoc, visibleLine, xOrigin, rcLine, iwl, DrawPhase::all);
}
ypos += vsPrint.lineHeight;
}