summaryrefslogtreecommitdiffstats
path: root/WebCore/editing/TextIterator.cpp
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2010-08-11 14:44:44 +0100
committerBen Murdoch <benm@google.com>2010-08-12 19:15:41 +0100
commitdd8bb3de4f353a81954234999f1fea748aee2ea9 (patch)
tree729b52bf09294f0d6c67cd5ea80aee1b727b7bd8 /WebCore/editing/TextIterator.cpp
parentf3d41ba51d86bf719c7a65ab5297aea3c17e2d98 (diff)
downloadexternal_webkit-dd8bb3de4f353a81954234999f1fea748aee2ea9.zip
external_webkit-dd8bb3de4f353a81954234999f1fea748aee2ea9.tar.gz
external_webkit-dd8bb3de4f353a81954234999f1fea748aee2ea9.tar.bz2
Merge WebKit at r65072 : Initial merge by git.
Change-Id: Ibcf418498376b2660aacb7f8d46ea7085ef91585
Diffstat (limited to 'WebCore/editing/TextIterator.cpp')
-rw-r--r--WebCore/editing/TextIterator.cpp155
1 files changed, 134 insertions, 21 deletions
diff --git a/WebCore/editing/TextIterator.cpp b/WebCore/editing/TextIterator.cpp
index f3bd9df..9589bff 100644
--- a/WebCore/editing/TextIterator.cpp
+++ b/WebCore/editing/TextIterator.cpp
@@ -37,6 +37,7 @@
#include "RenderTableCell.h"
#include "RenderTableRow.h"
#include "RenderTextControl.h"
+#include "RenderTextFragment.h"
#include "VisiblePosition.h"
#include "visible_units.h"
@@ -253,10 +254,13 @@ TextIterator::TextIterator()
, m_positionNode(0)
, m_textCharacters(0)
, m_textLength(0)
+ , m_remainingTextBox(0)
+ , m_firstLetterText(0)
, m_lastCharacter(0)
, m_emitsCharactersBetweenAllVisiblePositions(false)
, m_entersTextControls(false)
, m_emitsTextWithoutTranscoding(false)
+ , m_handledFirstLetter(false)
{
}
@@ -268,10 +272,16 @@ TextIterator::TextIterator(const Range* r, TextIteratorBehavior behavior)
, m_positionNode(0)
, m_textCharacters(0)
, m_textLength(0)
+ , m_remainingTextBox(0)
+ , m_firstLetterText(0)
, m_emitsCharactersBetweenAllVisiblePositions(behavior & TextIteratorEmitsCharactersBetweenAllVisiblePositions)
, m_entersTextControls(behavior & TextIteratorEntersTextControls)
, m_emitsTextWithoutTranscoding(behavior & TextIteratorEmitsTextsWithoutTranscoding)
+ , m_handledFirstLetter(false)
{
+ // FIXME: should support TextIteratorEndsAtEditingBoundary http://webkit.org/b/43609
+ ASSERT(behavior != TextIteratorEndsAtEditingBoundary);
+
if (!r)
return;
@@ -344,6 +354,12 @@ void TextIterator::advance()
return;
}
+ if (!m_textBox && m_remainingTextBox) {
+ m_textBox = m_remainingTextBox;
+ m_remainingTextBox = 0;
+ m_firstLetterText = 0;
+ m_offset = 0;
+ }
// handle remembered text box
if (m_textBox) {
handleTextBox();
@@ -417,6 +433,8 @@ void TextIterator::advance()
pushFullyClippedState(m_fullyClippedStack, m_node);
m_handledNode = false;
m_handledChildren = false;
+ m_handledFirstLetter = false;
+ m_firstLetterText = 0;
// how would this ever be?
if (m_positionNode)
@@ -435,8 +453,6 @@ bool TextIterator::handleTextNode()
return false;
RenderText* renderer = toRenderText(m_node->renderer());
- if (renderer->style()->visibility() != VISIBLE)
- return false;
m_lastTextNode = m_node;
String str = renderer->text();
@@ -444,10 +460,22 @@ bool TextIterator::handleTextNode()
// handle pre-formatted text
if (!renderer->style()->collapseWhiteSpace()) {
int runStart = m_offset;
- if (m_lastTextNodeEndedWithCollapsedSpace) {
+ if (m_lastTextNodeEndedWithCollapsedSpace && hasVisibleTextNode(renderer)) {
emitCharacter(' ', m_node, 0, runStart, runStart);
return false;
}
+ if (!m_handledFirstLetter && renderer->isTextFragment()) {
+ handleTextNodeFirstLetter(static_cast<RenderTextFragment*>(renderer));
+ if (m_firstLetterText) {
+ String firstLetter = m_firstLetterText->text();
+ emitText(m_node, m_firstLetterText, m_offset, firstLetter.length());
+ m_firstLetterText = 0;
+ m_textBox = 0;
+ return false;
+ }
+ }
+ if (renderer->style()->visibility() != VISIBLE)
+ return false;
int strLength = str.length();
int end = (m_node == m_endContainer) ? m_endOffset : INT_MAX;
int runEnd = min(strLength, end);
@@ -460,6 +488,15 @@ bool TextIterator::handleTextNode()
}
if (!renderer->firstTextBox() && str.length() > 0) {
+ if (!m_handledFirstLetter && renderer->isTextFragment()) {
+ handleTextNodeFirstLetter(static_cast<RenderTextFragment*>(renderer));
+ if (m_firstLetterText) {
+ handleTextBox();
+ return false;
+ }
+ }
+ if (renderer->style()->visibility() != VISIBLE)
+ return false;
m_lastTextNodeEndedWithCollapsedSpace = true; // entire block is collapsed space
return true;
}
@@ -475,13 +512,19 @@ bool TextIterator::handleTextNode()
}
m_textBox = renderer->containsReversedText() ? (m_sortedTextBoxes.isEmpty() ? 0 : m_sortedTextBoxes[0]) : renderer->firstTextBox();
+ if (!m_handledFirstLetter && renderer->isTextFragment() && !m_offset)
+ handleTextNodeFirstLetter(static_cast<RenderTextFragment*>(renderer));
handleTextBox();
return true;
}
void TextIterator::handleTextBox()
{
- RenderText* renderer = toRenderText(m_node->renderer());
+ RenderText* renderer = m_firstLetterText ? m_firstLetterText : toRenderText(m_node->renderer());
+ if (renderer->style()->visibility() != VISIBLE) {
+ m_textBox = 0;
+ return;
+ }
String str = renderer->text();
int start = m_offset;
int end = (m_node == m_endContainer) ? m_endOffset : INT_MAX;
@@ -527,7 +570,7 @@ void TextIterator::handleTextBox()
subrunEnd = runEnd;
m_offset = subrunEnd;
- emitText(m_node, runStart, subrunEnd);
+ emitText(m_node, renderer, runStart, subrunEnd);
}
// If we are doing a subrun that doesn't go to the end of the text box,
@@ -549,6 +592,33 @@ void TextIterator::handleTextBox()
if (renderer->containsReversedText())
++m_sortedTextBoxesPosition;
}
+ if (!m_textBox && m_remainingTextBox) {
+ m_textBox = m_remainingTextBox;
+ m_remainingTextBox = 0;
+ m_firstLetterText = 0;
+ m_offset = 0;
+ handleTextBox();
+ }
+}
+
+void TextIterator::handleTextNodeFirstLetter(RenderTextFragment* renderer)
+{
+ if (renderer->firstLetter()) {
+ RenderObject* r = renderer->firstLetter();
+ if (r->style()->visibility() != VISIBLE)
+ return;
+ for (RenderObject *currChild = r->firstChild(); currChild; currChild->nextSibling()) {
+ if (currChild->isText()) {
+ RenderText* firstLetter = toRenderText(currChild);
+ m_handledFirstLetter = true;
+ m_remainingTextBox = m_textBox;
+ m_textBox = firstLetter->firstTextBox();
+ m_firstLetterText = firstLetter;
+ return;
+ }
+ }
+ }
+ m_handledFirstLetter = true;
}
bool TextIterator::handleReplacedElement()
@@ -597,6 +667,18 @@ bool TextIterator::handleReplacedElement()
return true;
}
+bool TextIterator::hasVisibleTextNode(RenderText* renderer)
+{
+ if (renderer->style()->visibility() == VISIBLE)
+ return true;
+ if (renderer->isTextFragment()) {
+ RenderTextFragment* fragment = static_cast<RenderTextFragment*>(renderer);
+ if (fragment->firstLetter() && fragment->firstLetter()->style()->visibility() == VISIBLE)
+ return true;
+ }
+ return false;
+}
+
static bool shouldEmitTabBeforeNode(Node* node)
{
RenderObject* r = node->renderer();
@@ -888,9 +970,9 @@ void TextIterator::emitCharacter(UChar c, Node* textNode, Node* offsetBaseNode,
m_lastCharacter = c;
}
-void TextIterator::emitText(Node* textNode, int textStartOffset, int textEndOffset)
+void TextIterator::emitText(Node* textNode, RenderObject* renderObject, int textStartOffset, int textEndOffset)
{
- RenderText* renderer = toRenderText(m_node->renderer());
+ RenderText* renderer = toRenderText(renderObject);
m_text = m_emitsTextWithoutTranscoding ? renderer->textWithoutTranscoding() : renderer->text();
ASSERT(m_text.characters());
@@ -906,6 +988,11 @@ void TextIterator::emitText(Node* textNode, int textStartOffset, int textEndOffs
m_hasEmitted = true;
}
+void TextIterator::emitText(Node* textNode, int textStartOffset, int textEndOffset)
+{
+ emitText(textNode, m_node->renderer(), textStartOffset, textEndOffset);
+}
+
PassRefPtr<Range> TextIterator::range() const
{
// use the current run information, if we have it
@@ -944,13 +1031,19 @@ Node* TextIterator::node() const
// --------
SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator()
- : m_positionNode(0)
+ : m_behavior(TextIteratorDefaultBehavior)
+ , m_node(0)
+ , m_positionNode(0)
{
}
-SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r)
- : m_positionNode(0)
+SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r, TextIteratorBehavior behavior)
+ : m_behavior(behavior)
+ , m_node(0)
+ , m_positionNode(0)
{
+ ASSERT(m_behavior == TextIteratorDefaultBehavior || m_behavior == TextIteratorEndsAtEditingBoundary);
+
if (!r)
return;
@@ -974,7 +1067,7 @@ SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r)
}
}
- m_node = endNode;
+ setCurrentNode(endNode);
setUpFullyClippedStack(m_fullyClippedStack, m_node);
m_offset = endOffset;
m_handledNode = false;
@@ -1038,12 +1131,9 @@ void SimplifiedBackwardsTextIterator::advance()
}
}
// Exit all other containers.
- next = m_node->previousSibling();
- while (!next) {
- Node* parentNode = parentCrossingShadowBoundaries(m_node);
- if (!parentNode)
+ while (!m_node->previousSibling()) {
+ if (!setCurrentNode(parentCrossingShadowBoundaries(m_node)))
break;
- m_node = parentNode;
m_fullyClippedStack.pop();
exitNode();
if (m_positionNode) {
@@ -1051,14 +1141,17 @@ void SimplifiedBackwardsTextIterator::advance()
m_handledChildren = true;
return;
}
- next = m_node->previousSibling();
}
+
+ next = m_node->previousSibling();
m_fullyClippedStack.pop();
}
- m_node = next;
- if (m_node)
+ if (m_node && setCurrentNode(next))
pushFullyClippedState(m_fullyClippedStack, m_node);
+ else
+ clearCurrentNode();
+
// For the purpose of word boundary detection,
// we should iterate all visible text and trailing (collapsed) whitespaces.
m_offset = m_node ? maxOffsetIncludingCollapsedSpaces(m_node) : 0;
@@ -1137,6 +1230,26 @@ void SimplifiedBackwardsTextIterator::emitCharacter(UChar c, Node* node, int sta
m_lastCharacter = c;
}
+bool SimplifiedBackwardsTextIterator::crossesEditingBoundary(Node* node) const
+{
+ return m_node && m_node->isContentEditable() != node->isContentEditable();
+}
+
+bool SimplifiedBackwardsTextIterator::setCurrentNode(Node* node)
+{
+ if (!node)
+ return false;
+ if (m_behavior == TextIteratorEndsAtEditingBoundary && crossesEditingBoundary(node))
+ return false;
+ m_node = node;
+ return true;
+}
+
+void SimplifiedBackwardsTextIterator::clearCurrentNode()
+{
+ m_node = 0;
+}
+
PassRefPtr<Range> SimplifiedBackwardsTextIterator::range() const
{
if (m_positionNode)
@@ -1262,11 +1375,11 @@ BackwardsCharacterIterator::BackwardsCharacterIterator()
{
}
-BackwardsCharacterIterator::BackwardsCharacterIterator(const Range* range)
+BackwardsCharacterIterator::BackwardsCharacterIterator(const Range* range, TextIteratorBehavior behavior)
: m_offset(0)
, m_runOffset(0)
, m_atBreak(true)
- , m_textIterator(range)
+ , m_textIterator(range, behavior)
{
while (!atEnd() && !m_textIterator.length())
m_textIterator.advance();