| 195 | } |
| 196 | |
| 197 | DocumentView::VisibleLineRange DocumentView::getVisibleLineRange( const TextPosition& pos, |
| 198 | bool allowVisualLineEnd ) const { |
| 199 | if ( isOneToOne() ) { |
| 200 | DocumentView::VisibleLineRange info; |
| 201 | info.visibleIndex = static_cast<VisibleIndex>( pos.line() ); |
| 202 | info.range = mDoc->getLineRange( pos.line() ); |
| 203 | return info; |
| 204 | } |
| 205 | |
| 206 | Int64 fromIdx = static_cast<Int64>( toVisibleIndex( pos.line() ) ); |
| 207 | Int64 toIdx = static_cast<Int64>( toVisibleIndex( pos.line(), true ) ); |
| 208 | |
| 209 | DocumentView::VisibleLineRange info; |
| 210 | |
| 211 | // If we have no visible lines in range, return early |
| 212 | if ( fromIdx >= toIdx ) { |
| 213 | info.visibleIndex = static_cast<VisibleIndex>( toIdx ); |
| 214 | if ( info.visibleIndex != VisibleIndex::invalid ) { |
| 215 | info.range = { { pos.line(), mVisibleLines[toIdx].column() }, |
| 216 | mDoc->endOfLine( { pos.line(), 0ll } ) }; |
| 217 | } |
| 218 | return info; |
| 219 | } |
| 220 | |
| 221 | // Binary search implementation |
| 222 | Int64 left = fromIdx; |
| 223 | Int64 right = toIdx - 1; // Subtract 1 since we need to access [i+1] in the loop |
| 224 | |
| 225 | while ( left <= right ) { |
| 226 | Int64 mid = left + ( right - left ) / 2; |
| 227 | |
| 228 | Int64 fromCol = mVisibleLines[mid].column(); |
| 229 | Int64 toCol = mid + 1 <= toIdx |
| 230 | ? mVisibleLines[mid + 1].column() - ( allowVisualLineEnd ? 0 : 1 ) |
| 231 | : mDoc->getLineLength( pos.line() ); |
| 232 | |
| 233 | if ( pos.column() >= fromCol && pos.column() <= toCol ) { |
| 234 | // If it's between the limits we must check if it fits into the previous one |
| 235 | if ( allowVisualLineEnd && pos.column() == fromCol && mid - 1 >= 0 ) { |
| 236 | Int64 fromCol = mVisibleLines[mid - 1].column(); |
| 237 | Int64 toCol = mid <= toIdx |
| 238 | ? mVisibleLines[mid].column() - ( allowVisualLineEnd ? 0 : 1 ) |
| 239 | : mDoc->getLineLength( pos.line() ); |
| 240 | |
| 241 | info.visibleIndex = static_cast<VisibleIndex>( mid - 1 ); |
| 242 | info.range = { { pos.line(), fromCol }, { pos.line(), toCol } }; |
| 243 | return info; |
| 244 | } |
| 245 | |
| 246 | // Found the correct range |
| 247 | info.visibleIndex = static_cast<VisibleIndex>( mid ); |
| 248 | info.range = { { pos.line(), fromCol }, { pos.line(), toCol } }; |
| 249 | return info; |
| 250 | } |
| 251 | |
| 252 | if ( pos.column() < fromCol ) { |
| 253 | right = mid - 1; |
| 254 | } else { |
no test coverage detected