Reviewed by Hyatt
authorkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Aug 2004 23:40:49 +0000 (23:40 +0000)
committerkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Aug 2004 23:40:49 +0000 (23:40 +0000)
        Changes to improve our handling of object tags during editing, including
        fixing this bug:

        <rdar://problem/3744533> Problem editing <OBJECT> elements displayed by WebPlugIns

        Part of the fix for this bug involves removing the close() function from render objects.
        It was decided that this code was no longer needed, as the work it did could be moved
        to other, more modern, places.

        Fixed this bug:

        <rdar://problem/3748537> crash due to nil node passed into parentNode in computeTypingStyle deleting text

        Finally, I filed and fixed this bug I discovered while fixing the one above:

        <rdar://problem/3749338> Select-all + delete leaves editing view without blinking caret

        * khtml/editing/htmlediting_impl.cpp:
        (khtml::DeleteSelectionCommandImpl::computeTypingStyle): Fix for 3748537. Put in some more null
        checks. Bail, returning 0 for typing style if any null checks yield a null.
        (khtml::DeleteSelectionCommandImpl::doApply): Fix for 3749338. A removeNodeAndPrune call may wind
        up deleting the node where we calculated that we wanted to put the selection after deleting.
        If this happens, move this ending selection to a sensible alternative.
        (khtml::RemoveNodeAndPruneCommandImpl::doApply): Call previousNodeConsideringAtomicNodes instead
        of traversePreviousNode when doing the prune.
        * khtml/html/html_objectimpl.cpp:
        (HTMLObjectElementImpl::attach): Part of the fix for 3744533.
        (HTMLObjectElementImpl::recalcStyle): Change old strcmp check for type of renderer to be a call
        to canRenderImageType.
        (HTMLObjectElementImpl::childrenChanged): New function. Helps to keep object tags up to date
        as their children change. This also will help to make object tags respond properly to having their
        params changed by DOM calls.
        * khtml/html/html_objectimpl.h: Cosmetic change.
        * khtml/html/htmlparser.cpp:
        (KHTMLParser::insertNode): Remove call to obsolete closeRenderer() function.
        (KHTMLParser::popOneBlock): Ditto.
        * khtml/rendering/render_block.cpp:
        (khtml::RenderBlock::makeChildrenNonInline): Remove call to obsolete close() function.
        * khtml/rendering/render_container.cpp:
        (RenderContainer::updatePseudoChild): Ditto.
        * khtml/rendering/render_form.cpp: Remove obsolete close() function.
        * khtml/rendering/render_form.h: Ditto.
        * khtml/rendering/render_frames.cpp: Ditto.
        * khtml/rendering/render_frames.h: Ditto.
        * khtml/rendering/render_inline.cpp:
        (RenderInline::splitFlow): Remove calls to obsolete close() function.
        * khtml/rendering/render_object.h: Remove obsolete close() function.
        * khtml/rendering/render_table.cpp:
        (RenderTableCell::layout): Ditto.
        * khtml/rendering/render_table.h: Ditto.
        * khtml/xml/dom_docimpl.cpp:
        (DocumentImpl::closeInternal): Remove call to obsolete close() function.
        * khtml/xml/dom_nodeimpl.cpp: Remove obsolete m_rendererNeedsClose initialization.
        (NodeImpl::NodeImpl): Remove obsolete closeRenderer() function.
        (NodeImpl::attach): Remove call to obsolete close() function.
        (NodeImpl::isAtomicNode): New function. Helps to fix 3744533. Determines if a node should
        be treated as an atomic node for the purposes of editing.
        (NodeImpl::previousNodeConsideringAtomicNodes): New helper to traverse tree taking atomic nodes
        into account.
        (NodeImpl::nextNodeConsideringAtomicNodes): Ditto.
        (NodeImpl::previousLeafNode): Now calls nextNodeConsideringAtomicNodes to iterate. This helps to
        prevent deleting PARAM tag portions of object tags erroneously.
        (NodeImpl::nextLeafNode): Ditto.
        * khtml/xml/dom_nodeimpl.h: Removed m_rendererNeedsClose bit. Added declarations for new functions.
        * khtml/xml/dom_position.cpp:
        (DOM::Position::equivalentDeepPosition): Now takes atomic nodes into account as it drills down into the
        tree.
        * khtml/xml/xml_tokenizer.cpp:
        (khtml::XMLTokenizer::endElement): Remove call to obsolete closeRenderer() function.

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

