From 490bd6d8a999de72a17f02ecd2bc0d47145d648a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Mon, 3 Feb 2025 23:06:24 -0300 Subject: [PATCH] Implemented binary search in DocumentView::getVisibleLineRange. --- src/eepp/ui/doc/documentview.cpp | 55 ++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/src/eepp/ui/doc/documentview.cpp b/src/eepp/ui/doc/documentview.cpp index 704b3074e..4124a4181 100644 --- a/src/eepp/ui/doc/documentview.cpp +++ b/src/eepp/ui/doc/documentview.cpp @@ -324,26 +324,67 @@ DocumentView::VisibleLineRange DocumentView::getVisibleLineRange( const TextPosi info.range = mDoc->getLineRange( pos.line() ); return info; } + 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(); - Int64 toCol = i + 1 <= toIdx - ? mVisibleLines[i + 1].column() - ( allowVisualLineEnd ? 0 : 1 ) + + // If we have no visible lines in range, return early + if ( fromIdx >= toIdx ) { + info.visibleIndex = static_cast( toIdx ); + if ( info.visibleIndex != VisibleIndex::invalid ) { + info.range = { { pos.line(), mVisibleLines[toIdx].column() }, + mDoc->endOfLine( { pos.line(), 0ll } ) }; + } + return info; + } + + // Binary search implementation + Int64 left = fromIdx; + Int64 right = toIdx - 1; // Subtract 1 since we need to access [i+1] in the loop + + while ( left <= right ) { + Int64 mid = left + ( right - left ) / 2; + + Int64 fromCol = mVisibleLines[mid].column(); + Int64 toCol = mid + 1 <= toIdx + ? mVisibleLines[mid + 1].column() - ( allowVisualLineEnd ? 0 : 1 ) : mDoc->line( pos.line() ).size(); + if ( pos.column() >= fromCol && pos.column() <= toCol ) { - info.visibleIndex = static_cast( i ); + // If it's between the limits we must check if it fits into the previous one + if ( allowVisualLineEnd && pos.column() == fromCol && mid - 1 >= 0 ) { + Int64 fromCol = mVisibleLines[mid - 1].column(); + Int64 toCol = mid <= toIdx + ? mVisibleLines[mid].column() - ( allowVisualLineEnd ? 0 : 1 ) + : mDoc->line( pos.line() ).size(); + + info.visibleIndex = static_cast( mid - 1 ); + info.range = { { pos.line(), fromCol }, { pos.line(), toCol } }; + return info; + } + + // Found the correct range + info.visibleIndex = static_cast( mid ); info.range = { { pos.line(), fromCol }, { pos.line(), toCol } }; return info; } + + if ( pos.column() < fromCol ) { + right = mid - 1; + } else { + left = mid + 1; + } } + + // If we didn't find an exact match, return the last possible range eeASSERT( toIdx >= 0 ); info.visibleIndex = static_cast( toIdx ); - if ( info.visibleIndex != VisibleIndex::invalid ) + if ( info.visibleIndex != VisibleIndex::invalid ) { info.range = { { pos.line(), mVisibleLines[toIdx].column() }, mDoc->endOfLine( { pos.line(), 0ll } ) }; + } return info; }