OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 Position lastEditablePositionBeforePositionInRoot(const Position& position, Node
* highestRoot) | 499 Position lastEditablePositionBeforePositionInRoot(const Position& position, Node
* highestRoot) |
500 { | 500 { |
501 return lastEditablePositionBeforePositionInRootAlgorithm<Position>(position,
highestRoot); | 501 return lastEditablePositionBeforePositionInRootAlgorithm<Position>(position,
highestRoot); |
502 } | 502 } |
503 | 503 |
504 PositionInComposedTree lastEditablePositionBeforePositionInRoot(const PositionIn
ComposedTree& position, Node* highestRoot) | 504 PositionInComposedTree lastEditablePositionBeforePositionInRoot(const PositionIn
ComposedTree& position, Node* highestRoot) |
505 { | 505 { |
506 return lastEditablePositionBeforePositionInRootAlgorithm<PositionInComposedT
ree>(position, highestRoot); | 506 return lastEditablePositionBeforePositionInRootAlgorithm<PositionInComposedT
ree>(position, highestRoot); |
507 } | 507 } |
508 | 508 |
| 509 int uncheckedPreviousOffset(const Node* n, int current) |
| 510 { |
| 511 return n->layoutObject() ? n->layoutObject()->previousOffset(current) : curr
ent - 1; |
| 512 } |
| 513 |
| 514 static int uncheckedPreviousOffsetForBackwardDeletion(const Node* n, int current
) |
| 515 { |
| 516 return n->layoutObject() ? n->layoutObject()->previousOffsetForBackwardDelet
ion(current) : current - 1; |
| 517 } |
| 518 |
| 519 int uncheckedNextOffset(const Node* n, int current) |
| 520 { |
| 521 return n->layoutObject() ? n->layoutObject()->nextOffset(current) : current
+ 1; |
| 522 } |
| 523 |
| 524 template <typename Strategy> |
| 525 PositionAlgorithm<Strategy> previousPositionOfAlgorithm(const PositionAlgorithm<
Strategy>& position, PositionMoveType moveType) |
| 526 { |
| 527 Node* const node = position.anchorNode(); |
| 528 if (!node) |
| 529 return position; |
| 530 |
| 531 const int offset = position.computeEditingOffset(); |
| 532 |
| 533 if (offset > 0) { |
| 534 if (editingIgnoresContent(node)) |
| 535 return PositionAlgorithm<Strategy>::beforeNode(node); |
| 536 if (Node* child = Strategy::childAt(*node, offset - 1)) |
| 537 return PositionAlgorithm<Strategy>::lastPositionInOrAfterNode(child)
; |
| 538 |
| 539 // There are two reasons child might be 0: |
| 540 // 1) The node is node like a text node that is not an element, and |
| 541 // therefore has no children. Going backward one character at a |
| 542 // time is correct. |
| 543 // 2) The old offset was a bogus offset like (<br>, 1), and there is |
| 544 // no child. Going from 1 to 0 is correct. |
| 545 switch (moveType) { |
| 546 case PositionMoveType::CodePoint: |
| 547 return PositionAlgorithm<Strategy>(node, offset - 1); |
| 548 case PositionMoveType::Character: |
| 549 return PositionAlgorithm<Strategy>(node, uncheckedPreviousOffset(nod
e, offset)); |
| 550 case PositionMoveType::BackwardDeletion: |
| 551 return PositionAlgorithm<Strategy>(node, uncheckedPreviousOffsetForB
ackwardDeletion(node, offset)); |
| 552 } |
| 553 } |
| 554 |
| 555 if (ContainerNode* parent = Strategy::parent(*node)) { |
| 556 if (editingIgnoresContent(parent)) |
| 557 return PositionAlgorithm<Strategy>::beforeNode(parent); |
| 558 // TODO(yosin) We should use |Strategy::index(Node&)| instead of |
| 559 // |Node::nodeIndex()|. |
| 560 return PositionAlgorithm<Strategy>(parent, node->nodeIndex()); |
| 561 } |
| 562 return position; |
| 563 } |
| 564 |
| 565 Position previousPositionOf(const Position& position, PositionMoveType moveType) |
| 566 { |
| 567 return previousPositionOfAlgorithm<EditingStrategy>(position, moveType); |
| 568 } |
| 569 |
| 570 PositionInComposedTree previousPositionOf(const PositionInComposedTree& position
, PositionMoveType moveType) |
| 571 { |
| 572 return previousPositionOfAlgorithm<EditingInComposedTreeStrategy>(position,
moveType); |
| 573 } |
| 574 |
| 575 template <typename Strategy> |
| 576 PositionAlgorithm<Strategy> nextPositionOfAlgorithm(const PositionAlgorithm<Stra
tegy>& position, PositionMoveType moveType) |
| 577 { |
| 578 ASSERT(moveType != PositionMoveType::BackwardDeletion); |
| 579 |
| 580 Node* node = position.anchorNode(); |
| 581 if (!node) |
| 582 return position; |
| 583 |
| 584 const int offset = position.computeEditingOffset(); |
| 585 |
| 586 if (Node* child = Strategy::childAt(*node, offset)) |
| 587 return PositionAlgorithm<Strategy>::firstPositionInOrBeforeNode(child); |
| 588 |
| 589 // TODO(yosin) We should use |Strategy::lastOffsetForEditing()| instead of |
| 590 // DOM tree version. |
| 591 if (!Strategy::hasChildren(*node) && offset < EditingStrategy::lastOffsetFor
Editing(node)) { |
| 592 // There are two reasons child might be 0: |
| 593 // 1) The node is node like a text node that is not an element, and |
| 594 // therefore has no children. Going forward one character at a time |
| 595 // is correct. |
| 596 // 2) The new offset is a bogus offset like (<br>, 1), and there is no |
| 597 // child. Going from 0 to 1 is correct. |
| 598 return PositionAlgorithm<Strategy>::editingPositionOf(node, (moveType ==
PositionMoveType::Character) ? uncheckedNextOffset(node, offset) : offset + 1); |
| 599 } |
| 600 |
| 601 if (ContainerNode* parent = Strategy::parent(*node)) |
| 602 return PositionAlgorithm<Strategy>::editingPositionOf(parent, Strategy::
index(*node) + 1); |
| 603 return position; |
| 604 } |
| 605 |
| 606 Position nextPositionOf(const Position& position, PositionMoveType moveType) |
| 607 { |
| 608 return nextPositionOfAlgorithm<EditingStrategy>(position, moveType); |
| 609 } |
| 610 |
| 611 PositionInComposedTree nextPositionOf(const PositionInComposedTree& position, Po
sitionMoveType moveType) |
| 612 { |
| 613 return nextPositionOfAlgorithm<EditingInComposedTreeStrategy>(position, move
Type); |
| 614 } |
| 615 |
509 // FIXME: The method name, comment, and code say three different things here! | 616 // FIXME: The method name, comment, and code say three different things here! |
510 // Whether or not content before and after this node will collapse onto the same
line as it. | 617 // Whether or not content before and after this node will collapse onto the same
line as it. |
511 bool isBlock(const Node* node) | 618 bool isBlock(const Node* node) |
512 { | 619 { |
513 return node && node->layoutObject() && !node->layoutObject()->isInline() &&
!node->layoutObject()->isRubyText(); | 620 return node && node->layoutObject() && !node->layoutObject()->isInline() &&
!node->layoutObject()->isRubyText(); |
514 } | 621 } |
515 | 622 |
516 bool isInline(const Node* node) | 623 bool isInline(const Node* node) |
517 { | 624 { |
518 return node && node->layoutObject() && node->layoutObject()->isInline(); | 625 return node && node->layoutObject() && node->layoutObject()->isInline(); |
(...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1448 // if the selection starts just before a paragraph break, skip over it | 1555 // if the selection starts just before a paragraph break, skip over it |
1449 if (isEndOfParagraph(visiblePosition)) | 1556 if (isEndOfParagraph(visiblePosition)) |
1450 return mostForwardCaretPosition(visiblePosition.next().deepEquivalent())
; | 1557 return mostForwardCaretPosition(visiblePosition.next().deepEquivalent())
; |
1451 | 1558 |
1452 // otherwise, make sure to be at the start of the first selected node, | 1559 // otherwise, make sure to be at the start of the first selected node, |
1453 // instead of possibly at the end of the last node before the selection | 1560 // instead of possibly at the end of the last node before the selection |
1454 return mostForwardCaretPosition(visiblePosition.deepEquivalent()); | 1561 return mostForwardCaretPosition(visiblePosition.deepEquivalent()); |
1455 } | 1562 } |
1456 | 1563 |
1457 } // namespace blink | 1564 } // namespace blink |
OLD | NEW |