20 files changed:
WebCore/ChangeLog-2005-08-23
WebCore/khtml/editing/htmlediting_impl.cpp
WebCore/khtml/html/html_objectimpl.cpp
WebCore/khtml/html/html_objectimpl.h
WebCore/khtml/html/htmlparser.cpp
WebCore/khtml/rendering/render_block.cpp
WebCore/khtml/rendering/render_container.cpp
WebCore/khtml/rendering/render_form.cpp
WebCore/khtml/rendering/render_form.h
WebCore/khtml/rendering/render_frames.cpp
WebCore/khtml/rendering/render_frames.h
WebCore/khtml/rendering/render_inline.cpp
WebCore/khtml/rendering/render_object.h
WebCore/khtml/rendering/render_table.cpp
WebCore/khtml/rendering/render_table.h
WebCore/khtml/xml/dom_docimpl.cpp
WebCore/khtml/xml/dom_nodeimpl.cpp
WebCore/khtml/xml/dom_nodeimpl.h
WebCore/khtml/xml/dom_position.cpp
WebCore/khtml/xml/xml_tokenizer.cpp

index 35056a1d3f416bc08d94c6e4e2f139783b415e96..219c7ae6869ef512bfa7bef818fc996450b1a3c5 100644 (file)
@@ -1,3 +1,77 @@
+2004-08-03  Ken Kocienda  <kocienda@apple.com>
+
+        Reviewed by Hyatt
+
+        Changes to improve our handling of object tags during editing, including
+        fixing this bug:
+        
+        <rdar://problem/3744533> Problem editing <OBJECT> elements displayed by WebPlugIns 
+
+        Part of the fix for this bug involves removing the close() function from render objects.
+        It was decided that this code was no longer needed, as the work it did could be moved
+        to other, more modern, places.
+
+        Fixed this bug:
+        
+        <rdar://problem/3748537> crash due to nil node passed into parentNode in computeTypingStyle deleting text
+
+        Finally, I filed and fixed this bug I discovered while fixing the one above:
+        
+        <rdar://problem/3749338> Select-all + delete leaves editing view without blinking caret
+
+        * khtml/editing/htmlediting_impl.cpp:
+        (khtml::DeleteSelectionCommandImpl::computeTypingStyle): Fix for 3748537. Put in some more null
+        checks. Bail, returning 0 for typing style if any null checks yield a null.
+        (khtml::DeleteSelectionCommandImpl::doApply): Fix for 3749338. A removeNodeAndPrune call may wind
+        up deleting the node where we calculated that we wanted to put the selection after deleting.
+        If this happens, move this ending selection to a sensible alternative.
+        (khtml::RemoveNodeAndPruneCommandImpl::doApply): Call previousNodeConsideringAtomicNodes instead 
+        of traversePreviousNode when doing the prune.
+        * khtml/html/html_objectimpl.cpp:
+        (HTMLObjectElementImpl::attach): Part of the fix for 3744533.
+        (HTMLObjectElementImpl::recalcStyle): Change old strcmp check for type of renderer to be a call
+        to canRenderImageType.
+        (HTMLObjectElementImpl::childrenChanged): New function. Helps to keep object tags up to date 
+        as their children change. This also will help to make object tags respond properly to having their
+        params changed by DOM calls.
+        * khtml/html/html_objectimpl.h: Cosmetic change.
+        * khtml/html/htmlparser.cpp:
+        (KHTMLParser::insertNode): Remove call to obsolete closeRenderer() function.
+        (KHTMLParser::popOneBlock): Ditto.
+        * khtml/rendering/render_block.cpp:
+        (khtml::RenderBlock::makeChildrenNonInline): Remove call to obsolete close() function.
+        * khtml/rendering/render_container.cpp:
+        (RenderContainer::updatePseudoChild): Ditto.
+        * khtml/rendering/render_form.cpp: Remove obsolete close() function.
+        * khtml/rendering/render_form.h: Ditto.
+        * khtml/rendering/render_frames.cpp: Ditto.
+        * khtml/rendering/render_frames.h: Ditto.
+        * khtml/rendering/render_inline.cpp:
+        (RenderInline::splitFlow): Remove calls to obsolete close() function.
+        * khtml/rendering/render_object.h: Remove obsolete close() function.
+        * khtml/rendering/render_table.cpp:
+        (RenderTableCell::layout): Ditto.
+        * khtml/rendering/render_table.h: Ditto.
+        * khtml/xml/dom_docimpl.cpp:
+        (DocumentImpl::closeInternal): Remove call to obsolete close() function.
+        * khtml/xml/dom_nodeimpl.cpp: Remove obsolete m_rendererNeedsClose initialization.
+        (NodeImpl::NodeImpl): Remove obsolete closeRenderer() function.
+        (NodeImpl::attach): Remove call to obsolete close() function.
+        (NodeImpl::isAtomicNode): New function. Helps to fix 3744533. Determines if a node should
+        be treated as an atomic node for the purposes of editing.
+        (NodeImpl::previousNodeConsideringAtomicNodes): New helper to traverse tree taking atomic nodes
+        into account.
+        (NodeImpl::nextNodeConsideringAtomicNodes): Ditto.
+        (NodeImpl::previousLeafNode): Now calls nextNodeConsideringAtomicNodes to iterate. This helps to 
+        prevent deleting PARAM tag portions of object tags erroneously.
+        (NodeImpl::nextLeafNode): Ditto.
+        * khtml/xml/dom_nodeimpl.h: Removed m_rendererNeedsClose bit. Added declarations for new functions.
+        * khtml/xml/dom_position.cpp:
+        (DOM::Position::equivalentDeepPosition): Now takes atomic nodes into account as it drills down into the
+        tree.
+        * khtml/xml/xml_tokenizer.cpp:
+        (khtml::XMLTokenizer::endElement): Remove call to obsolete closeRenderer() function.
+
 2004-08-03  David Hyatt  <hyatt@apple.com>
 
        Add the deprecated text/xsl MIME type (introduced by Internet Explorer 5) as an acceptable MIME type for XML
