| 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/BackwardsTextBuffer.h" | 42 #include "core/editing/iterators/BackwardsTextBuffer.h" |
| 43 #include "core/editing/iterators/CharacterIterator.h" | 43 #include "core/editing/iterators/CharacterIterator.h" |
| 44 #include "core/editing/iterators/ExponentialAccumulator.h" |
| 44 #include "core/editing/iterators/ForwardsTextBuffer.h" | 45 #include "core/editing/iterators/ForwardsTextBuffer.h" |
| 45 #include "core/editing/iterators/SimplifiedBackwardsTextIterator.h" | 46 #include "core/editing/iterators/SimplifiedBackwardsTextIterator.h" |
| 46 #include "core/editing/iterators/TextIterator.h" | 47 #include "core/editing/iterators/TextIterator.h" |
| 47 #include "core/frame/LocalFrame.h" | 48 #include "core/frame/LocalFrame.h" |
| 48 #include "core/frame/Settings.h" | 49 #include "core/frame/Settings.h" |
| 49 #include "core/html/HTMLBRElement.h" | 50 #include "core/html/HTMLBRElement.h" |
| 50 #include "core/html/HTMLTextFormControlElement.h" | 51 #include "core/html/HTMLTextFormControlElement.h" |
| 51 #include "core/layout/HitTestRequest.h" | 52 #include "core/layout/HitTestRequest.h" |
| 52 #include "core/layout/HitTestResult.h" | 53 #include "core/layout/HitTestResult.h" |
| 53 #include "core/layout/LayoutBlockFlow.h" | 54 #include "core/layout/LayoutBlockFlow.h" |
| (...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 forwardsIterator.copyTextTo(&characters); | 680 forwardsIterator.copyTextTo(&characters); |
| 680 int i = endOfFirstWordBoundaryContext(characters.data(), characters.
size()); | 681 int i = endOfFirstWordBoundaryContext(characters.data(), characters.
size()); |
| 681 suffixString.pushRange(characters.data(), i); | 682 suffixString.pushRange(characters.data(), i); |
| 682 suffixLength += i; | 683 suffixLength += i; |
| 683 if (static_cast<unsigned>(i) < characters.size()) | 684 if (static_cast<unsigned>(i) < characters.size()) |
| 684 break; | 685 break; |
| 685 forwardsIterator.advance(); | 686 forwardsIterator.advance(); |
| 686 } | 687 } |
| 687 } | 688 } |
| 688 | 689 |
| 690 ExponentialAccumulator accumulator; |
| 689 BackwardsTextBuffer string; | 691 BackwardsTextBuffer string; |
| 690 string.pushRange(suffixString.data(), suffixString.size()); | 692 string.pushRange(suffixString.data(), suffixString.size()); |
| 691 | 693 |
| 692 SimplifiedBackwardsTextIteratorAlgorithm<Strategy> it(start, end); | 694 SimplifiedBackwardsTextIteratorAlgorithm<Strategy> it(start, end); |
| 693 unsigned next = 0; | 695 unsigned next = 0; |
| 694 bool needMoreContext = false; | 696 bool needMoreContext = false; |
| 695 while (!it.atEnd()) { | 697 while (!it.atEnd()) { |
| 696 bool inTextSecurityMode = it.isInTextSecurityMode(); | 698 bool inTextSecurityMode = it.isInTextSecurityMode(); |
| 697 // iterate to get chunks until the searchFunction returns a non-zero | 699 // iterate to get chunks until the searchFunction returns a non-zero |
| 698 // value. | 700 // value. |
| 699 if (!inTextSecurityMode) { | 701 if (!inTextSecurityMode) { |
| 700 it.copyTextTo(&string); | 702 while (!next && accumulator.size() < it.length()) { |
| 703 int accumulated = it.copyTextTo(&string, accumulator.size(), acc
umulator.capacity()); |
| 704 accumulator.grow(accumulated); |
| 705 // TODO(xiaochengh): The following line takes O(string.size()) |
| 706 // time, which makes the while loop take quadratic time in the |
| 707 // worst case. Should improve it in some way. |
| 708 next = searchFunction(string.data(), string.size(), string.size(
) - suffixLength, MayHaveMoreContext, needMoreContext); |
| 709 } |
| 710 if (next) |
| 711 break; |
| 701 } else { | 712 } else { |
| 702 // Treat bullets used in the text security mode as regular | 713 // Treat bullets used in the text security mode as regular |
| 703 // characters when looking for boundaries | 714 // characters when looking for boundaries |
| 704 string.pushCharacters('x', it.length()); | 715 string.pushCharacters('x', it.length()); |
| 716 next = 0; |
| 705 } | 717 } |
| 706 // TODO(xiaochengh): The following line takes O(string.size()) time, | |
| 707 // which makes the while loop take quadratic time in the worst case. | |
| 708 // Should improve it in some way. | |
| 709 next = searchFunction(string.data(), string.size(), string.size() - suff
ixLength, MayHaveMoreContext, needMoreContext); | |
| 710 if (next) | |
| 711 break; | |
| 712 it.advance(); | 718 it.advance(); |
| 719 accumulator.reset(); |
| 713 } | 720 } |
| 714 if (needMoreContext) { | 721 if (needMoreContext) { |
| 715 // The last search returned the beginning of the buffer and asked for | 722 // The last search returned the beginning of the buffer and asked for |
| 716 // more context, but there is no earlier text. Force a search with | 723 // more context, but there is no earlier text. Force a search with |
| 717 // what's available. | 724 // what's available. |
| 718 // TODO(xiaochengh): Do we have to search the whole string? | 725 // TODO(xiaochengh): Do we have to search the whole string? |
| 719 next = searchFunction(string.data(), string.size(), string.size() - suff
ixLength, DontHaveMoreContext, needMoreContext); | 726 next = searchFunction(string.data(), string.size(), string.size() - suff
ixLength, DontHaveMoreContext, needMoreContext); |
| 720 ASSERT(!needMoreContext); | 727 ASSERT(!needMoreContext); |
| 721 } | 728 } |
| 722 | 729 |
| 723 if (!next) | 730 if (!next) |
| 724 return createVisiblePosition(it.atEnd() ? it.startPosition() : pos); | 731 return createVisiblePosition(it.atEnd() ? it.startPosition() : pos); |
| 725 | 732 |
| 726 Node* node = it.startContainer(); | 733 Node* node = it.startContainer(); |
| 727 if (node->isTextNode() && static_cast<int>(next) <= node->maxCharacterOffset
()) { | 734 int boundaryOffset = it.length() - accumulator.size() + next; |
| 735 if (node->isTextNode() && boundaryOffset <= node->maxCharacterOffset()) { |
| 728 // The next variable contains a usable index into a text node | 736 // The next variable contains a usable index into a text node |
| 729 return createVisiblePosition(PositionTemplate<Strategy>(node, next)); | 737 return createVisiblePosition(PositionTemplate<Strategy>(node, boundaryOf
fset)); |
| 730 } | 738 } |
| 731 | 739 |
| 732 // Use the character iterator to translate the next value into a DOM | 740 // Use the character iterator to translate the next value into a DOM |
| 733 // position. | 741 // position. |
| 734 BackwardsCharacterIteratorAlgorithm<Strategy> charIt(start, end); | 742 BackwardsCharacterIteratorAlgorithm<Strategy> charIt(start, end); |
| 735 charIt.advance(string.size() - suffixLength - next); | 743 charIt.advance(string.size() - suffixLength - next); |
| 736 // TODO(yosin) charIt can get out of shadow host. | 744 // TODO(yosin) charIt can get out of shadow host. |
| 737 return createVisiblePosition(charIt.endPosition()); | 745 return createVisiblePosition(charIt.endPosition()); |
| 738 } | 746 } |
| 739 | 747 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 760 int length = characters.size(); | 768 int length = characters.size(); |
| 761 int i = startOfLastWordBoundaryContext(characters.data(), length); | 769 int i = startOfLastWordBoundaryContext(characters.data(), length); |
| 762 prefixString.pushRange(characters.data() + i, length - i); | 770 prefixString.pushRange(characters.data() + i, length - i); |
| 763 prefixLength += length - i; | 771 prefixLength += length - i; |
| 764 if (i > 0) | 772 if (i > 0) |
| 765 break; | 773 break; |
| 766 backwardsIterator.advance(); | 774 backwardsIterator.advance(); |
| 767 } | 775 } |
| 768 } | 776 } |
| 769 | 777 |
| 778 ExponentialAccumulator accumulator; |
| 770 ForwardsTextBuffer string; | 779 ForwardsTextBuffer string; |
| 771 string.pushRange(prefixString.data(), prefixString.size()); | 780 string.pushRange(prefixString.data(), prefixString.size()); |
| 772 | 781 |
| 773 const PositionTemplate<Strategy> searchStart = PositionTemplate<Strategy>::e
ditingPositionOf(start.anchorNode(), start.offsetInContainerNode()); | 782 const PositionTemplate<Strategy> searchStart = PositionTemplate<Strategy>::e
ditingPositionOf(start.anchorNode(), start.offsetInContainerNode()); |
| 774 const PositionTemplate<Strategy> searchEnd = PositionTemplate<Strategy>::las
tPositionInNode(boundary); | 783 const PositionTemplate<Strategy> searchEnd = PositionTemplate<Strategy>::las
tPositionInNode(boundary); |
| 775 TextIteratorAlgorithm<Strategy> it(searchStart, searchEnd, TextIteratorEmits
CharactersBetweenAllVisiblePositions); | 784 TextIteratorAlgorithm<Strategy> it(searchStart, searchEnd, TextIteratorEmits
CharactersBetweenAllVisiblePositions); |
| 776 const unsigned invalidOffset = static_cast<unsigned>(-1); | 785 const unsigned invalidOffset = static_cast<unsigned>(-1); |
| 777 unsigned next = invalidOffset; | 786 unsigned next = invalidOffset; |
| 778 unsigned offset = prefixLength; | 787 unsigned offset = prefixLength; |
| 779 bool needMoreContext = false; | 788 bool needMoreContext = false; |
| 780 while (!it.atEnd()) { | 789 while (!it.atEnd()) { |
| 781 // Keep asking the iterator for chunks until the search function | 790 // Keep asking the iterator for chunks until the search function |
| 782 // returns an end value not equal to the length of the string passed to | 791 // returns an end value not equal to the length of the string passed to |
| 783 // it. | 792 // it. |
| 784 bool inTextSecurityMode = it.isInTextSecurityMode(); | 793 bool inTextSecurityMode = it.isInTextSecurityMode(); |
| 785 if (!inTextSecurityMode) { | 794 if (!inTextSecurityMode) { |
| 786 it.copyTextTo(&string); | 795 while ((next == string.size() || next == invalidOffset) && accumulat
or.size() < it.length()) { |
| 796 int accumulated = it.copyTextTo(&string, accumulator.size(), acc
umulator.capacity()); |
| 797 accumulator.grow(accumulated); |
| 798 next = searchFunction(string.data(), string.size(), offset, MayH
aveMoreContext, needMoreContext); |
| 799 if (!needMoreContext) { |
| 800 // When the search does not need more context, skip all exam
ined |
| 801 // characters except the last one, in case it is a boundary. |
| 802 offset = string.size(); |
| 803 U16_BACK_1(string.data(), 0, offset); |
| 804 } |
| 805 } |
| 806 if (next != string.size()) |
| 807 break; |
| 787 } else { | 808 } else { |
| 788 // Treat bullets used in the text security mode as regular | 809 // Treat bullets used in the text security mode as regular |
| 789 // characters when looking for boundaries | 810 // characters when looking for boundaries |
| 790 string.pushCharacters('x', it.length()); | 811 string.pushCharacters('x', it.length()); |
| 812 next = string.size(); |
| 791 } | 813 } |
| 792 next = searchFunction(string.data(), string.size(), offset, MayHaveMoreC
ontext, needMoreContext); | |
| 793 if (next != string.size()) | |
| 794 break; | |
| 795 it.advance(); | 814 it.advance(); |
| 796 if (!needMoreContext) { | 815 accumulator.reset(); |
| 797 // When the search does not need more context, skip all examined | |
| 798 // characters except the last one, in case it is a boundary. | |
| 799 offset = string.size(); | |
| 800 U16_BACK_1(string.data(), 0, offset); | |
| 801 } | |
| 802 } | 816 } |
| 803 if (needMoreContext) { | 817 if (needMoreContext) { |
| 804 // The last search returned the end of the buffer and asked for more | 818 // The last search returned the end of the buffer and asked for more |
| 805 // context, but there is no further text. Force a search with what's | 819 // context, but there is no further text. Force a search with what's |
| 806 // available. | 820 // available. |
| 807 // TODO(xiaochengh): Do we still have to search the whole string? | 821 // TODO(xiaochengh): Do we still have to search the whole string? |
| 808 next = searchFunction(string.data(), string.size(), prefixLength, DontHa
veMoreContext, needMoreContext); | 822 next = searchFunction(string.data(), string.size(), prefixLength, DontHa
veMoreContext, needMoreContext); |
| 809 ASSERT(!needMoreContext); | 823 ASSERT(!needMoreContext); |
| 810 } | 824 } |
| 811 | 825 |
| (...skipping 2540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3352 { | 3366 { |
| 3353 return previousPositionOfAlgorithm<EditingStrategy>(visiblePosition, rule); | 3367 return previousPositionOfAlgorithm<EditingStrategy>(visiblePosition, rule); |
| 3354 } | 3368 } |
| 3355 | 3369 |
| 3356 VisiblePositionInFlatTree previousPositionOf(const VisiblePositionInFlatTree& vi
siblePosition, EditingBoundaryCrossingRule rule) | 3370 VisiblePositionInFlatTree previousPositionOf(const VisiblePositionInFlatTree& vi
siblePosition, EditingBoundaryCrossingRule rule) |
| 3357 { | 3371 { |
| 3358 return previousPositionOfAlgorithm<EditingInFlatTreeStrategy>(visiblePositio
n, rule); | 3372 return previousPositionOfAlgorithm<EditingInFlatTreeStrategy>(visiblePositio
n, rule); |
| 3359 } | 3373 } |
| 3360 | 3374 |
| 3361 } // namespace blink | 3375 } // namespace blink |
| OLD | NEW |