Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Side by Side Diff: third_party/WebKit/Source/core/editing/VisibleUnits.cpp

Issue 2363363002: Add VisiblePosition validity checks to VisibleUnits.cpp (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 * 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 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 return PositionWithAffinityTemplate<Strategy>(); 194 return PositionWithAffinityTemplate<Strategy>();
195 195
196 // Return the last position before |pos| that is in the same editable region 196 // Return the last position before |pos| that is in the same editable region
197 // as this position 197 // as this position
198 return lastEditablePositionBeforePositionInRoot(pos.position(), *highestRoot ); 198 return lastEditablePositionBeforePositionInRoot(pos.position(), *highestRoot );
199 } 199 }
200 200
201 template <typename Strategy> 201 template <typename Strategy>
202 static VisiblePositionTemplate<Strategy> honorEditingBoundaryAtOrBefore(const Vi siblePositionTemplate<Strategy>& pos, const PositionTemplate<Strategy>& anchor) 202 static VisiblePositionTemplate<Strategy> honorEditingBoundaryAtOrBefore(const Vi siblePositionTemplate<Strategy>& pos, const PositionTemplate<Strategy>& anchor)
203 { 203 {
204 DCHECK(pos.isValid()); 204 DCHECK(pos.isValid()) << pos;
205 return createVisiblePosition(honorEditingBoundaryAtOrBefore(pos.toPositionWi thAffinity(), anchor)); 205 return createVisiblePosition(honorEditingBoundaryAtOrBefore(pos.toPositionWi thAffinity(), anchor));
206 } 206 }
207 207
208 template <typename Strategy> 208 template <typename Strategy>
209 static VisiblePositionTemplate<Strategy> honorEditingBoundaryAtOrAfter(const Vis iblePositionTemplate<Strategy>& pos, const PositionTemplate<Strategy>& anchor) 209 static VisiblePositionTemplate<Strategy> honorEditingBoundaryAtOrAfter(const Vis iblePositionTemplate<Strategy>& pos, const PositionTemplate<Strategy>& anchor)
210 { 210 {
211 DCHECK(pos.isValid()) << pos;
211 if (pos.isNull()) 212 if (pos.isNull())
212 return pos; 213 return pos;
213 214
214 ContainerNode* highestRoot = highestEditableRoot(anchor); 215 ContainerNode* highestRoot = highestEditableRoot(anchor);
215 216
216 // Return empty position if |pos| is not somewhere inside the editable 217 // Return empty position if |pos| is not somewhere inside the editable
217 // region containing this position 218 // region containing this position
218 if (highestRoot && !pos.deepEquivalent().anchorNode()->isDescendantOf(highes tRoot)) 219 if (highestRoot && !pos.deepEquivalent().anchorNode()->isDescendantOf(highes tRoot))
219 return VisiblePositionTemplate<Strategy>(); 220 return VisiblePositionTemplate<Strategy>();
220 221
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 if (editable == hasEditableStyle(*node, editableType)) 308 if (editable == hasEditableStyle(*node, editableType))
308 return node; 309 return node;
309 node = nextAtomicLeafNode(*node); 310 node = nextAtomicLeafNode(*node);
310 } 311 }
311 return 0; 312 return 0;
312 } 313 }
313 314
314 // FIXME: consolidate with code in previousLinePosition. 315 // FIXME: consolidate with code in previousLinePosition.
315 static Position previousRootInlineBoxCandidatePosition(Node* node, const Visible Position& visiblePosition, EditableType editableType) 316 static Position previousRootInlineBoxCandidatePosition(Node* node, const Visible Position& visiblePosition, EditableType editableType)
316 { 317 {
317 DCHECK(visiblePosition.isValid()); 318 DCHECK(visiblePosition.isValid()) << visiblePosition;
318 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent(), editableType); 319 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent(), editableType);
319 Node* previousNode = previousLeafWithSameEditability(node, editableType); 320 Node* previousNode = previousLeafWithSameEditability(node, editableType);
320 321
321 while (previousNode && (!previousNode->layoutObject() || inSameLine(createVi siblePosition(firstPositionInOrBeforeNode(previousNode)), visiblePosition))) 322 while (previousNode && (!previousNode->layoutObject() || inSameLine(createVi siblePosition(firstPositionInOrBeforeNode(previousNode)), visiblePosition)))
322 previousNode = previousLeafWithSameEditability(previousNode, editableTyp e); 323 previousNode = previousLeafWithSameEditability(previousNode, editableTyp e);
323 324
324 while (previousNode && !previousNode->isShadowRoot()) { 325 while (previousNode && !previousNode->isShadowRoot()) {
325 if (highestEditableRoot(firstPositionInOrBeforeNode(previousNode), edita bleType) != highestRoot) 326 if (highestEditableRoot(firstPositionInOrBeforeNode(previousNode), edita bleType) != highestRoot)
326 break; 327 break;
327 328
328 Position pos = isHTMLBRElement(*previousNode) ? Position::beforeNode(pre viousNode) : 329 Position pos = isHTMLBRElement(*previousNode) ? Position::beforeNode(pre viousNode) :
329 Position::editingPositionOf(previousNode, caretMaxOffset(previousNod e)); 330 Position::editingPositionOf(previousNode, caretMaxOffset(previousNod e));
330 331
331 if (isVisuallyEquivalentCandidate(pos)) 332 if (isVisuallyEquivalentCandidate(pos))
332 return pos; 333 return pos;
333 334
334 previousNode = previousLeafWithSameEditability(previousNode, editableTyp e); 335 previousNode = previousLeafWithSameEditability(previousNode, editableTyp e);
335 } 336 }
336 return Position(); 337 return Position();
337 } 338 }
338 339
339 static Position nextRootInlineBoxCandidatePosition(Node* node, const VisiblePosi tion& visiblePosition, EditableType editableType) 340 static Position nextRootInlineBoxCandidatePosition(Node* node, const VisiblePosi tion& visiblePosition, EditableType editableType)
340 { 341 {
341 DCHECK(visiblePosition.isValid()); 342 DCHECK(visiblePosition.isValid()) << visiblePosition;
342 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent(), editableType); 343 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent(), editableType);
343 Node* nextNode = nextLeafWithSameEditability(node, editableType); 344 Node* nextNode = nextLeafWithSameEditability(node, editableType);
344 while (nextNode && (!nextNode->layoutObject() || inSameLine(createVisiblePos ition(firstPositionInOrBeforeNode(nextNode)), visiblePosition))) 345 while (nextNode && (!nextNode->layoutObject() || inSameLine(createVisiblePos ition(firstPositionInOrBeforeNode(nextNode)), visiblePosition)))
345 nextNode = nextLeafWithSameEditability(nextNode, ContentIsEditable); 346 nextNode = nextLeafWithSameEditability(nextNode, ContentIsEditable);
346 347
347 while (nextNode && !nextNode->isShadowRoot()) { 348 while (nextNode && !nextNode->isShadowRoot()) {
348 if (highestEditableRoot(firstPositionInOrBeforeNode(nextNode), editableT ype) != highestRoot) 349 if (highestEditableRoot(firstPositionInOrBeforeNode(nextNode), editableT ype) != highestRoot)
349 break; 350 break;
350 351
351 Position pos; 352 Position pos;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 for (size_t i = 0; i < m_leafBoxes.size(); ++i) { 436 for (size_t i = 0; i < m_leafBoxes.size(); ++i) {
436 if (box == m_leafBoxes[i]) 437 if (box == m_leafBoxes[i])
437 return i; 438 return i;
438 } 439 }
439 return 0; 440 return 0;
440 } 441 }
441 442
442 static const InlineTextBox* logicallyPreviousBox(const VisiblePosition& visibleP osition, const InlineTextBox* textBox, 443 static const InlineTextBox* logicallyPreviousBox(const VisiblePosition& visibleP osition, const InlineTextBox* textBox,
443 bool& previousBoxInDifferentBlock, CachedLogicallyOrderedLeafBoxes& leafBoxe s) 444 bool& previousBoxInDifferentBlock, CachedLogicallyOrderedLeafBoxes& leafBoxe s)
444 { 445 {
446 DCHECK(visiblePosition.isValid()) << visiblePosition;
445 const InlineBox* startBox = textBox; 447 const InlineBox* startBox = textBox;
446 448
447 const InlineTextBox* previousBox = leafBoxes.previousTextBox(&startBox->root (), textBox); 449 const InlineTextBox* previousBox = leafBoxes.previousTextBox(&startBox->root (), textBox);
448 if (previousBox) 450 if (previousBox)
449 return previousBox; 451 return previousBox;
450 452
451 previousBox = leafBoxes.previousTextBox(startBox->root().prevRootBox(), 0); 453 previousBox = leafBoxes.previousTextBox(startBox->root().prevRootBox(), 0);
452 if (previousBox) 454 if (previousBox)
453 return previousBox; 455 return previousBox;
454 456
(...skipping 21 matching lines...) Expand all
476 break; 478 break;
477 startBox = leafBoxes.firstBox(); 479 startBox = leafBoxes.firstBox();
478 } 480 }
479 return 0; 481 return 0;
480 } 482 }
481 483
482 484
483 static const InlineTextBox* logicallyNextBox(const VisiblePosition& visiblePosit ion, const InlineTextBox* textBox, 485 static const InlineTextBox* logicallyNextBox(const VisiblePosition& visiblePosit ion, const InlineTextBox* textBox,
484 bool& nextBoxInDifferentBlock, CachedLogicallyOrderedLeafBoxes& leafBoxes) 486 bool& nextBoxInDifferentBlock, CachedLogicallyOrderedLeafBoxes& leafBoxes)
485 { 487 {
488 DCHECK(visiblePosition.isValid()) << visiblePosition;
486 const InlineBox* startBox = textBox; 489 const InlineBox* startBox = textBox;
487 490
488 const InlineTextBox* nextBox = leafBoxes.nextTextBox(&startBox->root(), text Box); 491 const InlineTextBox* nextBox = leafBoxes.nextTextBox(&startBox->root(), text Box);
489 if (nextBox) 492 if (nextBox)
490 return nextBox; 493 return nextBox;
491 494
492 nextBox = leafBoxes.nextTextBox(startBox->root().nextRootBox(), 0); 495 nextBox = leafBoxes.nextTextBox(startBox->root().nextRootBox(), 0);
493 if (nextBox) 496 if (nextBox)
494 return nextBox; 497 return nextBox;
495 498
(...skipping 20 matching lines...) Expand all
516 if (!leafBoxes.size()) 519 if (!leafBoxes.size())
517 break; 520 break;
518 startBox = leafBoxes.firstBox(); 521 startBox = leafBoxes.firstBox();
519 } 522 }
520 return 0; 523 return 0;
521 } 524 }
522 525
523 static TextBreakIterator* wordBreakIteratorForMinOffsetBoundary(const VisiblePos ition& visiblePosition, const InlineTextBox* textBox, 526 static TextBreakIterator* wordBreakIteratorForMinOffsetBoundary(const VisiblePos ition& visiblePosition, const InlineTextBox* textBox,
524 int& previousBoxLength, bool& previousBoxInDifferentBlock, Vector<UChar, 102 4>& string, CachedLogicallyOrderedLeafBoxes& leafBoxes) 527 int& previousBoxLength, bool& previousBoxInDifferentBlock, Vector<UChar, 102 4>& string, CachedLogicallyOrderedLeafBoxes& leafBoxes)
525 { 528 {
529 DCHECK(visiblePosition.isValid()) << visiblePosition;
526 previousBoxInDifferentBlock = false; 530 previousBoxInDifferentBlock = false;
527 531
528 // FIXME: Handle the case when we don't have an inline text box. 532 // FIXME: Handle the case when we don't have an inline text box.
529 const InlineTextBox* previousBox = logicallyPreviousBox(visiblePosition, tex tBox, previousBoxInDifferentBlock, leafBoxes); 533 const InlineTextBox* previousBox = logicallyPreviousBox(visiblePosition, tex tBox, previousBoxInDifferentBlock, leafBoxes);
530 534
531 int len = 0; 535 int len = 0;
532 string.clear(); 536 string.clear();
533 if (previousBox) { 537 if (previousBox) {
534 previousBoxLength = previousBox->len(); 538 previousBoxLength = previousBox->len();
535 previousBox->getLineLayoutItem().text().appendTo(string, previousBox->st art(), previousBoxLength); 539 previousBox->getLineLayoutItem().text().appendTo(string, previousBox->st art(), previousBoxLength);
536 len += previousBoxLength; 540 len += previousBoxLength;
537 } 541 }
538 textBox->getLineLayoutItem().text().appendTo(string, textBox->start(), textB ox->len()); 542 textBox->getLineLayoutItem().text().appendTo(string, textBox->start(), textB ox->len());
539 len += textBox->len(); 543 len += textBox->len();
540 544
541 return wordBreakIterator(string.data(), len); 545 return wordBreakIterator(string.data(), len);
542 } 546 }
543 547
544 static TextBreakIterator* wordBreakIteratorForMaxOffsetBoundary(const VisiblePos ition& visiblePosition, const InlineTextBox* textBox, 548 static TextBreakIterator* wordBreakIteratorForMaxOffsetBoundary(const VisiblePos ition& visiblePosition, const InlineTextBox* textBox,
545 bool& nextBoxInDifferentBlock, Vector<UChar, 1024>& string, CachedLogicallyO rderedLeafBoxes& leafBoxes) 549 bool& nextBoxInDifferentBlock, Vector<UChar, 1024>& string, CachedLogicallyO rderedLeafBoxes& leafBoxes)
546 { 550 {
551 DCHECK(visiblePosition.isValid()) << visiblePosition;
547 nextBoxInDifferentBlock = false; 552 nextBoxInDifferentBlock = false;
548 553
549 // FIXME: Handle the case when we don't have an inline text box. 554 // FIXME: Handle the case when we don't have an inline text box.
550 const InlineTextBox* nextBox = logicallyNextBox(visiblePosition, textBox, ne xtBoxInDifferentBlock, leafBoxes); 555 const InlineTextBox* nextBox = logicallyNextBox(visiblePosition, textBox, ne xtBoxInDifferentBlock, leafBoxes);
551 556
552 int len = 0; 557 int len = 0;
553 string.clear(); 558 string.clear();
554 textBox->getLineLayoutItem().text().appendTo(string, textBox->start(), textB ox->len()); 559 textBox->getLineLayoutItem().text().appendTo(string, textBox->start(), textB ox->len());
555 len += textBox->len(); 560 len += textBox->len();
556 if (nextBox) { 561 if (nextBox) {
(...skipping 19 matching lines...) Expand all
576 { 581 {
577 bool boundary = iter->isBoundary(position); 582 bool boundary = iter->isBoundary(position);
578 return (hardLineBreak || boundary) && isWordTextBreak(iter); 583 return (hardLineBreak || boundary) && isWordTextBreak(iter);
579 } 584 }
580 585
581 enum CursorMovementDirection { MoveLeft, MoveRight }; 586 enum CursorMovementDirection { MoveLeft, MoveRight };
582 587
583 static VisiblePosition visualWordPosition(const VisiblePosition& visiblePosition , CursorMovementDirection direction, 588 static VisiblePosition visualWordPosition(const VisiblePosition& visiblePosition , CursorMovementDirection direction,
584 bool skipsSpaceWhenMovingRight) 589 bool skipsSpaceWhenMovingRight)
585 { 590 {
591 DCHECK(visiblePosition.isValid()) << visiblePosition;
586 if (visiblePosition.isNull()) 592 if (visiblePosition.isNull())
587 return VisiblePosition(); 593 return VisiblePosition();
588 594
589 TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition.dee pEquivalent()); 595 TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition.dee pEquivalent());
590 InlineBox* previouslyVisitedBox = 0; 596 InlineBox* previouslyVisitedBox = 0;
591 VisiblePosition current = visiblePosition; 597 VisiblePosition current = visiblePosition;
592 TextBreakIterator* iter = 0; 598 TextBreakIterator* iter = 0;
593 599
594 CachedLogicallyOrderedLeafBoxes leafBoxes; 600 CachedLogicallyOrderedLeafBoxes leafBoxes;
595 Vector<UChar, 1024> string; 601 Vector<UChar, 1024> string;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 if (isWordBreak) 652 if (isWordBreak)
647 return adjacentCharacterPosition; 653 return adjacentCharacterPosition;
648 654
649 current = adjacentCharacterPosition; 655 current = adjacentCharacterPosition;
650 } 656 }
651 return VisiblePosition(); 657 return VisiblePosition();
652 } 658 }
653 659
654 VisiblePosition leftWordPosition(const VisiblePosition& visiblePosition, bool sk ipsSpaceWhenMovingRight) 660 VisiblePosition leftWordPosition(const VisiblePosition& visiblePosition, bool sk ipsSpaceWhenMovingRight)
655 { 661 {
662 DCHECK(visiblePosition.isValid()) << visiblePosition;
656 VisiblePosition leftWordBreak = visualWordPosition(visiblePosition, MoveLeft , skipsSpaceWhenMovingRight); 663 VisiblePosition leftWordBreak = visualWordPosition(visiblePosition, MoveLeft , skipsSpaceWhenMovingRight);
657 leftWordBreak = honorEditingBoundaryAtOrBefore(leftWordBreak, visiblePositio n.deepEquivalent()); 664 leftWordBreak = honorEditingBoundaryAtOrBefore(leftWordBreak, visiblePositio n.deepEquivalent());
658 665
659 // FIXME: How should we handle a non-editable position? 666 // FIXME: How should we handle a non-editable position?
660 if (leftWordBreak.isNull() && isEditablePosition(visiblePosition.deepEquival ent())) { 667 if (leftWordBreak.isNull() && isEditablePosition(visiblePosition.deepEquival ent())) {
661 TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition .deepEquivalent()); 668 TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition .deepEquivalent());
662 leftWordBreak = blockDirection == LTR ? startOfEditableContent(visiblePo sition) : endOfEditableContent(visiblePosition); 669 leftWordBreak = blockDirection == LTR ? startOfEditableContent(visiblePo sition) : endOfEditableContent(visiblePosition);
663 } 670 }
664 return leftWordBreak; 671 return leftWordBreak;
665 } 672 }
666 673
667 VisiblePosition rightWordPosition(const VisiblePosition& visiblePosition, bool s kipsSpaceWhenMovingRight) 674 VisiblePosition rightWordPosition(const VisiblePosition& visiblePosition, bool s kipsSpaceWhenMovingRight)
668 { 675 {
676 DCHECK(visiblePosition.isValid()) << visiblePosition;
669 VisiblePosition rightWordBreak = visualWordPosition(visiblePosition, MoveRig ht, skipsSpaceWhenMovingRight); 677 VisiblePosition rightWordBreak = visualWordPosition(visiblePosition, MoveRig ht, skipsSpaceWhenMovingRight);
670 rightWordBreak = honorEditingBoundaryAtOrBefore(rightWordBreak, visiblePosit ion.deepEquivalent()); 678 rightWordBreak = honorEditingBoundaryAtOrBefore(rightWordBreak, visiblePosit ion.deepEquivalent());
671 679
672 // FIXME: How should we handle a non-editable position? 680 // FIXME: How should we handle a non-editable position?
673 if (rightWordBreak.isNull() && isEditablePosition(visiblePosition.deepEquiva lent())) { 681 if (rightWordBreak.isNull() && isEditablePosition(visiblePosition.deepEquiva lent())) {
674 TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition .deepEquivalent()); 682 TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition .deepEquivalent());
675 rightWordBreak = blockDirection == LTR ? endOfEditableContent(visiblePos ition) : startOfEditableContent(visiblePosition); 683 rightWordBreak = blockDirection == LTR ? endOfEditableContent(visiblePos ition) : startOfEditableContent(visiblePosition);
676 } 684 }
677 return rightWordBreak; 685 return rightWordBreak;
678 } 686 }
(...skipping 23 matching lines...) Expand all
702 return boundary; 710 return boundary;
703 } 711 }
704 712
705 enum BoundarySearchContextAvailability { DontHaveMoreContext, MayHaveMoreContext }; 713 enum BoundarySearchContextAvailability { DontHaveMoreContext, MayHaveMoreContext };
706 714
707 typedef unsigned (*BoundarySearchFunction)(const UChar*, unsigned length, unsign ed offset, BoundarySearchContextAvailability, bool& needMoreContext); 715 typedef unsigned (*BoundarySearchFunction)(const UChar*, unsigned length, unsign ed offset, BoundarySearchContextAvailability, bool& needMoreContext);
708 716
709 template <typename Strategy> 717 template <typename Strategy>
710 static VisiblePositionTemplate<Strategy> previousBoundary(const VisiblePositionT emplate<Strategy>& c, BoundarySearchFunction searchFunction) 718 static VisiblePositionTemplate<Strategy> previousBoundary(const VisiblePositionT emplate<Strategy>& c, BoundarySearchFunction searchFunction)
711 { 719 {
712 DCHECK(c.isValid()); 720 DCHECK(c.isValid()) << c;
713 const PositionTemplate<Strategy> pos = c.deepEquivalent(); 721 const PositionTemplate<Strategy> pos = c.deepEquivalent();
714 Node* boundary = parentEditingBoundary(pos); 722 Node* boundary = parentEditingBoundary(pos);
715 if (!boundary) 723 if (!boundary)
716 return VisiblePositionTemplate<Strategy>(); 724 return VisiblePositionTemplate<Strategy>();
717 725
718 const PositionTemplate<Strategy> start = PositionTemplate<Strategy>::editing PositionOf(boundary, 0).parentAnchoredEquivalent(); 726 const PositionTemplate<Strategy> start = PositionTemplate<Strategy>::editing PositionOf(boundary, 0).parentAnchoredEquivalent();
719 const PositionTemplate<Strategy> end = pos.parentAnchoredEquivalent(); 727 const PositionTemplate<Strategy> end = pos.parentAnchoredEquivalent();
720 728
721 ForwardsTextBuffer suffixString; 729 ForwardsTextBuffer suffixString;
722 if (requiresContextForWordBoundary(characterBefore(c))) { 730 if (requiresContextForWordBoundary(characterBefore(c))) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 // position. 796 // position.
789 BackwardsCharacterIteratorAlgorithm<Strategy> charIt(start, end); 797 BackwardsCharacterIteratorAlgorithm<Strategy> charIt(start, end);
790 charIt.advance(string.size() - suffixLength - next); 798 charIt.advance(string.size() - suffixLength - next);
791 // TODO(yosin) charIt can get out of shadow host. 799 // TODO(yosin) charIt can get out of shadow host.
792 return createVisiblePosition(charIt.endPosition()); 800 return createVisiblePosition(charIt.endPosition());
793 } 801 }
794 802
795 template <typename Strategy> 803 template <typename Strategy>
796 static VisiblePositionTemplate<Strategy> nextBoundary(const VisiblePositionTempl ate<Strategy>& c, BoundarySearchFunction searchFunction) 804 static VisiblePositionTemplate<Strategy> nextBoundary(const VisiblePositionTempl ate<Strategy>& c, BoundarySearchFunction searchFunction)
797 { 805 {
798 DCHECK(c.isValid()); 806 DCHECK(c.isValid()) << c;
799 PositionTemplate<Strategy> pos = c.deepEquivalent(); 807 PositionTemplate<Strategy> pos = c.deepEquivalent();
800 Node* boundary = parentEditingBoundary(pos); 808 Node* boundary = parentEditingBoundary(pos);
801 if (!boundary) 809 if (!boundary)
802 return VisiblePositionTemplate<Strategy>(); 810 return VisiblePositionTemplate<Strategy>();
803 811
804 Document& d = boundary->document(); 812 Document& d = boundary->document();
805 const PositionTemplate<Strategy> start(pos.parentAnchoredEquivalent()); 813 const PositionTemplate<Strategy> start(pos.parentAnchoredEquivalent());
806 814
807 BackwardsTextBuffer prefixString; 815 BackwardsTextBuffer prefixString;
808 if (requiresContextForWordBoundary(characterAfter(c))) { 816 if (requiresContextForWordBoundary(characterAfter(c))) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 needMoreContext = false; 911 needMoreContext = false;
904 int start, end; 912 int start, end;
905 U16_BACK_1(characters, 0, offset); 913 U16_BACK_1(characters, 0, offset);
906 findWordBoundary(characters, length, offset, &start, &end); 914 findWordBoundary(characters, length, offset, &start, &end);
907 return start; 915 return start;
908 } 916 }
909 917
910 template <typename Strategy> 918 template <typename Strategy>
911 static VisiblePositionTemplate<Strategy> startOfWordAlgorithm(const VisiblePosit ionTemplate<Strategy>& c, EWordSide side) 919 static VisiblePositionTemplate<Strategy> startOfWordAlgorithm(const VisiblePosit ionTemplate<Strategy>& c, EWordSide side)
912 { 920 {
921 DCHECK(c.isValid()) << c;
913 // TODO(yosin) This returns a null VP for c at the start of the document 922 // TODO(yosin) This returns a null VP for c at the start of the document
914 // and |side| == |LeftWordIfOnBoundary| 923 // and |side| == |LeftWordIfOnBoundary|
915 VisiblePositionTemplate<Strategy> p = c; 924 VisiblePositionTemplate<Strategy> p = c;
916 if (side == RightWordIfOnBoundary) { 925 if (side == RightWordIfOnBoundary) {
917 // at paragraph end, the startofWord is the current position 926 // at paragraph end, the startofWord is the current position
918 if (isEndOfParagraph(c)) 927 if (isEndOfParagraph(c))
919 return c; 928 return c;
920 929
921 p = nextPositionOf(c); 930 p = nextPositionOf(c);
922 if (p.isNull()) 931 if (p.isNull())
(...skipping 19 matching lines...) Expand all
942 needMoreContext = true; 951 needMoreContext = true;
943 return length; 952 return length;
944 } 953 }
945 needMoreContext = false; 954 needMoreContext = false;
946 return findWordEndBoundary(characters, length, offset); 955 return findWordEndBoundary(characters, length, offset);
947 } 956 }
948 957
949 template <typename Strategy> 958 template <typename Strategy>
950 static VisiblePositionTemplate<Strategy> endOfWordAlgorithm(const VisiblePositio nTemplate<Strategy>& c, EWordSide side) 959 static VisiblePositionTemplate<Strategy> endOfWordAlgorithm(const VisiblePositio nTemplate<Strategy>& c, EWordSide side)
951 { 960 {
961 DCHECK(c.isValid()) << c;
952 VisiblePositionTemplate<Strategy> p = c; 962 VisiblePositionTemplate<Strategy> p = c;
953 if (side == LeftWordIfOnBoundary) { 963 if (side == LeftWordIfOnBoundary) {
954 if (isStartOfParagraph(c)) 964 if (isStartOfParagraph(c))
955 return c; 965 return c;
956 966
957 p = previousPositionOf(c); 967 p = previousPositionOf(c);
958 if (p.isNull()) 968 if (p.isNull())
959 return c; 969 return c;
960 } else if (isEndOfParagraph(c)) { 970 } else if (isEndOfParagraph(c)) {
961 return c; 971 return c;
(...skipping 17 matching lines...) Expand all
979 if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset )) { 989 if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset )) {
980 needMoreContext = true; 990 needMoreContext = true;
981 return 0; 991 return 0;
982 } 992 }
983 needMoreContext = false; 993 needMoreContext = false;
984 return findNextWordFromIndex(characters, length, offset, false); 994 return findNextWordFromIndex(characters, length, offset, false);
985 } 995 }
986 996
987 VisiblePosition previousWordPosition(const VisiblePosition& c) 997 VisiblePosition previousWordPosition(const VisiblePosition& c)
988 { 998 {
999 DCHECK(c.isValid()) << c;
989 VisiblePosition prev = previousBoundary(c, previousWordPositionBoundary); 1000 VisiblePosition prev = previousBoundary(c, previousWordPositionBoundary);
990 return honorEditingBoundaryAtOrBefore(prev, c.deepEquivalent()); 1001 return honorEditingBoundaryAtOrBefore(prev, c.deepEquivalent());
991 } 1002 }
992 1003
993 static unsigned nextWordPositionBoundary(const UChar* characters, unsigned lengt h, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext) 1004 static unsigned nextWordPositionBoundary(const UChar* characters, unsigned lengt h, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
994 { 1005 {
995 if (mayHaveMoreContext && endOfFirstWordBoundaryContext(characters + offset, length - offset) == static_cast<int>(length - offset)) { 1006 if (mayHaveMoreContext && endOfFirstWordBoundaryContext(characters + offset, length - offset) == static_cast<int>(length - offset)) {
996 needMoreContext = true; 1007 needMoreContext = true;
997 return length; 1008 return length;
998 } 1009 }
999 needMoreContext = false; 1010 needMoreContext = false;
1000 return findNextWordFromIndex(characters, length, offset, true); 1011 return findNextWordFromIndex(characters, length, offset, true);
1001 } 1012 }
1002 1013
1003 VisiblePosition nextWordPosition(const VisiblePosition& c) 1014 VisiblePosition nextWordPosition(const VisiblePosition& c)
1004 { 1015 {
1016 DCHECK(c.isValid()) << c;
1005 VisiblePosition next = nextBoundary(c, nextWordPositionBoundary); 1017 VisiblePosition next = nextBoundary(c, nextWordPositionBoundary);
1006 return honorEditingBoundaryAtOrAfter(next, c.deepEquivalent()); 1018 return honorEditingBoundaryAtOrAfter(next, c.deepEquivalent());
1007 } 1019 }
1008 1020
1009 // --------- 1021 // ---------
1010 1022
1011 enum LineEndpointComputationMode { UseLogicalOrdering, UseInlineBoxOrdering }; 1023 enum LineEndpointComputationMode { UseLogicalOrdering, UseInlineBoxOrdering };
1012 template <typename Strategy> 1024 template <typename Strategy>
1013 static PositionWithAffinityTemplate<Strategy> startPositionForLine(const Positio nWithAffinityTemplate<Strategy>& c, LineEndpointComputationMode mode) 1025 static PositionWithAffinityTemplate<Strategy> startPositionForLine(const Positio nWithAffinityTemplate<Strategy>& c, LineEndpointComputationMode mode)
1014 { 1026 {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1066 } 1078 }
1067 1079
1068 static PositionInFlatTreeWithAffinity startOfLine(const PositionInFlatTreeWithAf finity& currentPosition) 1080 static PositionInFlatTreeWithAffinity startOfLine(const PositionInFlatTreeWithAf finity& currentPosition)
1069 { 1081 {
1070 return startOfLineAlgorithm<EditingInFlatTreeStrategy>(currentPosition); 1082 return startOfLineAlgorithm<EditingInFlatTreeStrategy>(currentPosition);
1071 } 1083 }
1072 1084
1073 // FIXME: Rename this function to reflect the fact it ignores bidi levels. 1085 // FIXME: Rename this function to reflect the fact it ignores bidi levels.
1074 VisiblePosition startOfLine(const VisiblePosition& currentPosition) 1086 VisiblePosition startOfLine(const VisiblePosition& currentPosition)
1075 { 1087 {
1076 DCHECK(currentPosition.isValid()); 1088 DCHECK(currentPosition.isValid()) << currentPosition;
1077 return createVisiblePosition(startOfLine(currentPosition.toPositionWithAffin ity())); 1089 return createVisiblePosition(startOfLine(currentPosition.toPositionWithAffin ity()));
1078 } 1090 }
1079 1091
1080 VisiblePositionInFlatTree startOfLine(const VisiblePositionInFlatTree& currentPo sition) 1092 VisiblePositionInFlatTree startOfLine(const VisiblePositionInFlatTree& currentPo sition)
1081 { 1093 {
1082 DCHECK(currentPosition.isValid()); 1094 DCHECK(currentPosition.isValid()) << currentPosition;
1083 return createVisiblePosition(startOfLine(currentPosition.toPositionWithAffin ity())); 1095 return createVisiblePosition(startOfLine(currentPosition.toPositionWithAffin ity()));
1084 } 1096 }
1085 1097
1086 template <typename Strategy> 1098 template <typename Strategy>
1087 static PositionWithAffinityTemplate<Strategy> logicalStartOfLineAlgorithm(const PositionWithAffinityTemplate<Strategy>& c) 1099 static PositionWithAffinityTemplate<Strategy> logicalStartOfLineAlgorithm(const PositionWithAffinityTemplate<Strategy>& c)
1088 { 1100 {
1089 // TODO: this is the current behavior that might need to be fixed. 1101 // TODO: this is the current behavior that might need to be fixed.
1090 // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail. 1102 // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail.
1091 PositionWithAffinityTemplate<Strategy> visPos = startPositionForLine(c, UseL ogicalOrdering); 1103 PositionWithAffinityTemplate<Strategy> visPos = startPositionForLine(c, UseL ogicalOrdering);
1092 1104
1093 if (ContainerNode* editableRoot = highestEditableRoot(c.position())) { 1105 if (ContainerNode* editableRoot = highestEditableRoot(c.position())) {
1094 if (!editableRoot->contains(visPos.position().computeContainerNode())) 1106 if (!editableRoot->contains(visPos.position().computeContainerNode()))
1095 return PositionWithAffinityTemplate<Strategy>(PositionTemplate<Strat egy>::firstPositionInNode(editableRoot)); 1107 return PositionWithAffinityTemplate<Strategy>(PositionTemplate<Strat egy>::firstPositionInNode(editableRoot));
1096 } 1108 }
1097 1109
1098 return honorEditingBoundaryAtOrBefore(visPos, c.position()); 1110 return honorEditingBoundaryAtOrBefore(visPos, c.position());
1099 } 1111 }
1100 1112
1101 VisiblePosition logicalStartOfLine(const VisiblePosition& currentPosition) 1113 VisiblePosition logicalStartOfLine(const VisiblePosition& currentPosition)
1102 { 1114 {
1103 DCHECK(currentPosition.isValid()); 1115 DCHECK(currentPosition.isValid()) << currentPosition;
1104 return createVisiblePosition(logicalStartOfLineAlgorithm<EditingStrategy>(cu rrentPosition.toPositionWithAffinity())); 1116 return createVisiblePosition(logicalStartOfLineAlgorithm<EditingStrategy>(cu rrentPosition.toPositionWithAffinity()));
1105 } 1117 }
1106 1118
1107 VisiblePositionInFlatTree logicalStartOfLine(const VisiblePositionInFlatTree& cu rrentPosition) 1119 VisiblePositionInFlatTree logicalStartOfLine(const VisiblePositionInFlatTree& cu rrentPosition)
1108 { 1120 {
1109 DCHECK(currentPosition.isValid()); 1121 DCHECK(currentPosition.isValid()) << currentPosition;
1110 return createVisiblePosition(logicalStartOfLineAlgorithm<EditingInFlatTreeSt rategy>(currentPosition.toPositionWithAffinity())); 1122 return createVisiblePosition(logicalStartOfLineAlgorithm<EditingInFlatTreeSt rategy>(currentPosition.toPositionWithAffinity()));
1111 } 1123 }
1112 1124
1113 template <typename Strategy> 1125 template <typename Strategy>
1114 static VisiblePositionTemplate<Strategy> endPositionForLine(const VisiblePositio nTemplate<Strategy>& c, LineEndpointComputationMode mode) 1126 static VisiblePositionTemplate<Strategy> endPositionForLine(const VisiblePositio nTemplate<Strategy>& c, LineEndpointComputationMode mode)
1115 { 1127 {
1116 DCHECK(c.isValid()); 1128 DCHECK(c.isValid()) << c;
1117 if (c.isNull()) 1129 if (c.isNull())
1118 return VisiblePositionTemplate<Strategy>(); 1130 return VisiblePositionTemplate<Strategy>();
1119 1131
1120 RootInlineBox* rootBox = RenderedPosition(c).rootBox(); 1132 RootInlineBox* rootBox = RenderedPosition(c).rootBox();
1121 if (!rootBox) { 1133 if (!rootBox) {
1122 // There are VisiblePositions at offset 0 in blocks without 1134 // There are VisiblePositions at offset 0 in blocks without
1123 // RootInlineBoxes, like empty editable blocks and bordered blocks. 1135 // RootInlineBoxes, like empty editable blocks and bordered blocks.
1124 const PositionTemplate<Strategy> p = c.deepEquivalent(); 1136 const PositionTemplate<Strategy> p = c.deepEquivalent();
1125 if (p.anchorNode()->layoutObject() && p.anchorNode()->layoutObject()->is LayoutBlock() && !p.computeEditingOffset()) 1137 if (p.anchorNode()->layoutObject() && p.anchorNode()->layoutObject()->is LayoutBlock() && !p.computeEditingOffset())
1126 return c; 1138 return c;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1163 pos = PositionTemplate<Strategy>::afterNode(endNode); 1175 pos = PositionTemplate<Strategy>::afterNode(endNode);
1164 } 1176 }
1165 1177
1166 return createVisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE); 1178 return createVisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE);
1167 } 1179 }
1168 1180
1169 // TODO(yosin) Rename this function to reflect the fact it ignores bidi levels. 1181 // TODO(yosin) Rename this function to reflect the fact it ignores bidi levels.
1170 template <typename Strategy> 1182 template <typename Strategy>
1171 static VisiblePositionTemplate<Strategy> endOfLineAlgorithm(const VisiblePositio nTemplate<Strategy>& currentPosition) 1183 static VisiblePositionTemplate<Strategy> endOfLineAlgorithm(const VisiblePositio nTemplate<Strategy>& currentPosition)
1172 { 1184 {
1185 DCHECK(currentPosition.isValid()) << currentPosition;
1173 // TODO(yosin) this is the current behavior that might need to be fixed. 1186 // TODO(yosin) this is the current behavior that might need to be fixed.
1174 // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail. 1187 // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail.
1175 VisiblePositionTemplate<Strategy> visPos = endPositionForLine(currentPositio n, UseInlineBoxOrdering); 1188 VisiblePositionTemplate<Strategy> visPos = endPositionForLine(currentPositio n, UseInlineBoxOrdering);
1176 1189
1177 // Make sure the end of line is at the same line as the given input 1190 // Make sure the end of line is at the same line as the given input
1178 // position. Else use the previous position to obtain end of line. This 1191 // position. Else use the previous position to obtain end of line. This
1179 // condition happens when the input position is before the space character 1192 // condition happens when the input position is before the space character
1180 // at the end of a soft-wrapped non-editable line. In this scenario, 1193 // at the end of a soft-wrapped non-editable line. In this scenario,
1181 // |endPositionForLine()| would incorrectly hand back a position in the next 1194 // |endPositionForLine()| would incorrectly hand back a position in the next
1182 // line instead. This fix is to account for the discrepancy between lines 1195 // line instead. This fix is to account for the discrepancy between lines
(...skipping 16 matching lines...) Expand all
1199 } 1212 }
1200 1213
1201 VisiblePositionInFlatTree endOfLine(const VisiblePositionInFlatTree& currentPosi tion) 1214 VisiblePositionInFlatTree endOfLine(const VisiblePositionInFlatTree& currentPosi tion)
1202 { 1215 {
1203 return endOfLineAlgorithm<EditingInFlatTreeStrategy>(currentPosition); 1216 return endOfLineAlgorithm<EditingInFlatTreeStrategy>(currentPosition);
1204 } 1217 }
1205 1218
1206 template <typename Strategy> 1219 template <typename Strategy>
1207 static bool inSameLogicalLine(const VisiblePositionTemplate<Strategy>& a, const VisiblePositionTemplate<Strategy>& b) 1220 static bool inSameLogicalLine(const VisiblePositionTemplate<Strategy>& a, const VisiblePositionTemplate<Strategy>& b)
1208 { 1221 {
1222 DCHECK(a.isValid()) << a;
1223 DCHECK(b.isValid()) << b;
1209 return a.isNotNull() && logicalStartOfLine(a).deepEquivalent() == logicalSta rtOfLine(b).deepEquivalent(); 1224 return a.isNotNull() && logicalStartOfLine(a).deepEquivalent() == logicalSta rtOfLine(b).deepEquivalent();
1210 } 1225 }
1211 1226
1212 template <typename Strategy> 1227 template <typename Strategy>
1213 VisiblePositionTemplate<Strategy> logicalEndOfLineAlgorithm(const VisiblePositio nTemplate<Strategy>& currentPosition) 1228 VisiblePositionTemplate<Strategy> logicalEndOfLineAlgorithm(const VisiblePositio nTemplate<Strategy>& currentPosition)
1214 { 1229 {
1215 DCHECK(currentPosition.isValid()); 1230 DCHECK(currentPosition.isValid()) << currentPosition;
1216 // TODO(yosin) this is the current behavior that might need to be fixed. 1231 // TODO(yosin) this is the current behavior that might need to be fixed.
1217 // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail. 1232 // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail.
1218 VisiblePositionTemplate<Strategy> visPos = endPositionForLine(currentPositio n, UseLogicalOrdering); 1233 VisiblePositionTemplate<Strategy> visPos = endPositionForLine(currentPositio n, UseLogicalOrdering);
1219 1234
1220 // Make sure the end of line is at the same line as the given input 1235 // Make sure the end of line is at the same line as the given input
1221 // position. For a wrapping line, the logical end position for the 1236 // position. For a wrapping line, the logical end position for the
1222 // not-last-2-lines might incorrectly hand back the logical beginning of the 1237 // not-last-2-lines might incorrectly hand back the logical beginning of the
1223 // next line. For example, 1238 // next line. For example,
1224 // <div contenteditable dir="rtl" style="line-break:before-white-space">xyz 1239 // <div contenteditable dir="rtl" style="line-break:before-white-space">xyz
1225 // a xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz </div> 1240 // a xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz </div>
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1269 return inSameLineAlgorithm<EditingStrategy>(a, b); 1284 return inSameLineAlgorithm<EditingStrategy>(a, b);
1270 } 1285 }
1271 1286
1272 bool inSameLine(const PositionInFlatTreeWithAffinity& position1, const PositionI nFlatTreeWithAffinity& position2) 1287 bool inSameLine(const PositionInFlatTreeWithAffinity& position1, const PositionI nFlatTreeWithAffinity& position2)
1273 { 1288 {
1274 return inSameLineAlgorithm<EditingInFlatTreeStrategy>(position1, position2); 1289 return inSameLineAlgorithm<EditingInFlatTreeStrategy>(position1, position2);
1275 } 1290 }
1276 1291
1277 bool inSameLine(const VisiblePosition& position1, const VisiblePosition& positio n2) 1292 bool inSameLine(const VisiblePosition& position1, const VisiblePosition& positio n2)
1278 { 1293 {
1294 DCHECK(position1.isValid()) << position1;
1295 DCHECK(position2.isValid()) << position2;
1279 return inSameLine(position1.toPositionWithAffinity(), position2.toPositionWi thAffinity()); 1296 return inSameLine(position1.toPositionWithAffinity(), position2.toPositionWi thAffinity());
1280 } 1297 }
1281 1298
1282 bool inSameLine(const VisiblePositionInFlatTree& position1, const VisiblePositio nInFlatTree& position2) 1299 bool inSameLine(const VisiblePositionInFlatTree& position1, const VisiblePositio nInFlatTree& position2)
1283 { 1300 {
1301 DCHECK(position1.isValid()) << position1;
1302 DCHECK(position2.isValid()) << position2;
1284 return inSameLine(position1.toPositionWithAffinity(), position2.toPositionWi thAffinity()); 1303 return inSameLine(position1.toPositionWithAffinity(), position2.toPositionWi thAffinity());
1285 } 1304 }
1286 1305
1287 template <typename Strategy> 1306 template <typename Strategy>
1288 bool isStartOfLineAlgorithm(const VisiblePositionTemplate<Strategy>& p) 1307 bool isStartOfLineAlgorithm(const VisiblePositionTemplate<Strategy>& p)
1289 { 1308 {
1309 DCHECK(p.isValid()) << p;
1290 return p.isNotNull() && p.deepEquivalent() == startOfLine(p).deepEquivalent( ); 1310 return p.isNotNull() && p.deepEquivalent() == startOfLine(p).deepEquivalent( );
1291 } 1311 }
1292 1312
1293 bool isStartOfLine(const VisiblePosition& p) 1313 bool isStartOfLine(const VisiblePosition& p)
1294 { 1314 {
1295 return isStartOfLineAlgorithm<EditingStrategy>(p); 1315 return isStartOfLineAlgorithm<EditingStrategy>(p);
1296 } 1316 }
1297 1317
1298 bool isStartOfLine(const VisiblePositionInFlatTree& p) 1318 bool isStartOfLine(const VisiblePositionInFlatTree& p)
1299 { 1319 {
1300 return isStartOfLineAlgorithm<EditingInFlatTreeStrategy>(p); 1320 return isStartOfLineAlgorithm<EditingInFlatTreeStrategy>(p);
1301 } 1321 }
1302 1322
1303 template <typename Strategy> 1323 template <typename Strategy>
1304 bool isEndOfLineAlgorithm(const VisiblePositionTemplate<Strategy>& p) 1324 bool isEndOfLineAlgorithm(const VisiblePositionTemplate<Strategy>& p)
1305 { 1325 {
1326 DCHECK(p.isValid()) << p;
1306 return p.isNotNull() && p.deepEquivalent() == endOfLine(p).deepEquivalent(); 1327 return p.isNotNull() && p.deepEquivalent() == endOfLine(p).deepEquivalent();
1307 } 1328 }
1308 1329
1309 bool isEndOfLine(const VisiblePosition& p) 1330 bool isEndOfLine(const VisiblePosition& p)
1310 { 1331 {
1311 return isEndOfLineAlgorithm<EditingStrategy>(p); 1332 return isEndOfLineAlgorithm<EditingStrategy>(p);
1312 } 1333 }
1313 1334
1314 bool isEndOfLine(const VisiblePositionInFlatTree& p) 1335 bool isEndOfLine(const VisiblePositionInFlatTree& p)
1315 { 1336 {
1316 return isEndOfLineAlgorithm<EditingInFlatTreeStrategy>(p); 1337 return isEndOfLineAlgorithm<EditingInFlatTreeStrategy>(p);
1317 } 1338 }
1318 1339
1319 template <typename Strategy> 1340 template <typename Strategy>
1320 static bool isLogicalEndOfLineAlgorithm(const VisiblePositionTemplate<Strategy>& p) 1341 static bool isLogicalEndOfLineAlgorithm(const VisiblePositionTemplate<Strategy>& p)
1321 { 1342 {
1343 DCHECK(p.isValid()) << p;
1322 return p.isNotNull() && p.deepEquivalent() == logicalEndOfLine(p).deepEquiva lent(); 1344 return p.isNotNull() && p.deepEquivalent() == logicalEndOfLine(p).deepEquiva lent();
1323 } 1345 }
1324 1346
1325 bool isLogicalEndOfLine(const VisiblePosition& p) 1347 bool isLogicalEndOfLine(const VisiblePosition& p)
1326 { 1348 {
1327 return isLogicalEndOfLineAlgorithm<EditingStrategy>(p); 1349 return isLogicalEndOfLineAlgorithm<EditingStrategy>(p);
1328 } 1350 }
1329 1351
1330 bool isLogicalEndOfLine(const VisiblePositionInFlatTree& p) 1352 bool isLogicalEndOfLine(const VisiblePositionInFlatTree& p)
1331 { 1353 {
1332 return isLogicalEndOfLineAlgorithm<EditingInFlatTreeStrategy>(p); 1354 return isLogicalEndOfLineAlgorithm<EditingInFlatTreeStrategy>(p);
1333 } 1355 }
1334 1356
1335 static inline LayoutPoint absoluteLineDirectionPointToLocalPointInBlock(RootInli neBox* root, LayoutUnit lineDirectionPoint) 1357 static inline LayoutPoint absoluteLineDirectionPointToLocalPointInBlock(RootInli neBox* root, LayoutUnit lineDirectionPoint)
1336 { 1358 {
1337 DCHECK(root); 1359 DCHECK(root);
1338 LineLayoutBlockFlow containingBlock = root->block(); 1360 LineLayoutBlockFlow containingBlock = root->block();
1339 FloatPoint absoluteBlockPoint = containingBlock.localToAbsolute(FloatPoint() ); 1361 FloatPoint absoluteBlockPoint = containingBlock.localToAbsolute(FloatPoint() );
1340 if (containingBlock.hasOverflowClip()) 1362 if (containingBlock.hasOverflowClip())
1341 absoluteBlockPoint -= FloatSize(containingBlock.scrolledContentOffset()) ; 1363 absoluteBlockPoint -= FloatSize(containingBlock.scrolledContentOffset()) ;
1342 1364
1343 if (root->block().isHorizontalWritingMode()) 1365 if (root->block().isHorizontalWritingMode())
1344 return LayoutPoint(LayoutUnit(lineDirectionPoint - absoluteBlockPoint.x( )), root->blockDirectionPointInLine()); 1366 return LayoutPoint(LayoutUnit(lineDirectionPoint - absoluteBlockPoint.x( )), root->blockDirectionPointInLine());
1345 1367
1346 return LayoutPoint(root->blockDirectionPointInLine(), LayoutUnit(lineDirecti onPoint - absoluteBlockPoint.y())); 1368 return LayoutPoint(root->blockDirectionPointInLine(), LayoutUnit(lineDirecti onPoint - absoluteBlockPoint.y()));
1347 } 1369 }
1348 1370
1349 VisiblePosition previousLinePosition(const VisiblePosition& visiblePosition, Lay outUnit lineDirectionPoint, EditableType editableType) 1371 VisiblePosition previousLinePosition(const VisiblePosition& visiblePosition, Lay outUnit lineDirectionPoint, EditableType editableType)
1350 { 1372 {
1351 DCHECK(visiblePosition.isValid()); 1373 DCHECK(visiblePosition.isValid()) << visiblePosition;
1352 1374
1353 Position p = visiblePosition.deepEquivalent(); 1375 Position p = visiblePosition.deepEquivalent();
1354 Node* node = p.anchorNode(); 1376 Node* node = p.anchorNode();
1355 1377
1356 if (!node) 1378 if (!node)
1357 return VisiblePosition(); 1379 return VisiblePosition();
1358 1380
1359 LayoutObject* layoutObject = node->layoutObject(); 1381 LayoutObject* layoutObject = node->layoutObject();
1360 if (!layoutObject) 1382 if (!layoutObject)
1361 return VisiblePosition(); 1383 return VisiblePosition();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1394 // Move to the start of the content in this block, which effectively moves u s 1416 // Move to the start of the content in this block, which effectively moves u s
1395 // to the start of the line we're on. 1417 // to the start of the line we're on.
1396 Element* rootElement = hasEditableStyle(*node, editableType) ? rootEditableE lement(*node, editableType) : node->document().documentElement(); 1418 Element* rootElement = hasEditableStyle(*node, editableType) ? rootEditableE lement(*node, editableType) : node->document().documentElement();
1397 if (!rootElement) 1419 if (!rootElement)
1398 return VisiblePosition(); 1420 return VisiblePosition();
1399 return VisiblePosition::firstPositionInNode(rootElement); 1421 return VisiblePosition::firstPositionInNode(rootElement);
1400 } 1422 }
1401 1423
1402 VisiblePosition nextLinePosition(const VisiblePosition& visiblePosition, LayoutU nit lineDirectionPoint, EditableType editableType) 1424 VisiblePosition nextLinePosition(const VisiblePosition& visiblePosition, LayoutU nit lineDirectionPoint, EditableType editableType)
1403 { 1425 {
1404 DCHECK(visiblePosition.isValid()); 1426 DCHECK(visiblePosition.isValid()) << visiblePosition;
1405 1427
1406 Position p = visiblePosition.deepEquivalent(); 1428 Position p = visiblePosition.deepEquivalent();
1407 Node* node = p.anchorNode(); 1429 Node* node = p.anchorNode();
1408 1430
1409 if (!node) 1431 if (!node)
1410 return VisiblePosition(); 1432 return VisiblePosition();
1411 1433
1412 LayoutObject* layoutObject = node->layoutObject(); 1434 LayoutObject* layoutObject = node->layoutObject();
1413 if (!layoutObject) 1435 if (!layoutObject)
1414 return VisiblePosition(); 1436 return VisiblePosition();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1460 static unsigned startSentenceBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&) 1482 static unsigned startSentenceBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
1461 { 1483 {
1462 TextBreakIterator* iterator = sentenceBreakIterator(characters, length); 1484 TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
1463 // FIXME: The following function can return -1; we don't handle that. 1485 // FIXME: The following function can return -1; we don't handle that.
1464 return iterator->preceding(length); 1486 return iterator->preceding(length);
1465 } 1487 }
1466 1488
1467 template <typename Strategy> 1489 template <typename Strategy>
1468 static VisiblePositionTemplate<Strategy> startOfSentenceAlgorithm(const VisibleP ositionTemplate<Strategy>& c) 1490 static VisiblePositionTemplate<Strategy> startOfSentenceAlgorithm(const VisibleP ositionTemplate<Strategy>& c)
1469 { 1491 {
1492 DCHECK(c.isValid()) << c;
1470 return previousBoundary(c, startSentenceBoundary); 1493 return previousBoundary(c, startSentenceBoundary);
1471 } 1494 }
1472 1495
1473 VisiblePosition startOfSentence(const VisiblePosition& c) 1496 VisiblePosition startOfSentence(const VisiblePosition& c)
1474 { 1497 {
1475 return startOfSentenceAlgorithm<EditingStrategy>(c); 1498 return startOfSentenceAlgorithm<EditingStrategy>(c);
1476 } 1499 }
1477 1500
1478 VisiblePositionInFlatTree startOfSentence(const VisiblePositionInFlatTree& c) 1501 VisiblePositionInFlatTree startOfSentence(const VisiblePositionInFlatTree& c)
1479 { 1502 {
1480 return startOfSentenceAlgorithm<EditingInFlatTreeStrategy>(c); 1503 return startOfSentenceAlgorithm<EditingInFlatTreeStrategy>(c);
1481 } 1504 }
1482 1505
1483 static unsigned endSentenceBoundary(const UChar* characters, unsigned length, un signed, BoundarySearchContextAvailability, bool&) 1506 static unsigned endSentenceBoundary(const UChar* characters, unsigned length, un signed, BoundarySearchContextAvailability, bool&)
1484 { 1507 {
1485 TextBreakIterator* iterator = sentenceBreakIterator(characters, length); 1508 TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
1486 return iterator->next(); 1509 return iterator->next();
1487 } 1510 }
1488 1511
1489 // TODO(yosin) This includes the space after the punctuation that marks the end 1512 // TODO(yosin) This includes the space after the punctuation that marks the end
1490 // of the sentence. 1513 // of the sentence.
1491 template <typename Strategy> 1514 template <typename Strategy>
1492 static VisiblePositionTemplate<Strategy> endOfSentenceAlgorithm(const VisiblePos itionTemplate<Strategy>& c) 1515 static VisiblePositionTemplate<Strategy> endOfSentenceAlgorithm(const VisiblePos itionTemplate<Strategy>& c)
1493 { 1516 {
1517 DCHECK(c.isValid()) << c;
1494 return nextBoundary(c, endSentenceBoundary); 1518 return nextBoundary(c, endSentenceBoundary);
1495 } 1519 }
1496 1520
1497 VisiblePosition endOfSentence(const VisiblePosition& c) 1521 VisiblePosition endOfSentence(const VisiblePosition& c)
1498 { 1522 {
1499 return endOfSentenceAlgorithm<EditingStrategy>(c); 1523 return endOfSentenceAlgorithm<EditingStrategy>(c);
1500 } 1524 }
1501 1525
1502 VisiblePositionInFlatTree endOfSentence(const VisiblePositionInFlatTree& c) 1526 VisiblePositionInFlatTree endOfSentence(const VisiblePositionInFlatTree& c)
1503 { 1527 {
1504 return endOfSentenceAlgorithm<EditingInFlatTreeStrategy>(c); 1528 return endOfSentenceAlgorithm<EditingInFlatTreeStrategy>(c);
1505 } 1529 }
1506 1530
1507 static unsigned previousSentencePositionBoundary(const UChar* characters, unsign ed length, unsigned, BoundarySearchContextAvailability, bool&) 1531 static unsigned previousSentencePositionBoundary(const UChar* characters, unsign ed length, unsigned, BoundarySearchContextAvailability, bool&)
1508 { 1532 {
1509 // FIXME: This is identical to startSentenceBoundary. I'm pretty sure that's not right. 1533 // FIXME: This is identical to startSentenceBoundary. I'm pretty sure that's not right.
1510 TextBreakIterator* iterator = sentenceBreakIterator(characters, length); 1534 TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
1511 // FIXME: The following function can return -1; we don't handle that. 1535 // FIXME: The following function can return -1; we don't handle that.
1512 return iterator->preceding(length); 1536 return iterator->preceding(length);
1513 } 1537 }
1514 1538
1515 VisiblePosition previousSentencePosition(const VisiblePosition& c) 1539 VisiblePosition previousSentencePosition(const VisiblePosition& c)
1516 { 1540 {
1541 DCHECK(c.isValid()) << c;
1517 VisiblePosition prev = previousBoundary(c, previousSentencePositionBoundary) ; 1542 VisiblePosition prev = previousBoundary(c, previousSentencePositionBoundary) ;
1518 return honorEditingBoundaryAtOrBefore(prev, c.deepEquivalent()); 1543 return honorEditingBoundaryAtOrBefore(prev, c.deepEquivalent());
1519 } 1544 }
1520 1545
1521 static unsigned nextSentencePositionBoundary(const UChar* characters, unsigned l ength, unsigned, BoundarySearchContextAvailability, bool&) 1546 static unsigned nextSentencePositionBoundary(const UChar* characters, unsigned l ength, unsigned, BoundarySearchContextAvailability, bool&)
1522 { 1547 {
1523 // FIXME: This is identical to endSentenceBoundary. This isn't right, it nee ds to 1548 // FIXME: This is identical to endSentenceBoundary. This isn't right, it nee ds to
1524 // move to the equivlant position in the following sentence. 1549 // move to the equivlant position in the following sentence.
1525 TextBreakIterator* iterator = sentenceBreakIterator(characters, length); 1550 TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
1526 return iterator->following(0); 1551 return iterator->following(0);
1527 } 1552 }
1528 1553
1529 VisiblePosition nextSentencePosition(const VisiblePosition& c) 1554 VisiblePosition nextSentencePosition(const VisiblePosition& c)
1530 { 1555 {
1556 DCHECK(c.isValid()) << c;
1531 VisiblePosition next = nextBoundary(c, nextSentencePositionBoundary); 1557 VisiblePosition next = nextBoundary(c, nextSentencePositionBoundary);
1532 return honorEditingBoundaryAtOrAfter(next, c.deepEquivalent()); 1558 return honorEditingBoundaryAtOrAfter(next, c.deepEquivalent());
1533 } 1559 }
1534 1560
1535 template <typename Strategy> 1561 template <typename Strategy>
1536 PositionTemplate<Strategy> startOfParagraphAlgorithm(const PositionTemplate<Stra tegy>& position, EditingBoundaryCrossingRule boundaryCrossingRule) 1562 PositionTemplate<Strategy> startOfParagraphAlgorithm(const PositionTemplate<Stra tegy>& position, EditingBoundaryCrossingRule boundaryCrossingRule)
1537 { 1563 {
1538 Node* const startNode = position.anchorNode(); 1564 Node* const startNode = position.anchorNode();
1539 1565
1540 if (!startNode) 1566 if (!startNode)
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
1762 return isEndOfParagraphAlgorithm<EditingStrategy>(pos, boundaryCrossingRule) ; 1788 return isEndOfParagraphAlgorithm<EditingStrategy>(pos, boundaryCrossingRule) ;
1763 } 1789 }
1764 1790
1765 bool isEndOfParagraph(const VisiblePositionInFlatTree& pos, EditingBoundaryCross ingRule boundaryCrossingRule) 1791 bool isEndOfParagraph(const VisiblePositionInFlatTree& pos, EditingBoundaryCross ingRule boundaryCrossingRule)
1766 { 1792 {
1767 return isEndOfParagraphAlgorithm<EditingInFlatTreeStrategy>(pos, boundaryCro ssingRule); 1793 return isEndOfParagraphAlgorithm<EditingInFlatTreeStrategy>(pos, boundaryCro ssingRule);
1768 } 1794 }
1769 1795
1770 VisiblePosition previousParagraphPosition(const VisiblePosition& p, LayoutUnit x ) 1796 VisiblePosition previousParagraphPosition(const VisiblePosition& p, LayoutUnit x )
1771 { 1797 {
1798 DCHECK(p.isValid()) << p;
1772 VisiblePosition pos = p; 1799 VisiblePosition pos = p;
1773 do { 1800 do {
1774 VisiblePosition n = previousLinePosition(pos, x); 1801 VisiblePosition n = previousLinePosition(pos, x);
1775 if (n.isNull() || n.deepEquivalent() == pos.deepEquivalent()) 1802 if (n.isNull() || n.deepEquivalent() == pos.deepEquivalent())
1776 break; 1803 break;
1777 pos = n; 1804 pos = n;
1778 } while (inSameParagraph(p, pos)); 1805 } while (inSameParagraph(p, pos));
1779 return pos; 1806 return pos;
1780 } 1807 }
1781 1808
1782 VisiblePosition nextParagraphPosition(const VisiblePosition& p, LayoutUnit x) 1809 VisiblePosition nextParagraphPosition(const VisiblePosition& p, LayoutUnit x)
1783 { 1810 {
1811 DCHECK(p.isValid()) << p;
1784 VisiblePosition pos = p; 1812 VisiblePosition pos = p;
1785 do { 1813 do {
1786 VisiblePosition n = nextLinePosition(pos, x); 1814 VisiblePosition n = nextLinePosition(pos, x);
1787 if (n.isNull() || n.deepEquivalent() == pos.deepEquivalent()) 1815 if (n.isNull() || n.deepEquivalent() == pos.deepEquivalent())
1788 break; 1816 break;
1789 pos = n; 1817 pos = n;
1790 } while (inSameParagraph(p, pos)); 1818 } while (inSameParagraph(p, pos));
1791 return pos; 1819 return pos;
1792 } 1820 }
1793 1821
1794 // --------- 1822 // ---------
1795 1823
1796 VisiblePosition startOfBlock(const VisiblePosition& visiblePosition, EditingBoun daryCrossingRule rule) 1824 VisiblePosition startOfBlock(const VisiblePosition& visiblePosition, EditingBoun daryCrossingRule rule)
1797 { 1825 {
1826 DCHECK(visiblePosition.isValid()) << visiblePosition;
1798 Position position = visiblePosition.deepEquivalent(); 1827 Position position = visiblePosition.deepEquivalent();
1799 Element* startBlock = position.computeContainerNode() ? enclosingBlock(posit ion.computeContainerNode(), rule) : 0; 1828 Element* startBlock = position.computeContainerNode() ? enclosingBlock(posit ion.computeContainerNode(), rule) : 0;
1800 return startBlock ? VisiblePosition::firstPositionInNode(startBlock) : Visib lePosition(); 1829 return startBlock ? VisiblePosition::firstPositionInNode(startBlock) : Visib lePosition();
1801 } 1830 }
1802 1831
1803 VisiblePosition endOfBlock(const VisiblePosition& visiblePosition, EditingBounda ryCrossingRule rule) 1832 VisiblePosition endOfBlock(const VisiblePosition& visiblePosition, EditingBounda ryCrossingRule rule)
1804 { 1833 {
1834 DCHECK(visiblePosition.isValid()) << visiblePosition;
1805 Position position = visiblePosition.deepEquivalent(); 1835 Position position = visiblePosition.deepEquivalent();
1806 Element* endBlock = position.computeContainerNode() ? enclosingBlock(positio n.computeContainerNode(), rule) : 0; 1836 Element* endBlock = position.computeContainerNode() ? enclosingBlock(positio n.computeContainerNode(), rule) : 0;
1807 return endBlock ? VisiblePosition::lastPositionInNode(endBlock) : VisiblePos ition(); 1837 return endBlock ? VisiblePosition::lastPositionInNode(endBlock) : VisiblePos ition();
1808 } 1838 }
1809 1839
1810 bool inSameBlock(const VisiblePosition& a, const VisiblePosition& b) 1840 bool inSameBlock(const VisiblePosition& a, const VisiblePosition& b)
1811 { 1841 {
1842 // TODO(xiaochengh): Ensure that this function is called with valid |a| and
1843 // |b|, and add |DCHECK(a.isValid())| and |DCHECK(b.isValid())|
1812 return !a.isNull() && enclosingBlock(a.deepEquivalent().computeContainerNode ()) == enclosingBlock(b.deepEquivalent().computeContainerNode()); 1844 return !a.isNull() && enclosingBlock(a.deepEquivalent().computeContainerNode ()) == enclosingBlock(b.deepEquivalent().computeContainerNode());
1813 } 1845 }
1814 1846
1815 bool isStartOfBlock(const VisiblePosition& pos) 1847 bool isStartOfBlock(const VisiblePosition& pos)
1816 { 1848 {
1849 DCHECK(pos.isValid()) << pos;
1817 return pos.isNotNull() && pos.deepEquivalent() == startOfBlock(pos, CanCross EditingBoundary).deepEquivalent(); 1850 return pos.isNotNull() && pos.deepEquivalent() == startOfBlock(pos, CanCross EditingBoundary).deepEquivalent();
1818 } 1851 }
1819 1852
1820 bool isEndOfBlock(const VisiblePosition& pos) 1853 bool isEndOfBlock(const VisiblePosition& pos)
1821 { 1854 {
1855 DCHECK(pos.isValid()) << pos;
1822 return pos.isNotNull() && pos.deepEquivalent() == endOfBlock(pos, CanCrossEd itingBoundary).deepEquivalent(); 1856 return pos.isNotNull() && pos.deepEquivalent() == endOfBlock(pos, CanCrossEd itingBoundary).deepEquivalent();
1823 } 1857 }
1824 1858
1825 // --------- 1859 // ---------
1826 1860
1827 template <typename Strategy> 1861 template <typename Strategy>
1828 static VisiblePositionTemplate<Strategy> startOfDocumentAlgorithm(const VisibleP ositionTemplate<Strategy>& visiblePosition) 1862 static VisiblePositionTemplate<Strategy> startOfDocumentAlgorithm(const VisibleP ositionTemplate<Strategy>& visiblePosition)
1829 { 1863 {
1830 DCHECK(visiblePosition.isValid()); 1864 DCHECK(visiblePosition.isValid()) << visiblePosition;
1831 Node* node = visiblePosition.deepEquivalent().anchorNode(); 1865 Node* node = visiblePosition.deepEquivalent().anchorNode();
1832 if (!node || !node->document().documentElement()) 1866 if (!node || !node->document().documentElement())
1833 return VisiblePositionTemplate<Strategy>(); 1867 return VisiblePositionTemplate<Strategy>();
1834 1868
1835 return createVisiblePosition(PositionTemplate<Strategy>::firstPositionInNode (node->document().documentElement())); 1869 return createVisiblePosition(PositionTemplate<Strategy>::firstPositionInNode (node->document().documentElement()));
1836 } 1870 }
1837 1871
1838 VisiblePosition startOfDocument(const VisiblePosition& c) 1872 VisiblePosition startOfDocument(const VisiblePosition& c)
1839 { 1873 {
1840 return startOfDocumentAlgorithm<EditingStrategy>(c); 1874 return startOfDocumentAlgorithm<EditingStrategy>(c);
1841 } 1875 }
1842 1876
1843 VisiblePositionInFlatTree startOfDocument(const VisiblePositionInFlatTree& c) 1877 VisiblePositionInFlatTree startOfDocument(const VisiblePositionInFlatTree& c)
1844 { 1878 {
1845 return startOfDocumentAlgorithm<EditingInFlatTreeStrategy>(c); 1879 return startOfDocumentAlgorithm<EditingInFlatTreeStrategy>(c);
1846 } 1880 }
1847 1881
1848 template <typename Strategy> 1882 template <typename Strategy>
1849 static VisiblePositionTemplate<Strategy> endOfDocumentAlgorithm(const VisiblePos itionTemplate<Strategy>& visiblePosition) 1883 static VisiblePositionTemplate<Strategy> endOfDocumentAlgorithm(const VisiblePos itionTemplate<Strategy>& visiblePosition)
1850 { 1884 {
1851 DCHECK(visiblePosition.isValid()); 1885 DCHECK(visiblePosition.isValid()) << visiblePosition;
1852 Node* node = visiblePosition.deepEquivalent().anchorNode(); 1886 Node* node = visiblePosition.deepEquivalent().anchorNode();
1853 if (!node || !node->document().documentElement()) 1887 if (!node || !node->document().documentElement())
1854 return VisiblePositionTemplate<Strategy>(); 1888 return VisiblePositionTemplate<Strategy>();
1855 1889
1856 Element* doc = node->document().documentElement(); 1890 Element* doc = node->document().documentElement();
1857 return createVisiblePosition(PositionTemplate<Strategy>::lastPositionInNode( doc)); 1891 return createVisiblePosition(PositionTemplate<Strategy>::lastPositionInNode( doc));
1858 } 1892 }
1859 1893
1860 VisiblePosition endOfDocument(const VisiblePosition& c) 1894 VisiblePosition endOfDocument(const VisiblePosition& c)
1861 { 1895 {
1862 return endOfDocumentAlgorithm<EditingStrategy>(c); 1896 return endOfDocumentAlgorithm<EditingStrategy>(c);
1863 } 1897 }
1864 1898
1865 VisiblePositionInFlatTree endOfDocument(const VisiblePositionInFlatTree& c) 1899 VisiblePositionInFlatTree endOfDocument(const VisiblePositionInFlatTree& c)
1866 { 1900 {
1867 return endOfDocumentAlgorithm<EditingInFlatTreeStrategy>(c); 1901 return endOfDocumentAlgorithm<EditingInFlatTreeStrategy>(c);
1868 } 1902 }
1869 1903
1870 bool isStartOfDocument(const VisiblePosition& p) 1904 bool isStartOfDocument(const VisiblePosition& p)
1871 { 1905 {
1906 DCHECK(p.isValid()) << p;
1872 return p.isNotNull() && previousPositionOf(p, CanCrossEditingBoundary).isNul l(); 1907 return p.isNotNull() && previousPositionOf(p, CanCrossEditingBoundary).isNul l();
1873 } 1908 }
1874 1909
1875 bool isEndOfDocument(const VisiblePosition& p) 1910 bool isEndOfDocument(const VisiblePosition& p)
1876 { 1911 {
1912 DCHECK(p.isValid()) << p;
1877 return p.isNotNull() && nextPositionOf(p, CanCrossEditingBoundary).isNull(); 1913 return p.isNotNull() && nextPositionOf(p, CanCrossEditingBoundary).isNull();
1878 } 1914 }
1879 1915
1880 // --------- 1916 // ---------
1881 1917
1882 VisiblePosition startOfEditableContent(const VisiblePosition& visiblePosition) 1918 VisiblePosition startOfEditableContent(const VisiblePosition& visiblePosition)
1883 { 1919 {
1920 DCHECK(visiblePosition.isValid()) << visiblePosition;
1884 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent()); 1921 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent());
1885 if (!highestRoot) 1922 if (!highestRoot)
1886 return VisiblePosition(); 1923 return VisiblePosition();
1887 1924
1888 return VisiblePosition::firstPositionInNode(highestRoot); 1925 return VisiblePosition::firstPositionInNode(highestRoot);
1889 } 1926 }
1890 1927
1891 VisiblePosition endOfEditableContent(const VisiblePosition& visiblePosition) 1928 VisiblePosition endOfEditableContent(const VisiblePosition& visiblePosition)
1892 { 1929 {
1930 DCHECK(visiblePosition.isValid()) << visiblePosition;
1893 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent()); 1931 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent());
1894 if (!highestRoot) 1932 if (!highestRoot)
1895 return VisiblePosition(); 1933 return VisiblePosition();
1896 1934
1897 return VisiblePosition::lastPositionInNode(highestRoot); 1935 return VisiblePosition::lastPositionInNode(highestRoot);
1898 } 1936 }
1899 1937
1900 bool isEndOfEditableOrNonEditableContent(const VisiblePosition& position) 1938 bool isEndOfEditableOrNonEditableContent(const VisiblePosition& position)
1901 { 1939 {
1940 DCHECK(position.isValid()) << position;
1902 return position.isNotNull() && nextPositionOf(position).isNull(); 1941 return position.isNotNull() && nextPositionOf(position).isNull();
1903 } 1942 }
1904 1943
1905 // TODO(yosin) We should rename |isEndOfEditableOrNonEditableContent()| what 1944 // TODO(yosin) We should rename |isEndOfEditableOrNonEditableContent()| what
1906 // this function does, e.g. |isLastVisiblePositionOrEndOfInnerEditor()|. 1945 // this function does, e.g. |isLastVisiblePositionOrEndOfInnerEditor()|.
1907 bool isEndOfEditableOrNonEditableContent(const VisiblePositionInFlatTree& positi on) 1946 bool isEndOfEditableOrNonEditableContent(const VisiblePositionInFlatTree& positi on)
1908 { 1947 {
1948 DCHECK(position.isValid()) << position;
1909 if (position.isNull()) 1949 if (position.isNull())
1910 return false; 1950 return false;
1911 const VisiblePositionInFlatTree nextPosition = nextPositionOf(position); 1951 const VisiblePositionInFlatTree nextPosition = nextPositionOf(position);
1912 if (nextPosition.isNull()) 1952 if (nextPosition.isNull())
1913 return true; 1953 return true;
1914 // In DOM version, following condition, the last position of inner editor 1954 // In DOM version, following condition, the last position of inner editor
1915 // of INPUT/TEXTAREA element, by |nextPosition().isNull()|, because of 1955 // of INPUT/TEXTAREA element, by |nextPosition().isNull()|, because of
1916 // an inner editor is an only leaf node. 1956 // an inner editor is an only leaf node.
1917 if (!nextPosition.deepEquivalent().isAfterAnchor()) 1957 if (!nextPosition.deepEquivalent().isAfterAnchor())
1918 return false; 1958 return false;
1919 return isHTMLTextFormControlElement(nextPosition.deepEquivalent().anchorNode ()); 1959 return isHTMLTextFormControlElement(nextPosition.deepEquivalent().anchorNode ());
1920 } 1960 }
1921 1961
1922 VisiblePosition leftBoundaryOfLine(const VisiblePosition& c, TextDirection direc tion) 1962 VisiblePosition leftBoundaryOfLine(const VisiblePosition& c, TextDirection direc tion)
1923 { 1963 {
1964 DCHECK(c.isValid()) << c;
1924 return direction == LTR ? logicalStartOfLine(c) : logicalEndOfLine(c); 1965 return direction == LTR ? logicalStartOfLine(c) : logicalEndOfLine(c);
1925 } 1966 }
1926 1967
1927 VisiblePosition rightBoundaryOfLine(const VisiblePosition& c, TextDirection dire ction) 1968 VisiblePosition rightBoundaryOfLine(const VisiblePosition& c, TextDirection dire ction)
1928 { 1969 {
1970 DCHECK(c.isValid()) << c;
1929 return direction == LTR ? logicalEndOfLine(c) : logicalStartOfLine(c); 1971 return direction == LTR ? logicalEndOfLine(c) : logicalStartOfLine(c);
1930 } 1972 }
1931 1973
1932 static bool isNonTextLeafChild(LayoutObject* object) 1974 static bool isNonTextLeafChild(LayoutObject* object)
1933 { 1975 {
1934 if (object->slowFirstChild()) 1976 if (object->slowFirstChild())
1935 return false; 1977 return false;
1936 if (object->isText()) 1978 if (object->isText())
1937 return false; 1979 return false;
1938 return true; 1980 return true;
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
2180 return computeInlineBoxPositionTemplate<EditingStrategy>(position, affinity) ; 2222 return computeInlineBoxPositionTemplate<EditingStrategy>(position, affinity) ;
2181 } 2223 }
2182 2224
2183 InlineBoxPosition computeInlineBoxPosition(const PositionInFlatTree& position, T extAffinity affinity) 2225 InlineBoxPosition computeInlineBoxPosition(const PositionInFlatTree& position, T extAffinity affinity)
2184 { 2226 {
2185 return computeInlineBoxPositionTemplate<EditingInFlatTreeStrategy>(position, affinity); 2227 return computeInlineBoxPositionTemplate<EditingInFlatTreeStrategy>(position, affinity);
2186 } 2228 }
2187 2229
2188 InlineBoxPosition computeInlineBoxPosition(const VisiblePosition& position) 2230 InlineBoxPosition computeInlineBoxPosition(const VisiblePosition& position)
2189 { 2231 {
2232 DCHECK(position.isValid()) << position;
2190 return computeInlineBoxPosition(position.deepEquivalent(), position.affinity ()); 2233 return computeInlineBoxPosition(position.deepEquivalent(), position.affinity ());
2191 } 2234 }
2192 2235
2193 InlineBoxPosition computeInlineBoxPosition(const VisiblePositionInFlatTree& posi tion) 2236 InlineBoxPosition computeInlineBoxPosition(const VisiblePositionInFlatTree& posi tion)
2194 { 2237 {
2238 DCHECK(position.isValid()) << position;
2195 return computeInlineBoxPosition(position.deepEquivalent(), position.affinity ()); 2239 return computeInlineBoxPosition(position.deepEquivalent(), position.affinity ());
2196 } 2240 }
2197 2241
2198 InlineBoxPosition computeInlineBoxPosition(const Position& position, TextAffinit y affinity, TextDirection primaryDirection) 2242 InlineBoxPosition computeInlineBoxPosition(const Position& position, TextAffinit y affinity, TextDirection primaryDirection)
2199 { 2243 {
2200 return computeInlineBoxPositionTemplate<EditingStrategy>(position, affinity, primaryDirection); 2244 return computeInlineBoxPositionTemplate<EditingStrategy>(position, affinity, primaryDirection);
2201 } 2245 }
2202 2246
2203 InlineBoxPosition computeInlineBoxPosition(const PositionInFlatTree& position, T extAffinity affinity, TextDirection primaryDirection) 2247 InlineBoxPosition computeInlineBoxPosition(const PositionInFlatTree& position, T extAffinity affinity, TextDirection primaryDirection)
2204 { 2248 {
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after
2801 } 2845 }
2802 2846
2803 bool isVisuallyEquivalentCandidate(const PositionInFlatTree& position) 2847 bool isVisuallyEquivalentCandidate(const PositionInFlatTree& position)
2804 { 2848 {
2805 return isVisuallyEquivalentCandidateAlgorithm<EditingInFlatTreeStrategy>(pos ition); 2849 return isVisuallyEquivalentCandidateAlgorithm<EditingInFlatTreeStrategy>(pos ition);
2806 } 2850 }
2807 2851
2808 template <typename Strategy> 2852 template <typename Strategy>
2809 static IntRect absoluteCaretBoundsOfAlgorithm(const VisiblePositionTemplate<Stra tegy>& visiblePosition) 2853 static IntRect absoluteCaretBoundsOfAlgorithm(const VisiblePositionTemplate<Stra tegy>& visiblePosition)
2810 { 2854 {
2855 // TODO(xiaochengh): Ensure that this function is called with a valid
2856 // |visiblePosition|, and add |DCHECK(visiblePosition.isValid())|;
2811 LayoutObject* layoutObject; 2857 LayoutObject* layoutObject;
2812 LayoutRect localRect = localCaretRectOfPosition(visiblePosition.toPositionWi thAffinity(), layoutObject); 2858 LayoutRect localRect = localCaretRectOfPosition(visiblePosition.toPositionWi thAffinity(), layoutObject);
2813 if (localRect.isEmpty() || !layoutObject) 2859 if (localRect.isEmpty() || !layoutObject)
2814 return IntRect(); 2860 return IntRect();
2815 2861
2816 return layoutObject->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoun dingBox(); 2862 return layoutObject->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoun dingBox();
2817 } 2863 }
2818 2864
2819 IntRect absoluteCaretBoundsOf(const VisiblePosition& visiblePosition) 2865 IntRect absoluteCaretBoundsOf(const VisiblePosition& visiblePosition)
2820 { 2866 {
2821 return absoluteCaretBoundsOfAlgorithm<EditingStrategy>(visiblePosition); 2867 return absoluteCaretBoundsOfAlgorithm<EditingStrategy>(visiblePosition);
2822 } 2868 }
2823 2869
2824 IntRect absoluteCaretBoundsOf(const VisiblePositionInFlatTree& visiblePosition) 2870 IntRect absoluteCaretBoundsOf(const VisiblePositionInFlatTree& visiblePosition)
2825 { 2871 {
2826 return absoluteCaretBoundsOfAlgorithm<EditingInFlatTreeStrategy>(visiblePosi tion); 2872 return absoluteCaretBoundsOfAlgorithm<EditingInFlatTreeStrategy>(visiblePosi tion);
2827 } 2873 }
2828 2874
2829 template <typename Strategy> 2875 template <typename Strategy>
2830 static VisiblePositionTemplate<Strategy> skipToEndOfEditingBoundary(const Visibl ePositionTemplate<Strategy>& pos, const PositionTemplate<Strategy>& anchor) 2876 static VisiblePositionTemplate<Strategy> skipToEndOfEditingBoundary(const Visibl ePositionTemplate<Strategy>& pos, const PositionTemplate<Strategy>& anchor)
2831 { 2877 {
2832 DCHECK(pos.isValid()); 2878 DCHECK(pos.isValid()) << pos;
2833 if (pos.isNull()) 2879 if (pos.isNull())
2834 return pos; 2880 return pos;
2835 2881
2836 ContainerNode* highestRoot = highestEditableRoot(anchor); 2882 ContainerNode* highestRoot = highestEditableRoot(anchor);
2837 ContainerNode* highestRootOfPos = highestEditableRoot(pos.deepEquivalent()); 2883 ContainerNode* highestRootOfPos = highestEditableRoot(pos.deepEquivalent());
2838 2884
2839 // Return |pos| itself if the two are from the very same editable region, 2885 // Return |pos| itself if the two are from the very same editable region,
2840 // or both are non-editable. 2886 // or both are non-editable.
2841 if (highestRootOfPos == highestRoot) 2887 if (highestRootOfPos == highestRoot)
2842 return pos; 2888 return pos;
2843 2889
2844 // If this is not editable but |pos| has an editable root, skip to the end 2890 // If this is not editable but |pos| has an editable root, skip to the end
2845 if (!highestRoot && highestRootOfPos) 2891 if (!highestRoot && highestRootOfPos)
2846 return createVisiblePosition(PositionTemplate<Strategy>(highestRootOfPos , PositionAnchorType::AfterAnchor).parentAnchoredEquivalent()); 2892 return createVisiblePosition(PositionTemplate<Strategy>(highestRootOfPos , PositionAnchorType::AfterAnchor).parentAnchoredEquivalent());
2847 2893
2848 // That must mean that |pos| is not editable. Return the next position after 2894 // That must mean that |pos| is not editable. Return the next position after
2849 // |pos| that is in the same editable region as this position 2895 // |pos| that is in the same editable region as this position
2850 DCHECK(highestRoot); 2896 DCHECK(highestRoot);
2851 return firstEditableVisiblePositionAfterPositionInRoot(pos.deepEquivalent(), *highestRoot); 2897 return firstEditableVisiblePositionAfterPositionInRoot(pos.deepEquivalent(), *highestRoot);
2852 } 2898 }
2853 2899
2854 template <typename Strategy> 2900 template <typename Strategy>
2855 static UChar32 characterAfterAlgorithm(const VisiblePositionTemplate<Strategy>& visiblePosition) 2901 static UChar32 characterAfterAlgorithm(const VisiblePositionTemplate<Strategy>& visiblePosition)
2856 { 2902 {
2903 // TODO(xiaochengh): Ensure that this function is called with a valid
2904 // |visiblePosition|, and add |DCHECK(visiblePosition.isValid())|
2857 // We canonicalize to the first of two equivalent candidates, but the second 2905 // We canonicalize to the first of two equivalent candidates, but the second
2858 // of the two candidates is the one that will be inside the text node 2906 // of the two candidates is the one that will be inside the text node
2859 // containing the character after this visible position. 2907 // containing the character after this visible position.
2860 const PositionTemplate<Strategy> pos = mostForwardCaretPosition(visiblePosit ion.deepEquivalent()); 2908 const PositionTemplate<Strategy> pos = mostForwardCaretPosition(visiblePosit ion.deepEquivalent());
2861 if (!pos.isOffsetInAnchor()) 2909 if (!pos.isOffsetInAnchor())
2862 return 0; 2910 return 0;
2863 Node* containerNode = pos.computeContainerNode(); 2911 Node* containerNode = pos.computeContainerNode();
2864 if (!containerNode || !containerNode->isTextNode()) 2912 if (!containerNode || !containerNode->isTextNode())
2865 return 0; 2913 return 0;
2866 unsigned offset = static_cast<unsigned>(pos.offsetInContainerNode()); 2914 unsigned offset = static_cast<unsigned>(pos.offsetInContainerNode());
(...skipping 11 matching lines...) Expand all
2878 } 2926 }
2879 2927
2880 UChar32 characterAfter(const VisiblePositionInFlatTree& visiblePosition) 2928 UChar32 characterAfter(const VisiblePositionInFlatTree& visiblePosition)
2881 { 2929 {
2882 return characterAfterAlgorithm<EditingInFlatTreeStrategy>(visiblePosition); 2930 return characterAfterAlgorithm<EditingInFlatTreeStrategy>(visiblePosition);
2883 } 2931 }
2884 2932
2885 template <typename Strategy> 2933 template <typename Strategy>
2886 static UChar32 characterBeforeAlgorithm(const VisiblePositionTemplate<Strategy>& visiblePosition) 2934 static UChar32 characterBeforeAlgorithm(const VisiblePositionTemplate<Strategy>& visiblePosition)
2887 { 2935 {
2936 // TODO(xiaochengh): Ensure that this function is called with a valid
2937 // |visiblePosition|, and add |DCHECK(visiblePosition.isValid())|
2888 return characterAfter(previousPositionOf(visiblePosition)); 2938 return characterAfter(previousPositionOf(visiblePosition));
2889 } 2939 }
2890 2940
2891 UChar32 characterBefore(const VisiblePosition& visiblePosition) 2941 UChar32 characterBefore(const VisiblePosition& visiblePosition)
2892 { 2942 {
2893 return characterBeforeAlgorithm<EditingStrategy>(visiblePosition); 2943 return characterBeforeAlgorithm<EditingStrategy>(visiblePosition);
2894 } 2944 }
2895 2945
2896 UChar32 characterBefore(const VisiblePositionInFlatTree& visiblePosition) 2946 UChar32 characterBefore(const VisiblePositionInFlatTree& visiblePosition)
2897 { 2947 {
2898 return characterBeforeAlgorithm<EditingInFlatTreeStrategy>(visiblePosition); 2948 return characterBeforeAlgorithm<EditingInFlatTreeStrategy>(visiblePosition);
2899 } 2949 }
2900 2950
2901 template <typename Strategy> 2951 template <typename Strategy>
2902 static PositionTemplate<Strategy> leftVisuallyDistinctCandidate(const VisiblePos itionTemplate<Strategy>& visiblePosition) 2952 static PositionTemplate<Strategy> leftVisuallyDistinctCandidate(const VisiblePos itionTemplate<Strategy>& visiblePosition)
2903 { 2953 {
2954 DCHECK(visiblePosition.isValid()) << visiblePosition;
2904 const PositionTemplate<Strategy> deepPosition = visiblePosition.deepEquivale nt(); 2955 const PositionTemplate<Strategy> deepPosition = visiblePosition.deepEquivale nt();
2905 PositionTemplate<Strategy> p = deepPosition; 2956 PositionTemplate<Strategy> p = deepPosition;
2906 2957
2907 if (p.isNull()) 2958 if (p.isNull())
2908 return PositionTemplate<Strategy>(); 2959 return PositionTemplate<Strategy>();
2909 2960
2910 const PositionTemplate<Strategy> downstreamStart = mostForwardCaretPosition( p); 2961 const PositionTemplate<Strategy> downstreamStart = mostForwardCaretPosition( p);
2911 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); 2962 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode());
2912 const TextAffinity affinity = visiblePosition.affinity(); 2963 const TextAffinity affinity = visiblePosition.affinity();
2913 2964
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
3046 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) != downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) 3097 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
3047 return p; 3098 return p;
3048 3099
3049 DCHECK_NE(p, deepPosition); 3100 DCHECK_NE(p, deepPosition);
3050 } 3101 }
3051 } 3102 }
3052 3103
3053 template <typename Strategy> 3104 template <typename Strategy>
3054 VisiblePositionTemplate<Strategy> leftPositionOfAlgorithm(const VisiblePositionT emplate<Strategy>& visiblePosition) 3105 VisiblePositionTemplate<Strategy> leftPositionOfAlgorithm(const VisiblePositionT emplate<Strategy>& visiblePosition)
3055 { 3106 {
3056 DCHECK(visiblePosition.isValid()); 3107 DCHECK(visiblePosition.isValid()) << visiblePosition;
3057 const PositionTemplate<Strategy> pos = leftVisuallyDistinctCandidate(visible Position); 3108 const PositionTemplate<Strategy> pos = leftVisuallyDistinctCandidate(visible Position);
3058 // TODO(yosin) Why can't we move left from the last position in a tree? 3109 // TODO(yosin) Why can't we move left from the last position in a tree?
3059 if (pos.atStartOfTree() || pos.atEndOfTree()) 3110 if (pos.atStartOfTree() || pos.atEndOfTree())
3060 return VisiblePositionTemplate<Strategy>(); 3111 return VisiblePositionTemplate<Strategy>();
3061 3112
3062 const VisiblePositionTemplate<Strategy> left = createVisiblePosition(pos); 3113 const VisiblePositionTemplate<Strategy> left = createVisiblePosition(pos);
3063 DCHECK_NE(left.deepEquivalent(), visiblePosition.deepEquivalent()); 3114 DCHECK_NE(left.deepEquivalent(), visiblePosition.deepEquivalent());
3064 3115
3065 return directionOfEnclosingBlock(left.deepEquivalent()) == LTR ? honorEditin gBoundaryAtOrBefore(left, visiblePosition.deepEquivalent()) : honorEditingBounda ryAtOrAfter(left, visiblePosition.deepEquivalent()); 3116 return directionOfEnclosingBlock(left.deepEquivalent()) == LTR ? honorEditin gBoundaryAtOrBefore(left, visiblePosition.deepEquivalent()) : honorEditingBounda ryAtOrAfter(left, visiblePosition.deepEquivalent());
3066 } 3117 }
3067 3118
3068 VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition) 3119 VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition)
3069 { 3120 {
3070 return leftPositionOfAlgorithm<EditingStrategy>(visiblePosition); 3121 return leftPositionOfAlgorithm<EditingStrategy>(visiblePosition);
3071 } 3122 }
3072 3123
3073 VisiblePositionInFlatTree leftPositionOf(const VisiblePositionInFlatTree& visibl ePosition) 3124 VisiblePositionInFlatTree leftPositionOf(const VisiblePositionInFlatTree& visibl ePosition)
3074 { 3125 {
3075 return leftPositionOfAlgorithm<EditingInFlatTreeStrategy>(visiblePosition); 3126 return leftPositionOfAlgorithm<EditingInFlatTreeStrategy>(visiblePosition);
3076 } 3127 }
3077 3128
3078 template <typename Strategy> 3129 template <typename Strategy>
3079 static PositionTemplate<Strategy> rightVisuallyDistinctCandidate(const VisiblePo sitionTemplate<Strategy>& visiblePosition) 3130 static PositionTemplate<Strategy> rightVisuallyDistinctCandidate(const VisiblePo sitionTemplate<Strategy>& visiblePosition)
3080 { 3131 {
3132 DCHECK(visiblePosition.isValid()) << visiblePosition;
3081 const PositionTemplate<Strategy> deepPosition = visiblePosition.deepEquivale nt(); 3133 const PositionTemplate<Strategy> deepPosition = visiblePosition.deepEquivale nt();
3082 PositionTemplate<Strategy> p = deepPosition; 3134 PositionTemplate<Strategy> p = deepPosition;
3083 if (p.isNull()) 3135 if (p.isNull())
3084 return PositionTemplate<Strategy>(); 3136 return PositionTemplate<Strategy>();
3085 3137
3086 const PositionTemplate<Strategy> downstreamStart = mostForwardCaretPosition( p); 3138 const PositionTemplate<Strategy> downstreamStart = mostForwardCaretPosition( p);
3087 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); 3139 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode());
3088 const TextAffinity affinity = visiblePosition.affinity(); 3140 const TextAffinity affinity = visiblePosition.affinity();
3089 3141
3090 while (true) { 3142 while (true) {
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
3225 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) != downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) 3277 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
3226 return p; 3278 return p;
3227 3279
3228 DCHECK_NE(p, deepPosition); 3280 DCHECK_NE(p, deepPosition);
3229 } 3281 }
3230 } 3282 }
3231 3283
3232 template <typename Strategy> 3284 template <typename Strategy>
3233 static VisiblePositionTemplate<Strategy> rightPositionOfAlgorithm(const VisibleP ositionTemplate<Strategy>& visiblePosition) 3285 static VisiblePositionTemplate<Strategy> rightPositionOfAlgorithm(const VisibleP ositionTemplate<Strategy>& visiblePosition)
3234 { 3286 {
3235 DCHECK(visiblePosition.isValid()); 3287 DCHECK(visiblePosition.isValid()) << visiblePosition;
3236 const PositionTemplate<Strategy> pos = rightVisuallyDistinctCandidate(visibl ePosition); 3288 const PositionTemplate<Strategy> pos = rightVisuallyDistinctCandidate(visibl ePosition);
3237 // FIXME: Why can't we move left from the last position in a tree? 3289 // FIXME: Why can't we move left from the last position in a tree?
3238 if (pos.atStartOfTree() || pos.atEndOfTree()) 3290 if (pos.atStartOfTree() || pos.atEndOfTree())
3239 return VisiblePositionTemplate<Strategy>(); 3291 return VisiblePositionTemplate<Strategy>();
3240 3292
3241 const VisiblePositionTemplate<Strategy> right = createVisiblePosition(pos); 3293 const VisiblePositionTemplate<Strategy> right = createVisiblePosition(pos);
3242 DCHECK_NE(right.deepEquivalent(), visiblePosition.deepEquivalent()); 3294 DCHECK_NE(right.deepEquivalent(), visiblePosition.deepEquivalent());
3243 3295
3244 return directionOfEnclosingBlock(right.deepEquivalent()) == LTR ? honorEditi ngBoundaryAtOrAfter(right, visiblePosition.deepEquivalent()) : honorEditingBound aryAtOrBefore(right, visiblePosition.deepEquivalent()); 3296 return directionOfEnclosingBlock(right.deepEquivalent()) == LTR ? honorEditi ngBoundaryAtOrAfter(right, visiblePosition.deepEquivalent()) : honorEditingBound aryAtOrBefore(right, visiblePosition.deepEquivalent());
3245 } 3297 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3279 } 3331 }
3280 3332
3281 VisiblePositionInFlatTree nextPositionOf(const VisiblePositionInFlatTree& visibl ePosition, EditingBoundaryCrossingRule rule) 3333 VisiblePositionInFlatTree nextPositionOf(const VisiblePositionInFlatTree& visibl ePosition, EditingBoundaryCrossingRule rule)
3282 { 3334 {
3283 return nextPositionOfAlgorithm<EditingInFlatTreeStrategy>(visiblePosition, r ule); 3335 return nextPositionOfAlgorithm<EditingInFlatTreeStrategy>(visiblePosition, r ule);
3284 } 3336 }
3285 3337
3286 template <typename Strategy> 3338 template <typename Strategy>
3287 static VisiblePositionTemplate<Strategy> skipToStartOfEditingBoundary(const Visi blePositionTemplate<Strategy>& pos, const PositionTemplate<Strategy>& anchor) 3339 static VisiblePositionTemplate<Strategy> skipToStartOfEditingBoundary(const Visi blePositionTemplate<Strategy>& pos, const PositionTemplate<Strategy>& anchor)
3288 { 3340 {
3289 DCHECK(pos.isValid()); 3341 DCHECK(pos.isValid()) << pos;
3290 if (pos.isNull()) 3342 if (pos.isNull())
3291 return pos; 3343 return pos;
3292 3344
3293 ContainerNode* highestRoot = highestEditableRoot(anchor); 3345 ContainerNode* highestRoot = highestEditableRoot(anchor);
3294 ContainerNode* highestRootOfPos = highestEditableRoot(pos.deepEquivalent()); 3346 ContainerNode* highestRootOfPos = highestEditableRoot(pos.deepEquivalent());
3295 3347
3296 // Return |pos| itself if the two are from the very same editable region, or 3348 // Return |pos| itself if the two are from the very same editable region, or
3297 // both are non-editable. 3349 // both are non-editable.
3298 if (highestRootOfPos == highestRoot) 3350 if (highestRootOfPos == highestRoot)
3299 return pos; 3351 return pos;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
3344 { 3396 {
3345 return previousPositionOfAlgorithm<EditingStrategy>(visiblePosition, rule); 3397 return previousPositionOfAlgorithm<EditingStrategy>(visiblePosition, rule);
3346 } 3398 }
3347 3399
3348 VisiblePositionInFlatTree previousPositionOf(const VisiblePositionInFlatTree& vi siblePosition, EditingBoundaryCrossingRule rule) 3400 VisiblePositionInFlatTree previousPositionOf(const VisiblePositionInFlatTree& vi siblePosition, EditingBoundaryCrossingRule rule)
3349 { 3401 {
3350 return previousPositionOfAlgorithm<EditingInFlatTreeStrategy>(visiblePositio n, rule); 3402 return previousPositionOfAlgorithm<EditingInFlatTreeStrategy>(visiblePositio n, rule);
3351 } 3403 }
3352 3404
3353 } // namespace blink 3405 } // namespace blink
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698