index 76faf6331aded4e5d530f73609e2e3e099ad951d..a593ce2a462bfa1bf5caec1922e1b293e5ecf7de 100644 (file)
@@ -1179,8 +1179,13 @@ bool DeleteSelectionCommandImpl::containsOnlyWhitespace(const Position &start, c
 CSSStyleDeclarationImpl *DeleteSelectionCommandImpl::computeTypingStyle(const Position &pos) const
 {
     ElementImpl *element = pos.element();
+    if (!element)
+        return 0;
+
     ElementImpl *shallowElement = pos.equivalentShallowPosition().element();
-    
+    if (!shallowElement)
+        return 0;
+
     ElementImpl *parent = Position(shallowElement->parentNode(), 0).element();
     if (!parent)
         return 0;
@@ -1353,6 +1358,9 @@ void DeleteSelectionCommandImpl::doApply()
     if (startCompletelySelected) {
         LOG(Editing,  "start node delete case 1");
         removeNodeAndPrune(downstreamStart.node(), startBlock);
+        // Fix up ending position if the prune operation removed the position's node from the document
+        if (!endingPosition.node()->inDocument())
+            endingPosition = upstreamStart;
     }
     else if (onlyWhitespace && isWS(upstreamStart)) {
         // Selection only contains whitespace. This is really a special-case to 
@@ -1387,15 +1395,21 @@ void DeleteSelectionCommandImpl::doApply()
         // work on intermediate nodes
         while (n != upstreamEnd.node()) {
             NodeImpl *d = n;
-            n = n->traverseNextNode();
+            n = n->nextNodeConsideringAtomicNodes();
             if (d->renderer() && d->renderer()->isEditable())
                 removeNodeAndPrune(d, startBlock);
+            // Fix up ending position if the prune operation removed the position's node from the document
+            if (!endingPosition.node()->inDocument())
+                endingPosition = Position(n, n->caretMinOffset());
         }
         
         // work on end node
         ASSERT(n == upstreamEnd.node());
         if (endCompletelySelected) {
             removeNodeAndPrune(upstreamEnd.node(), startBlock);
+            // Fix up ending position if the prune operation removed the position's node from the document
+            if (!endingPosition.node()->inDocument())
+                endingPosition = downstreamEnd;
         }
         else if (upstreamEnd.node()->isTextNode()) {
             if (upstreamEnd.offset() > 0) {
@@ -1431,6 +1445,9 @@ void DeleteSelectionCommandImpl::doApply()
         endingPosition = endingPosition.equivalentDownstreamPosition();
     }
 
+    // Fall back to the start block if the ending position is not in the document.
+    if (!endingPosition.node()->inDocument())
+        endingPosition = Position(startBlock, 0);
     debugPosition("ending position:     ", endingPosition);
     setEndingSelection(endingPosition);
 
@@ -2253,13 +2270,13 @@ void RemoveNodeAndPruneCommandImpl::doApply()
 {
     NodeImpl *editableBlock = m_pruneNode->enclosingBlockFlowElement();
     NodeImpl *pruneNode = m_pruneNode;
-    NodeImpl *node = pruneNode->traversePreviousNode();
+    NodeImpl *node = pruneNode->previousNodeConsideringAtomicNodes();
     removeNode(pruneNode);
     while (1) {
         if (node == m_stopNode || editableBlock != node->enclosingBlockFlowElement() || !shouldPruneNode(node))
             break;
         pruneNode = node;
-        node = node->traversePreviousNode();
+        node = node->previousNodeConsideringAtomicNodes();
         removeNode(pruneNode);
     }
 }
index f5755d578e049664cee1b53a7cfdaa8b6cdf9948..9c00fbe864b4738477fdc48acdb95d4246982e81 100644 (file)
@@ -496,11 +496,8 @@ void HTMLObjectElementImpl::attach()
                 imageObj->setImage(m_imageLoader->image());
             }
         } else {
-            // If we are already cleared, then it means that we were attach()-ed previously
-            // with no renderer. We will actually need to do an update in order to ensure
-            // that the plugin shows up.  This fix is necessary to work with async
-            // render tree construction caused by stylesheet loads. -dwh
-            needWidgetUpdate = false;
+            needWidgetUpdate = true;
+            setChanged();
         }
     }
 
@@ -519,14 +516,21 @@ void HTMLObjectElementImpl::detach()
   HTMLElementImpl::detach();
 }
 
