diff --git a/scintilla/src/EditModel.h b/scintilla/src/EditModel.h index 5972c11eaa..66b6752ae0 100644 --- a/scintilla/src/EditModel.h +++ b/scintilla/src/EditModel.h @@ -59,6 +59,7 @@ class EditModel { ActionDuration durationWrapOneUnit; ActionDuration durationWrapOneThread; static constexpr uint32_t IdleLineWrapTime = 250; + static constexpr uint32_t MaxPaintTextTime = 16; // 60Hz void *idleTaskTimer; EditModel(); @@ -71,7 +72,7 @@ class EditModel { virtual Sci::Line TopLineOfMain() const noexcept = 0; virtual Point GetVisibleOriginInMain() const noexcept = 0; virtual Sci::Line LinesOnScreen() const noexcept = 0; - virtual void OnLineWrapped(Sci::Line lineDoc, int linesWrapped) = 0; + virtual void OnLineWrapped(Sci::Line lineDoc, int linesWrapped, int option) = 0; bool BidirectionalEnabled() const noexcept; bool BidirectionalR2L() const noexcept { return bidirectional == Scintilla::Bidirectional::R2L; diff --git a/scintilla/src/EditView.cxx b/scintilla/src/EditView.cxx index d738bfec97..8f7f107813 100644 --- a/scintilla/src/EditView.cxx +++ b/scintilla/src/EditView.cxx @@ -435,7 +435,7 @@ struct LayoutWorker { const int endPos = ll->numCharsInLine; if (endPos - startPos > blockSize*2 && !model.BidirectionalEnabled()) { posInLine = std::max(posInLine, ll->caretPosition) + blockSize; - if (posInLine > static_cast(endPos)) { + if (static_cast(endPos - posInLine) < blockSize) { posInLine = endPos; } else if (option < LayoutLineOption::IdleUpdate) { // layout as much as possible to avoid unexpected scrolling @@ -651,7 +651,7 @@ uint64_t EditView::LayoutLine(const EditModel &model, Surface *surface, const Vi const bool partialLine = validity == LineLayout::ValidLevel::lines && ll->PartialPosition() && width == ll->widthLine; if (validity == LineLayout::ValidLevel::invalid - || (option != LayoutLineOption::KeepPosition && ll->PartialPosition())) { + || (option != LayoutLineOption::PaintText && ll->PartialPosition())) { //if (ll->maxLineLength > LayoutWorker::blockSize) { // printf("start layout line=%zd, posInLine=%d\n", line + 1, posInLine); //} @@ -753,8 +753,9 @@ uint64_t EditView::LayoutLine(const EditModel &model, Surface *surface, const Vi } validity = LineLayout::ValidLevel::lines; - if (partialLine && option == LayoutLineOption::AutoUpdate && linesWrapped != ll->lines) { - const_cast(model).OnLineWrapped(line, ll->lines); + if (linesWrapped != ll->lines && ((option == LayoutLineOption::AutoUpdate && partialLine) + || (option == LayoutLineOption::PaintText && ll->PartialPosition()))) { + const_cast(model).OnLineWrapped(line, ll->lines, static_cast(option)); } } ll->validity = validity; @@ -2701,6 +2702,7 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V surface->SetMode(model.CurrentSurfaceMode()); } + model.SetIdleTaskTime(EditModel::MaxPaintTextTime); const Point ptOrigin = model.GetVisibleOriginInMain(); const int screenLinePaintFirst = static_cast(rcArea.top) / vsDraw.lineHeight; @@ -2744,7 +2746,7 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V phase = DrawPhase::back; } - do { + while (true) { int yposScreen = screenLinePaintFirst * vsDraw.lineHeight; int ypos = bufferedDraw ? 0 : yposScreen; const int bottom = static_cast(rcArea.bottom); @@ -2766,7 +2768,7 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V if (lineDoc != lineDocPrevious) { lineDocPrevious = lineDoc; ll = RetrieveLineLayout(lineDoc, model); - LayoutLine(model, surface, vsDraw, ll, model.wrapWidth, LayoutLineOption::KeepPosition); + LayoutLine(model, surface, vsDraw, ll, model.wrapWidth, LayoutLineOption::PaintText); if (model.BidirectionalEnabled()) { // Fill the line bidi data UpdateBidiData(model, vsDraw, ll); @@ -2775,7 +2777,10 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V #if defined(TIME_PAINTING) durLayout += ep.Reset(); #endif - if (ll) { + { +#if defined(__clang__) + __builtin_assume(ll != nullptr); // suppress [clang-analyzer-core.CallAndMessage] +#endif ll->containsCaret = vsDraw.selection.visible && (lineDoc == lineCaret) && (ll->lines == 1 || !vsDraw.caretLine.subLine || ll->InLine(caretOffset, subLine)); @@ -2837,8 +2842,11 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V visibleLine++; } + if (phase >= DrawPhase::carets) { + break; + } phase = static_cast(static_cast(phase) << 1); - } while (phase < DrawPhase::all); + } #if defined(TIME_PAINTING) if (durPaint < 0.00000001) durPaint = 0.00000001; diff --git a/scintilla/src/EditView.h b/scintilla/src/EditView.h index 5cf281aaad..f6bedc1fa4 100644 --- a/scintilla/src/EditView.h +++ b/scintilla/src/EditView.h @@ -37,7 +37,7 @@ enum class LayoutLineOption { AutoUpdate = 0, ManualUpdate = 1, IdleUpdate = 2, - KeepPosition = 3, + PaintText = 3, Printing = 4, CallerMultiThreaded = 8, DisablePartialLayout = 16, diff --git a/scintilla/src/Editor.cxx b/scintilla/src/Editor.cxx index 12f74b97b4..79cec6d337 100644 --- a/scintilla/src/Editor.cxx +++ b/scintilla/src/Editor.cxx @@ -1498,13 +1498,13 @@ bool Editor::WrapOneLine(Surface *surface, Sci::Position positionInsert) { return pcs->SetHeight(lineToWrap, linesWrapped); } -void Editor::OnLineWrapped(Sci::Line lineDoc, int linesWrapped) { +void Editor::OnLineWrapped(Sci::Line lineDoc, int linesWrapped, int option) { if (Wrapping()) { //printf("%s(%zd, %d)\n", __func__, lineDoc, linesWrapped); if (vs.annotationVisible != AnnotationVisible::Hidden) { linesWrapped += pdoc->AnnotationLines(lineDoc); } - if (pcs->SetHeight(lineDoc, linesWrapped)) { + if (pcs->SetHeight(lineDoc, linesWrapped) && option == static_cast(LayoutLineOption::AutoUpdate)) { NeedWrapping(lineDoc, lineDoc + 1, false); SetScrollBars(); SetVerticalScrollPos(); diff --git a/scintilla/src/Editor.h b/scintilla/src/Editor.h index cf5d8a0788..5ec839d2d3 100644 --- a/scintilla/src/Editor.h +++ b/scintilla/src/Editor.h @@ -327,7 +327,7 @@ class Editor : public EditModel, public DocWatcher { PRectangle GetTextRectangle() const noexcept; Sci::Line LinesOnScreen() const noexcept override; - void OnLineWrapped(Sci::Line lineDoc, int linesWrapped) override; + void OnLineWrapped(Sci::Line lineDoc, int linesWrapped, int option) override; Sci::Line LinesToScroll() const noexcept; Sci::Line MaxScrollPos() const noexcept; SelectionPosition ClampPositionIntoDocument(SelectionPosition sp) const noexcept;