diff options
Diffstat (limited to 'src/3rdparty/webkit/WebCore/editing/TextIterator.cpp')
-rw-r--r-- | src/3rdparty/webkit/WebCore/editing/TextIterator.cpp | 96 |
1 files changed, 56 insertions, 40 deletions
diff --git a/src/3rdparty/webkit/WebCore/editing/TextIterator.cpp b/src/3rdparty/webkit/WebCore/editing/TextIterator.cpp index aee34df72f..a1b3bc578b 100644 --- a/src/3rdparty/webkit/WebCore/editing/TextIterator.cpp +++ b/src/3rdparty/webkit/WebCore/editing/TextIterator.cpp @@ -42,6 +42,7 @@ #include "visible_units.h" #if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION +#include "TextBreakIteratorInternalICU.h" #include <unicode/usearch.h> #endif @@ -143,7 +144,7 @@ unsigned BitStack::size() const // -------- -static inline Node* parentOrShadowParent(Node* node) +static inline Node* parentCrossingShadowBoundaries(Node* node) { if (Node* parent = node->parentNode()) return parent; @@ -155,20 +156,50 @@ static inline Node* parentOrShadowParent(Node* node) static unsigned depthCrossingShadowBoundaries(Node* node) { unsigned depth = 0; - for (Node* parent = parentOrShadowParent(node); parent; parent = parentOrShadowParent(parent)) + for (Node* parent = parentCrossingShadowBoundaries(node); parent; parent = parentCrossingShadowBoundaries(parent)) ++depth; return depth; } #endif +// This function is like Range::pastLastNode, except for the fact that it can climb up out of shadow trees. +static Node* nextInPreOrderCrossingShadowBoundaries(Node* rangeEndContainer, int rangeEndOffset) +{ + if (!rangeEndContainer) + return 0; + if (rangeEndOffset >= 0 && !rangeEndContainer->offsetInCharacters()) { + if (Node* next = rangeEndContainer->childNode(rangeEndOffset)) + return next; + } + for (Node* node = rangeEndContainer; node; node = parentCrossingShadowBoundaries(node)) { + if (Node* next = node->nextSibling()) + return next; + } + return 0; +} + +static Node* previousInPostOrderCrossingShadowBoundaries(Node* rangeStartContainer, int rangeStartOffset) +{ + if (!rangeStartContainer) + return 0; + if (rangeStartOffset > 0 && !rangeStartContainer->offsetInCharacters()) { + if (Node* previous = rangeStartContainer->childNode(rangeStartOffset - 1)) + return previous; + } + for (Node* node = rangeStartContainer; node; node = parentCrossingShadowBoundaries(node)) { + if (Node* previous = node->previousSibling()) + return previous; + } + return 0; +} + +// -------- + static inline bool fullyClipsContents(Node* node) { RenderObject* renderer = node->renderer(); - if (!renderer || !renderer->isBox()) - return false; - RenderStyle* style = renderer->style(); - if (style->overflowX() == OVISIBLE && style->overflowY() == OVISIBLE) + if (!renderer || !renderer->isBox() || !renderer->hasOverflowClip()) return false; return toRenderBox(renderer)->size().isEmpty(); } @@ -195,7 +226,7 @@ static void setUpFullyClippedStack(BitStack& stack, Node* node) { // Put the nodes in a vector so we can iterate in reverse order. Vector<Node*, 100> ancestry; - for (Node* parent = parentOrShadowParent(node); parent; parent = parentOrShadowParent(parent)) + for (Node* parent = parentCrossingShadowBoundaries(node); parent; parent = parentCrossingShadowBoundaries(parent)) ancestry.append(parent); // Call pushFullyClippedState on each node starting with the earliest ancestor. @@ -265,7 +296,7 @@ TextIterator::TextIterator(const Range* r, bool emitCharactersBetweenAllVisibleP m_handledChildren = false; // calculate first out of bounds node - m_pastEndNode = r->pastLastNode(); + m_pastEndNode = nextInPreOrderCrossingShadowBoundaries(endContainer, endOffset); // initialize node processing state m_needAnotherNewline = false; @@ -352,14 +383,14 @@ void TextIterator::advance() next = m_node->nextSibling(); if (!next) { bool pastEnd = m_node->traverseNextNode() == m_pastEndNode; - Node* parentNode = parentOrShadowParent(m_node); + Node* parentNode = parentCrossingShadowBoundaries(m_node); while (!next && parentNode) { if ((pastEnd && parentNode == m_endContainer) || m_endContainer->isDescendantOf(parentNode)) return; bool haveRenderer = m_node->renderer(); m_node = parentNode; m_fullyClippedStack.pop(); - parentNode = parentOrShadowParent(m_node); + parentNode = parentCrossingShadowBoundaries(m_node); if (haveRenderer) exitNode(); if (m_positionNode) { @@ -883,14 +914,14 @@ Node* TextIterator::node() const // -------- -SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator() : m_positionNode(0) +SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator() + : m_positionNode(0) { } SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r) + : m_positionNode(0) { - m_positionNode = 0; - if (!r) return; @@ -932,15 +963,8 @@ SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r) m_lastTextNode = 0; m_lastCharacter = '\n'; - - if (startOffset == 0 || !startNode->firstChild()) { - m_pastStartNode = startNode->previousSibling(); - while (!m_pastStartNode && startNode->parentNode()) { - startNode = startNode->parentNode(); - m_pastStartNode = startNode->previousSibling(); - } - } else - m_pastStartNode = startNode->childNode(startOffset - 1); + + m_pastStartNode = previousInPostOrderCrossingShadowBoundaries(startNode, startOffset); advance(); } @@ -987,7 +1011,7 @@ void SimplifiedBackwardsTextIterator::advance() // Exit all other containers. next = m_node->previousSibling(); while (!next) { - Node* parentNode = parentOrShadowParent(m_node); + Node* parentNode = parentCrossingShadowBoundaries(m_node); if (!parentNode) break; m_node = parentNode; @@ -1053,26 +1077,22 @@ bool SimplifiedBackwardsTextIterator::handleNonTextNode() { // We can use a linefeed in place of a tab because this simple iterator is only used to // find boundaries, not actual content. A linefeed breaks words, sentences, and paragraphs. - if (shouldEmitNewlineForNode(m_node) || - shouldEmitNewlineAfterNode(m_node) || - shouldEmitTabBeforeNode(m_node)) { + if (shouldEmitNewlineForNode(m_node) || shouldEmitNewlineAfterNode(m_node) || shouldEmitTabBeforeNode(m_node)) { unsigned index = m_node->nodeIndex(); - // The start of this emitted range is wrong, ensuring correctness would require - // VisiblePositions and so would be slow. previousBoundary expects this. + // The start of this emitted range is wrong. Ensuring correctness would require + // VisiblePositions and so would be slow. previousBoundary expects this. emitCharacter('\n', m_node->parentNode(), index + 1, index + 1); } - return true; } void SimplifiedBackwardsTextIterator::exitNode() { - if (shouldEmitNewlineForNode(m_node) || - shouldEmitNewlineBeforeNode(m_node) || - shouldEmitTabBeforeNode(m_node)) - // The start of this emitted range is wrong, ensuring correctness would require - // VisiblePositions and so would be slow. previousBoundary expects this. + if (shouldEmitNewlineForNode(m_node) || shouldEmitNewlineBeforeNode(m_node) || shouldEmitTabBeforeNode(m_node)) { + // The start of this emitted range is wrong. Ensuring correctness would require + // VisiblePositions and so would be slow. previousBoundary expects this. emitCharacter('\n', m_node, 0, 0); + } } void SimplifiedBackwardsTextIterator::emitCharacter(UChar c, Node* node, int startOffset, int endOffset) @@ -1386,13 +1406,9 @@ static UStringSearch* createSearcher() // Provide a non-empty pattern and non-empty text so usearch_open will not fail, // but it doesn't matter exactly what it is, since we don't perform any searches // without setting both the pattern and the text. - - // Pass empty string for the locale for now to get the Unicode Collation Algorithm, - // rather than something locale-specific. - UErrorCode status = U_ZERO_ERROR; - UStringSearch* searcher = usearch_open(&newlineCharacter, 1, &newlineCharacter, 1, "", 0, &status); - ASSERT(status == U_ZERO_ERROR); + UStringSearch* searcher = usearch_open(&newlineCharacter, 1, &newlineCharacter, 1, currentSearchLocaleID(), 0, &status); + ASSERT(status == U_ZERO_ERROR || status == U_USING_FALLBACK_WARNING); return searcher; } |