-void HTMLObjectElementImpl::recalcStyle( StyleChange ch )
+void HTMLObjectElementImpl::recalcStyle(StyleChange ch)
 {
-    if (needWidgetUpdate) {
-        if(m_render && std::strcmp( m_render->renderName(),  "RenderPartObject" ) == 0 )
-            static_cast<RenderPartObject*>(m_render)->updateWidget();
+    if (needWidgetUpdate && m_render && !canRenderImageType(serviceType)) {
+        static_cast<RenderPartObject*>(m_render)->updateWidget();
         needWidgetUpdate = false;
     }
-    HTMLElementImpl::recalcStyle( ch );
+    HTMLElementImpl::recalcStyle(ch);
+}
+
+void HTMLObjectElementImpl::childrenChanged()
+{
+    if (inDocument()) {
+        needWidgetUpdate = true;
+        setChanged();
+    }
 }
 
 bool HTMLObjectElementImpl::isURLAttribute(AttributeImpl *attr) const
index 0c18901fc27b8425c4ad24dfa0107c3b8781eb8c..37225a6971105a1f5e6d26a70a0a07d4e14335c3 100644 (file)
@@ -130,7 +130,8 @@ public:
     virtual khtml::RenderObject *createRenderer(RenderArena *, khtml::RenderStyle *);
     virtual void detach();
     
-    virtual void recalcStyle( StyleChange ch );
+    virtual void recalcStyle(StyleChange ch);
+    virtual void childrenChanged();
 
     DocumentImpl* contentDocument() const;
     
index ff6c5faeb0bc54a369be1e1c2091db2287f3b014..80d2f8c37b6d5c92a080fc2cddae1d872faf6227 100644 (file)
@@ -338,7 +338,6 @@ bool KHTMLParser::insertNode(NodeImpl *n, bool flat)
                 if (!states.isEmpty())
                     n->restoreState(states);
             }
-            n->closeRenderer();
 #endif
         }
 
