LayoutTests:
authorjusting <justing@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 31 Oct 2006 20:34:28 +0000 (20:34 +0000)
committerjusting <justing@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 31 Oct 2006 20:34:28 +0000 (20:34 +0000)
        Reviewed by harrison

        * editing/execCommand/create-list-1.html: Removed.
        * editing/execCommand/create-list-with-hr-expected.checksum:
        * editing/execCommand/create-list-with-hr-expected.png:
        * editing/execCommand/create-list-with-hr-expected.txt:
        * editing/execCommand/remove-list-1-expected.checksum:
        * editing/execCommand/remove-list-1-expected.png:
        * editing/execCommand/remove-list-1-expected.txt:
        * fast/text/attributed-substring-from-range-001-expected.txt:

WebCore:

        Reviewed by harrison

        <rdar://problem/4808375>
        REGRESSION: TextIterator slowed down, affecting Find on Page & Copy (etc.) [11460}

        Completely back out r17276 because of performance issues.

        * editing/TextIterator.cpp:
        (WebCore::TextIterator::TextIterator):
        (WebCore::TextIterator::advance):
        (WebCore::TextIterator::handleTextNode):
        (WebCore::TextIterator::handleTextBox):
        (WebCore::TextIterator::handleReplacedElement):
        (WebCore::TextIterator::handleNonTextNode):
        (WebCore::TextIterator::exitNode):
        (WebCore::TextIterator::emitCharacter):
        (WebCore::TextIterator::range):
        (WebCore::SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator):
        (WebCore::SimplifiedBackwardsTextIterator::advance):
        (WebCore::SimplifiedBackwardsTextIterator::handleTextNode):
        (WebCore::SimplifiedBackwardsTextIterator::handleReplacedElement):
        (WebCore::SimplifiedBackwardsTextIterator::emitCharacter):
        (WebCore::SimplifiedBackwardsTextIterator::emitNewline):
        (WebCore::SimplifiedBackwardsTextIterator::range):
        (WebCore::CharacterIterator::range):
        (WebCore::TextIterator::rangeFromLocationAndLength):
        * editing/TextIterator.h:
        (WebCore::TextIterator::atEnd):
        (WebCore::SimplifiedBackwardsTextIterator::atEnd):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@17490 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/execCommand/create-list-1.html-disabled [moved from LayoutTests/editing/execCommand/create-list-1.html with 100% similarity]
LayoutTests/editing/execCommand/create-list-with-hr-expected.checksum
LayoutTests/editing/execCommand/create-list-with-hr-expected.png
LayoutTests/editing/execCommand/create-list-with-hr-expected.txt
LayoutTests/editing/execCommand/remove-list-1-expected.checksum
LayoutTests/editing/execCommand/remove-list-1-expected.png
LayoutTests/editing/execCommand/remove-list-1-expected.txt
LayoutTests/fast/text/attributed-substring-from-range-001-expected.txt
WebCore/ChangeLog
WebCore/editing/TextIterator.cpp
WebCore/editing/TextIterator.h

index dbcd23b11f0032a5c3d5994604460ac2860a4c0a..6de8dbbbbb4151bf1357752d702c29b66e38283a 100644 (file)
@@ -1,3 +1,16 @@
+2006-10-31  Justin Garcia  <justin.garcia@apple.com>
+
+        Reviewed by harrison
+
+        * editing/execCommand/create-list-1.html: Removed.
+        * editing/execCommand/create-list-with-hr-expected.checksum:
+        * editing/execCommand/create-list-with-hr-expected.png:
+        * editing/execCommand/create-list-with-hr-expected.txt:
+        * editing/execCommand/remove-list-1-expected.checksum:
+        * editing/execCommand/remove-list-1-expected.png:
+        * editing/execCommand/remove-list-1-expected.txt:
+        * fast/text/attributed-substring-from-range-001-expected.txt:
+
 2006-10-31  Vladimir Olexa  <vladimir.olexa@gmail.com>
 
         Reviewed by Geoff.
