diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/CellBuffer.cxx | 103 | ||||
| -rw-r--r-- | src/CellBuffer.h | 29 | ||||
| -rw-r--r-- | src/CharacterType.h | 38 | ||||
| -rw-r--r-- | src/Document.cxx | 52 | ||||
| -rw-r--r-- | src/Document.h | 1 | ||||
| -rw-r--r-- | src/EditView.cxx | 63 | ||||
| -rw-r--r-- | src/Editor.cxx | 21 | ||||
| -rw-r--r-- | src/Editor.h | 4 |
8 files changed, 209 insertions, 102 deletions
diff --git a/src/CellBuffer.cxx b/src/CellBuffer.cxx index 3e9deb934..1eac3f9c2 100644 --- a/src/CellBuffer.cxx +++ b/src/CellBuffer.cxx @@ -439,35 +439,90 @@ const char *CellBuffer::InsertString(Sci::Position position, const char *s, Sci: return data; } -bool CellBuffer::SetStyleAt(Sci::Position position, char styleValue) noexcept { - if (!hasStyles) { - return false; - } - const char curVal = style.ValueAt(position); - if (curVal != styleValue) { - style.SetValueAt(position, styleValue); - return true; - } else { - return false; +namespace { + +ChangedRange CopyBytes(char *p, const char *styles, Sci::Position length, Sci::Position offset) noexcept { + for (Sci::Position start = 0; start < length; start++) { + if (p[start] != styles[start]) { + for (Sci::Position end = length - 1; end >= 0; end--) { + if (p[end] != styles[end]) { + memcpy(p+start, styles+start, end-start+1); + return { start + offset, end + offset }; + } + } + } } + return {}; } -bool CellBuffer::SetStyleFor(Sci::Position position, Sci::Position lengthStyle, char styleValue) noexcept { - if (!hasStyles) { - return false; - } - bool changed = false; - PLATFORM_ASSERT(lengthStyle == 0 || - (lengthStyle > 0 && lengthStyle + position <= style.Length())); - while (lengthStyle--) { - const char curVal = style.ValueAt(position); - if (curVal != styleValue) { - style.SetValueAt(position, styleValue); - changed = true; +ChangedRange SetBytes(char *p, char style, Sci::Position length, Sci::Position offset) noexcept { + for (Sci::Position start = 0; start < length; start++) { + if (p[start] != style) { + for (Sci::Position end = length - 1; end >= 0; end--) { + if (p[end] != style) { + memset(p+start, style, end-start+1); + return { start + offset, end + offset }; + } + } } - position++; } - return changed; + return {}; +} + +struct Lengths { + Sci::Position length1; + Sci::Position length2; +}; + +Lengths SplitUpdate(const SplitVector<char> &style, Sci::Position position, Sci::Position length) noexcept { + length = std::min(length, style.Length() - position); + + // Divide length into two parts if it overlaps the gap + const Sci::Position part1Length = style.GapPosition(); + + // If all after gap then place in length1 to avoid second call + if (position >= part1Length) { + return { length, 0 }; + } + // If all before gap then place in length1 + const Sci::Position beforeGap = part1Length - position; + if (length <= beforeGap) { + return { length, 0 }; + } + // Some before gap and some after gap so put portion in length1 and rest in length2 + return { beforeGap, length - beforeGap }; +} + +} + +ChangedRange CellBuffer::SetStyles(Sci::Position position, const char *styles, Sci::Position length) noexcept { + if (!hasStyles || (position < 0) || (length <= 0)) { + return {}; + } + + const Lengths lengths = SplitUpdate(style, position, length); + ChangedRange cr = CopyBytes(&style[position], styles, lengths.length1, position); + if (lengths.length2) { + const ChangedRange cr2 = CopyBytes(&style[position + lengths.length1], styles + lengths.length1, + lengths.length2, position + lengths.length1); + cr.Merge(cr2); + } + return cr; +} + +ChangedRange CellBuffer::SetStyleFor(Sci::Position position, Sci::Position length, char value) noexcept { + if (!hasStyles || (position < 0) || (length <= 0)) { + return {}; + } + + const Lengths lengths = SplitUpdate(style, position, length); + ChangedRange cr = SetBytes(&style[position], value, lengths.length1, position); + if (lengths.length2) { + const ChangedRange cr2 = SetBytes(&style[position + lengths.length1], value, + lengths.length2, position + lengths.length1); + cr.Merge(cr2); + } + return cr; } // The char* returned is to an allocation owned by the undo history diff --git a/src/CellBuffer.h b/src/CellBuffer.h index 1b035597a..11479f14a 100644 --- a/src/CellBuffer.h +++ b/src/CellBuffer.h @@ -10,6 +10,11 @@ namespace Scintilla::Internal { +struct Failure : public std::runtime_error { + Status status; + Failure(Status status_) : std::runtime_error("failure with status"), status(status_) {} +}; + // Interface to per-line data that wants to see each line insertion and deletion class PerLine { public: @@ -66,6 +71,24 @@ struct SplitView { } }; +struct ChangedRange { + Sci::Position start = Sci::invalidPosition; + Sci::Position end = Sci::invalidPosition; + ChangedRange() noexcept = default; + ChangedRange(Sci::Position start_, Sci::Position end_) noexcept : start(start_), end(end_) {} + [[nodiscard]] bool Empty() const noexcept { + return start < 0; + } + void Merge(const ChangedRange &cr2) noexcept { + if (cr2.start >= 0) { + if (start < 0) { + *this = cr2; + } else { + end = cr2.end; + } + } + } +}; /** * Holder for an expandable array of characters that supports undo and line markers. @@ -141,9 +164,9 @@ public: const char *InsertString(Sci::Position position, const char *s, Sci::Position insertLength, bool &startSequence); /// Setting styles for positions outside the range of the buffer is safe and has no effect. - /// @return true if the style of a character is changed. - bool SetStyleAt(Sci::Position position, char styleValue) noexcept; - bool SetStyleFor(Sci::Position position, Sci::Position lengthStyle, char styleValue) noexcept; + /// @return range where style of characters changed. + ChangedRange SetStyles(Sci::Position position, const char *styles, Sci::Position length) noexcept; + ChangedRange SetStyleFor(Sci::Position position, Sci::Position length, char value) noexcept; const char *DeleteChars(Sci::Position position, Sci::Position deleteLength, bool &startSequence); diff --git a/src/CharacterType.h b/src/CharacterType.h index 437fb8c5c..a7732cec9 100644 --- a/src/CharacterType.h +++ b/src/CharacterType.h @@ -12,12 +12,29 @@ namespace Scintilla::Internal { // Functions for classifying characters +template <typename T, typename... Args> +constexpr bool AnyOf(T t, Args... args) noexcept { +#if defined(__clang__) + static_assert(__is_integral(T) || __is_enum(T)); +#endif + return ((t == args) || ...); +} + +// prevent pointer without <type_traits> +template <typename T, typename... Args> +constexpr void AnyOf([[maybe_unused]] T *t, [[maybe_unused]] Args... args) noexcept {} +template <typename T, typename... Args> +constexpr void AnyOf([[maybe_unused]] const T *t, [[maybe_unused]] Args... args) noexcept {} + /** * Check if a character is a space. * This is ASCII specific but is safe with chars >= 0x80. */ +constexpr int charTab = 0x09; +constexpr int charCarriageReturn = 0x0D; + constexpr bool IsASpace(int ch) noexcept { - return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d)); + return (ch == ' ') || ((ch >= charTab) && (ch <= charCarriageReturn)); } constexpr bool IsSpaceOrTab(int ch) noexcept { @@ -44,17 +61,18 @@ constexpr bool IsADigit(int ch) noexcept { } constexpr bool IsADigit(int ch, int base) noexcept { - if (base <= 10) { + constexpr int digits = 10; + if (base <= digits) { return (ch >= '0') && (ch < '0' + base); - } else { - return ((ch >= '0') && (ch <= '9')) || - ((ch >= 'A') && (ch < 'A' + base - 10)) || - ((ch >= 'a') && (ch < 'a' + base - 10)); } + return ((ch >= '0') && (ch <= '9')) || + ((ch >= 'A') && (ch < 'A' + base - digits)) || + ((ch >= 'a') && (ch < 'a' + base - digits)); } constexpr bool IsASCII(int ch) noexcept { - return (ch >= 0) && (ch < 0x80); + constexpr int lastASCII = 0x7F; + return (ch >= 0) && (ch <= lastASCII); } constexpr bool IsLowerCase(int ch) noexcept { @@ -122,16 +140,14 @@ template <typename T> constexpr T MakeUpperCase(T ch) noexcept { if (ch < 'a' || ch > 'z') return ch; - else - return ch - 'a' + 'A'; + return ch - 'a' + 'A'; } template <typename T> constexpr T MakeLowerCase(T ch) noexcept { if (ch < 'A' || ch > 'Z') return ch; - else - return ch - 'A' + 'a'; + return ch - 'A' + 'a'; } int CompareCaseInsensitive(const char *a, const char *b) noexcept; diff --git a/src/Document.cxx b/src/Document.cxx index 458c1e93f..289fb6731 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -530,6 +530,13 @@ void SCI_METHOD Document::SetErrorStatus(int status) { } } +void Document::CheckPosition(Sci::Position pos) const { + PLATFORM_ASSERT((pos >= 0) && (pos <= LengthNoExcept())); + if ((pos < 0) || (pos > LengthNoExcept())) { + throw Failure(Status::OutsideDocument); + } +} + Sci_Position SCI_METHOD Document::LineFromPosition(Sci_Position pos) const { return cb.LineFromPosition(pos); } @@ -1485,6 +1492,7 @@ Sci::Position Document::InsertString(Sci::Position position, const char *s, Sci: if (insertLength <= 0) { return 0; } + CheckPosition(position); CheckReadOnly(); // Application may change read only state here if (cb.IsReadOnly()) { return 0; @@ -1907,8 +1915,7 @@ std::string Document::TransformLineEnds(const char *s, size_t len, EndOfLine eol void Document::ConvertLineEnds(EndOfLine eolModeSet) { UndoGroup ug(this); - const Sci::Position length = Length(); - for (Sci::Position pos = 0; pos < length; pos++) { + for (Sci::Position pos = 0; pos < LengthNoExcept(); pos++) { const char ch = cb.CharAt(pos); if (ch == '\r') { if (cb.CharAt(pos + 1) == '\n') { @@ -2572,10 +2579,10 @@ bool SCI_METHOD Document::SetStyleFor(Sci_Position length, char style) { return false; } enteredStyling++; - const Sci::Position prevEndStyled = endStyled; - if (cb.SetStyleFor(endStyled, length, style)) { + const ChangedRange cr = cb.SetStyleFor(endStyled, length, style); + if (!cr.Empty()) { const DocModification mh(ModificationFlags::ChangeStyle | ModificationFlags::User, - prevEndStyled, length); + cr.start, cr.end - cr.start + 1); NotifyModified(mh); } endStyled += length; @@ -2588,22 +2595,11 @@ bool SCI_METHOD Document::SetStyles(Sci_Position length, const char *styles) { return false; } enteredStyling++; - bool didChange = false; - Sci::Position startMod = 0; - Sci::Position endMod = 0; - for (int iPos = 0; iPos < length; iPos++, endStyled++) { - PLATFORM_ASSERT(endStyled < Length()); - if (cb.SetStyleAt(endStyled, styles[iPos])) { - if (!didChange) { - startMod = endStyled; - } - didChange = true; - endMod = endStyled; - } - } - if (didChange) { + const ChangedRange cr = cb.SetStyles(endStyled, styles, length); + endStyled += length; + if (!cr.Empty()) { const DocModification mh(ModificationFlags::ChangeStyle | ModificationFlags::User, - startMod, endMod - startMod + 1); + cr.start, cr.end - cr.start + 1); NotifyModified(mh); } enteredStyling--; @@ -3022,7 +3018,7 @@ Sci::Position Document::BraceMatch(Sci::Position position, Sci::Position /*maxRe return -1; const int styBrace = StyleIndexAt(position); int direction = -1; - if (chBrace == '(' || chBrace == '[' || chBrace == '{' || chBrace == '<') + if (AnyOf(chBrace, '(', '[', '{', '<')) direction = 1; int depth = 1; position = useStartPos ? startPos : position + direction; @@ -3035,7 +3031,7 @@ Sci::Position Document::BraceMatch(Sci::Position position, Sci::Position /*maxRe while ((position >= 0) && (position < LengthNoExcept())) { const unsigned char chAtPos = CharAt(position); - if (chAtPos == chBrace || chAtPos == chSeek) { + if (AnyOf(chAtPos, chBrace, chSeek)) { if (((position > GetEndStyled()) || (StyleIndexAt(position) == styBrace)) && (chAtPos <= maxSafeChar || position == MovePositionOutsideChar(position, direction, false))) { depth += (chAtPos == chBrace) ? 1 : -1; @@ -3141,7 +3137,9 @@ public: const Document *doc; Sci::Position position; - explicit ByteIterator(const Document *doc_=nullptr, Sci::Position position_=0) noexcept : + ByteIterator() noexcept : + ByteIterator(nullptr) {} + explicit ByteIterator(const Document *doc_, Sci::Position position_=0) noexcept : doc(doc_), position(position_) { } char operator*() const noexcept { @@ -3206,7 +3204,9 @@ public: using pointer = wchar_t*; using reference = wchar_t&; - explicit UTF8Iterator(const Document *doc_=nullptr, Sci::Position position_=0) noexcept : + UTF8Iterator() noexcept : + UTF8Iterator(nullptr) {} + explicit UTF8Iterator(const Document *doc_, Sci::Position position_=0) noexcept : doc(doc_), position(position_) { if (doc) { ReadCharacter(); @@ -3295,7 +3295,9 @@ public: using pointer = wchar_t*; using reference = wchar_t&; - explicit UTF8Iterator(const Document *doc_=nullptr, Sci::Position position_=0) noexcept : + UTF8Iterator() noexcept : + UTF8Iterator(nullptr) {} + explicit UTF8Iterator(const Document *doc_, Sci::Position position_=0) noexcept : doc(doc_), position(position_) { } wchar_t operator*() const noexcept { diff --git a/src/Document.h b/src/Document.h index 7fd150f37..dfb0a7ff5 100644 --- a/src/Document.h +++ b/src/Document.h @@ -369,6 +369,7 @@ public: int SCI_METHOD DEVersion() const noexcept override; void SCI_METHOD SetErrorStatus(int status) override; + void CheckPosition(Sci::Position pos) const; Sci_Position SCI_METHOD LineFromPosition(Sci_Position pos) const override; Sci::Line SciLineFromPosition(Sci::Position pos) const noexcept; // Avoids casting LineFromPosition diff --git a/src/EditView.cxx b/src/EditView.cxx index 2608f11e5..b25053845 100644 --- a/src/EditView.cxx +++ b/src/EditView.cxx @@ -352,7 +352,7 @@ 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); @@ -522,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); @@ -610,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) { @@ -1286,6 +1286,7 @@ 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. + surface->FillRectangleAligned(rcSegment, Fill(textBack)); FillLineRemainder(surface, model, vsDraw, ll, line, rcLine, rcSegment.right, subLine); } @@ -1346,7 +1347,7 @@ void EditView::DrawEOLAnnotationText(Surface *surface, const EditModel &model, c namespace { constexpr bool AnnotationBoxedOrIndented(AnnotationVisible annotationVisible) noexcept { - return annotationVisible == AnnotationVisible::Boxed || annotationVisible == AnnotationVisible::Indented; + return AnyOf(annotationVisible, AnnotationVisible::Boxed, AnnotationVisible::Indented); } } @@ -1673,7 +1674,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(); @@ -1682,21 +1683,27 @@ void DrawBackground(Surface *surface, const EditModel &model, const ViewStyle &v // Blob display inIndentation = false; } - surface->FillRectangleAligned(rcSegment, Fill(textBack)); - } else { + } + surface->FillRectangleAligned(rcSegment, Fill(textBack)); + if (!ts.representation) { // Normal text display - surface->FillRectangleAligned(rcSegment, Fill(textBack)); if (vsDraw.viewWhitespace != WhiteSpace::Invisible) { - for (int cpos = 0; cpos <= i - ts.start; cpos++) { - if (ll->chars[cpos + ts.start] == ' ') { + for (int cpos = 0; cpos <= i - ts.start; ) { + int countSpaces = 0; + while ((countSpaces <= i - ts.start - cpos) && (ll->chars[cpos + ts.start + countSpaces] == ' ')) { + countSpaces++; + } + if (countSpaces) { if (drawWhitespaceBackground && vsDraw.WhiteSpaceVisible(inIndentation)) { const PRectangle rcSpace = Intersection(rcLine, - ll->SpanByte(cpos + ts.start).Offset(horizontalOffset)); + ll->Span(cpos + ts.start, cpos + ts.start + countSpaces).Offset(horizontalOffset)); surface->FillRectangleAligned(rcSpace, vsDraw.ElementColourForced(Element::WhiteSpaceBack).Opaque()); } + cpos += countSpaces; } else { inIndentation = false; + cpos++; } } } @@ -2178,7 +2185,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)) @@ -2310,7 +2317,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi void EditView::DrawIndentGuidesOverEmpty(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, Sci::Line line, int xStart, PRectangle rcLine, int subLine, Sci::Line lineVisible) { - if ((vsDraw.viewIndentationGuides == IndentView::LookForward || vsDraw.viewIndentationGuides == IndentView::LookBoth) + if (AnyOf(vsDraw.viewIndentationGuides, IndentView::LookForward, IndentView::LookBoth) && (subLine == 0)) { const Sci::Position posLineStart = model.pdoc->LineStart(line); int indentSpace = model.pdoc->GetLineIndentation(line); @@ -2525,14 +2532,14 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V for (;;) { int yposScreen = screenLinePaintFirst * vsDraw.lineHeight; int ypos = bufferedDraw ? 0 : yposScreen; - Sci::Line visibleLine = model.TopLineOfMain() + screenLinePaintFirst; - while (visibleLine < model.pcs->LinesDisplayed() && yposScreen < rcArea.bottom) { + Sci::Line lineVisible = model.TopLineOfMain() + screenLinePaintFirst; + while (lineVisible < model.pcs->LinesDisplayed() && yposScreen < rcArea.bottom) { - const Sci::Line lineDoc = model.pcs->DocFromDisplay(visibleLine); + const Sci::Line lineDoc = model.pcs->DocFromDisplay(lineVisible); // Only visible lines should be handled by the code within the loop PLATFORM_ASSERT(model.pcs->GetVisible(lineDoc)); const Sci::Line lineStartSet = model.pcs->DisplayFromDoc(lineDoc); - const int subLine = static_cast<int>(visibleLine - lineStartSet); + const int subLine = static_cast<int>(lineVisible - lineStartSet); // Copy this line and its styles from the document into local arrays // and determine the x position at which each character starts. @@ -2574,7 +2581,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, xOrigin, rcLine, subLine, phase); + DrawLine(surface, model, vsDraw, ll.get(), lineDoc, lineVisible, xOrigin, rcLine, subLine, phase); #if defined(TIME_PAINTING) durPaint += ep.Duration(true); #endif @@ -2609,7 +2616,7 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V } yposScreen += vsDraw.lineHeight; - visibleLine++; + lineVisible++; } if (phase >= DrawPhase::carets) { @@ -2704,7 +2711,7 @@ Sci::Position EditView::FormatRange(bool draw, CharacterRangeFull chrg, Rectangl } else if (colourMode == PrintOption::BlackOnWhite) { it->fore = black; it->back = white; - } else if (colourMode == PrintOption::ColourOnWhite || colourMode == PrintOption::ColourOnWhiteDefaultBG) { + } else if (AnyOf(colourMode, PrintOption::ColourOnWhite, PrintOption::ColourOnWhiteDefaultBG)) { it->back = white; } } @@ -2756,7 +2763,7 @@ Sci::Position EditView::FormatRange(bool draw, CharacterRangeFull chrg, Rectangl Sci::Line lineDoc = linePrintStart; Sci::Position nPrintPos = chrg.cpMin; - int visibleLine = 0; + int lineVisible = 0; int widthPrint = rc.right - rc.left - vsPrint.fixedColumnWidth; if (printParameters.wrapState == Wrap::None) widthPrint = LineLayout::wrapWidthInfinite; @@ -2785,23 +2792,23 @@ Sci::Position EditView::FormatRange(bool draw, CharacterRangeFull chrg, Rectangl // When document line is wrapped over multiple display lines, find where // to start printing from to ensure a particular position is on the first // line of the page. - if (visibleLine == 0) { + if (lineVisible == 0) { const Sci::Position startWithinLine = nPrintPos - model.pdoc->LineStart(lineDoc); for (int iwl = 0; iwl < ll.lines - 1; iwl++) { if (ll.LineStart(iwl) <= startWithinLine && ll.LineStart(iwl + 1) >= startWithinLine) { - visibleLine = -iwl; + lineVisible = -iwl; } } if (ll.lines > 1 && startWithinLine >= ll.LineStart(ll.lines - 1)) { - visibleLine = -(ll.lines - 1); + lineVisible = -(ll.lines - 1); } } if (draw && lineNumberWidth && (ypos + vsPrint.lineHeight <= rc.bottom) && - (visibleLine >= 0)) { + (lineVisible >= 0)) { const std::string number = std::to_string(lineDoc + 1) + lineNumberPrintSpace; PRectangle rcNumber = rcLine; rcNumber.right = rcNumber.left + lineNumberWidth; @@ -2820,15 +2827,15 @@ Sci::Position EditView::FormatRange(bool draw, CharacterRangeFull chrg, Rectangl for (int iwl = 0; iwl < ll.lines; iwl++) { if (ypos + vsPrint.lineHeight <= rc.bottom) { - if (visibleLine >= 0) { + if (lineVisible >= 0) { if (draw) { rcLine.top = static_cast<XYPOSITION>(ypos); rcLine.bottom = static_cast<XYPOSITION>(ypos + vsPrint.lineHeight); - DrawLine(surface, model, vsPrint, &ll, lineDoc, visibleLine, xOrigin, rcLine, iwl, DrawPhase::all); + DrawLine(surface, model, vsPrint, &ll, lineDoc, lineVisible, xOrigin, rcLine, iwl, DrawPhase::all); } ypos += vsPrint.lineHeight; } - visibleLine++; + lineVisible++; if (iwl == ll.lines - 1) nPrintPos = model.pdoc->LineStart(lineDoc + 1); else diff --git a/src/Editor.cxx b/src/Editor.cxx index 5b42407e3..1dfa8fd6b 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -3818,7 +3818,7 @@ int Editor::DelWordOrLine(Message iMessage) { // Rightwards and leftwards deletions differ in treatment of virtual space. // Clear virtual space for leftwards, realise for rightwards. - const bool leftwards = (iMessage == Message::DelWordLeft) || (iMessage == Message::DelLineLeft); + const bool leftwards = AnyOf(iMessage, Message::DelWordLeft, Message::DelLineLeft); if (!additionalSelectionTyping) { InvalidateWholeSelection(); @@ -4029,14 +4029,14 @@ int Editor::KeyCommand(Message iMessage) { break; case Message::DeleteBack: DelCharBack(true); - if ((caretSticky == CaretSticky::Off) || (caretSticky == CaretSticky::WhiteSpace)) { + if (AnyOf(caretSticky, CaretSticky::Off, CaretSticky::WhiteSpace)) { SetLastXChosen(); } EnsureCaretVisible(); break; case Message::DeleteBackNotLine: DelCharBack(false); - if ((caretSticky == CaretSticky::Off) || (caretSticky == CaretSticky::WhiteSpace)) { + if (AnyOf(caretSticky, CaretSticky::Off, CaretSticky::WhiteSpace)) { SetLastXChosen(); } EnsureCaretVisible(); @@ -4053,7 +4053,7 @@ int Editor::KeyCommand(Message iMessage) { case Message::BackTab: case Message::LineDedent: Indent(false, iMessage == Message::LineDedent); - if ((caretSticky == CaretSticky::Off) || (caretSticky == CaretSticky::WhiteSpace)) { + if (AnyOf(caretSticky, CaretSticky::Off, CaretSticky::WhiteSpace)) { SetLastXChosen(); } EnsureCaretVisible(); @@ -4859,7 +4859,7 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, KeyMod modi wordSelectAnchorEndPos = endWord; wordSelectInitialCaretPos = sel.MainCaret(); WordSelection(wordSelectInitialCaretPos); - } else if (selectionUnit == TextUnit::subLine || selectionUnit == TextUnit::wholeLine) { + } else if (AnyOf(selectionUnit, TextUnit::subLine, TextUnit::wholeLine)) { lineAnchorPos = newPos.Position(); LineSelection(lineAnchorPos, lineAnchorPos, selectionUnit == TextUnit::wholeLine); //Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos); @@ -4919,7 +4919,7 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, KeyMod modi // Switch to just the click position SetSelection(newPos, newPos); } - if (!sel.Range(selectionPart).Empty()) { + if (dragDropEnabled && !sel.Range(selectionPart).Empty()) { inDragDrop = DragDrop::initial; } } @@ -5395,7 +5395,7 @@ Sci::Position Editor::PositionAfterMaxStyling(Sci::Position posMax, bool scrolli } void Editor::StartIdleStyling(bool truncatedLastStyling) { - if ((idleStyling == IdleStyling::All) || (idleStyling == IdleStyling::AfterVisible)) { + if (AnyOf(idleStyling, IdleStyling::All, IdleStyling::AfterVisible)) { if (pdoc->GetEndStyled() < pdoc->Length()) { // Style remainder of document in idle time needIdleStyling = true; @@ -5899,6 +5899,8 @@ Sci::Position Editor::GetTag(char *tagValue, int tagNumber) { } Sci::Position Editor::ReplaceTarget(ReplaceType replaceType, std::string_view text) { + pdoc->CheckPosition(targetRange.start.Position()); + UndoGroup ug(pdoc); std::string substituted; // Copy in case of re-entrance @@ -6344,7 +6346,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { case Message::Paste: Paste(); - if ((caretSticky == CaretSticky::Off) || (caretSticky == CaretSticky::WhiteSpace)) { + if (AnyOf(caretSticky, CaretSticky::Off, CaretSticky::WhiteSpace)) { SetLastXChosen(); } EnsureCaretVisible(); @@ -6697,6 +6699,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { Sci::Position insertPos = PositionFromUPtr(wParam); if (insertPos == -1) insertPos = CurrentPosition(); + pdoc->CheckPosition(insertPos); Sci::Position newCurrent = CurrentPosition(); const char *sz = ConstCharPtrFromSPtr(lParam); const Sci::Position lengthInserted = pdoc->InsertString(insertPos, sz, strlen(sz)); @@ -6984,7 +6987,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { return static_cast<sptr_t>(vs.tabDrawMode); case Message::SetTabDrawMode: - vs.tabDrawMode = static_cast<TabDrawMode>(wParam); + SetAppearance(vs.tabDrawMode, static_cast<TabDrawMode>(wParam)); Redraw(); break; diff --git a/src/Editor.h b/src/Editor.h index 95b83f1f7..0243d5b63 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -16,7 +16,7 @@ class Timer { public: bool ticking; int ticksToWait; - enum {tickSize = 100}; + static constexpr int tickSize = 100; TickerID tickerID; Timer() noexcept; @@ -226,7 +226,7 @@ protected: // ScintillaBase subclass needs access to much of Editor Timer timer; Timer autoScrollTimer; - enum { autoScrollDelay = 200 }; + static constexpr int autoScrollDelay = 200; Idler idler; |