@@ -1547,7 +1546,6 @@ void KHTMLParser::popOneBlock(bool delBlock)
             if (!states.isEmpty())
                 current->restoreState(states);
         }
-        current->closeRenderer();
     }
 #endif
 
index d844185c71a31444392291e760154082da6a1f46..b3a7a233ff28496056183e828b9900263044c54e 100644 (file)
@@ -259,7 +259,6 @@ void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
             box->appendChildNode(removeChildNode(no));
         }
         box->appendChildNode(removeChildNode(inlineRunEnd));
-        box->close();
         box->setPos(box->xPos(), -500000);
     }
 }
index 29d6e3f122853114a960da1bb6f04837a62b948f..de491be27b71cc9a27b1f956571cc182801518c3 100644 (file)
@@ -327,7 +327,6 @@ void RenderContainer::updatePseudoChild(RenderStyle::PseudoId type, RenderObject
         // Add the pseudo after we've installed all our content, so that addChild will be able to find the text
         // inside the inline for e.g., first-letter styling.
         addChild(pseudoContainer, insertBefore);
-        pseudoContainer->close();
     }
 }
 
index a9a09537b598dcecf0458d7917dab828b3b46d75..9afe1c8a463a05aed083231d69898ae393e65202 100644 (file)
@@ -1576,13 +1576,6 @@ void RenderTextArea::updateFromElement()
     RenderFormElement::updateFromElement();
 }
 
-void RenderTextArea::close( )
-{
-    element()->setValue( element()->defaultValue() );
-
-    RenderFormElement::close();
-}
-
 QString RenderTextArea::text()
 {
     QString txt;
index b50407a84467ec0f4692dfb327895ef836e344e8..d4edeb176f813e86407175f10a6993c6b091d939 100644 (file)
@@ -463,7 +463,6 @@ public:
 
     virtual const char *renderName() const { return "RenderTextArea"; }
     virtual void calcMinMaxWidth();
-    virtual void close ( );
     virtual void updateFromElement();
     virtual void setStyle(RenderStyle *);
 
index e5238246b7e550e6761c1db902562762a0702c82..2e9da86f69446593dbf18d0403a1d7edf679562a 100644 (file)
@@ -821,14 +821,6 @@ void RenderPartObject::updateWidget()
   }
 }
 
-// ugly..
-void RenderPartObject::close()
-{
-    if ( element()->id() == ID_OBJECT )
-        updateWidget();
-    RenderPart::close();
-}
-
 bool RenderPartObject::partLoadingErrorNotify( khtml::ChildFrame *childFrame, const KURL& url, const QString& serviceType )
 {
     KHTMLPart *part = static_cast<KHTMLView *>(m_view)->part();
index 6ff9a201f0782d8d942febdad77320541009554d..6b9e3a741f58616681d9c071df182833d52d8223 100644 (file)
@@ -149,8 +149,6 @@ public:
 
     virtual const char *renderName() const { return "RenderPartObject"; }
 
-    virtual void close();
-
     virtual void layout( );
     virtual void updateWidget();
 
index 69fe29a20c313d7ee4367d32ae46098e8a40f478..62ff1592d8e0d4a0e0ee2eb51bfd0b939861af3e 100644 (file)
@@ -243,13 +243,10 @@ void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox
     newBlockBox->addChildToFlow(newChild, 0);
 
     // XXXdwh is any of this even necessary? I don't think it is.
-    pre->close();
     pre->setPos(0, -500000);
     pre->setNeedsLayout(true);
-    newBlockBox->close();
     newBlockBox->setPos(0, -500000);
     newBlockBox->setNeedsLayout(true);
-    post->close();
     post->setPos(0, -500000);
     post->setNeedsLayout(true);
 
index 6e71dc79785b45751cfe3c6423292e88b7f3156b..633d2ba1a00be7864f00634633bc8ddfa883b5d5 100644 (file)
@@ -425,9 +425,6 @@ public:
     // repaint and do not need a relayout
     virtual void updateFromElement() {};
 
-    // The corresponding closing element has been parsed. ### remove me
-    virtual void close() { }
-
     virtual int availableHeight() const { return 0; }
 
     // Whether or not the element shrinks to its max width (rather than filling the width
index 4b9ab22e34fb0befe0c5595afd871640a4c62727..d857fbc9d86da5e05a71e379731f3e1a27091d2a 100644 (file)
@@ -492,12 +492,6 @@ void RenderTable::calcMinMaxWidth()
 #endif
 }
 