index f738018c157210260fbcbb832f99494272673044..1277b2d61d48d5bfcea74cf3ed5e25096d934844 100644 (file)
@@ -1 +1 @@
-f557f6e45eb1c0240e2e0e6edfa6b0cc
\ No newline at end of file
+3aa8d95ca4314bc71d4ea99e0f639506
\ No newline at end of file
index a423abe902a4cf3f3e0de0e7875f50d01a98f857..932c0a3ce4e3b26ced7731e49cbb4d7280fbcaeb 100644 (file)
Binary files a/LayoutTests/editing/execCommand/create-list-with-hr-expected.png and b/LayoutTests/editing/execCommand/create-list-with-hr-expected.png differ
index 797d7533cb37f2621cf7699b617a82ad96f76955..c81f6f02f11362e53d90730f08a113f775ca7d4e 100644 (file)
@@ -2,7 +2,7 @@ EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML
 EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > LI > UL > DIV > BODY > HTML > #document to 0 of DIV > LI > UL > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 122 of #text > B > P > BODY > HTML > #document to 122 of #text > B > P > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
 layer at (0,0) size 800x600
@@ -26,4 +26,4 @@ layer at (0,0) size 800x600
               RenderBlock {HR} at (0,0) size 744x2 [border: (1px inset #000000)]
             RenderBlock (anonymous) at (0,36) size 744x0
         RenderBlock (anonymous) at (0,44) size 784x0
-caret: position 0 of child 0 {HR} of child 0 {DIV} of child 0 {LI} of child 0 {UL} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
+caret: position 122 of child 0 {#text} of child 1 {B} of child 0 {P} of child 0 {BODY} of child 0 {HTML} of document
index f8a2259e346d236ba739df95b60392a45a3fd87e..9aebb0e2638847ab3670b658f7103bf4e6cfa0f0 100644 (file)
@@ -1 +1 @@
-2b441a195ceda3a506ff2bb266cbe8a2
\ No newline at end of file
+958726dee6c5c5c73089d158c46f17c5
\ No newline at end of file
index 80bdf66abe39350bfa4ec0adeb0ae42c32c19ae3..0cf1c88640bbe9b0a98dc4e38d7b689a7724f66a 100644 (file)
Binary files a/LayoutTests/editing/execCommand/remove-list-1-expected.png and b/LayoutTests/editing/execCommand/remove-list-1-expected.png differ
index 179d10c5d8f15c9365a677e19ff925e0cdebe28f..520d167db23627a27a67ccaa45ccdfdb508ac45c 100644 (file)
@@ -4,7 +4,7 @@ EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of LI > OL > DIV > BODY > HTML > #document to 49 of #text > LI > OL > DIV > BODY > HTML > #document toDOMRange:range from 0 of LI > OL > DIV > BODY > HTML > #document to 49 of #text > LI > OL > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > BODY > HTML > #document to 49 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
 layer at (0,0) size 800x600
@@ -23,5 +23,4 @@ layer at (0,0) size 800x600
         RenderBR {BR} at (0,0) size 0x18
         RenderText {#text} at (0,18) size 322x18
           text run at (0,18) width 322: "There should be a empty paragraph above this one."
-selection start: position 0 of child 0 {BR} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
-selection end:   position 49 of child 1 {#text} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
+caret: position 0 of child 0 {BR} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
index 87b6df9c0530fe642d9c05cfd10afc4d09bfba5b..cdfbcb0361561bf8a50a1318948ca70ce3e8b7ee 100644 (file)
@@ -8,9 +8,9 @@ Testing text with br elements (<div><br></div>hello<br>)
 (0, 2): {}h{ NSColor = NSCalibratedWhiteColorSpace 0 1; NSFont = "Times-Roman 16.00 pt. S [] (0xXXXXXXXX) fobj=0xXXXXXXXX, spc=4.00"; }
 (1, 1): h{ NSColor = NSCalibratedWhiteColorSpace 0 1; NSFont = "Times-Roman 16.00 pt. S [] (0xXXXXXXXX) fobj=0xXXXXXXXX, spc=4.00"; }
 (1, 5): hello{ NSColor = NSCalibratedWhiteColorSpace 0 1; NSFont = "Times-Roman 16.00 pt. S [] (0xXXXXXXXX) fobj=0xXXXXXXXX, spc=4.00"; }
-(1, 6): hello{ NSColor = NSCalibratedWhiteColorSpace 0 1; NSFont = "Times-Roman 16.00 pt. S [] (0xXXXXXXXX) fobj=0xXXXXXXXX, spc=4.00"; }
-(1, 100): hello{ NSColor = NSCalibratedWhiteColorSpace 0 1; NSFont = "Times-Roman 16.00 pt. S [] (0xXXXXXXXX) fobj=0xXXXXXXXX, spc=4.00"; }
-(6, 1):
+(1, 6): hello{ NSColor = NSCalibratedWhiteColorSpace 0 1; NSFont = "Times-Roman 16.00 pt. S [] (0xXXXXXXXX) fobj=0xXXXXXXXX, spc=4.00"; } {}
+(1, 100): hello{ NSColor = NSCalibratedWhiteColorSpace 0 1; NSFont = "Times-Roman 16.00 pt. S [] (0xXXXXXXXX) fobj=0xXXXXXXXX, spc=4.00"; } {}
+(6, 1): {}
 (7, 1):
 (100, 0): undefined
 (100, 100): undefined
index 4eb129e2b64d7e8940895bb58ac157dcc8a8e9b8..d1112f7eb1f4fff6d53223d55eaf2fa494baa17b 100644 (file)
@@ -1,3 +1,35 @@
+2006-10-31  Justin Garcia  <justin.garcia@apple.com>
+
+        Reviewed by harrison
+        
+        <rdar://problem/4808375>
+        REGRESSION: TextIterator slowed down, affecting Find on Page & Copy (etc.) [11460}
+        
+        Completely back out r17276 because of performance issues.
+
+        * editing/TextIterator.cpp:
+        (WebCore::TextIterator::TextIterator):
+        (WebCore::TextIterator::advance):
+        (WebCore::TextIterator::handleTextNode):
+        (WebCore::TextIterator::handleTextBox):
+        (WebCore::TextIterator::handleReplacedElement):
+        (WebCore::TextIterator::handleNonTextNode):
+        (WebCore::TextIterator::exitNode):
+        (WebCore::TextIterator::emitCharacter):
+        (WebCore::TextIterator::range):
+        (WebCore::SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator):
+        (WebCore::SimplifiedBackwardsTextIterator::advance):
+        (WebCore::SimplifiedBackwardsTextIterator::handleTextNode):
+        (WebCore::SimplifiedBackwardsTextIterator::handleReplacedElement):
+        (WebCore::SimplifiedBackwardsTextIterator::emitCharacter):
+        (WebCore::SimplifiedBackwardsTextIterator::emitNewline):
+        (WebCore::SimplifiedBackwardsTextIterator::range):
+        (WebCore::CharacterIterator::range):
+        (WebCore::TextIterator::rangeFromLocationAndLength):
+        * editing/TextIterator.h:
+        (WebCore::TextIterator::atEnd):
+        (WebCore::SimplifiedBackwardsTextIterator::atEnd):
+
 2006-10-31  Darin Adler  <darin@apple.com>
 
         Reviewed by Brady.
index 54c89429c9e10a0262153f18fa906a86d0f640bd..b073a2c59e930eb102139e9b24d7507f36f34071 100644 (file)
@@ -73,11 +73,11 @@ private:
     CircularSearchBuffer &operator=(const CircularSearchBuffer&);
 };
 
-TextIterator::TextIterator() : m_endContainer(0), m_endOffset(0), m_lastCharacter(0)
+TextIterator::TextIterator() : m_endContainer(0), m_endOffset(0), m_positionNode(0), m_lastCharacter(0)
 {
 }
 
-TextIterator::TextIterator(const Range *r, IteratorKind kind) : m_endContainer(0), m_endOffset(0)
+TextIterator::TextIterator(const Range *r, IteratorKind kind) : m_endContainer(0), m_endOffset(0), m_positionNode(0)
 {
     if (!r)
         return;
@@ -120,8 +120,8 @@ TextIterator::TextIterator(const Range *r, IteratorKind kind) : m_endContainer(0
         m_lastCharacter = '\n';
 
 #ifndef NDEBUG
-    // Need this just because of the assert in advance().
-    m_range = new Range(m_node->document(), Position(m_node, 0), Position(m_node, 0));
+    // need this just because of the assert in advance()
+    m_positionNode = m_node;
 #endif
 
     // identify the first run
@@ -131,16 +131,13 @@ TextIterator::TextIterator(const Range *r, IteratorKind kind) : m_endContainer(0
 void TextIterator::advance()
 {
     // reset the run information
-    m_range = 0;
+    m_positionNode = 0;
     m_textLength = 0;
 
     // handle remembered node that needed a newline after the text node's newline
     if (m_needAnotherNewline) {
-        VisiblePosition lastInNode(Position(m_node, maxDeepOffset(m_node)));
-        VisiblePosition next = lastInNode.next();
-        Position start = lastInNode.deepEquivalent();
-        Position end = next.isNull() ? start : next.deepEquivalent();
-        emitCharacter('\n', start, end);
+        // emit the newline, with position a collapsed range at the end of current node.
+        emitCharacter('\n', m_node->parentNode(), m_node, 1, 1);
         m_needAnotherNewline = false;
         return;
     }
@@ -148,7 +145,7 @@ void TextIterator::advance()
     // handle remembered text box
     if (m_textBox) {
         handleTextBox();
-        if (m_range)
+        if (m_positionNode)
             return;
     }
 
@@ -165,7 +162,7 @@ void TextIterator::advance()
                     m_handledNode = handleReplacedElement();
             } else
                 m_handledNode = handleNonTextNode();
-            if (m_range)
+            if (m_positionNode)
                 return;
         }
 
@@ -181,7 +178,7 @@ void TextIterator::advance()
                 while (!next && m_node->parentNode()) {
                     m_node = m_node->parentNode();
                     exitNode();
-                    if (m_range) {
+                    if (m_positionNode) {
                         m_handledNode = true;
                         m_handledChildren = true;
                         return;
@@ -196,8 +193,8 @@ void TextIterator::advance()
         m_handledNode = false;
         m_handledChildren = false;
 
-        // FIXME: How would this ever be?
-        if (m_range)
+        // how would this ever be?
+        if (m_positionNode)
             return;
     }
 }
@@ -218,7 +215,7 @@ bool TextIterator::handleTextNode()
     if (!renderer->style()->collapseWhiteSpace()) {
         int runStart = m_offset;
         if (m_lastTextNodeEndedWithCollapsedSpace) {
-            emitCharacter(' ', Position(m_node, runStart), Position(m_node, runStart));
+            emitCharacter(' ', m_node, 0, runStart, runStart);
             return false;
         }
         int strLength = str.length();
@@ -228,8 +225,10 @@ bool TextIterator::handleTextNode()
         if (runStart >= runEnd)
             return true;
 
-        m_range = new Range(m_node->document(), Position(m_node, runStart), Position(m_node, runEnd));
-        
+        m_positionNode = m_node;
+        m_positionOffsetBaseNode = 0;
+        m_positionStartOffset = runStart;
+        m_positionEndOffset = runEnd;
         m_textCharacters = str.characters() + runStart;
         m_textLength = runEnd - runStart;
 
@@ -273,7 +272,7 @@ void TextIterator::handleTextBox()
         bool needSpace = m_lastTextNodeEndedWithCollapsedSpace
             || (m_textBox == firstTextBox && textBoxStart == runStart && runStart > 0);
         if (needSpace && !isCollapsibleWhitespace(m_lastCharacter) && m_lastCharacter) {
-            emitCharacter(' ', Position(m_node, runStart), Position(m_node, runStart));
+            emitCharacter(' ', m_node, 0, runStart, runStart);
             return;
         }
         int textBoxEnd = textBoxStart + m_textBox->m_len;
@@ -292,7 +291,7 @@ void TextIterator::handleTextBox()
             // or a run of characters that does not include a newline.
             // This effectively translates newlines to spaces without copying the text.
             if (str[runStart] == '\n') {
-                emitCharacter(' ', Position(m_node, runStart), Position(m_node, runStart + 1));
+                emitCharacter(' ', m_node, 0, runStart, runStart + 1);
                 m_offset = runStart + 1;
             } else {
                 int subrunEnd = str.find('\n', runStart);
@@ -301,7 +300,10 @@ void TextIterator::handleTextBox()
 
                 m_offset = subrunEnd;
 
-                m_range = new Range(m_node->document(), Position(m_node, runStart), Position(m_node, subrunEnd));
+                m_positionNode = m_node;
+                m_positionOffsetBaseNode = 0;
+                m_positionStartOffset = runStart;
+                m_positionEndOffset = subrunEnd;
                 m_textCharacters = str.characters() + runStart;
                 m_textLength = subrunEnd - runStart;
 
@@ -311,8 +313,7 @@ void TextIterator::handleTextBox()
 
             // If we are doing a subrun that doesn't go to the end of the text box,
             // come back again to finish handling this text box; don't advance to the next one.
-            ExceptionCode ec;
-            if (m_range->endOffset(ec) < textBoxEnd)
+            if (m_positionEndOffset < textBoxEnd)
                 return;
 
             // Advance and return
@@ -334,11 +335,14 @@ void TextIterator::handleTextBox()
 bool TextIterator::handleReplacedElement()
 {
     if (m_lastTextNodeEndedWithCollapsedSpace) {
-        emitCharacter(' ', positionAfterNode(m_lastTextNode), positionAfterNode(m_lastTextNode));
+        emitCharacter(' ', m_lastTextNode->parentNode(), m_lastTextNode, 1, 1);
         return false;
     }
 
-    m_range = new Range(m_node->document(), positionBeforeNode(m_node), positionAfterNode(m_node));
+    m_positionNode = m_node->parentNode();
+    m_positionOffsetBaseNode = m_node;
+    m_positionStartOffset = 0;
+    m_positionEndOffset = 1;
 
     m_textCharacters = 0;
     m_textLength = 0;
@@ -466,20 +470,15 @@ static bool shouldEmitExtraNewlineForNode(Node* node)
 bool TextIterator::handleNonTextNode()
 {
     if (shouldEmitNewlineForNode(m_node)) {
-        Position start = positionBeforeNode(m_node);
-        VisiblePosition next = VisiblePosition(start).next();
-        Position end = next.isNull() ? start : next.deepEquivalent();
-        emitCharacter('\n', start, end);
+        emitCharacter('\n', m_node->parentNode(), m_node, 0, 1);
     } else if (m_lastCharacter != '\n' && m_lastTextNode) {
-        // Only add the tab or newline if not at the start of a line.
-        // FIXME: The ranges for these emitted characters should be the part of the 
-        // document that this imaginary character would occupy.
+        // only add the tab or newline if not at the start of a line
         if (shouldEmitTabBeforeNode(m_node))
-            emitCharacter('\t', positionBeforeNode(m_lastTextNode), positionAfterNode(m_lastTextNode));
+            emitCharacter('\t', m_lastTextNode->parentNode(), m_lastTextNode, 0, 1);
         else if (shouldEmitNewlinesBeforeAndAfterNode(m_node))
-            emitCharacter('\n', positionBeforeNode(m_lastTextNode), positionAfterNode(m_lastTextNode));
+            emitCharacter('\n', m_lastTextNode->parentNode(), m_lastTextNode, 0, 1);
         else if (shouldEmitSpaceBeforeAndAfterNode(m_node))
-            emitCharacter(' ', positionBeforeNode(m_lastTextNode), positionAfterNode(m_lastTextNode));
+            emitCharacter(' ', m_lastTextNode->parentNode(), m_lastTextNode, 0, 1);
     }
 
     return true;
@@ -491,34 +490,29 @@ void TextIterator::exitNode()
         // use extra newline to represent margin bottom, as needed
         bool addNewline = shouldEmitExtraNewlineForNode(m_node);
         
-        VisiblePosition lastInNode(Position(m_node, maxDeepOffset(m_node)));
-        VisiblePosition next = lastInNode.next();
-        Position start = lastInNode.deepEquivalent();
-        Position end = next.isNull() ? start : next.deepEquivalent();
-        
         if (m_lastCharacter != '\n') {
-
-            emitCharacter('\n', start, end);
+            // insert a newline with a position following this block
+            emitCharacter('\n', m_node->parentNode(), m_node, 1, 1);
 
             // remember whether to later add a newline for the current node
             assert(!m_needAnotherNewline);
             m_needAnotherNewline = addNewline;
         } else if (addNewline) {
             // insert a newline with a position following this block
-            emitCharacter('\n', start, end);
+            emitCharacter('\n', m_node->parentNode(), m_node, 1, 1);
         }
-    } else if (shouldEmitSpaceBeforeAndAfterNode(m_node)) {
-        VisiblePosition lastInNode(Position(m_node, maxDeepOffset(m_node)));
-        VisiblePosition next = lastInNode.next();
-        Position start = lastInNode.deepEquivalent();
-        Position end = next.isNull() ? start : next.deepEquivalent();
-        emitCharacter(' ', start, end);
-    }
+    } else if (shouldEmitSpaceBeforeAndAfterNode(m_node))
+        emitCharacter(' ', m_node->parentNode(), m_node, 1, 1);
 }
 
-void TextIterator::emitCharacter(UChar c, const Position& start, const Position& end)
+void TextIterator::emitCharacter(UChar c, Node *textNode, Node *offsetBaseNode, int textStartOffset, int textEndOffset)
 {
-    m_range = start.isNull() ? 0 : new Range(start.node()->document(), start, end);
+    // remember information with which to construct the TextIterator::range()
+    // NOTE: textNode is often not a text node, so the range will specify child nodes of positionNode
+    m_positionNode = textNode;
+    m_positionOffsetBaseNode = offsetBaseNode;
+    m_positionStartOffset = textStartOffset;
+    m_positionEndOffset = textEndOffset;
  
     // remember information with which to construct the TextIterator::characters() and length()
     m_singleCharacterBuffer = c;
@@ -532,21 +526,32 @@ void TextIterator::emitCharacter(UChar c, const Position& start, const Position&
 
 PassRefPtr<Range> TextIterator::range() const
 {
-    if (m_range)
-        return m_range;
-        
+    // use the current run information, if we have it
+    if (m_positionNode) {
+        if (m_positionOffsetBaseNode) {
+            int index = m_positionOffsetBaseNode->nodeIndex();
+            m_positionStartOffset += index;
+            m_positionEndOffset += index;
+            m_positionOffsetBaseNode = 0;
+        }
+        return new Range(m_positionNode->document(), m_positionNode, m_positionStartOffset, m_positionNode, m_positionEndOffset);
+    }
+
+    // otherwise, return the end of the overall range we were given
     if (m_endContainer)
         return new Range(m_endContainer->document(), m_endContainer, m_endOffset, m_endContainer, m_endOffset);
-    
+        
     return 0;
 }
 
-SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator()
+SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator() : m_positionNode(0)
 {
 }
 
 SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range *r)
 {
+    m_positionNode = 0;
+
     if (!r)
         return;
 
@@ -587,7 +592,7 @@ SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range *r)
 
 #ifndef NDEBUG
     // Need this just because of the assert.
-    m_range = new Range(endNode->document(), Position(endNode, 0), Position(endNode, 0));
+    m_positionNode = endNode;
 #endif
 
     m_lastTextNode = 0;
@@ -598,9 +603,9 @@ SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range *r)
 
 void SimplifiedBackwardsTextIterator::advance()
 {
-    assert(m_range);
+    assert(m_positionNode);
 
-    m_range = 0;
+    m_positionNode = 0;
     m_textLength = 0;
 
     while (m_node) {
@@ -615,7 +620,7 @@ void SimplifiedBackwardsTextIterator::advance()
                     m_handledNode = handleReplacedElement();
             } else
                 m_handledNode = handleNonTextNode();
-            if (m_range)
+            if (m_positionNode)
                 return;
         }
 
@@ -663,7 +668,7 @@ void SimplifiedBackwardsTextIterator::advance()
             m_offset = 0;
         m_handledNode = false;
         
-        if (m_range)
+        if (m_positionNode)
             return;
     }
 }
@@ -678,21 +683,26 @@ bool SimplifiedBackwardsTextIterator::handleTextNode()
     if (!renderer->firstTextBox() && str.length() > 0)
         return true;
 
-    Position end(m_node, m_offset);
+    m_positionEndOffset = m_offset;
+
     m_offset = (m_node == m_startNode) ? m_startOffset : 0;
-    Position start(m_node, m_offset);
-    m_range = new Range(m_node->document(), start, end);
-    m_textLength = end.offset() - start.offset();
-    m_textCharacters = str.characters() + start.offset();
+    m_positionNode = m_node;
+    m_positionStartOffset = m_offset;
+    m_textLength = m_positionEndOffset - m_positionStartOffset;
+    m_textCharacters = str.characters() + m_positionStartOffset;
 
-    m_lastCharacter = str[end.offset() - 1];
+    m_lastCharacter = str[m_positionEndOffset - 1];
 
     return true;
 }
 
 bool SimplifiedBackwardsTextIterator::handleReplacedElement()
 {
-    m_range = new Range(m_node->document(), positionBeforeNode(m_node), positionAfterNode(m_node));
+    int offset = m_node->nodeIndex();
+
+    m_positionNode = m_node->parentNode();
+    m_positionStartOffset = offset;
+    m_positionEndOffset = offset + 1;
 
     m_textCharacters = 0;
     m_textLength = 0;
@@ -724,12 +734,12 @@ void SimplifiedBackwardsTextIterator::exitNode()
     handleNonTextNode();
 }
 
-void SimplifiedBackwardsTextIterator::emitCharacter(UChar c, const Position& start, const Position& end)
+void SimplifiedBackwardsTextIterator::emitCharacter(UChar c, Node *node, int startOffset, int endOffset)
 {
     m_singleCharacterBuffer = c;
-    
-    m_range = start.isNull() ? 0 : new Range(start.node()->document(), start, end);
-    
+    m_positionNode = node;
+    m_positionStartOffset = startOffset;
+    m_positionEndOffset = endOffset;
     m_textCharacters = &m_singleCharacterBuffer;
     m_textLength = 1;
     m_lastCharacter = c;
@@ -737,16 +747,21 @@ void SimplifiedBackwardsTextIterator::emitCharacter(UChar c, const Position& sta
 
 void SimplifiedBackwardsTextIterator::emitNewline()
 {
-    if (m_lastTextNode)
-        emitCharacter('\n', positionBeforeNode(m_lastTextNode), positionAfterNode(m_lastTextNode));
-    else
-        emitCharacter('\n', positionBeforeNode(m_node), positionAfterNode(m_node));
+    int offset;
+    
+    if (m_lastTextNode) {
+        offset = m_lastTextNode->nodeIndex();
+        emitCharacter('\n', m_lastTextNode->parentNode(), offset, offset + 1);
+    } else {
+        offset = m_node->nodeIndex();
+        emitCharacter('\n', m_node->parentNode(), offset, offset + 1);
+    }
 }
 
 PassRefPtr<Range> SimplifiedBackwardsTextIterator::range() const
 {
-    if (m_range)
-        return m_range;
+    if (m_positionNode)
+        return new Range(m_positionNode->document(), m_positionNode, m_positionStartOffset, m_positionNode, m_positionEndOffset);
     
     return new Range(m_startNode->document(), m_startNode, m_startOffset, m_startNode, m_startOffset);
 }
@@ -766,8 +781,7 @@ CharacterIterator::CharacterIterator(const Range *r)
 
 PassRefPtr<Range> CharacterIterator::range() const
 {
-    ExceptionCode ec;
-    RefPtr<Range> r = m_textIterator.range()->cloneRange(ec);
+    RefPtr<Range> r = m_textIterator.range();
     if (!m_textIterator.atEnd()) {
         if (m_textIterator.length() <= 1) {
             assert(m_runOffset == 0);
@@ -1037,11 +1051,14 @@ PassRefPtr<Range> TextIterator::rangeFromLocationAndLength(Element *scope, int r
         if (rangeLocation >= docTextPosition && rangeLocation <= docTextPosition + len) {
             startRangeFound = true;
             int exception = 0;
-            if (rangeLocation == docTextPosition + len)
-                resultRange->setStart(textRunRange->endContainer(exception), textRunRange->endOffset(exception), exception);
-            else {
+            if (textRunRange->startContainer(exception)->isTextNode()) {
                 int offset = rangeLocation - docTextPosition;
                 resultRange->setStart(textRunRange->startContainer(exception), offset + textRunRange->startOffset(exception), exception);
+            } else {
+                if (rangeLocation == docTextPosition)
+                    resultRange->setStart(textRunRange->startContainer(exception), textRunRange->startOffset(exception), exception);
+                else
+                    resultRange->setStart(textRunRange->endContainer(exception), textRunRange->endOffset(exception), exception);
             }
         }
 
@@ -1056,9 +1073,10 @@ PassRefPtr<Range> TextIterator::rangeFromLocationAndLength(Element *scope, int r
                 else
                     resultRange->setEnd(textRunRange->endContainer(exception), textRunRange->endOffset(exception), exception);
             }
-            
-            docTextPosition += len;
-            break;
+            if (!(rangeLength == 0 && rangeEnd == docTextPosition + len)) {
+                docTextPosition += len;
+                break;
+            }
         }
         docTextPosition += len;
     }
index cf9d3c80338a8ab3f9d5c4265c69d0a92fb615ae..f11cc0cedabee1295b8c922b80f935f5c1545d8f 100644 (file)
@@ -62,7 +62,7 @@ public:
     TextIterator();
     explicit TextIterator(const Range *, IteratorKind kind = CONTENT );
     
-    bool atEnd() const { return !m_range; }
+    bool atEnd() const { return !m_positionNode; }
     void advance();
     
     int length() const { return m_textLength; }
@@ -79,7 +79,7 @@ private:
     bool handleReplacedElement();
     bool handleNonTextNode();
     void handleTextBox();
-    void emitCharacter(UChar, const Position&, const Position&);
+    void emitCharacter(UChar, Node *textNode, Node *offsetBaseNode, int textStartOffset, int textEndOffset);
     
     // Current position, not necessarily of the text being returned, but position
     // as we walk through the DOM tree.
@@ -94,7 +94,10 @@ private:
     Node *m_pastEndNode;
     
     // The current text and its position, in the form to be returned from the iterator.
-    RefPtr<Range> m_range;
+    Node *m_positionNode;
+    mutable Node *m_positionOffsetBaseNode;
+    mutable int m_positionStartOffset;
+    mutable int m_positionEndOffset;
     const UChar* m_textCharacters;
     int m_textLength;
     
@@ -125,7 +128,7 @@ public:
     SimplifiedBackwardsTextIterator();
     explicit SimplifiedBackwardsTextIterator(const Range *);
     
-    bool atEnd() const { return !m_range; }
+    bool atEnd() const { return !m_positionNode; }
     void advance();
     
     int length() const { return m_textLength; }
@@ -138,7 +141,7 @@ private:
     bool handleTextNode();
     bool handleReplacedElement();
     bool handleNonTextNode();
-    void emitCharacter(UChar, const Position&, const Position&);
+    void emitCharacter(UChar, Node *Node, int startOffset, int endOffset);
     void emitNewline();
     
     // Current position, not necessarily of the text being returned, but position
@@ -153,7 +156,9 @@ private:
     int m_startOffset;
     
     // The current text and its position, in the form to be returned from the iterator.
-    RefPtr<Range> m_range;
+    Node* m_positionNode;
+    int m_positionStartOffset;
+    int m_positionEndOffset;
     const UChar* m_textCharacters;
     int m_textLength;