From 3b1ad7723b3d14a79bfd5bc1fffa06f3b3840203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Mon, 30 Sep 2024 01:36:30 -0300 Subject: [PATCH] Some performance optimizations + fix page up and page down with line-wrap enabled. --- include/eepp/ui/doc/textdocument.hpp | 16 +++-- include/eepp/ui/uicodeeditor.hpp | 28 +++++--- src/eepp/ui/doc/documentview.cpp | 1 + src/eepp/ui/doc/textdocument.cpp | 45 +++++++----- src/eepp/ui/uicodeeditor.cpp | 104 ++++++++++++++++++--------- 5 files changed, 129 insertions(+), 65 deletions(-) diff --git a/include/eepp/ui/doc/textdocument.hpp b/include/eepp/ui/doc/textdocument.hpp index b68968b14..39be22ddd 100644 --- a/include/eepp/ui/doc/textdocument.hpp +++ b/include/eepp/ui/doc/textdocument.hpp @@ -226,14 +226,20 @@ class EE_API TextDocument { TextPosition previousChar( TextPosition position ) const; - TextPosition previousWordBoundary( TextPosition position, - bool ignoreFirstNonWord = true ) const; + TextPosition previousWordBoundary( TextPosition position, bool ignoreFirstNonWord = true, + std::size_t maxSeekChars = 1024, + bool returnInvalidOnMaxSeek = false ) const; - TextPosition nextWordBoundary( TextPosition position, bool ignoreFirstNonWord = true ) const; + TextPosition nextWordBoundary( TextPosition position, bool ignoreFirstNonWord = true, + std::size_t maxSeekChars = 1024, + bool returnInvalidOnMaxSeek = false ) const; - TextPosition previousSpaceBoundaryInLine( TextPosition position ) const; + TextPosition previousSpaceBoundaryInLine( TextPosition position, + std::size_t maxSeekChars = 1024, + bool returnInvalidOnMaxSeek = false ) const; - TextPosition nextSpaceBoundaryInLine( TextPosition position ) const; + TextPosition nextSpaceBoundaryInLine( TextPosition position, std::size_t maxSeekChars = 1024, + bool returnInvalidOnMaxSeek = false ) const; TextPosition startOfWord( TextPosition position ) const; diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index ab93feba9..e272181b3 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -429,6 +429,10 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void moveToNextLine(); + void moveToPreviousPage(); + + void moveToNextPage(); + void moveToStartOfLine(); void moveToEndOfLine(); @@ -503,10 +507,11 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { virtual Int64 getColFromXOffset( VisibleIndex visibleIndex, const Float& x ) const; - std::vector - getTextRangeRectangles( const TextRange& range, const Vector2f& startScroll, - std::optional lineRange = {}, - std::optional lineHeight = {} ); + std::vector getTextRangeRectangles( + const TextRange& range, const Vector2f& startScroll, + std::optional lineRange = {}, std::optional lineHeight = {}, + std::optional visibleLineRange = + {} /* if passed it will clip rectangles against the visual line range */ ); virtual Float getLineWidth( const Int64& docLine ); @@ -960,18 +965,19 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { virtual void drawLineText( const Int64& line, Vector2f position, const Float& fontSize, const Float& lineHeight, - const DocumentViewLineRange& visualLineRange ); + const DocumentViewLineRange& visibleLineRange ); virtual void drawSelectionMatch( const DocumentLineRange& lineRange, const Vector2f& startScroll, const Float& lineHeight ); virtual void drawWordMatch( const String& text, const DocumentLineRange& lineRange, const Vector2f& startScroll, const Float& lineHeight, - bool ignoreSelectionMatch = false ); + bool ignoreSelectionMatch = false, + const DocumentViewLineRange& visibleLineRange = {} ); virtual void drawWhitespaces( const DocumentLineRange& lineRange, const Vector2f& startScroll, const Float& lineHeight, - const DocumentViewLineRange& visualLineRange ); + const DocumentViewLineRange& visibleLineRange ); virtual void drawIndentationGuides( const DocumentLineRange& lineRange, const Vector2f& startScroll, const Float& lineHeight ); @@ -981,14 +987,16 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { virtual void drawTextRange( const TextRange& range, const DocumentLineRange& lineRange, const Vector2f& startScroll, const Float& lineHeight, - const Color& backgroundColor ); + const Color& backgroundColor, + const DocumentViewLineRange& visibleLineRange ); virtual void drawLineNumbers( const DocumentLineRange& lineRange, const Vector2f& startScroll, const Vector2f& screenStart, const Float& lineHeight, const Float& lineNumberWidth, const int& lineNumberDigits, const Float& fontSize ); - virtual void drawColorPreview( const Vector2f& startScroll, const Float& lineHeight ); + virtual void drawColorPreview( const Vector2f& startScroll, const Float& lineHeight, + const DocumentViewLineRange& visibleLineRange ); virtual void onFontChanged(); @@ -1046,7 +1054,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void drawWordRanges( const TextRanges& ranges, const DocumentLineRange& lineRange, const Vector2f& startScroll, const Float& lineHeight, - bool ignoreSelectionMatch ); + bool ignoreSelectionMatch, const DocumentViewLineRange& visibleLineRange ); void updateHighlightWordCache(); diff --git a/src/eepp/ui/doc/documentview.cpp b/src/eepp/ui/doc/documentview.cpp index 202d49be0..6a382cdbc 100644 --- a/src/eepp/ui/doc/documentview.cpp +++ b/src/eepp/ui/doc/documentview.cpp @@ -326,6 +326,7 @@ DocumentView::VisibleLineRange DocumentView::getVisibleLineRange( const TextPosi } Int64 fromIdx = static_cast( toVisibleIndex( pos.line() ) ); Int64 toIdx = static_cast( toVisibleIndex( pos.line(), true ) ); + // TODO: Implement binary search DocumentView::VisibleLineRange info; for ( Int64 i = fromIdx; i < toIdx; i++ ) { Int64 fromCol = mVisibleLines[i].column(); diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index 768a1ba3e..574af1c78 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -1380,13 +1380,15 @@ TextPosition TextDocument::previousChar( TextPosition position ) const { return positionOffset( position, TextPosition( 0, -1 ) ); } -TextPosition TextDocument::previousWordBoundary( TextPosition position, - bool ignoreFirstNonWord ) const { +TextPosition TextDocument::previousWordBoundary( TextPosition position, bool ignoreFirstNonWord, + std::size_t maxSeekChars, + bool returnInvalidOnMaxSeek ) const { auto ch = getChar( positionOffset( position, -1 ) ); bool inWord = !isNonWord( ch ); if ( !ignoreFirstNonWord && !inWord ) return position; String::StringBaseType nextChar = 0; + Int64 seekedChars = static_cast( maxSeekChars ); do { TextPosition curPos = position; position = positionOffset( position, -1 ); @@ -1394,17 +1396,20 @@ TextPosition TextDocument::previousWordBoundary( TextPosition position, break; } nextChar = getChar( positionOffset( position, -1 ) ); - } while ( ( inWord && !isNonWord( nextChar ) ) || ( !inWord && nextChar == ch ) ); - return position; + } while ( ( ( inWord && !isNonWord( nextChar ) ) || ( !inWord && nextChar == ch ) ) && + --seekedChars ); + return returnInvalidOnMaxSeek && seekedChars == 0 ? TextPosition() : position; } -TextPosition TextDocument::nextWordBoundary( TextPosition position, - bool ignoreFirstNonWord ) const { +TextPosition TextDocument::nextWordBoundary( TextPosition position, bool ignoreFirstNonWord, + std::size_t maxSeekChars, + bool returnInvalidOnMaxSeek ) const { auto ch = getChar( position ); bool inWord = !isNonWord( ch ); if ( !ignoreFirstNonWord && !inWord ) return position; String::StringBaseType nextChar = 0; + Int64 seekedChars = static_cast( maxSeekChars ); do { TextPosition curPos = position; position = positionOffset( position, 1 ); @@ -1412,14 +1417,18 @@ TextPosition TextDocument::nextWordBoundary( TextPosition position, break; } nextChar = getChar( position ); - } while ( ( inWord && !isNonWord( nextChar ) ) || ( !inWord && nextChar == ch ) ); - return position; + } while ( ( ( inWord && !isNonWord( nextChar ) ) || ( !inWord && nextChar == ch ) ) && + --seekedChars ); + return returnInvalidOnMaxSeek && seekedChars == 0 ? TextPosition() : position; } -TextPosition TextDocument::previousSpaceBoundaryInLine( TextPosition position ) const { +TextPosition TextDocument::previousSpaceBoundaryInLine( TextPosition position, + std::size_t maxSeekChars, + bool returnInvalidOnMaxSeek ) const { auto ch = getChar( positionOffset( position, -1 ) ); bool inWord = ch != ' '; String::StringBaseType nextChar = 0; + Int64 seekedChars = static_cast( maxSeekChars ); do { TextPosition curPos = position; position = positionOffset( position, -1 ); @@ -1430,14 +1439,16 @@ TextPosition TextDocument::previousSpaceBoundaryInLine( TextPosition position ) break; } nextChar = getChar( positionOffset( position, -1 ) ); - } while ( ( inWord && nextChar != ' ' ) || ( !inWord && nextChar == ch ) ); - return position; + } while ( ( ( inWord && nextChar != ' ' ) || ( !inWord && nextChar == ch ) ) && --seekedChars ); + return returnInvalidOnMaxSeek && seekedChars == 0 ? TextPosition() : position; } -TextPosition TextDocument::nextSpaceBoundaryInLine( TextPosition position ) const { +TextPosition TextDocument::nextSpaceBoundaryInLine( TextPosition position, std::size_t maxSeekChars, + bool returnInvalidOnMaxSeek ) const { auto ch = getChar( position ); bool inWord = ch != ' '; String::StringBaseType nextChar = 0; + Int64 seekedChars = static_cast( maxSeekChars ); do { TextPosition curPos = position; position = positionOffset( position, 1 ); @@ -1448,8 +1459,8 @@ TextPosition TextDocument::nextSpaceBoundaryInLine( TextPosition position ) cons break; } nextChar = getChar( position ); - } while ( ( inWord && nextChar != ' ' ) || ( !inWord && nextChar == ch ) ); - return position; + } while ( ( ( inWord && nextChar != ' ' ) || ( !inWord && nextChar == ch ) ) && --seekedChars ); + return returnInvalidOnMaxSeek && seekedChars == 0 ? TextPosition() : position; } TextPosition TextDocument::startOfWord( TextPosition position ) const { @@ -1987,8 +1998,10 @@ const Uint64& TextDocument::getModificationId() const { void TextDocument::selectWord( bool withMulticursor ) { if ( !hasSelection() ) { - setSelection( { nextWordBoundary( getSelection().start(), false ), - previousWordBoundary( getSelection().start(), false ) } ); + setSelection( { nextWordBoundary( getSelection().start(), false, + std::numeric_limits::max() ), + previousWordBoundary( getSelection().start(), false, + std::numeric_limits::max() ) } ); } else if ( withMulticursor ) { String text( getSelectedText() ); auto res( find( text, getBottomMostCursor().normalized().end() ) ); diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index 406c03b10..85ef250dc 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -252,7 +252,7 @@ void UICodeEditor::draw() { Color col; auto lineRange = getDocumentLineRange(); - auto visualLineRange = getVisibleLineRange(); + auto visibleLineRange = getVisibleLineRange(); Float charSize = getCharacterSize(); Float lineHeight = getLineHeight(); int lineNumberDigits = getLineNumberDigits(); @@ -297,7 +297,8 @@ void UICodeEditor::draw() { if ( mHighlightTextRange.isValid() && mHighlightTextRange.hasSelection() ) { drawTextRange( mHighlightTextRange, lineRange, startScroll, lineHeight, - mColorScheme.getEditorSyntaxStyle( "selection_region"_sst ).color ); + mColorScheme.getEditorSyntaxStyle( "selection_region"_sst ).color, + visibleLineRange ); } if ( mHighlightSelectionMatch && mDoc->hasSelection() && mDoc->getSelection().inSameLine() ) { @@ -308,13 +309,14 @@ void UICodeEditor::draw() { auto selections = mDoc->getSelectionsSorted(); for ( const auto& sel : selections ) { drawTextRange( sel, lineRange, startScroll, lineHeight, - mFontStyleConfig.getFontSelectionBackColor() ); + mFontStyleConfig.getFontSelectionBackColor(), visibleLineRange ); } } if ( !mHighlightWord.isEmpty() ) { Lock l( mHighlightWordCacheMutex ); - drawWordRanges( mHighlightWordCache, lineRange, startScroll, lineHeight, true ); + drawWordRanges( mHighlightWordCache, lineRange, startScroll, lineHeight, true, + visibleLineRange ); } if ( mShowIndentationGuides ) { @@ -323,7 +325,7 @@ void UICodeEditor::draw() { // Draw tab marker if ( mShowWhitespaces ) { - drawWhitespaces( lineRange, startScroll, lineHeight, visualLineRange ); + drawWhitespaces( lineRange, startScroll, lineHeight, visibleLineRange ); } if ( mShowLineEndings ) { @@ -341,7 +343,7 @@ void UICodeEditor::draw() { for ( auto& plugin : mPlugins ) plugin->drawBeforeLineText( this, i, curScroll, charSize, lineHeight ); - drawLineText( i, curScroll, charSize, lineHeight, visualLineRange ); + drawLineText( i, curScroll, charSize, lineHeight, visibleLineRange ); for ( auto& plugin : mPlugins ) plugin->drawAfterLineText( this, i, curScroll, charSize, lineHeight ); @@ -384,11 +386,11 @@ void UICodeEditor::draw() { } if ( mColorPreview && mPreviewColorRange.isValid() && isMouseOver() && !mMinimapHover ) { - drawColorPreview( startScroll, lineHeight ); + drawColorPreview( startScroll, lineHeight, visibleLineRange ); } if ( mMinimapEnabled ) - drawMinimap( screenStart, lineRange, visualLineRange ); + drawMinimap( screenStart, lineRange, visibleLineRange ); if ( mPluginsTopSpace > 0 ) { Float curTopPos = 0.f; @@ -3001,6 +3003,14 @@ void UICodeEditor::moveToNextLine() { jumpLinesDown( 1 ); } +void UICodeEditor::moveToPreviousPage() { + jumpLinesUp( -getViewPortLineCount().y ); +} + +void UICodeEditor::moveToNextPage() { + jumpLinesDown( getViewPortLineCount().y ); +} + void UICodeEditor::moveToStartOfLine() { for ( size_t i = 0; i < mDoc->getSelections().size(); ++i ) { auto selection = mDoc->getSelectionIndex( i ); @@ -3392,7 +3402,8 @@ void UICodeEditor::drawSelectionMatch( const DocumentLineRange& lineRange, void UICodeEditor::drawWordRanges( const TextRanges& ranges, const DocumentLineRange& lineRange, const Vector2f& startScroll, const Float& lineHeight, - bool ignoreSelectionMatch ) { + bool ignoreSelectionMatch, + const DocumentViewLineRange& visibleLineRange ) { if ( ranges.empty() ) return; Primitives primitives; @@ -3420,7 +3431,7 @@ void UICodeEditor::drawWordRanges( const TextRanges& ranges, const DocumentLineR auto rects = getTextRangeRectangles( { { range.start().line(), startCol }, { range.start().line(), endCol } }, startScroll, - {}, lineHeight ); + {}, lineHeight, visibleLineRange ); for ( const auto& rect : rects ) { if ( area.intersect( rect ) ) { @@ -3436,7 +3447,8 @@ void UICodeEditor::drawWordRanges( const TextRanges& ranges, const DocumentLineR void UICodeEditor::drawWordMatch( const String& text, const DocumentLineRange& lineRange, const Vector2f& startScroll, const Float& lineHeight, - bool ignoreSelectionMatch ) { + bool ignoreSelectionMatch, + const DocumentViewLineRange& visibleLineRange ) { if ( text.empty() ) return; Primitives primitives; @@ -3467,8 +3479,9 @@ void UICodeEditor::drawWordMatch( const String& text, const DocumentLineRange& l Int64 startCol = pos; Int64 endCol = pos + text.size(); - auto rects = getTextRangeRectangles( { { ln, startCol }, { ln, endCol } }, - startScroll, {}, lineHeight ); + auto rects = + getTextRangeRectangles( { { ln, startCol }, { ln, endCol } }, startScroll, {}, + lineHeight, visibleLineRange ); for ( const auto& rect : rects ) primitives.drawRectangle( rect ); @@ -3483,7 +3496,7 @@ void UICodeEditor::drawWordMatch( const String& text, const DocumentLineRange& l void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Float& fontSize, const Float& lineHeight, - const DocumentViewLineRange& visualLineRange ) { + const DocumentViewLineRange& visibleLineRange ) { Vector2f originalPosition( position ); const auto& tokens = mDoc->getHighlighter()->getLine( line ); const String& strLine = mDoc->line( line ).getText(); @@ -3509,8 +3522,9 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo FontStyleConfig fontStyle( mFontStyleConfig ); fontStyle.CharacterSize = fontSize; - const auto drawHandDown = [this, &fontStyle, &lineHeight]() { - auto rects = getTextRangeRectangles( mLinkPosition, getScreenScroll(), {}, lineHeight ); + const auto drawHandDown = [this, &fontStyle, &lineHeight, &visibleLineRange]() { + auto rects = getTextRangeRectangles( mLinkPosition, getScreenScroll(), {}, lineHeight, + visibleLineRange ); auto screenBounds = getScreenBounds(); if ( !std::any_of( rects.begin(), rects.end(), [&screenBounds]( const Rectf& rect ) { return screenBounds.intersect( rect ); @@ -3563,9 +3577,9 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo auto textSize = std::min( (Int64)( (Int64)token.len - tokenPos ), maxLength ); String::View text = strLine.view().substr( pos, textSize ); - if ( curVisibleIndex >= static_cast( visualLineRange.first ) && + if ( curVisibleIndex >= static_cast( visibleLineRange.first ) && curVisibleIndex <= - static_cast( visibleIndexOffset( visualLineRange.second, 1 ) ) ) { + static_cast( visibleIndexOffset( visibleLineRange.second, 1 ) ) ) { if ( !mUseDefaultStyle ) { const SyntaxColorScheme::Style& style = mColorScheme.getSyntaxStyle( token.type ); @@ -3604,7 +3618,7 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo nextLineCol = strLine.size(); } - if ( curVisibleIndex > static_cast( visualLineRange.second ) + 1 ) { + if ( curVisibleIndex > static_cast( visibleLineRange.second ) + 1 ) { ended = true; break; } @@ -3693,7 +3707,8 @@ 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 lineHeight ) { + std::optional lineHeight, + std::optional visibleLineRange ) { std::vector rects; Float lh = lineHeight ? *lineHeight : getLineHeight(); Int64 startLine = @@ -3710,6 +3725,13 @@ UICodeEditor::getTextRangeRectangles( const TextRange& range, const Vector2f& st ln == range.start().line() ? range.start() : mDoc->startOfLine( { ln, 0 } ) ); auto toInfo = mDocView.getVisibleLineRange( ln == range.end().line() ? range.end() : mDoc->endOfLine( { ln, 0 } ) ); + if ( visibleLineRange ) { + if ( fromInfo.visibleIndex < visibleLineRange->first ) + fromInfo.visibleIndex = visibleLineRange->first; + if ( toInfo.visibleIndex > visibleLineRange->second ) + toInfo.visibleIndex = visibleLineRange->second; + } + for ( Int64 visibleIdx = static_cast( fromInfo.visibleIndex ); visibleIdx <= static_cast( toInfo.visibleIndex ); visibleIdx++ ) { auto info = @@ -3779,11 +3801,13 @@ UICodeEditor::getTextRangeRectangles( const TextRange& range, const Vector2f& st void UICodeEditor::drawTextRange( const TextRange& range, const DocumentLineRange& lineRange, const Vector2f& startScroll, const Float& lineHeight, - const Color& backgroundColor ) { + const Color& backgroundColor, + const DocumentViewLineRange& visibleLineRange ) { Primitives primitives; primitives.setForceDraw( false ); primitives.setColor( Color( backgroundColor ).blendAlpha( mAlpha ) ); - auto rects = getTextRangeRectangles( range, startScroll, lineRange, lineHeight ); + auto rects = + getTextRangeRectangles( range, startScroll, lineRange, lineHeight, visibleLineRange ); for ( const auto& rect : rects ) primitives.drawRectangle( rect ); if ( !rects.empty() ) @@ -3908,10 +3932,12 @@ void UICodeEditor::drawLineNumbers( const DocumentLineRange& lineRange, const Ve } } -void UICodeEditor::drawColorPreview( const Vector2f& startScroll, const Float& lineHeight ) { +void UICodeEditor::drawColorPreview( const Vector2f& startScroll, const Float& lineHeight, + const DocumentViewLineRange& visibleLineRange ) { Primitives primitives; primitives.setColor( mPreviewColor ); - auto rects = getTextRangeRectangles( mPreviewColorRange, startScroll, {}, lineHeight ); + auto rects = + getTextRangeRectangles( mPreviewColorRange, startScroll, {}, lineHeight, visibleLineRange ); for ( const auto& rect : rects ) { primitives.drawRectangle( Rectf( Vector2f( rect.Left + mScroll.x, rect.Top + lineHeight ), Sizef( rect.getWidth(), lineHeight * 2 ) ) ); @@ -3920,7 +3946,7 @@ void UICodeEditor::drawColorPreview( const Vector2f& startScroll, const Float& l void UICodeEditor::drawWhitespaces( const DocumentLineRange& lineRange, const Vector2f& startScroll, const Float& lineHeight, - const DocumentViewLineRange& visualLineRange ) { + const DocumentViewLineRange& visibleLineRange ) { static const String tab = "\t"; Float tabWidth = getTextWidth( tab ); Float glyphW = getGlyphWidth(); @@ -3946,8 +3972,8 @@ void UICodeEditor::drawWhitespaces( const DocumentLineRange& lineRange, const Ve adv->setColor( color ); cpoint->setColor( color ); - auto startRange = mDocView.getVisibleIndexRange( visualLineRange.first ); - auto endRange = mDocView.getVisibleIndexRange( visualLineRange.second ); + auto startRange = mDocView.getVisibleIndexRange( visibleLineRange.first ); + auto endRange = mDocView.getVisibleIndexRange( visibleLineRange.second ); TextRange visibleDocRange( startRange.start(), endRange.end() ); for ( auto index = lineRange.first; index <= lineRange.second; index++ ) { @@ -4070,6 +4096,8 @@ void UICodeEditor::drawLineEndings( const DocumentLineRange& lineRange, const Ve void UICodeEditor::registerCommands() { mDoc->setCommand( "move-to-previous-line", [this] { moveToPreviousLine(); } ); mDoc->setCommand( "move-to-next-line", [this] { moveToNextLine(); } ); + mDoc->setCommand( "move-to-previous-page", [this] { moveToPreviousPage(); } ); + mDoc->setCommand( "move-to-next-page", [this] { moveToNextPage(); } ); mDoc->setCommand( "move-to-start-of-line", []( Client* client ) { static_cast( client )->moveToStartOfLine(); } ); @@ -4170,9 +4198,11 @@ void UICodeEditor::checkMouseOverColor( const Vector2i& position ) { resetPreviewColor(); return; } - TextPosition start( mDoc->previousWordBoundary( pos ) ); - if ( start.column() > 0 && start.column() < (Int64)line.size() ) { - TextPosition end( mDoc->nextWordBoundary( pos ) ); + TextPosition start( mDoc->previousWordBoundary( pos, true, 12, true ) ); + if ( start.isValid() && start.column() > 0 && start.column() < (Int64)line.size() ) { + TextPosition end( mDoc->nextWordBoundary( pos, true, 12, true ) ); + if ( !end.isValid() ) + return; TextRange wordPos = { { start.line(), start.column() - 1 }, end }; String word = mDoc->getText( wordPos ); bool found = false; @@ -4223,8 +4253,11 @@ String UICodeEditor::checkMouseOverLink( const Vector2i& position ) { if ( mDoc->getChar( pos ) == '\n' ) return resetLinkOver( position ); - TextPosition startB( mDoc->previousSpaceBoundaryInLine( pos ) ); - TextPosition endB( mDoc->nextSpaceBoundaryInLine( pos ) ); + TextPosition startB( mDoc->previousSpaceBoundaryInLine( pos, 1024, true ) ); + TextPosition endB( mDoc->nextSpaceBoundaryInLine( pos, 1024, true ) ); + + if ( !startB.isValid() || !endB.isValid() ) + return resetLinkOver( position ); if ( startB.column() >= (Int64)line.size() || endB.column() >= (Int64)line.size() ) return resetLinkOver( position ); @@ -4424,14 +4457,17 @@ void UICodeEditor::drawMinimap( const Vector2f& start, const DocumentLineRange&, endidx < static_cast( rangeStart.visibleIndex ) ) continue; - if ( ranges.isSorted() && static_cast( rangeEnd.visibleIndex ) > endidx ) + if ( ranges.isSorted() && static_cast( rangeStart.visibleIndex ) > endidx && + static_cast( rangeEnd.visibleIndex ) > endidx ) break; if ( lineSkip == static_cast( rangeStart.visibleIndex ) ) continue; auto selRects = getTextRangeRectangles( - range, { 0, rect.Top - minimapStartLine * lineSpacing }, {}, lineSpacing ); + range, { 0, rect.Top - minimapStartLine * lineSpacing }, {}, lineSpacing, + DocumentViewLineRange{ static_cast( minimapStartLine ), + static_cast( endidx ) } ); for ( auto& selRect : selRects ) { auto curLine = eefloor( selRect.Top / lineSpacing );