-void RenderTable::close()
-{
-//    kdDebug( 6040 ) << "RenderTable::close()" << endl;
-    setNeedsLayoutAndMinMaxRecalc();
-}
-
 int RenderTable::borderTopExtra()
 {
     if (tCaption && tCaption->style()->captionSide()!=CAPBOTTOM)
@@ -1674,16 +1668,6 @@ void RenderTableCell::layout()
     m_widthChanged = false;
 }
 
-void RenderTableCell::close()
-{
-    RenderBlock::close();
-
-#ifdef DEBUG_LAYOUT
-    kdDebug( 6040 ) << renderName() << "(RenderTableCell)::close() total height =" << m_height << endl;
-#endif
-}
-
-
 void RenderTableCell::computeAbsoluteRepaintRect(QRect& r, bool f)
 {
     r.setY(r.y() + _topExtra);
index 6202aae8433e3947647717f7e7340499a20933b5..44a81e9aa1f5288cebf3dcbb984cdcd47adc294e 100644 (file)
@@ -105,7 +105,6 @@ public:
     virtual void paintBoxDecorations(PaintInfo& i, int _tx, int _ty);
     virtual void layout();
     virtual void calcMinMaxWidth();
-    virtual void close();
 
     virtual RenderBlock* firstLineBlock() const;
     virtual void updateFirstLetter();
@@ -363,8 +362,6 @@ public:
 
     void paintCollapsedBorder(QPainter* p, int x, int y, int w, int h);
     
-    virtual void close();
-
     // lie position to outside observers
     virtual int yPos() const { return m_y + _topExtra; }
 
index 9d431a8f67abe1d20504b2b319f2809a2472dbde..5566d1c0377ab4f67944ded1d73b2c792c67d78e 100644 (file)
@@ -1358,9 +1358,6 @@ void DocumentImpl::closeInternal( bool checkTokenizer )
 {
     if (parsing() || (checkTokenizer && !m_tokenizer)) return;
 
-    if ( m_render )
-        m_render->close();
-
     // on an explicit document.close(), the tokenizer might still be waiting on scripts,
     // and in that case we don't want to destroy it because that will prevent the
     // scripts from getting processed.
index 18de58f763fc804c282e299f01a3e747bccfaec4..b11f8631d946c60cc7bfa8313852d47ed5c8a632 100644 (file)
@@ -75,8 +75,7 @@ NodeImpl::NodeImpl(DocumentPtr *doc)
       m_focused( false ),
       m_active( false ),
       m_styleElement( false ),
-      m_implicit( false ),
-      m_rendererNeedsClose( false )
+      m_implicit( false )
 {
     if (document)
         document->ref();
@@ -1098,28 +1097,10 @@ void NodeImpl::dump(QTextStream *stream, QString ind) const
 }
 #endif
 
-void NodeImpl::closeRenderer()
-{
-    // It's important that we close the renderer, even if it hasn't been
-    // created yet. This happens even more because of the FOUC fixes we did
-    // at Apple, which prevent renderers from being created until the stylesheets
-    // are all loaded. If the renderer is not here to be closed, we set a flag,
-    // then close it later when it's attached.
-    assert(!m_rendererNeedsClose);
-    if (m_render)
-        m_render->close();
-    else
-        m_rendererNeedsClose = true;
-}
-
 void NodeImpl::attach()
 {
     assert(!attached());
     assert(!m_render || (m_render->style() && m_render->parent()));
-    if (m_render && m_rendererNeedsClose) {
-        m_render->close();
-        m_rendererNeedsClose = false;
-    }
     m_attached = true;
 }
 
@@ -1220,24 +1201,59 @@ RenderObject * NodeImpl::nextRenderer()
     return 0;
 }
 
+bool NodeImpl::isAtomicNode() const
+{
+    return !hasChildNodes() || (id() == ID_OBJECT && renderer() && renderer()->isReplaced());
+}
+
+NodeImpl *NodeImpl::previousNodeConsideringAtomicNodes() const
+{
+    if (previousSibling()) {
+        NodeImpl *n = previousSibling();
+        while (!n->isAtomicNode() && n->lastChild())
+            n = n->lastChild();
+        return n;
+    }
+    else if (parentNode()) {
+        return parentNode();
+    }
+    else {
+        return 0;
+    }
+}
+
+NodeImpl *NodeImpl::nextNodeConsideringAtomicNodes() const
+{
+    if (!isAtomicNode() && firstChild())
+       return firstChild();
+    if (nextSibling())
+       return nextSibling();
+    const NodeImpl *n = this;
+    while (n && !n->nextSibling())
+        n = n->parentNode();
+    if (n)
+        return n->nextSibling();
+    return 0;
+}
+
 NodeImpl *NodeImpl::previousLeafNode() const
 {
-    NodeImpl *node = traversePreviousNode();
+    NodeImpl *node = previousNodeConsideringAtomicNodes();
     while (node) {
-        if (!node->hasChildNodes())
+        if (node->isAtomicNode())
             return node;
-        node = node->traversePreviousNode();
+        node = node->previousNodeConsideringAtomicNodes();
     }
     return 0;
 }
 
 NodeImpl *NodeImpl::nextLeafNode() const
 {
-    NodeImpl *node = traverseNextNode();
+    NodeImpl *node = nextNodeConsideringAtomicNodes();
     while (node) {
-        if (!node->hasChildNodes())
+        if (node->isAtomicNode())
             return node;
-        node = node->traverseNextNode();
+        node = node->nextNodeConsideringAtomicNodes();
     }
     return 0;
 }
index 8175804152f31ec6eb64f0db56a5e1559b9af3ec..7a3a62ded962d98d4b1926928fe19a3f190306f9 100644 (file)
@@ -144,6 +144,10 @@ public:
     virtual void setFirstChild(NodeImpl *child);
     virtual void setLastChild(NodeImpl *child);
 
+    bool isAtomicNode() const;
+    NodeImpl *previousNodeConsideringAtomicNodes() const;
+    NodeImpl *nextNodeConsideringAtomicNodes() const;
+    
     /** (Not part of the official DOM)
      * Returns the next leaf node.
      *
@@ -371,8 +375,6 @@ public:
      */
     virtual void detach();
 
-    void closeRenderer();
-
     void createRendererIfNeeded();
     virtual khtml::RenderStyle *styleForRenderer(khtml::RenderObject *parent);
     virtual bool rendererIsNeeded(khtml::RenderStyle *);
@@ -466,9 +468,8 @@ protected:
     bool m_active : 1;
     bool m_styleElement : 1; // contains stylesheet text
     bool m_implicit : 1; // implicitely generated by the parser
-    bool m_rendererNeedsClose : 1;
 
-    // 1 bit unused
+    // 3 bits unused
 };
 
 // this is the full Node Implementation with parents and children.
