[scintilla:bugs] #2511 Some doubtful use of `LineLayout::maxLineLength`

1 view
Skip to first unread message

Zufu Liu

unread,
Jun 5, 2026, 3:30:34 AMJun 5
to scintill...@googlegroups.com

[bugs:#2511] Some doubtful use of `LineLayout::maxLineLength`

Status: open
Group: Bug
Labels: layout Scintilla
Created: Fri Jun 05, 2026 07:30 AM UTC by Zufu Liu
Last Updated: Fri Jun 05, 2026 07:30 AM UTC
Owner: Neil Hodgson

The last character, style and position for LineLayout is at numCharsInLine index, for lineLength = model.pdoc->LineStart(lineNumber + 1) - model.pdoc->LineStart(lineNumber), maxLineLength >= lineLength >= numCharsInLine >= numCharsBeforeEOL.

maxLineLength is growth only (by LineLayout::Resize() method), it's tight to capacity for chars, styles and positions, so it may extremely larger than lineLength (line length with EOL), some code seems to treat it as lineLength.

  1. Inside EditView::StartEndDisplayLine(), the check if (posInLine <= ll->maxLineLength) can (?) be changed into osInLine <= ll->numCharsInLine.

  2. Inside LineLayout::PointFromPosition():

// In case of very long line put x at arbitrary large position
if (posInLine > maxLineLength) {
    pt.x = positions[maxLineLength] - positions[LineStart(lines)];
}

when posInLine > numCharsInLine, the result will be negative (positions beyond numCharsInLine are cleared and never write into), the code can be changed to use numCharsInLine:

// In case of very long line put x at arbitrary large position
if (posInLine > numCharsInLine) {
    pt.x = positions[numCharsInLine] - positions[LineStart(lines)];
}
  1. Inside LineLayout::ClearPositions(), change maxLineLength to numCharsInLine could speedup word wrap on slow system, note that chars and styles beyond numCharsInLine are not cleared.

LineLayoutCache::Retrieve() can be changed to use ReSet() to reset the layout:

if (cache[pos] && !cache[pos]->CanHold(lineNumber, maxChars)) {
    //cache[pos].reset();
    cache[pos].ReSet(lineNumber, maxChars);
}

Sent from sourceforge.net because scintill...@googlegroups.com is subscribed to https://sourceforge.net/p/scintilla/bugs/

To unsubscribe from further messages, a project admin can change settings at https://sourceforge.net/p/scintilla/admin/bugs/options. Or, if this is a mailing list, you can unsubscribe from the mailing list.

Zufu Liu

unread,
Jun 5, 2026, 3:59:58 AMJun 5
to scintill...@googlegroups.com

I'm find these when try to align up maxLineLength to reduce resizing (similar to LineLayoutCache), and check whether it will makes word wrap faster ([feature-requests:#1481]), the gain is tiny (line wraps in random order and resizing count is small).

Neil Hodgson

unread,
Jun 11, 2026, 3:34:57 AMJun 11
to scintill...@googlegroups.com
  1. "// In case of very long line". The comment doesn't really match the code. Its like that because LineLayout::maxLineLength used to be a hard coded constant =4000. Longer lines were just truncated.

Bounding to numCharsInLine seems OK.

  1. No side effect (change to posRet can occur unless posInLine <= ll->numCharsBeforeEOL (3rd clause of if) so the change appears OK. Drop the redundant clause too.

  2. "ClearPositions(), change maxLineLength to numCharsInLine". Leaving dead values is less stable than clearing to 0 and could lead to more subtle bugs that are dependent on history.

  3. "Retrieve() can be changed to use ReSet()". That appears to save a LineLayout allocation so might be worthwhile.


[bugs:#2511] Some doubtful use of `LineLayout::maxLineLength`

Status: open
Group: Bug
Labels: layout Scintilla
Created: Fri Jun 05, 2026 07:30 AM UTC by Zufu Liu

Last Updated: Fri Jun 05, 2026 07:59 AM UTC
Owner: Neil Hodgson

Zufu Liu

unread,
Jun 11, 2026, 6:05:04 AMJun 11
to scintill...@googlegroups.com

Bounding to nnumCharsInLine seems OK.

will 1 be added like LineLayout::XInLine() ?

XYPOSITION LineLayout::XInLine(Sci::Position index) const noexcept {
    // For positions inside line return value from positions
    // For positions after line return last position + 1.0
    if (index <= numCharsInLine) {
        return positions[index];
    }
    return positions[numCharsInLine] + 1.0;
}

"Retrieve() can be changed to use ReSet()". That appears to save a LineLayout allocation so might be worthwhile.

EditView::FormatRange() can move LineLayout ll out from the loop, and reset it in the loop.


[bugs:#2511] Some doubtful use of `LineLayout::maxLineLength`

Status: open
Group: Bug
Labels: layout Scintilla
Created: Fri Jun 05, 2026 07:30 AM UTC by Zufu Liu

Last Updated: Thu Jun 11, 2026 07:34 AM UTC
Owner: Neil Hodgson

Neil Hodgson

unread,
Jun 11, 2026, 7:28:33 PMJun 11
to scintill...@googlegroups.com

The +1 is about drawing some indicators more visibly and is only ever called from DrawIndicator.

EditView::FormatRange() ... ll out from the loop

It is cleaner to minimize the lifetime of variables and its unlikely avoiding some allocations will be significant here.


[bugs:#2511] Some doubtful use of `LineLayout::maxLineLength`

Status: open
Group: Bug
Labels: layout Scintilla
Created: Fri Jun 05, 2026 07:30 AM UTC by Zufu Liu

Last Updated: Thu Jun 11, 2026 10:04 AM UTC
Owner: Neil Hodgson

Zufu Liu

unread,
Jun 12, 2026, 5:59:21 AMJun 12
to scintill...@googlegroups.com

Following is the change:

diff -r a2c9fad98106 src/EditView.cxx
--- a/src/EditView.cxx
+++ b/src/EditView.cxx
@@ -807,7 +807,7 @@
        const Sci::Position posLineStart = model.pdoc->LineStart(line);
        LayoutLine(model, surface, vs, ll.get(), model.wrapWidth);
        const Sci::Position posInLine = pos - posLineStart;

-       if (posInLine <= ll->maxLineLength) {
+       if (posInLine <= ll->numCharsInLine) {
            for (int subLine = 0; subLine < ll->lines; subLine++) {
                if ((posInLine >= ll->LineStart(subLine)) &&
                    (posInLine <= ll->LineStart(subLine + 1)) &&
diff -r a2c9fad98106 src/PositionCache.cxx
--- a/src/PositionCache.cxx
+++ b/src/PositionCache.cxx
@@ -258,11 +258,6 @@

 Point LineLayout::PointFromPosition(int posInLine, int lineHeight, PointEnd pe) const noexcept {
    Point pt;

-   // In case of very long line put x at arbitrary large position
-   if (posInLine > maxLineLength) {
-       pt.x = positions[maxLineLength] - positions[LineStart(lines)];
-   }
-
    for (int subLine = 0; subLine < lines; subLine++) {
        const Range rangeSubLine = SubLineRange(subLine, Scope::visibleOnly);
        if (posInLine >= rangeSubLine.start) {
@@ -605,7 +600,7 @@

    if (pos < cache.size()) {
        if (cache[pos] && !cache[pos]->CanHold(lineNumber, maxChars)) {

-           cache[pos].reset();
+           cache[pos]->ReSet(lineNumber, maxChars);
        }
        if (!cache[pos]) {
            cache[pos] = std::make_shared<LineLayout>(lineNumber, maxChars);

removed // In case of very long line put x at arbitrary large position block from LineLayout::PointFromPosition(), pt.x previous has zero or negative, using numCharsInLine makes it has zero as LineStart(lines) returns numCharsInLine.

Attachments:


[bugs:#2511] Some doubtful use of `LineLayout::maxLineLength`

Status: open
Group: Bug
Labels: layout Scintilla
Created: Fri Jun 05, 2026 07:30 AM UTC by Zufu Liu

Last Updated: Thu Jun 11, 2026 11:28 PM UTC
Owner: Neil Hodgson

Neil Hodgson

unread,
Jun 12, 2026, 9:07:54 PMJun 12
to scintill...@googlegroups.com
  • status: open --> open-fixed
  • Comment:

Committed with [033c34].


[bugs:#2511] Some doubtful use of `LineLayout::maxLineLength`

Status: open-fixed


Group: Bug
Labels: layout Scintilla
Created: Fri Jun 05, 2026 07:30 AM UTC by Zufu Liu

Last Updated: Fri Jun 12, 2026 09:59 AM UTC
Owner: Neil Hodgson

Reply all
Reply to author
Forward
0 new messages