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 * | 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 23 matching lines...) Expand all Loading... | |
34 #include "core/editing/EditingUtilities.h" | 34 #include "core/editing/EditingUtilities.h" |
35 #include "core/editing/FrameSelection.h" | 35 #include "core/editing/FrameSelection.h" |
36 #include "core/editing/Position.h" | 36 #include "core/editing/Position.h" |
37 #include "core/editing/PositionIterator.h" | 37 #include "core/editing/PositionIterator.h" |
38 #include "core/editing/RenderedPosition.h" | 38 #include "core/editing/RenderedPosition.h" |
39 #include "core/editing/TextAffinity.h" | 39 #include "core/editing/TextAffinity.h" |
40 #include "core/editing/VisiblePosition.h" | 40 #include "core/editing/VisiblePosition.h" |
41 #include "core/editing/iterators/BackwardsCharacterIterator.h" | 41 #include "core/editing/iterators/BackwardsCharacterIterator.h" |
42 #include "core/editing/iterators/CharacterIterator.h" | 42 #include "core/editing/iterators/CharacterIterator.h" |
43 #include "core/editing/iterators/SimplifiedBackwardsTextIterator.h" | 43 #include "core/editing/iterators/SimplifiedBackwardsTextIterator.h" |
44 #include "core/editing/iterators/TextAccumulator.h" | |
44 #include "core/editing/iterators/TextIterator.h" | 45 #include "core/editing/iterators/TextIterator.h" |
45 #include "core/frame/LocalFrame.h" | 46 #include "core/frame/LocalFrame.h" |
46 #include "core/frame/Settings.h" | 47 #include "core/frame/Settings.h" |
47 #include "core/html/HTMLBRElement.h" | 48 #include "core/html/HTMLBRElement.h" |
48 #include "core/html/HTMLTextFormControlElement.h" | 49 #include "core/html/HTMLTextFormControlElement.h" |
49 #include "core/layout/HitTestRequest.h" | 50 #include "core/layout/HitTestRequest.h" |
50 #include "core/layout/HitTestResult.h" | 51 #include "core/layout/HitTestResult.h" |
51 #include "core/layout/LayoutBlockFlow.h" | 52 #include "core/layout/LayoutBlockFlow.h" |
52 #include "core/layout/LayoutInline.h" | 53 #include "core/layout/LayoutInline.h" |
53 #include "core/layout/LayoutObject.h" | 54 #include "core/layout/LayoutObject.h" |
(...skipping 605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
659 static VisiblePositionTemplate<Strategy> previousBoundary(const VisiblePositionT emplate<Strategy>& c, BoundarySearchFunction searchFunction) | 660 static VisiblePositionTemplate<Strategy> previousBoundary(const VisiblePositionT emplate<Strategy>& c, BoundarySearchFunction searchFunction) |
660 { | 661 { |
661 const PositionTemplate<Strategy> pos = c.deepEquivalent(); | 662 const PositionTemplate<Strategy> pos = c.deepEquivalent(); |
662 Node* boundary = parentEditingBoundary(pos); | 663 Node* boundary = parentEditingBoundary(pos); |
663 if (!boundary) | 664 if (!boundary) |
664 return VisiblePositionTemplate<Strategy>(); | 665 return VisiblePositionTemplate<Strategy>(); |
665 | 666 |
666 const PositionTemplate<Strategy> start = PositionTemplate<Strategy>::editing PositionOf(boundary, 0).parentAnchoredEquivalent(); | 667 const PositionTemplate<Strategy> start = PositionTemplate<Strategy>::editing PositionOf(boundary, 0).parentAnchoredEquivalent(); |
667 const PositionTemplate<Strategy> end = pos.parentAnchoredEquivalent(); | 668 const PositionTemplate<Strategy> end = pos.parentAnchoredEquivalent(); |
668 | 669 |
669 Vector<UChar, 1024> string; | 670 ForwardsTextBuffer suffixString; |
670 unsigned suffixLength = 0; | 671 unsigned suffixLength = 0; |
671 | 672 |
672 if (requiresContextForWordBoundary(characterBefore(c))) { | 673 if (requiresContextForWordBoundary(characterBefore(c))) { |
673 TextIteratorAlgorithm<Strategy> forwardsIterator(end, PositionTemplate<S trategy>::afterNode(boundary)); | 674 TextIteratorAlgorithm<Strategy> forwardsIterator(end, PositionTemplate<S trategy>::afterNode(boundary)); |
674 while (!forwardsIterator.atEnd()) { | 675 while (!forwardsIterator.atEnd()) { |
675 Vector<UChar, 1024> characters; | 676 // TODO(xiaochengh): Eliminate this intermediate buffer. |
677 ForwardsTextBuffer characters; | |
676 forwardsIterator.copyTextTo(characters); | 678 forwardsIterator.copyTextTo(characters); |
677 int i = endOfFirstWordBoundaryContext(characters.data(), characters. size()); | 679 int i = endOfFirstWordBoundaryContext(characters.data(), characters. size()); |
678 string.append(characters.data(), i); | 680 suffixString.push(characters.data(), i); |
679 suffixLength += i; | 681 suffixLength += i; |
680 if (static_cast<unsigned>(i) < characters.size()) | 682 if (static_cast<unsigned>(i) < characters.size()) |
681 break; | 683 break; |
682 forwardsIterator.advance(); | 684 forwardsIterator.advance(); |
683 } | 685 } |
684 } | 686 } |
685 | 687 |
688 BackwardsTextAccumulator string; | |
689 string.push(suffixString.data(), suffixString.size()); | |
690 | |
686 SimplifiedBackwardsTextIteratorAlgorithm<Strategy> it(start, end); | 691 SimplifiedBackwardsTextIteratorAlgorithm<Strategy> it(start, end); |
687 unsigned next = 0; | 692 unsigned next = 0; |
688 bool needMoreContext = false; | 693 bool needMoreContext = false; |
689 while (!it.atEnd()) { | 694 while (!it.atEnd()) { |
690 bool inTextSecurityMode = it.isInTextSecurityMode(); | |
691 // iterate to get chunks until the searchFunction returns a non-zero | 695 // iterate to get chunks until the searchFunction returns a non-zero |
692 // value. | 696 // value. |
693 // TODO(xiaochengh): Iterative prepending has quadratic running time | 697 string.extract(it); |
yosin_UTC9
2016/02/09 02:28:04
it.copyTo(string)
| |
694 // in the worst case. Should improve it to linear. | |
695 if (!inTextSecurityMode) { | |
696 it.copyTextTo(string); | |
697 } else { | |
698 // Treat bullets used in the text security mode as regular | |
699 // characters when looking for boundaries | |
700 Vector<UChar, 1024> iteratorString; | |
701 iteratorString.fill('x', it.length()); | |
702 string.prepend(iteratorString.data(), iteratorString.size()); | |
703 } | |
704 // TODO(xiaochengh): The following line takes O(string.size()) time, | 698 // TODO(xiaochengh): The following line takes O(string.size()) time, |
705 // which makes the while loop take quadratic time in the worst case. | 699 // which makes the while loop take quadratic time in the worst case. |
706 // Should improve it in some way. | 700 // Should improve it in some way. |
707 next = searchFunction(string.data(), string.size(), string.size() - suff ixLength, MayHaveMoreContext, needMoreContext); | 701 next = searchFunction(string.data(), string.size(), string.size() - suff ixLength, MayHaveMoreContext, needMoreContext); |
708 if (next) | 702 if (next) |
709 break; | 703 break; |
710 it.advance(); | 704 string.advance(it); |
yosin_UTC9
2016/02/09 02:28:05
if (string.isSomeCondition()) {
string.resetAccu
| |
711 } | 705 } |
712 if (needMoreContext) { | 706 if (needMoreContext) { |
713 // The last search returned the beginning of the buffer and asked for | 707 // The last search returned the beginning of the buffer and asked for |
714 // more context, but there is no earlier text. Force a search with | 708 // more context, but there is no earlier text. Force a search with |
715 // what's available. | 709 // what's available. |
716 // TODO(xiaochengh): Do we have to search the whole string? | 710 // TODO(xiaochengh): Do we have to search the whole string? |
717 next = searchFunction(string.data(), string.size(), string.size() - suff ixLength, DontHaveMoreContext, needMoreContext); | 711 next = searchFunction(string.data(), string.size(), string.size() - suff ixLength, DontHaveMoreContext, needMoreContext); |
718 ASSERT(!needMoreContext); | 712 ASSERT(!needMoreContext); |
719 } | 713 } |
720 | 714 |
721 if (!next) | 715 if (!next) |
722 return createVisiblePosition(it.atEnd() ? it.startPosition() : pos); | 716 return createVisiblePosition(it.atEnd() ? it.startPosition() : pos); |
723 | 717 |
724 Node* node = it.startContainer(); | 718 Node* node = it.startContainer(); |
725 if (node->isTextNode() && static_cast<int>(next) <= node->maxCharacterOffset ()) { | 719 int boundaryOffset = it.length() - string.accumulatedLengthInCurrentNode() + next; |
720 if (node->isTextNode() && boundaryOffset <= node->maxCharacterOffset()) { | |
726 // The next variable contains a usable index into a text node | 721 // The next variable contains a usable index into a text node |
727 return createVisiblePosition(PositionTemplate<Strategy>(node, next)); | 722 return createVisiblePosition(PositionTemplate<Strategy>(node, boundaryOf fset)); |
728 } | 723 } |
729 | 724 |
730 // Use the character iterator to translate the next value into a DOM | 725 // Use the character iterator to translate the next value into a DOM |
731 // position. | 726 // position. |
732 BackwardsCharacterIteratorAlgorithm<Strategy> charIt(start, end); | 727 BackwardsCharacterIteratorAlgorithm<Strategy> charIt(start, end); |
733 charIt.advance(string.size() - suffixLength - next); | 728 charIt.advance(string.size() - suffixLength - next); |
734 // TODO(yosin) charIt can get out of shadow host. | 729 // TODO(yosin) charIt can get out of shadow host. |
735 return createVisiblePosition(charIt.endPosition()); | 730 return createVisiblePosition(charIt.endPosition()); |
736 } | 731 } |
737 | 732 |
738 template <typename Strategy> | 733 template <typename Strategy> |
739 static VisiblePositionTemplate<Strategy> nextBoundary(const VisiblePositionTempl ate<Strategy>& c, BoundarySearchFunction searchFunction) | 734 static VisiblePositionTemplate<Strategy> nextBoundary(const VisiblePositionTempl ate<Strategy>& c, BoundarySearchFunction searchFunction) |
740 { | 735 { |
741 PositionTemplate<Strategy> pos = c.deepEquivalent(); | 736 PositionTemplate<Strategy> pos = c.deepEquivalent(); |
742 Node* boundary = parentEditingBoundary(pos); | 737 Node* boundary = parentEditingBoundary(pos); |
743 if (!boundary) | 738 if (!boundary) |
744 return VisiblePositionTemplate<Strategy>(); | 739 return VisiblePositionTemplate<Strategy>(); |
745 | 740 |
746 Document& d = boundary->document(); | 741 Document& d = boundary->document(); |
747 const PositionTemplate<Strategy> start(pos.parentAnchoredEquivalent()); | 742 const PositionTemplate<Strategy> start(pos.parentAnchoredEquivalent()); |
748 | 743 |
749 Vector<UChar, 1024> string; | 744 BackwardsTextBuffer prefixString; |
750 unsigned prefixLength = 0; | 745 unsigned prefixLength = 0; |
751 | 746 |
752 if (requiresContextForWordBoundary(characterAfter(c))) { | 747 if (requiresContextForWordBoundary(characterAfter(c))) { |
753 SimplifiedBackwardsTextIteratorAlgorithm<Strategy> backwardsIterator(Pos itionTemplate<Strategy>::firstPositionInNode(&d), start); | 748 SimplifiedBackwardsTextIteratorAlgorithm<Strategy> backwardsIterator(Pos itionTemplate<Strategy>::firstPositionInNode(&d), start); |
754 while (!backwardsIterator.atEnd()) { | 749 while (!backwardsIterator.atEnd()) { |
755 Vector<UChar, 1024> characters; | 750 // TODO(xiaochengh): Eliminate this intermediate buffer. |
751 BackwardsTextBuffer characters; | |
756 backwardsIterator.copyTextTo(characters); | 752 backwardsIterator.copyTextTo(characters); |
757 int length = characters.size(); | 753 int length = characters.size(); |
758 int i = startOfLastWordBoundaryContext(characters.data(), length); | 754 int i = startOfLastWordBoundaryContext(characters.data(), length); |
759 // TODO(xiaochengh): Iterative prepending has quadratic running | 755 prefixString.push(characters.data() + i, length - i); |
760 // time in the worst case. Should improve it to linear. | |
761 string.prepend(characters.data() + i, length - i); | |
762 prefixLength += length - i; | 756 prefixLength += length - i; |
763 if (i > 0) | 757 if (i > 0) |
764 break; | 758 break; |
765 backwardsIterator.advance(); | 759 backwardsIterator.advance(); |
766 } | 760 } |
767 } | 761 } |
768 | 762 |
763 ForwardsTextAccumulator string; | |
764 string.push(prefixString.data(), prefixString.size()); | |
765 | |
769 const PositionTemplate<Strategy> searchStart = PositionTemplate<Strategy>::e ditingPositionOf(start.anchorNode(), start.offsetInContainerNode()); | 766 const PositionTemplate<Strategy> searchStart = PositionTemplate<Strategy>::e ditingPositionOf(start.anchorNode(), start.offsetInContainerNode()); |
770 const PositionTemplate<Strategy> searchEnd = PositionTemplate<Strategy>::las tPositionInNode(boundary); | 767 const PositionTemplate<Strategy> searchEnd = PositionTemplate<Strategy>::las tPositionInNode(boundary); |
771 TextIteratorAlgorithm<Strategy> it(searchStart, searchEnd, TextIteratorEmits CharactersBetweenAllVisiblePositions); | 768 TextIteratorAlgorithm<Strategy> it(searchStart, searchEnd, TextIteratorEmits CharactersBetweenAllVisiblePositions); |
772 const unsigned invalidOffset = static_cast<unsigned>(-1); | 769 const unsigned invalidOffset = static_cast<unsigned>(-1); |
773 unsigned next = invalidOffset; | 770 unsigned next = invalidOffset; |
774 unsigned offset = prefixLength; | 771 unsigned offset = prefixLength; |
775 bool needMoreContext = false; | 772 bool needMoreContext = false; |
776 while (!it.atEnd()) { | 773 while (!it.atEnd()) { |
777 // Keep asking the iterator for chunks until the search function | 774 // Keep asking the iterator for chunks until the search function |
778 // returns an end value not equal to the length of the string passed to | 775 // returns an end value not equal to the length of the string passed to |
779 // it. | 776 // it. |
780 bool inTextSecurityMode = it.isInTextSecurityMode(); | 777 string.extract(it); |
781 if (!inTextSecurityMode) { | |
782 it.copyTextTo(string); | |
783 } else { | |
784 // Treat bullets used in the text security mode as regular | |
785 // characters when looking for boundaries | |
786 Vector<UChar, 1024> iteratorString; | |
787 iteratorString.fill('x', it.length()); | |
788 string.append(iteratorString.data(), iteratorString.size()); | |
789 } | |
790 next = searchFunction(string.data(), string.size(), offset, MayHaveMoreC ontext, needMoreContext); | 778 next = searchFunction(string.data(), string.size(), offset, MayHaveMoreC ontext, needMoreContext); |
791 if (next != string.size()) | 779 if (next != string.size()) |
792 break; | 780 break; |
793 it.advance(); | 781 string.advance(it); |
794 if (!needMoreContext) { | 782 if (!needMoreContext) { |
795 // When the search does not need more context, skip all examined | 783 // When the search does not need more context, skip all examined |
796 // characters except the last one, in case it is a boundary. | 784 // characters except the last one, in case it is a boundary. |
797 offset = string.size(); | 785 offset = string.size(); |
798 U16_BACK_1(string.data(), 0, offset); | 786 U16_BACK_1(string.data(), 0, offset); |
799 } | 787 } |
800 } | 788 } |
801 if (needMoreContext) { | 789 if (needMoreContext) { |
802 // The last search returned the end of the buffer and asked for more | 790 // The last search returned the end of the buffer and asked for more |
803 // context, but there is no further text. Force a search with what's | 791 // context, but there is no further text. Force a search with what's |
(...skipping 2523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3327 { | 3315 { |
3328 return previousPositionOfAlgorithm<EditingStrategy>(visiblePosition, rule); | 3316 return previousPositionOfAlgorithm<EditingStrategy>(visiblePosition, rule); |
3329 } | 3317 } |
3330 | 3318 |
3331 VisiblePositionInComposedTree previousPositionOf(const VisiblePositionInComposed Tree& visiblePosition, EditingBoundaryCrossingRule rule) | 3319 VisiblePositionInComposedTree previousPositionOf(const VisiblePositionInComposed Tree& visiblePosition, EditingBoundaryCrossingRule rule) |
3332 { | 3320 { |
3333 return previousPositionOfAlgorithm<EditingInComposedTreeStrategy>(visiblePos ition, rule); | 3321 return previousPositionOfAlgorithm<EditingInComposedTreeStrategy>(visiblePos ition, rule); |
3334 } | 3322 } |
3335 | 3323 |
3336 } // namespace blink | 3324 } // namespace blink |
OLD | NEW |