index 5d9c8c3aca49d07164508c767a5743570f6ad06a..46fd376546990f68e593f4bc688c66ce08befb47 100644 (file)
@@ -596,7 +596,7 @@ Position Position::equivalentShallowPosition() const
 
 Position Position::equivalentDeepPosition() const
 {
-    if (isEmpty() || !node()->hasChildNodes())
+    if (isEmpty() || node()->isAtomicNode())
         return *this;
 
     NodeImpl *child = 0;
@@ -606,7 +606,7 @@ Position Position::equivalentDeepPosition() const
         child = node()->childNode(offset());
     ASSERT(child);
     Position pos(child, 0);
-    while (pos.node()->hasChildNodes()) {
+    while (!child->isAtomicNode() && pos.node()->hasChildNodes()) {
         child = pos.node()->firstChild();
         ASSERT(child);
         pos = Position(child, 0);
index 8a4cbf2fab38a2225fd7e0c27b77b17251ea5e35..ef7aa1a4a592623dd63ac3dfe4a23251ead268b0 100644 (file)
@@ -323,7 +323,6 @@ void XMLTokenizer::endElement()
     if (m_currentNode->nodeType() == Node::TEXT_NODE)
         exitText();
     if (m_currentNode->parentNode() != 0) {
-        m_currentNode->closeRenderer();
         do {
             m_currentNode = m_currentNode->parentNode();
         } while (m_currentNode && m_currentNode->implicitNode());