diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index fca31431b..a9cb0f8bd 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -453,12 +453,21 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void unregisterPlugin( UICodeEditorPlugin* plugin ); + virtual Vector2f getTextPositionOffset( const TextPosition& pos ) const; + + Vector2f getTextPositionOffsetSanitized( TextPosition pos ) const; + virtual Int64 getColFromXOffset( Int64 visualLine, const Float& x ) const; virtual Float getXOffsetCol( const TextPosition& position ) const; Float getXOffsetColSanitized( TextPosition position ) const; + std::vector + getTextRangeRectangles( const TextRange& range, const Vector2f& startScroll, + std::optional> lineRange = {}, + std::optional lineHeight = {} ); + virtual Float getLineWidth( const Int64& docLine ); size_t characterWidth( const String& str ) const; @@ -610,6 +619,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { Vector2f getScreenStart() const; + Vector2f getScreenScroll() const; + Float getViewportWidth( const bool& forceVScroll = false ) const; bool getShowIndentationGuides() const; diff --git a/src/eepp/ui/linewrapping.cpp b/src/eepp/ui/linewrapping.cpp index 405030f0e..3ca2b06df 100644 --- a/src/eepp/ui/linewrapping.cpp +++ b/src/eepp/ui/linewrapping.cpp @@ -326,7 +326,8 @@ TextRange LineWrapping::getVisualLineRange( Int64 visualLine ) const { return mDoc->getLineRange( visualLine ); auto start = getDocumentLine( visualLine ); auto end = start; - if ( visualLine + 1 < static_cast( mWrappedLines.size() ) ) { + if ( visualLine + 1 < static_cast( mWrappedLines.size() ) && + mWrappedLines[visualLine + 1].line() == start.line() ) { end.setColumn( mWrappedLines[visualLine + 1].column() ); } else { end.setColumn( mDoc->line( start.line() ).size() ); diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index 0de679008..df190a162 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -357,10 +357,8 @@ void UICodeEditor::draw() { } if ( hasFocus() && getUISceneNode()->getWindow()->getIME().isEditing() ) { - Vector2f cursorPos( startScroll.x + getXOffsetCol( cursor ), - startScroll.y + - mLineWrapping.toWrappedIndex( cursor.line() ) * lineHeight + - getLineOffset() ); + auto offset = getTextPositionOffset( cursor ); + Vector2f cursorPos( startScroll.x + offset.x, startScroll.y + offset.y ); FontStyleConfig config( mFontStyleConfig ); config.FontColor = mFontStyleConfig.getFontSelectedColor(); getUISceneNode()->getWindow()->getIME().draw( cursorPos, getFontHeight(), config, @@ -1056,8 +1054,8 @@ Rectf UICodeEditor::getScreenPosition( const TextPosition& position ) const { Vector2f screenStart( getScreenStart() ); Vector2f start( screenStart.x + getGutterWidth(), screenStart.y ); Vector2f startScroll( start - mScroll ); - return { { startScroll.x + getXOffsetColSanitized( position ), - startScroll.y + lineHeight * position.line() }, + auto offset = getTextPositionOffsetSanitized( position ); + return { { startScroll.x + offset.x, startScroll.y + offset.y }, { getGlyphWidth(), lineHeight } }; } @@ -1547,10 +1545,8 @@ Vector2f UICodeEditor::getRelativeScreenPosition( const TextPosition& pos ) { Float gutterWidth = getGutterWidth(); Vector2f start( gutterWidth, getPluginsTopSpace() ); Vector2f startScroll( start - mScroll ); - auto lineHeight = getLineHeight(); - return { startScroll.x + getXOffsetCol( pos ), - startScroll.y + mLineWrapping.toWrappedIndex( pos.line() ) * lineHeight + - getLineOffset() }; + auto offset = getTextPositionOffset( pos ); + return { startScroll.x + offset.x, startScroll.y + offset.y + getLineOffset() }; } bool UICodeEditor::getShowLinesRelativePosition() const { @@ -1569,13 +1565,11 @@ UIScrollBar* UICodeEditor::getHScrollBar() const { return mHScrollBar; } -void UICodeEditor::drawCursor( const Vector2f& startScroll, const Float& lineHeight, +void UICodeEditor::drawCursor( const Vector2f& startScroll, const Float&, const TextPosition& cursor ) { if ( mCursorVisible && !mLocked && isTextSelectionEnabled() ) { - Vector2f cursorPos( startScroll.x + getXOffsetCol( cursor ), - startScroll.y + - mLineWrapping.toWrappedIndex( cursor.line() ) * lineHeight + - getLineOffset() ); + auto offset = getTextPositionOffset( cursor ); + Vector2f cursorPos( startScroll.x + offset.x, startScroll.y + offset.y ); Primitives primitives; primitives.setColor( Color( mCaretColor ).blendAlpha( mAlpha ) ); primitives.drawRectangle( @@ -2047,21 +2041,22 @@ void UICodeEditor::setScrollY( const Float& val, bool emmitEvent ) { } } -Float UICodeEditor::getXOffsetCol( const TextPosition& position ) const { +Vector2f UICodeEditor::getTextPositionOffset( const TextPosition& position ) const { if ( mLineWrapping.isWrappedLine( position.line() ) ) { auto info = mLineWrapping.getVisualLineInfo( position ); if ( mFont && !mFont->isMonospace() ) { - return Text::findCharacterPos( - ( position.column() == - (Int64)mDoc->line( position.line() ).getText().size() ) - ? position.column() - 1 - : position.column(), - mFont, getCharacterSize(), - mDoc->line( position.line() ) - .getText() - .substr( info.range.start().column(), info.range.end().column() ), - mFontStyleConfig.Style, mTabWidth ) - .x; + return { + Text::findCharacterPos( + ( position.column() == (Int64)mDoc->line( position.line() ).getText().size() ) + ? position.column() - 1 + : position.column(), + mFont, getCharacterSize(), + mDoc->line( position.line() ) + .getText() + .substr( info.range.start().column(), info.range.end().column() ), + mFontStyleConfig.Style, mTabWidth ) + .x, + info.visualIndex * getLineHeight() }; } const String& line = mDoc->line( position.line() ).getText(); Float glyphWidth = getGlyphWidth(); @@ -2074,17 +2069,19 @@ Float UICodeEditor::getXOffsetCol( const TextPosition& position ) const { x += glyphWidth; } } - return x; + + return { x, info.visualIndex * getLineHeight() }; } if ( mFont && !mFont->isMonospace() ) { - return Text::findCharacterPos( - ( position.column() == (Int64)mDoc->line( position.line() ).getText().size() ) - ? position.column() - 1 - : position.column(), - mFont, getCharacterSize(), mDoc->line( position.line() ).getText(), - mFontStyleConfig.Style, mTabWidth ) - .x; + return { Text::findCharacterPos( + ( position.column() == (Int64)mDoc->line( position.line() ).getText().size() ) + ? position.column() - 1 + : position.column(), + mFont, getCharacterSize(), mDoc->line( position.line() ).getText(), + mFontStyleConfig.Style, mTabWidth ) + .x, + getLineHeight() * mLineWrapping.toWrappedIndex( position.line() ) }; } const String& line = mDoc->line( position.line() ).getText(); @@ -2098,7 +2095,11 @@ Float UICodeEditor::getXOffsetCol( const TextPosition& position ) const { x += glyphWidth; } } - return x; + return { x, getLineHeight() * mLineWrapping.toWrappedIndex( position.line() ) }; +} + +Float UICodeEditor::getXOffsetCol( const TextPosition& position ) const { + return getTextPositionOffset( position ).x; } template size_t UICodeEditor::characterWidth( const StringType& str ) const { @@ -2150,6 +2151,17 @@ Float UICodeEditor::getXOffsetColSanitized( TextPosition position ) const { return getXOffsetCol( position ); } +Vector2f UICodeEditor::getTextPositionOffsetSanitized( TextPosition position ) const { + position.setLine( eeclamp( position.line(), 0L, mDoc->linesCount() - 1 ) ); + // This is different from sanitizePosition, sinze allows the last character. + position.setColumn( + eeclamp( position.column(), 0L, + eemax( 0, position.line() < static_cast( mDoc->linesCount() ) + ? mDoc->line( position.line() ).size() + : 0 ) ) ); + return getTextPositionOffset( position ); +} + const bool& UICodeEditor::isLocked() const { return mLocked; } @@ -2636,14 +2648,17 @@ Int64 UICodeEditor::getColFromXOffset( Int64 visualLine, const Float& x ) const for ( int i = 0; i < len; i++ ) { bool isTab = ( line[i] == '\t' ); if ( xOffset >= x ) { - return xOffset - x > ( isTab ? hTab : glyphWidth * 0.5f ) ? eemax( 0, i - 1 ) - : i; + auto col = xOffset - x > ( isTab ? hTab : glyphWidth * 0.5f ) + ? eemax( 0, i - 1 ) + : i; + return visualRange.start().column() + col; } else if ( isTab && ( xOffset + tabWidth > x ) ) { - return x - xOffset > hTab ? eemin( i + 1, line.size() - 1 ) : i; + auto col = x - xOffset > hTab ? eemin( i + 1, line.size() - 1 ) : i; + return visualRange.start().column() + col; } xOffset += isTab ? tabWidth : glyphWidth; } - return static_cast( line.size() ) - 1; + return visualRange.start().column() + static_cast( line.size() ) - 1; } if ( mFont && !mFont->isMonospace() ) { @@ -3085,10 +3100,10 @@ void UICodeEditor::drawMatchingBrackets( const Vector2f& startScroll, const Floa primitive.setForceDraw( false ); primitive.setColor( Color( mMatchingBracketColor ).blendAlpha( mAlpha ) ); auto drawBracket = [&]( const TextPosition& pos ) { - primitive.drawRectangle( Rectf( - Vector2f( startScroll.x + getXOffsetCol( pos ), - startScroll.y + mLineWrapping.toWrappedIndex( pos.line() ) * lineHeight ), - Sizef( getGlyphWidth(), lineHeight ) ) ); + auto offset = getTextPositionOffset( pos ); + primitive.drawRectangle( + Rectf( Vector2f( startScroll.x + offset.x, startScroll.y + offset.y ), + Sizef( getGlyphWidth(), lineHeight ) ) ); }; drawBracket( mMatchingBrackets.start() ); drawBracket( mMatchingBrackets.end() ); @@ -3136,15 +3151,15 @@ void UICodeEditor::drawWordRanges( const TextRanges& ranges, const std::pair& } } - Rectf selRect; Int64 startCol = pos; Int64 endCol = pos + text.size(); - selRect.Top = startScroll.y + mLineWrapping.toWrappedIndex( ln ) * lineHeight; - selRect.Bottom = selRect.Top + lineHeight; - selRect.Left = startScroll.x + getXOffsetCol( { ln, startCol } ); - selRect.Right = startScroll.x + getXOffsetCol( { ln, endCol } ); - primitives.drawRectangle( selRect ); + auto rects = getTextRangeRectangles( { { ln, startCol }, { ln, endCol } }, + startScroll, {}, lineHeight ); + for ( const auto& rect : rects ) + primitives.drawRectangle( rect ); + pos = endCol; } else { break; @@ -3421,68 +3435,104 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo } } +std::vector +UICodeEditor::getTextRangeRectangles( const TextRange& range, const Vector2f& startScroll, + std::optional> lineRange, + std::optional lHeight ) { + std::vector rects; + Float lineHeight = lHeight ? *lHeight : getLineHeight(); + int startLine = + eemax( lineRange ? lineRange->first : range.start().line(), range.start().line() ); + int endLine = + eemin( lineRange ? lineRange->second : range.end().line(), range.end().line() ); + for ( auto ln = startLine; ln <= endLine; ln++ ) { + const String& line = mDoc->line( ln ).getText(); + Rectf selRect; + if ( mLineWrapping.isWrappedLine( ln ) ) { + auto fromInfo = mLineWrapping.getVisualLineInfo( + ln == range.start().line() ? range.start() : mDoc->startOfLine( { ln, 0 } ) ); + auto toInfo = mLineWrapping.getVisualLineInfo( + ln == range.end().line() ? range.end() : mDoc->endOfLine( { ln, 0 } ) ); + auto firstWrappedIndex = mLineWrapping.toWrappedIndex( ln ); + for ( Int64 visibleIdx = fromInfo.visualIndex; visibleIdx <= toInfo.visualIndex; + visibleIdx++ ) { + auto info = mLineWrapping.getDocumentLine( visibleIdx ); + Vector2f startOffset; + Vector2f endOffset; + if ( ln == range.start().line() && fromInfo.range.start().line() == ln && + fromInfo.visualIndex == visibleIdx ) { + startOffset = getTextPositionOffset( range.start() ); + } else { + startOffset = getTextPositionOffset( info ); + } + selRect.Top = startScroll.y + startOffset.y; + selRect.Bottom = selRect.Top + lineHeight; + selRect.Left = startScroll.x + startOffset.x; + if ( ln == range.end().line() && toInfo.range.end().line() == ln && + toInfo.visualIndex == visibleIdx ) { + endOffset = getTextPositionOffset( range.end() ); + } else { + auto nextInfo = mLineWrapping.getDocumentLine( visibleIdx + 1 ); + if ( nextInfo.line() == info.line() ) { + endOffset = getTextPositionOffset( { info.line(), nextInfo.column() - 1 } ); + } else { + endOffset = getTextPositionOffset( mDoc->endOfLine( { ln, 0 } ) ); + } + } + selRect.Right = startScroll.x + endOffset.x; + if ( visibleIdx != firstWrappedIndex ) { + selRect.Left += mLineWrapping.getLineOffset( info.line() ); + selRect.Right += mLineWrapping.getLineOffset( info.line() ); + } + rects.push_back( selRect ); + } + } else { + if ( range.start().line() == ln ) { + auto startOffset = getTextPositionOffset( { ln, range.start().column() } ); + selRect.Top = startScroll.y + startOffset.y; + selRect.Bottom = selRect.Top + lineHeight; + selRect.Left = startScroll.x + startOffset.x; + if ( range.end().line() == ln ) { + selRect.Right = + startScroll.x + getTextPositionOffset( { ln, range.end().column() } ).x; + } else { + selRect.Right = + startScroll.x + + getTextPositionOffset( { ln, static_cast( line.length() ) } ).x; + } + } else if ( range.end().line() == ln ) { + auto startOffset = getTextPositionOffset( { ln, 0 } ); + selRect.Top = startScroll.y + startOffset.y; + selRect.Bottom = selRect.Top + lineHeight; + selRect.Left = startScroll.x + startOffset.x; + selRect.Right = + startScroll.x + getTextPositionOffset( { ln, range.end().column() } ).x; + } else { + auto startOffset = getTextPositionOffset( { ln, 0 } ); + selRect.Top = startScroll.y + startOffset.y; + selRect.Bottom = selRect.Top + lineHeight; + selRect.Left = startScroll.x + startOffset.x; + selRect.Right = + startScroll.x + + getTextPositionOffset( { ln, static_cast( line.length() ) } ).x; + } + rects.push_back( selRect ); + } + } + return rects; +} + void UICodeEditor::drawTextRange( const TextRange& range, const std::pair& lineRange, const Vector2f& startScroll, const Float& lineHeight, const Color& backgroundColor ) { Primitives primitives; primitives.setForceDraw( false ); primitives.setColor( Color( backgroundColor ).blendAlpha( mAlpha ) ); - - int startLine = eemax( lineRange.first, range.start().line() ); - int endLine = eemin( lineRange.second, range.end().line() ); - - for ( auto ln = startLine; ln <= endLine; ln++ ) { - const String& line = mDoc->line( ln ).getText(); - Rectf selRect; - - if ( mLineWrapping.isWrappedLine( ln ) ) { - if ( range.start().line() == ln ) { - - } else if ( range.end().line() == ln ) { - - } else { - auto vline = mLineWrapping.getVisualLine( ln ); - for ( size_t subIdx = 0; subIdx < vline.visualLines.size(); subIdx++ ) { - selRect.Top = startScroll.y + ( vline.visualIndex + subIdx ) * lineHeight; - selRect.Bottom = selRect.Top + lineHeight; - selRect.Left = - startScroll.x + getXOffsetCol( { ln, vline.visualLines[subIdx].column() } ); - if ( subIdx + 1 < vline.visualLines.size() ) { - selRect.Right = - startScroll.x + - getXOffsetCol( { ln, vline.visualLines[subIdx + 1].column() - 1 } ); - } else { - selRect.Right = - startScroll.x + getXOffsetCol( mDoc->endOfLine( { ln, 0 } ) ); - } - primitives.drawRectangle( selRect ); - } - } - } else { - selRect.Top = startScroll.y + mLineWrapping.toWrappedIndex( ln ) * lineHeight; - selRect.Bottom = selRect.Top + lineHeight; - if ( range.start().line() == ln ) { - selRect.Left = startScroll.x + getXOffsetCol( { ln, range.start().column() } ); - if ( range.end().line() == ln ) { - selRect.Right = startScroll.x + getXOffsetCol( { ln, range.end().column() } ); - } else { - selRect.Right = startScroll.x + - getXOffsetCol( { ln, static_cast( line.length() ) } ); - } - } else if ( range.end().line() == ln ) { - selRect.Left = startScroll.x + getXOffsetCol( { ln, 0 } ); - selRect.Right = startScroll.x + getXOffsetCol( { ln, range.end().column() } ); - } else { - selRect.Left = startScroll.x + getXOffsetCol( { ln, 0 } ); - selRect.Right = - startScroll.x + getXOffsetCol( { ln, static_cast( line.length() ) } ); - } - - primitives.drawRectangle( selRect ); - } - } - - primitives.setForceDraw( true ); + auto rects = getTextRangeRectangles( range, startScroll, lineRange, lineHeight ); + for ( const auto& rect : rects ) + primitives.drawRectangle( rect ); + if ( !rects.empty() ) + primitives.setForceDraw( true ); } void UICodeEditor::drawLineNumbers( const std::pair& lineRange, @@ -4189,6 +4239,14 @@ Vector2f UICodeEditor::getScreenStart() const { eefloor( mScreenPos.y + mPaddingPx.Top ) ); } +Vector2f UICodeEditor::getScreenScroll() const { + Float gutterWidth = getGutterWidth(); + Vector2f screenStart( getScreenStart() ); + Vector2f start( screenStart.x + gutterWidth, screenStart.y + getPluginsTopSpace() ); + Vector2f startScroll( start - mScroll ); + return startScroll; +} + Float UICodeEditor::getMinimapLineSpacing() const { return eemax( 1.f, eefloor( 2 * PixelDensity::getPixelDensity() * mMinimapConfig.scale ) ); } diff --git a/src/eepp/ui/uitextedit.cpp b/src/eepp/ui/uitextedit.cpp index 43eb35d35..e26833d3a 100644 --- a/src/eepp/ui/uitextedit.cpp +++ b/src/eepp/ui/uitextedit.cpp @@ -117,8 +117,8 @@ bool UITextEdit::applyProperty( const StyleSheetProperty& attribute ) { void UITextEdit::drawCursor( const Vector2f& startScroll, const Float& lineHeight, const TextPosition& cursor ) { if ( mCursorVisible && !mLocked && isTextSelectionEnabled() ) { - Vector2f cursorPos( startScroll.x + getXOffsetCol( cursor ), - startScroll.y + cursor.line() * lineHeight ); + auto offset = getTextPositionOffset( cursor ); + Vector2f cursorPos( startScroll.x + offset.x, startScroll.y + offset.y ); Primitives primitives; primitives.setColor( Color( mFontStyleConfig.FontColor ).blendAlpha( mAlpha ) ); primitives.drawRectangle( diff --git a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp index 1fcbcdd65..607e158b1 100644 --- a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp +++ b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp @@ -848,8 +848,8 @@ void AutoCompletePlugin::drawSignatureHelp( UICodeEditor* editor, const Vector2f return; auto curSig = mSignatureHelp.signatures[curSigIdx]; Float vdiff = drawUp ? -mRowHeight : mRowHeight; - Vector2f pos( startScroll.x + editor->getXOffsetCol( mSignatureHelpPosition ), - startScroll.y + mSignatureHelpPosition.line() * lineHeight + vdiff ); + auto offset = editor->getTextPositionOffset( mSignatureHelpPosition ); + Vector2f pos( startScroll.x + offset.x, startScroll.y + offset.y + vdiff ); primitives.setColor( Color( selectedStyle.background ).blendAlpha( editor->getAlpha() ) ); String str; if ( mSignatureHelp.signatures.size() > 1 ) { @@ -889,9 +889,9 @@ void AutoCompletePlugin::drawSignatureHelp( UICodeEditor* editor, const Vector2f ( curParam.end - curParam.start ) * editor->getGlyphWidth(), curParamRect.getPosition().y }, curParamRect.getSize() } ) ) { - pos = { startScroll.x - curParam.start * editor->getGlyphWidth() + - editor->getXOffsetCol( mSignatureHelpPosition ), - startScroll.y + mSignatureHelpPosition.line() * lineHeight + vdiff }; + auto offset = editor->getTextPositionOffset( mSignatureHelpPosition ); + pos = { startScroll.x - curParam.start * editor->getGlyphWidth() + offset.x, + startScroll.y + offset.y + vdiff }; boxRect.setPosition( pos ); @@ -947,8 +947,8 @@ void AutoCompletePlugin::postDraw( UICodeEditor* editor, const Vector2f& startSc suggestions = mSuggestions; } - Vector2f cursorPos( startScroll.x + editor->getXOffsetCol( start ), - startScroll.y + cursor.line() * lineHeight + lineHeight ); + auto offset = editor->getTextPositionOffset( start ); + Vector2f cursorPos( startScroll.x + offset.x, startScroll.y + offset.y + lineHeight ); size_t largestString = 0; size_t max = eemin( mSuggestionsMaxVisible, suggestions.size() ); diff --git a/src/tools/ecode/plugins/linter/linterplugin.cpp b/src/tools/ecode/plugins/linter/linterplugin.cpp index 1473d083d..c7eab4cd7 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.cpp +++ b/src/tools/ecode/plugins/linter/linterplugin.cpp @@ -1041,7 +1041,8 @@ void LinterPlugin::drawAfterLineText( UICodeEditor* editor, const Int64& index, line.setColor( color ); Int64 strSize = match.range.end().column() - match.range.start().column(); - Vector2f pos = { position.x + editor->getXOffsetCol( match.range.start() ), position.y }; + Vector2f pos = { position.x + editor->getTextPositionOffset( match.range.start() ).x, + position.y }; if ( strSize <= 0 ) { strSize = 1; pos = { position.x, position.y }; diff --git a/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp b/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp index d04e2d49d..3cde3cd82 100644 --- a/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp +++ b/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp @@ -346,7 +346,7 @@ void XMLToolsPlugin::XMLToolsClient::clearMatch() { } void XMLToolsPlugin::drawBeforeLineText( UICodeEditor* editor, const Int64& index, - Vector2f position, const Float& /*fontSize*/, + Vector2f /*position*/, const Float& /*fontSize*/, const Float& lineHeight ) { if ( !isOverMatch( &editor->getDocument(), index ) ) return; @@ -356,13 +356,14 @@ void XMLToolsPlugin::drawBeforeLineText( UICodeEditor* editor, const Int64& inde p.setColor( blendedColor ); const ClientMatch& match = mMatches[&editor->getDocument()]; + auto screenScroll = editor->getScreenScroll(); for ( const auto& range : { match.matchBracket, match.currentBracket } ) { if ( range.start().line() != index || !range.inSameLine() ) continue; - Float offset1 = editor->getXOffsetCol( range.normalized().start() ); - Float offset2 = editor->getXOffsetCol( range.normalized().end() ); - p.drawRectangle( - Rectf( { position.x + offset1, position.y }, { ( offset2 - offset1 ), lineHeight } ) ); + auto rects = + editor->getTextRangeRectangles( range.normalized(), screenScroll, {}, lineHeight ); + for ( const auto& rect : rects ) + p.drawRectangle( rect ); } }