| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. |
| 3 * Portions Copyright (c) 2011 Motorola Mobility, Inc. All rights reserved. | 3 * Portions Copyright (c) 2011 Motorola Mobility, Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 ASSERT_NOT_REACHED(); | 113 ASSERT_NOT_REACHED(); |
| 114 return honorEditingBoundaryAtOrBefore(prev); | 114 return honorEditingBoundaryAtOrBefore(prev); |
| 115 } | 115 } |
| 116 | 116 |
| 117 Position VisiblePosition::leftVisuallyDistinctCandidate() const | 117 Position VisiblePosition::leftVisuallyDistinctCandidate() const |
| 118 { | 118 { |
| 119 Position p = m_deepPosition; | 119 Position p = m_deepPosition; |
| 120 if (p.isNull()) | 120 if (p.isNull()) |
| 121 return Position(); | 121 return Position(); |
| 122 | 122 |
| 123 Position downstreamStart = p.downstream(); | 123 Position downstreamStart = mostForwardCaretPosition(p); |
| 124 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); | 124 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); |
| 125 | 125 |
| 126 while (true) { | 126 while (true) { |
| 127 InlineBoxPosition boxPosition = computeInlineBoxPosition(p, m_affinity,
primaryDirection); | 127 InlineBoxPosition boxPosition = computeInlineBoxPosition(p, m_affinity,
primaryDirection); |
| 128 InlineBox* box = boxPosition.inlineBox; | 128 InlineBox* box = boxPosition.inlineBox; |
| 129 int offset = boxPosition.offsetInBox; | 129 int offset = boxPosition.offsetInBox; |
| 130 if (!box) | 130 if (!box) |
| 131 return primaryDirection == LTR ? previousVisuallyDistinctCandidate(m
_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition); | 131 return primaryDirection == LTR ? previousVisuallyDistinctCandidate(m
_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition); |
| 132 | 132 |
| 133 LayoutObject* layoutObject = &box->layoutObject(); | 133 LayoutObject* layoutObject = &box->layoutObject(); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 level = box->bidiLevel(); | 246 level = box->bidiLevel(); |
| 247 } | 247 } |
| 248 layoutObject = &box->layoutObject(); | 248 layoutObject = &box->layoutObject(); |
| 249 offset = primaryDirection == LTR ? box->caretMinOffset() : box->
caretMaxOffset(); | 249 offset = primaryDirection == LTR ? box->caretMinOffset() : box->
caretMaxOffset(); |
| 250 } | 250 } |
| 251 break; | 251 break; |
| 252 } | 252 } |
| 253 | 253 |
| 254 p = Position::editingPositionOf(layoutObject->node(), offset); | 254 p = Position::editingPositionOf(layoutObject->node(), offset); |
| 255 | 255 |
| 256 if ((isVisuallyEquivalentCandidate(p) && p.downstream() != downstreamSta
rt) || p.atStartOfTree() || p.atEndOfTree()) | 256 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) !=
downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) |
| 257 return p; | 257 return p; |
| 258 | 258 |
| 259 ASSERT(p != m_deepPosition); | 259 ASSERT(p != m_deepPosition); |
| 260 } | 260 } |
| 261 } | 261 } |
| 262 | 262 |
| 263 VisiblePosition VisiblePosition::left() const | 263 VisiblePosition VisiblePosition::left() const |
| 264 { | 264 { |
| 265 Position pos = leftVisuallyDistinctCandidate(); | 265 Position pos = leftVisuallyDistinctCandidate(); |
| 266 // FIXME: Why can't we move left from the last position in a tree? | 266 // FIXME: Why can't we move left from the last position in a tree? |
| 267 if (pos.atStartOfTree() || pos.atEndOfTree()) | 267 if (pos.atStartOfTree() || pos.atEndOfTree()) |
| 268 return VisiblePosition(); | 268 return VisiblePosition(); |
| 269 | 269 |
| 270 VisiblePosition left = VisiblePosition(pos); | 270 VisiblePosition left = VisiblePosition(pos); |
| 271 ASSERT(left.deepEquivalent() != m_deepPosition); | 271 ASSERT(left.deepEquivalent() != m_deepPosition); |
| 272 | 272 |
| 273 return directionOfEnclosingBlock(left.deepEquivalent()) == LTR ? honorEditin
gBoundaryAtOrBefore(left) : honorEditingBoundaryAtOrAfter(left); | 273 return directionOfEnclosingBlock(left.deepEquivalent()) == LTR ? honorEditin
gBoundaryAtOrBefore(left) : honorEditingBoundaryAtOrAfter(left); |
| 274 } | 274 } |
| 275 | 275 |
| 276 Position VisiblePosition::rightVisuallyDistinctCandidate() const | 276 Position VisiblePosition::rightVisuallyDistinctCandidate() const |
| 277 { | 277 { |
| 278 Position p = m_deepPosition; | 278 Position p = m_deepPosition; |
| 279 if (p.isNull()) | 279 if (p.isNull()) |
| 280 return Position(); | 280 return Position(); |
| 281 | 281 |
| 282 Position downstreamStart = p.downstream(); | 282 Position downstreamStart = mostForwardCaretPosition(p); |
| 283 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); | 283 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); |
| 284 | 284 |
| 285 while (true) { | 285 while (true) { |
| 286 InlineBoxPosition boxPosition = computeInlineBoxPosition(p, m_affinity,
primaryDirection); | 286 InlineBoxPosition boxPosition = computeInlineBoxPosition(p, m_affinity,
primaryDirection); |
| 287 InlineBox* box = boxPosition.inlineBox; | 287 InlineBox* box = boxPosition.inlineBox; |
| 288 int offset = boxPosition.offsetInBox; | 288 int offset = boxPosition.offsetInBox; |
| 289 if (!box) | 289 if (!box) |
| 290 return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_dee
pPosition) : previousVisuallyDistinctCandidate(m_deepPosition); | 290 return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_dee
pPosition) : previousVisuallyDistinctCandidate(m_deepPosition); |
| 291 | 291 |
| 292 LayoutObject* layoutObject = &box->layoutObject(); | 292 LayoutObject* layoutObject = &box->layoutObject(); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 level = box->bidiLevel(); | 408 level = box->bidiLevel(); |
| 409 } | 409 } |
| 410 layoutObject = &box->layoutObject(); | 410 layoutObject = &box->layoutObject(); |
| 411 offset = primaryDirection == LTR ? box->caretMaxOffset() : box->
caretMinOffset(); | 411 offset = primaryDirection == LTR ? box->caretMaxOffset() : box->
caretMinOffset(); |
| 412 } | 412 } |
| 413 break; | 413 break; |
| 414 } | 414 } |
| 415 | 415 |
| 416 p = Position::editingPositionOf(layoutObject->node(), offset); | 416 p = Position::editingPositionOf(layoutObject->node(), offset); |
| 417 | 417 |
| 418 if ((isVisuallyEquivalentCandidate(p) && p.downstream() != downstreamSta
rt) || p.atStartOfTree() || p.atEndOfTree()) | 418 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) !=
downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) |
| 419 return p; | 419 return p; |
| 420 | 420 |
| 421 ASSERT(p != m_deepPosition); | 421 ASSERT(p != m_deepPosition); |
| 422 } | 422 } |
| 423 } | 423 } |
| 424 | 424 |
| 425 VisiblePosition VisiblePosition::right() const | 425 VisiblePosition VisiblePosition::right() const |
| 426 { | 426 { |
| 427 Position pos = rightVisuallyDistinctCandidate(); | 427 Position pos = rightVisuallyDistinctCandidate(); |
| 428 // FIXME: Why can't we move left from the last position in a tree? | 428 // FIXME: Why can't we move left from the last position in a tree? |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 // That must mean that |pos| is not editable. Return the next position after
pos that is in the same editable region as this position | 542 // That must mean that |pos| is not editable. Return the next position after
pos that is in the same editable region as this position |
| 543 return firstEditableVisiblePositionAfterPositionInRoot(pos.deepEquivalent(),
highestRoot); | 543 return firstEditableVisiblePositionAfterPositionInRoot(pos.deepEquivalent(),
highestRoot); |
| 544 } | 544 } |
| 545 | 545 |
| 546 template <typename PositionType> | 546 template <typename PositionType> |
| 547 static PositionType canonicalizeCandidate(const PositionType& candidate) | 547 static PositionType canonicalizeCandidate(const PositionType& candidate) |
| 548 { | 548 { |
| 549 if (candidate.isNull()) | 549 if (candidate.isNull()) |
| 550 return PositionType(); | 550 return PositionType(); |
| 551 ASSERT(isVisuallyEquivalentCandidate(candidate)); | 551 ASSERT(isVisuallyEquivalentCandidate(candidate)); |
| 552 PositionType upstream = candidate.upstream(); | 552 PositionType upstream = mostBackwardCaretPosition(candidate); |
| 553 if (isVisuallyEquivalentCandidate(upstream)) | 553 if (isVisuallyEquivalentCandidate(upstream)) |
| 554 return upstream; | 554 return upstream; |
| 555 return candidate; | 555 return candidate; |
| 556 } | 556 } |
| 557 | 557 |
| 558 template <typename PositionType> | 558 template <typename PositionType> |
| 559 static PositionType canonicalPosition(const PositionType& passedPosition) | 559 static PositionType canonicalPosition(const PositionType& passedPosition) |
| 560 { | 560 { |
| 561 // Sometimes updating selection positions can be extremely expensive and occ
ur | 561 // Sometimes updating selection positions can be extremely expensive and occ
ur |
| 562 // frequently. Often calling preventDefault on mousedown events can avoid | 562 // frequently. Often calling preventDefault on mousedown events can avoid |
| (...skipping 11 matching lines...) Expand all Loading... |
| 574 // the appropriate layoutObject for VisiblePosition's like these, or b) cano
nicalize to the rightmost candidate | 574 // the appropriate layoutObject for VisiblePosition's like these, or b) cano
nicalize to the rightmost candidate |
| 575 // unless the affinity is upstream. | 575 // unless the affinity is upstream. |
| 576 if (position.isNull()) | 576 if (position.isNull()) |
| 577 return PositionType(); | 577 return PositionType(); |
| 578 | 578 |
| 579 ASSERT(position.document()); | 579 ASSERT(position.document()); |
| 580 position.document()->updateLayoutIgnorePendingStylesheets(); | 580 position.document()->updateLayoutIgnorePendingStylesheets(); |
| 581 | 581 |
| 582 Node* node = position.computeContainerNode(); | 582 Node* node = position.computeContainerNode(); |
| 583 | 583 |
| 584 PositionType candidate = position.upstream(); | 584 PositionType candidate = mostBackwardCaretPosition(position); |
| 585 if (isVisuallyEquivalentCandidate(candidate)) | 585 if (isVisuallyEquivalentCandidate(candidate)) |
| 586 return candidate; | 586 return candidate; |
| 587 candidate = position.downstream(); | 587 candidate = mostForwardCaretPosition(position); |
| 588 if (isVisuallyEquivalentCandidate(candidate)) | 588 if (isVisuallyEquivalentCandidate(candidate)) |
| 589 return candidate; | 589 return candidate; |
| 590 | 590 |
| 591 // When neither upstream or downstream gets us to a candidate (upstream/down
stream won't leave | 591 // When neither upstream or downstream gets us to a candidate (upstream/down
stream won't leave |
| 592 // blocks or enter new ones), we search forward and backward until we find o
ne. | 592 // blocks or enter new ones), we search forward and backward until we find o
ne. |
| 593 PositionType next = canonicalizeCandidate(nextCandidate(position)); | 593 PositionType next = canonicalizeCandidate(nextCandidate(position)); |
| 594 PositionType prev = canonicalizeCandidate(previousCandidate(position)); | 594 PositionType prev = canonicalizeCandidate(previousCandidate(position)); |
| 595 Node* nextNode = next.anchorNode(); | 595 Node* nextNode = next.anchorNode(); |
| 596 Node* prevNode = prev.anchorNode(); | 596 Node* prevNode = prev.anchorNode(); |
| 597 | 597 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 if (!inSameLine(PositionWithAffinityTemplate<Strategy>(deepPosition), Positi
onWithAffinityTemplate<Strategy>(deepPosition, TextAffinity::Upstream))) | 659 if (!inSameLine(PositionWithAffinityTemplate<Strategy>(deepPosition), Positi
onWithAffinityTemplate<Strategy>(deepPosition, TextAffinity::Upstream))) |
| 660 return; | 660 return; |
| 661 m_affinity = TextAffinity::Downstream; | 661 m_affinity = TextAffinity::Downstream; |
| 662 } | 662 } |
| 663 | 663 |
| 664 UChar32 VisiblePosition::characterAfter() const | 664 UChar32 VisiblePosition::characterAfter() const |
| 665 { | 665 { |
| 666 // We canonicalize to the first of two equivalent candidates, but the second | 666 // We canonicalize to the first of two equivalent candidates, but the second |
| 667 // of the two candidates is the one that will be inside the text node | 667 // of the two candidates is the one that will be inside the text node |
| 668 // containing the character after this visible position. | 668 // containing the character after this visible position. |
| 669 Position pos = m_deepPosition.downstream(); | 669 Position pos = mostForwardCaretPosition(m_deepPosition); |
| 670 if (!pos.isOffsetInAnchor()) | 670 if (!pos.isOffsetInAnchor()) |
| 671 return 0; | 671 return 0; |
| 672 Node* containerNode = pos.computeContainerNode(); | 672 Node* containerNode = pos.computeContainerNode(); |
| 673 if (!containerNode || !containerNode->isTextNode()) | 673 if (!containerNode || !containerNode->isTextNode()) |
| 674 return 0; | 674 return 0; |
| 675 unsigned offset = static_cast<unsigned>(pos.offsetInContainerNode()); | 675 unsigned offset = static_cast<unsigned>(pos.offsetInContainerNode()); |
| 676 Text* textNode = toText(containerNode); | 676 Text* textNode = toText(containerNode); |
| 677 unsigned length = textNode->length(); | 677 unsigned length = textNode->length(); |
| 678 if (offset >= length) | 678 if (offset >= length) |
| 679 return 0; | 679 return 0; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 769 else | 769 else |
| 770 fprintf(stderr, "Cannot showTree for (nil) VisiblePosition.\n"); | 770 fprintf(stderr, "Cannot showTree for (nil) VisiblePosition.\n"); |
| 771 } | 771 } |
| 772 | 772 |
| 773 void showTree(const blink::VisiblePosition& vpos) | 773 void showTree(const blink::VisiblePosition& vpos) |
| 774 { | 774 { |
| 775 vpos.showTreeForThis(); | 775 vpos.showTreeForThis(); |
| 776 } | 776 } |
| 777 | 777 |
| 778 #endif | 778 #endif |
| OLD | NEW |