| 1311 | */ |
| 1312 | |
| 1313 | Editor::XYScrollPosition Editor::XYScrollToMakeVisible ( const SelectionRange range, const XYScrollOptions options ) |
| 1314 | { |
| 1315 | PRectangle rcClient = GetTextRectangle(); |
| 1316 | Point pt = LocationFromPosition ( range.caret ); |
| 1317 | Point ptAnchor = LocationFromPosition ( range.anchor ); |
| 1318 | const Point ptOrigin = GetVisibleOriginInMain(); |
| 1319 | pt.x += ptOrigin.x; |
| 1320 | pt.y += ptOrigin.y; |
| 1321 | ptAnchor.x += ptOrigin.x; |
| 1322 | ptAnchor.y += ptOrigin.y; |
| 1323 | const Point ptBottomCaret ( pt.x, pt.y + vs.lineHeight - 1 ); |
| 1324 | XYScrollPosition newXY ( xOffset, topLine ); |
| 1325 | if ( rcClient.Empty() ) { |
| 1326 | return newXY; |
| 1327 | } |
| 1328 | // Vertical positioning |
| 1329 | if ( ( options & xysVertical ) && ( pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || ( caretYPolicy & CARET_STRICT ) != 0 ) ) { |
| 1330 | const int lineCaret = DisplayFromPosition ( range.caret.Position() ); |
| 1331 | const int linesOnScreen = LinesOnScreen(); |
| 1332 | const int halfScreen = Platform::Maximum ( linesOnScreen - 1, 2 ) / 2; |
| 1333 | const bool bSlop = ( caretYPolicy & CARET_SLOP ) != 0; |
| 1334 | const bool bStrict = ( caretYPolicy & CARET_STRICT ) != 0; |
| 1335 | const bool bJump = ( caretYPolicy & CARET_JUMPS ) != 0; |
| 1336 | const bool bEven = ( caretYPolicy & CARET_EVEN ) != 0; |
| 1337 | // It should be possible to scroll the window to show the caret, |
| 1338 | // but this fails to remove the caret on GTK+ |
| 1339 | if ( bSlop ) { // A margin is defined |
| 1340 | int yMoveT, yMoveB; |
| 1341 | if ( bStrict ) { |
| 1342 | int yMarginT, yMarginB; |
| 1343 | if ( ! ( options & xysUseMargin ) ) { |
| 1344 | // In drag mode, avoid moves |
| 1345 | // otherwise, a double click will select several lines. |
| 1346 | yMarginT = yMarginB = 0; |
| 1347 | } else { |
| 1348 | // yMarginT must equal to caretYSlop, with a minimum of 1 and |
| 1349 | // a maximum of slightly less than half the heigth of the text area. |
| 1350 | yMarginT = Platform::Clamp ( caretYSlop, 1, halfScreen ); |
| 1351 | if ( bEven ) { |
| 1352 | yMarginB = yMarginT; |
| 1353 | } else { |
| 1354 | yMarginB = linesOnScreen - yMarginT - 1; |
| 1355 | } |
| 1356 | } |
| 1357 | yMoveT = yMarginT; |
| 1358 | if ( bEven ) { |
| 1359 | if ( bJump ) { |
| 1360 | yMoveT = Platform::Clamp ( caretYSlop * 3, 1, halfScreen ); |
| 1361 | } |
| 1362 | yMoveB = yMoveT; |
| 1363 | } else { |
| 1364 | yMoveB = linesOnScreen - yMoveT - 1; |
| 1365 | } |
| 1366 | if ( lineCaret < topLine + yMarginT ) { |
| 1367 | // Caret goes too high |
| 1368 | newXY.topLine = lineCaret - yMoveT; |
| 1369 | } else if ( lineCaret > topLine + linesOnScreen - 1 - yMarginB ) { |
| 1370 | // Caret goes too low |