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 @@
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)
: 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;
Document* document = position.document();
// The |position| will have no document if it is null (as in no position).
Document* document = startPosition.document();
// The position will have no document if it is null (as in no position).
if (!document)
return;
// 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
// 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);
// FIXME: why do we stop going trough the text if we were not able to select something on the right?
if (!forwardIterator.atEnd())
forwardIterator.advance(maxLength - halfMaxLength);
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);
return;
}
......@@ -66,7 +82,7 @@ SurroundingText::SurroundingText(const Position& position, unsigned maxLength)
// 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
// 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);
if (!backwardsIterator.atEnd())
backwardsIterator.advance(halfMaxLength);
......@@ -77,7 +93,8 @@ SurroundingText::SurroundingText(const Position& position, unsigned maxLength)
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());
ASSERT(m_contentRange);
}
......@@ -112,9 +129,14 @@ String SurroundingText::content() const
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
......@@ -42,16 +42,21 @@ class Range;
class SurroundingText {
WTF_MAKE_NONCOPYABLE(SurroundingText);
public:
SurroundingText(const Range&, unsigned maxLength);
SurroundingText(const Position&, unsigned maxLength);
String content() const;
unsigned positionOffsetInContent() const;
unsigned startOffsetInContent() const;
unsigned endOffsetInContent() const;
PassRefPtrWillBeRawPtr<Range> rangeFromContentOffsets(unsigned startOffsetInContent, unsigned endOffsetInContent);
private:
void initialize(const Position&, const Position&, unsigned maxLength);
RefPtrWillBePersistent<Range> m_contentRange;
size_t m_positionOffsetInContent;
size_t m_startOffsetInContent;
size_t m_endOffsetInContent;
};
} // namespace WebCore
......
......@@ -58,7 +58,8 @@ TEST_F(SurroundingTextTest, BasicCaretSelection)
SurroundingText surroundingText(selection.start(), 1);
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)
// maxlength/2 is used on the left and right.
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)
SurroundingText surroundingText(selection.start(), 42);
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)
SurroundingText surroundingText(selection.start(), 42);
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)
SurroundingText surroundingText(selection.start(), 2);
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)
SurroundingText surroundingText(selection.start(), 42);
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)
SurroundingText surroundingText(selection.start(), 1);
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)
SurroundingText surroundingText(selection.start(), 5);
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)
SurroundingText surroundingText(selection.start(), 1337);
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)
SurroundingText surroundingText(selection.start(), 2);
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)
SurroundingText surroundingText(selection.start(), 1337);
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
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)
......
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