Commit f223fbf4 authored by mlamouri@chromium.org's avatar mlamouri@chromium.org

Make SurroundingText work for a Range.

It generalize the algorithm to find the surrounding text to be able to
work with a starting position and an ending position. The goal is to be
able to get the surrounding text arround the current selection.

BUG=330238

Review URL: https://codereview.chromium.org/323983006

git-svn-id: svn://svn.chromium.org/blink/trunk@176015 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent e83c6683
...@@ -39,26 +39,42 @@ ...@@ -39,26 +39,42 @@
namespace WebCore { namespace WebCore {
SurroundingText::SurroundingText(const Range& range, unsigned maxLength)
: m_startOffsetInContent(0)
, m_endOffsetInContent(0)
{
initialize(range.startPosition(), range.endPosition(), maxLength);
}
SurroundingText::SurroundingText(const Position& position, unsigned maxLength) SurroundingText::SurroundingText(const Position& position, unsigned maxLength)
: m_positionOffsetInContent(0) : m_startOffsetInContent(0)
, m_endOffsetInContent(0)
{
initialize(position, position, maxLength);
}
void SurroundingText::initialize(const Position& startPosition, const Position& endPosition, unsigned maxLength)
{ {
ASSERT(startPosition.document() == endPosition.document());
const unsigned halfMaxLength = maxLength / 2; const unsigned halfMaxLength = maxLength / 2;
Document* document = position.document(); Document* document = startPosition.document();
// The |position| will have no document if it is null (as in no position). // The position will have no document if it is null (as in no position).
if (!document) if (!document)
return; return;
// The forward range starts at the selection end and ends at the document's // The forward range starts at the selection end and ends at the document's
// end. It will then be updated to only contain the text in the text in the // end. It will then be updated to only contain the text in the text in the
// right range around the selection. // right range around the selection.
RefPtrWillBeRawPtr<Range> forwardRange = Range::create(*document, position, lastPositionInNode(document->documentElement()).parentAnchoredEquivalent()); RefPtrWillBeRawPtr<Range> forwardRange = Range::create(*document, endPosition, lastPositionInNode(document->documentElement()).parentAnchoredEquivalent());
CharacterIterator forwardIterator(forwardRange.get(), TextIteratorStopsOnFormControls); CharacterIterator forwardIterator(forwardRange.get(), TextIteratorStopsOnFormControls);
// FIXME: why do we stop going trough the text if we were not able to select something on the right?
if (!forwardIterator.atEnd()) if (!forwardIterator.atEnd())
forwardIterator.advance(maxLength - halfMaxLength); forwardIterator.advance(maxLength - halfMaxLength);
forwardRange = forwardIterator.range(); forwardRange = forwardIterator.range();
if (!forwardRange || !Range::create(*document, position, forwardRange->startPosition())->text().length()) { if (!forwardRange || !Range::create(*document, endPosition, forwardRange->startPosition())->text().length()) {
ASSERT(forwardRange); ASSERT(forwardRange);
return; return;
} }
...@@ -66,7 +82,7 @@ SurroundingText::SurroundingText(const Position& position, unsigned maxLength) ...@@ -66,7 +82,7 @@ SurroundingText::SurroundingText(const Position& position, unsigned maxLength)
// Same as with the forward range but with the backward range. The range // Same as with the forward range but with the backward range. The range
// starts at the document's start and ends at the selection start and will // starts at the document's start and ends at the selection start and will
// be updated. // be updated.
RefPtrWillBeRawPtr<Range> backwardsRange = Range::create(*document, firstPositionInNode(document->documentElement()).parentAnchoredEquivalent(), position); RefPtrWillBeRawPtr<Range> backwardsRange = Range::create(*document, firstPositionInNode(document->documentElement()).parentAnchoredEquivalent(), startPosition);
BackwardsCharacterIterator backwardsIterator(backwardsRange.get(), TextIteratorStopsOnFormControls); BackwardsCharacterIterator backwardsIterator(backwardsRange.get(), TextIteratorStopsOnFormControls);
if (!backwardsIterator.atEnd()) if (!backwardsIterator.atEnd())
backwardsIterator.advance(halfMaxLength); backwardsIterator.advance(halfMaxLength);
...@@ -77,7 +93,8 @@ SurroundingText::SurroundingText(const Position& position, unsigned maxLength) ...@@ -77,7 +93,8 @@ SurroundingText::SurroundingText(const Position& position, unsigned maxLength)
return; return;
} }
m_positionOffsetInContent = Range::create(*document, backwardsRange->endPosition(), position)->text().length(); m_startOffsetInContent = Range::create(*document, backwardsRange->endPosition(), startPosition)->text().length();
m_endOffsetInContent = Range::create(*document, backwardsRange->endPosition(), endPosition)->text().length();
m_contentRange = Range::create(*document, backwardsRange->endPosition(), forwardRange->startPosition()); m_contentRange = Range::create(*document, backwardsRange->endPosition(), forwardRange->startPosition());
ASSERT(m_contentRange); ASSERT(m_contentRange);
} }
...@@ -112,9 +129,14 @@ String SurroundingText::content() const ...@@ -112,9 +129,14 @@ String SurroundingText::content() const
return String(); return String();
} }
unsigned SurroundingText::positionOffsetInContent() const unsigned SurroundingText::startOffsetInContent() const
{
return m_startOffsetInContent;
}
unsigned SurroundingText::endOffsetInContent() const
{ {
return m_positionOffsetInContent; return m_endOffsetInContent;
} }
} // namespace WebCore } // namespace WebCore
...@@ -42,16 +42,21 @@ class Range; ...@@ -42,16 +42,21 @@ class Range;
class SurroundingText { class SurroundingText {
WTF_MAKE_NONCOPYABLE(SurroundingText); WTF_MAKE_NONCOPYABLE(SurroundingText);
public: public:
SurroundingText(const Range&, unsigned maxLength);
SurroundingText(const Position&, unsigned maxLength); SurroundingText(const Position&, unsigned maxLength);
String content() const; String content() const;
unsigned positionOffsetInContent() const; unsigned startOffsetInContent() const;
unsigned endOffsetInContent() const;
PassRefPtrWillBeRawPtr<Range> rangeFromContentOffsets(unsigned startOffsetInContent, unsigned endOffsetInContent); PassRefPtrWillBeRawPtr<Range> rangeFromContentOffsets(unsigned startOffsetInContent, unsigned endOffsetInContent);
private: private:
void initialize(const Position&, const Position&, unsigned maxLength);
RefPtrWillBePersistent<Range> m_contentRange; RefPtrWillBePersistent<Range> m_contentRange;
size_t m_positionOffsetInContent; size_t m_startOffsetInContent;
size_t m_endOffsetInContent;
}; };
} // namespace WebCore } // namespace WebCore
......
...@@ -58,7 +58,8 @@ TEST_F(SurroundingTextTest, BasicCaretSelection) ...@@ -58,7 +58,8 @@ TEST_F(SurroundingTextTest, BasicCaretSelection)
SurroundingText surroundingText(selection.start(), 1); SurroundingText surroundingText(selection.start(), 1);
EXPECT_EQ("f", surroundingText.content()); EXPECT_EQ("f", surroundingText.content());
EXPECT_EQ(0u, surroundingText.positionOffsetInContent()); EXPECT_EQ(0u, surroundingText.startOffsetInContent());
EXPECT_EQ(0u, surroundingText.endOffsetInContent());
} }
{ {
...@@ -67,7 +68,8 @@ TEST_F(SurroundingTextTest, BasicCaretSelection) ...@@ -67,7 +68,8 @@ TEST_F(SurroundingTextTest, BasicCaretSelection)
// maxlength/2 is used on the left and right. // maxlength/2 is used on the left and right.
EXPECT_EQ("foo", surroundingText.content().simplifyWhiteSpace()); EXPECT_EQ("foo", surroundingText.content().simplifyWhiteSpace());
EXPECT_EQ(1u, surroundingText.positionOffsetInContent()); EXPECT_EQ(1u, surroundingText.startOffsetInContent());
EXPECT_EQ(1u, surroundingText.endOffsetInContent());
} }
{ {
...@@ -75,7 +77,8 @@ TEST_F(SurroundingTextTest, BasicCaretSelection) ...@@ -75,7 +77,8 @@ TEST_F(SurroundingTextTest, BasicCaretSelection)
SurroundingText surroundingText(selection.start(), 42); SurroundingText surroundingText(selection.start(), 42);
EXPECT_EQ("foo bar", surroundingText.content().simplifyWhiteSpace()); EXPECT_EQ("foo bar", surroundingText.content().simplifyWhiteSpace());
EXPECT_EQ(1u, surroundingText.positionOffsetInContent()); EXPECT_EQ(1u, surroundingText.startOffsetInContent());
EXPECT_EQ(1u, surroundingText.endOffsetInContent());
} }
{ {
...@@ -85,7 +88,8 @@ TEST_F(SurroundingTextTest, BasicCaretSelection) ...@@ -85,7 +88,8 @@ TEST_F(SurroundingTextTest, BasicCaretSelection)
SurroundingText surroundingText(selection.start(), 42); SurroundingText surroundingText(selection.start(), 42);
EXPECT_EQ(0u, surroundingText.content().length()); EXPECT_EQ(0u, surroundingText.content().length());
EXPECT_EQ(0u, surroundingText.positionOffsetInContent()); EXPECT_EQ(0u, surroundingText.startOffsetInContent());
EXPECT_EQ(0u, surroundingText.endOffsetInContent());
} }
{ {
...@@ -93,7 +97,8 @@ TEST_F(SurroundingTextTest, BasicCaretSelection) ...@@ -93,7 +97,8 @@ TEST_F(SurroundingTextTest, BasicCaretSelection)
SurroundingText surroundingText(selection.start(), 2); SurroundingText surroundingText(selection.start(), 2);
EXPECT_EQ("ar", surroundingText.content()); EXPECT_EQ("ar", surroundingText.content());
EXPECT_EQ(1u, surroundingText.positionOffsetInContent()); EXPECT_EQ(1u, surroundingText.startOffsetInContent());
EXPECT_EQ(1u, surroundingText.endOffsetInContent());
} }
{ {
...@@ -101,7 +106,58 @@ TEST_F(SurroundingTextTest, BasicCaretSelection) ...@@ -101,7 +106,58 @@ TEST_F(SurroundingTextTest, BasicCaretSelection)
SurroundingText surroundingText(selection.start(), 42); SurroundingText surroundingText(selection.start(), 42);
EXPECT_EQ("foo bar", surroundingText.content().simplifyWhiteSpace()); EXPECT_EQ("foo bar", surroundingText.content().simplifyWhiteSpace());
EXPECT_EQ(7u, surroundingText.positionOffsetInContent()); EXPECT_EQ(7u, surroundingText.startOffsetInContent());
EXPECT_EQ(7u, surroundingText.endOffsetInContent());
}
}
TEST_F(SurroundingTextTest, BasicRangeSelection)
{
setHTML(String("<p id='selection'>Lorem ipsum dolor sit amet</p>"));
{
VisibleSelection selection = select(0, 5);
SurroundingText surroundingText(*selection.firstRange(), 1);
EXPECT_EQ("Lorem ", surroundingText.content());
EXPECT_EQ(0u, surroundingText.startOffsetInContent());
EXPECT_EQ(5u, surroundingText.endOffsetInContent());
}
{
VisibleSelection selection = select(0, 5);
SurroundingText surroundingText(*selection.firstRange(), 5);
EXPECT_EQ("Lorem ip", surroundingText.content().simplifyWhiteSpace());
EXPECT_EQ(1u, surroundingText.startOffsetInContent());
EXPECT_EQ(6u, surroundingText.endOffsetInContent());
}
{
VisibleSelection selection = select(0, 5);
SurroundingText surroundingText(*selection.firstRange(), 42);
EXPECT_EQ("Lorem ipsum dolor sit amet", surroundingText.content().simplifyWhiteSpace());
EXPECT_EQ(1u, surroundingText.startOffsetInContent());
EXPECT_EQ(6u, surroundingText.endOffsetInContent());
}
{
VisibleSelection selection = select(6, 11);
SurroundingText surroundingText(*selection.firstRange(), 2);
EXPECT_EQ(" ipsum ", surroundingText.content());
EXPECT_EQ(1u, surroundingText.startOffsetInContent());
EXPECT_EQ(6u, surroundingText.endOffsetInContent());
}
{
VisibleSelection selection = select(6, 11);
SurroundingText surroundingText(*selection.firstRange(), 42);
EXPECT_EQ("Lorem ipsum dolor sit amet", surroundingText.content().simplifyWhiteSpace());
EXPECT_EQ(7u, surroundingText.startOffsetInContent());
EXPECT_EQ(12u, surroundingText.endOffsetInContent());
} }
} }
...@@ -114,7 +170,8 @@ TEST_F(SurroundingTextTest, TreeCaretSelection) ...@@ -114,7 +170,8 @@ TEST_F(SurroundingTextTest, TreeCaretSelection)
SurroundingText surroundingText(selection.start(), 1); SurroundingText surroundingText(selection.start(), 1);
EXPECT_EQ("f", surroundingText.content()); EXPECT_EQ("f", surroundingText.content());
EXPECT_EQ(0u, surroundingText.positionOffsetInContent()); EXPECT_EQ(0u, surroundingText.startOffsetInContent());
EXPECT_EQ(0u, surroundingText.endOffsetInContent());
} }
{ {
...@@ -122,7 +179,8 @@ TEST_F(SurroundingTextTest, TreeCaretSelection) ...@@ -122,7 +179,8 @@ TEST_F(SurroundingTextTest, TreeCaretSelection)
SurroundingText surroundingText(selection.start(), 5); SurroundingText surroundingText(selection.start(), 5);
EXPECT_EQ("foo", surroundingText.content().simplifyWhiteSpace()); EXPECT_EQ("foo", surroundingText.content().simplifyWhiteSpace());
EXPECT_EQ(1u, surroundingText.positionOffsetInContent()); EXPECT_EQ(1u, surroundingText.startOffsetInContent());
EXPECT_EQ(1u, surroundingText.endOffsetInContent());
} }
{ {
...@@ -130,7 +188,8 @@ TEST_F(SurroundingTextTest, TreeCaretSelection) ...@@ -130,7 +188,8 @@ TEST_F(SurroundingTextTest, TreeCaretSelection)
SurroundingText surroundingText(selection.start(), 1337); SurroundingText surroundingText(selection.start(), 1337);
EXPECT_EQ("This is outside of foo bar the selected node", surroundingText.content().simplifyWhiteSpace()); EXPECT_EQ("This is outside of foo bar the selected node", surroundingText.content().simplifyWhiteSpace());
EXPECT_EQ(20u, surroundingText.positionOffsetInContent()); EXPECT_EQ(20u, surroundingText.startOffsetInContent());
EXPECT_EQ(20u, surroundingText.endOffsetInContent());
} }
{ {
...@@ -138,7 +197,8 @@ TEST_F(SurroundingTextTest, TreeCaretSelection) ...@@ -138,7 +197,8 @@ TEST_F(SurroundingTextTest, TreeCaretSelection)
SurroundingText surroundingText(selection.start(), 2); SurroundingText surroundingText(selection.start(), 2);
EXPECT_EQ("ar", surroundingText.content()); EXPECT_EQ("ar", surroundingText.content());
EXPECT_EQ(1u, surroundingText.positionOffsetInContent()); EXPECT_EQ(1u, surroundingText.startOffsetInContent());
EXPECT_EQ(1u, surroundingText.endOffsetInContent());
} }
{ {
...@@ -146,7 +206,58 @@ TEST_F(SurroundingTextTest, TreeCaretSelection) ...@@ -146,7 +206,58 @@ TEST_F(SurroundingTextTest, TreeCaretSelection)
SurroundingText surroundingText(selection.start(), 1337); SurroundingText surroundingText(selection.start(), 1337);
EXPECT_EQ("This is outside of foo bar the selected node", surroundingText.content().simplifyWhiteSpace()); EXPECT_EQ("This is outside of foo bar the selected node", surroundingText.content().simplifyWhiteSpace());
EXPECT_EQ(26u, surroundingText.positionOffsetInContent()); EXPECT_EQ(26u, surroundingText.startOffsetInContent());
EXPECT_EQ(26u, surroundingText.endOffsetInContent());
}
}
TEST_F(SurroundingTextTest, TreeRangeSelection)
{
setHTML(String("<div>This is outside of <p id='selection'>foo bar</p> the selected node</div>"));
{
VisibleSelection selection = select(0, 1);
SurroundingText surroundingText(*selection.firstRange(), 1);
EXPECT_EQ("fo", surroundingText.content().simplifyWhiteSpace());
EXPECT_EQ(0u, surroundingText.startOffsetInContent());
EXPECT_EQ(1u, surroundingText.endOffsetInContent());
}
{
VisibleSelection selection = select(0, 3);
SurroundingText surroundingText(*selection.firstRange(), 12);
EXPECT_EQ("e of foo bar", surroundingText.content().simplifyWhiteSpace());
EXPECT_EQ(5u, surroundingText.startOffsetInContent());
EXPECT_EQ(8u, surroundingText.endOffsetInContent());
}
{
VisibleSelection selection = select(0, 3);
SurroundingText surroundingText(*selection.firstRange(), 1337);
EXPECT_EQ("This is outside of foo bar the selected node", surroundingText.content().simplifyWhiteSpace());
EXPECT_EQ(20u, surroundingText.startOffsetInContent());
EXPECT_EQ(23u, surroundingText.endOffsetInContent());
}
{
VisibleSelection selection = select(4, 7);
SurroundingText surroundingText(*selection.firstRange(), 12);
EXPECT_EQ("foo bar the se", surroundingText.content().simplifyWhiteSpace());
EXPECT_EQ(5u, surroundingText.startOffsetInContent());
EXPECT_EQ(8u, surroundingText.endOffsetInContent());
}
{
VisibleSelection selection = select(0, 7);
SurroundingText surroundingText(*selection.firstRange(), 1337);
EXPECT_EQ("This is outside of foo bar the selected node", surroundingText.content().simplifyWhiteSpace());
EXPECT_EQ(20u, surroundingText.startOffsetInContent());
EXPECT_EQ(27u, surroundingText.endOffsetInContent());
} }
} }
......
...@@ -55,7 +55,8 @@ WebString WebSurroundingText::textContent() const ...@@ -55,7 +55,8 @@ WebString WebSurroundingText::textContent() const
size_t WebSurroundingText::hitOffsetInTextContent() const size_t WebSurroundingText::hitOffsetInTextContent() const
{ {
return m_private->positionOffsetInContent(); ASSERT(m_private->startOffsetInContent() == m_private->endOffsetInContent());
return m_private->startOffsetInContent();
} }
WebRange WebSurroundingText::rangeFromContentOffsets(size_t startOffsetInContent, size_t endOffsetInContent) WebRange WebSurroundingText::rangeFromContentOffsets(size_t startOffsetInContent, size_t endOffsetInContent)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment