Title: [96084] trunk/Source/WebCore
Revision
96084
Author
[email protected]
Date
2011-09-27 02:00:08 -0700 (Tue, 27 Sep 2011)

Log Message

Encapsulate m_firstNodeInserted and m_lastLeafInserted in node insertion logic
https://bugs.webkit.org/show_bug.cgi?id=68875

Reviewed by Kent Tamura.

Added InsertedNode class inside ReplaceSelection to encapsulate m_firstNodeInserted and m_lastLeafInserted.
Deployed it in removeRedundantStylesAndKeepStyleSpanInline, doApply, and insertAsListItems of ReplaceSelectionCommand.

* editing/DeleteSelectionCommand.cpp:
(WebCore::DeleteSelectionCommand::removeNode):
(WebCore::DeleteSelectionCommand::handleGeneralDelete):
* editing/ReplaceSelectionCommand.cpp:
(WebCore::ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline):
(WebCore::ReplaceSelectionCommand::doApply):
(WebCore::ReplaceSelectionCommand::insertAsListItems):
* editing/ReplaceSelectionCommand.h:
(WebCore::ReplaceSelectionCommand::InsertedNodes::respondToNodeInsertion):
(WebCore::ReplaceSelectionCommand::InsertedNodes::willRemoveNode):
(WebCore::ReplaceSelectionCommand::InsertedNodes::firstNodeInserted):
(WebCore::ReplaceSelectionCommand::InsertedNodes::lastLeafInserted):
(WebCore::ReplaceSelectionCommand::InsertedNodes::pastLastLeaf):
* editing/htmlediting.cpp:
(WebCore::updatePositionForNodeRemoval): Moved from DeleteSelectionCommand.cpp.
* editing/htmlediting.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (96083 => 96084)


--- trunk/Source/WebCore/ChangeLog	2011-09-27 08:56:26 UTC (rev 96083)
+++ trunk/Source/WebCore/ChangeLog	2011-09-27 09:00:08 UTC (rev 96084)
@@ -1,3 +1,30 @@
+2011-09-27  Ryosuke Niwa  <[email protected]>
+
+        Encapsulate m_firstNodeInserted and m_lastLeafInserted in node insertion logic
+        https://bugs.webkit.org/show_bug.cgi?id=68875
+
+        Reviewed by Kent Tamura.
+
+        Added InsertedNode class inside ReplaceSelection to encapsulate m_firstNodeInserted and m_lastLeafInserted.
+        Deployed it in removeRedundantStylesAndKeepStyleSpanInline, doApply, and insertAsListItems of ReplaceSelectionCommand.
+
+        * editing/DeleteSelectionCommand.cpp:
+        (WebCore::DeleteSelectionCommand::removeNode):
+        (WebCore::DeleteSelectionCommand::handleGeneralDelete):
+        * editing/ReplaceSelectionCommand.cpp:
+        (WebCore::ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline):
+        (WebCore::ReplaceSelectionCommand::doApply):
+        (WebCore::ReplaceSelectionCommand::insertAsListItems):
+        * editing/ReplaceSelectionCommand.h:
+        (WebCore::ReplaceSelectionCommand::InsertedNodes::respondToNodeInsertion):
+        (WebCore::ReplaceSelectionCommand::InsertedNodes::willRemoveNode):
+        (WebCore::ReplaceSelectionCommand::InsertedNodes::firstNodeInserted):
+        (WebCore::ReplaceSelectionCommand::InsertedNodes::lastLeafInserted):
+        (WebCore::ReplaceSelectionCommand::InsertedNodes::pastLastLeaf):
+        * editing/htmlediting.cpp:
+        (WebCore::updatePositionForNodeRemoval): Moved from DeleteSelectionCommand.cpp.
+        * editing/htmlediting.h:
+
 2011-09-27  Arun Patole  <[email protected]>
 
         Audio element doesn't emit the 'playing' event every time it starts playing, after it has finished playing.

Modified: trunk/Source/WebCore/editing/DeleteSelectionCommand.cpp (96083 => 96084)


--- trunk/Source/WebCore/editing/DeleteSelectionCommand.cpp	2011-09-27 08:56:26 UTC (rev 96083)
+++ trunk/Source/WebCore/editing/DeleteSelectionCommand.cpp	2011-09-27 09:00:08 UTC (rev 96084)
@@ -314,36 +314,6 @@
     return false;
 }
 
-static void updatePositionForNodeRemoval(Node* node, Position& position)
-{
-    if (position.isNull())
-        return;
-    switch (position.anchorType()) {
-    case Position::PositionIsBeforeChildren:
-        if (position.containerNode() == node)
-            position = positionInParentBeforeNode(node);
-        break;
-    case Position::PositionIsAfterChildren:
-        if (position.containerNode() == node)
-            position = positionInParentAfterNode(node);
-        break;
-    case Position::PositionIsOffsetInAnchor:
-        if (position.containerNode() == node->parentNode() && static_cast<unsigned>(position.offsetInContainerNode()) > node->nodeIndex())
-            position.moveToOffset(position.offsetInContainerNode() - 1);
-        else if (node->contains(position.containerNode()))
-            position = positionInParentBeforeNode(node);
-        break;
-    case Position::PositionIsAfterAnchor:
-        if (node->contains(position.anchorNode()))
-            position = positionInParentAfterNode(node);
-        break;
-    case Position::PositionIsBeforeAnchor:
-        if (node->contains(position.anchorNode()))
-            position = positionInParentBeforeNode(node);
-        break;
-    }
-}
-
 static Position firstEditablePositionInNode(Node* node)
 {
     ASSERT(node);
@@ -407,9 +377,9 @@
         m_needPlaceholder = true;
     
     // FIXME: Update the endpoints of the range being deleted.
-    updatePositionForNodeRemoval(node.get(), m_endingPosition);
-    updatePositionForNodeRemoval(node.get(), m_leadingWhitespace);
-    updatePositionForNodeRemoval(node.get(), m_trailingWhitespace);
+    updatePositionForNodeRemoval(m_endingPosition, node.get());
+    updatePositionForNodeRemoval(m_leadingWhitespace, node.get());
+    updatePositionForNodeRemoval(m_trailingWhitespace, node.get());
     
     CompositeEditCommand::removeNode(node);
 }
@@ -506,7 +476,7 @@
                 RefPtr<Node> nextNode = node->traverseNextSibling();
                 // if we just removed a node from the end container, update end position so the
                 // check above will work
-                updatePositionForNodeRemoval(node.get(), m_downstreamEnd);
+                updatePositionForNodeRemoval(m_downstreamEnd, node.get());
                 removeNode(node.get());
                 node = nextNode.get();
             } else {

Modified: trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp (96083 => 96084)


--- trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp	2011-09-27 08:56:26 UTC (rev 96083)
+++ trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp	2011-09-27 09:00:08 UTC (rev 96084)
@@ -347,6 +347,25 @@
     }
 }
 
+inline void ReplaceSelectionCommand::InsertedNodes::respondToNodeInsertion(Node* node)
+{
+    if (!node)
+        return;
+    
+    if (!m_firstNodeInserted)
+        m_firstNodeInserted = node;
+    
+    m_lastNodeInserted = node;
+}
+
+inline void ReplaceSelectionCommand::InsertedNodes::willRemoveNode(Node* node)
+{
+    if (m_firstNodeInserted == node)
+        m_firstNodeInserted = node->traverseNextNode();
+    if (m_lastNodeInserted == node)
+        m_lastNodeInserted = node->lastChild() ? node->lastChild() : node->traverseNextSibling();
+}
+
 ReplaceSelectionCommand::ReplaceSelectionCommand(Document* document, PassRefPtr<DocumentFragment> fragment, CommandOptions options, EditAction editAction)
     : CompositeEditCommand(document)
     , m_selectReplacement(options & SelectReplacement)
@@ -476,11 +495,11 @@
 
 // Style rules that match just inserted elements could change their appearance, like
 // a div inserted into a document with div { display:inline; }.
-void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline()
+void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(InsertedNodes& insertedNodes)
 {
-    RefPtr<Node> pastEndNode = m_lastLeafInserted ? m_lastLeafInserted->traverseNextNode() : 0;
+    RefPtr<Node> pastEndNode = insertedNodes.pastLastLeaf();
     RefPtr<Node> next;
-    for (RefPtr<Node> node = m_firstNodeInserted.get(); node && node != pastEndNode; node = next) {
+    for (RefPtr<Node> node = insertedNodes.firstNodeInserted(); node && node != pastEndNode; node = next) {
         // FIXME: <rdar://problem/5371536> Style rules that match pasted content can change it's appearance
 
         next = node->traverseNextNode();
@@ -504,9 +523,10 @@
         }
 
         if (!inlineStyle || newInlineStyle->isEmpty()) {
-            if (isStyleSpanOrSpanWithOnlyStyleAttribute(element))
+            if (isStyleSpanOrSpanWithOnlyStyleAttribute(element)) {
+                insertedNodes.willRemoveNode(element);
                 removeNodePreservingChildren(element);
-            else
+            } else
                 removeNodeAttribute(element, styleAttr);
         } else if (newInlineStyle->style()->length() != inlineStyle->length())
             setNodeAttribute(element, styleAttr, newInlineStyle->style()->cssText());
@@ -515,6 +535,7 @@
         // Keep this code around for backward compatibility
         if (isLegacyAppleStyleSpan(element)) {
             if (!element->firstChild()) {
+                insertedNodes.willRemoveNode(element);
                 removeNodePreservingChildren(element);
                 continue;
             }
@@ -552,7 +573,7 @@
     
     // We don't have to make sure that m_firstNodeInserted isn't inside a select or script element, because
     // it is a top level node in the fragment and the user can't insert into those elements.
-    if (!m_firstNodeInserted->renderer() && 
+    if (!m_firstNodeInserted->renderer() &&
         m_firstNodeInserted->isTextNode()) {
         if (m_firstNodeInserted == m_lastLeafInserted) {
             removeNode(m_firstNodeInserted.get());
@@ -803,7 +824,7 @@
 
     return EditingStyle::elementIsStyledSpanOrHTMLEquivalent(element);
 }
-    
+
 void ReplaceSelectionCommand::doApply()
 {
     VisibleSelection selection = endingSelection();
@@ -986,7 +1007,8 @@
     // 6) Select the replacement if requested, and match style if requested.
     
     VisiblePosition startOfInsertedContent, endOfInsertedContent;
-    
+
+    InsertedNodes insertedNodes;
     RefPtr<Node> refNode = fragment.firstChild();
     RefPtr<Node> node = refNode->nextSibling();
     
@@ -995,9 +1017,11 @@
     Node* blockStart = enclosingBlock(insertionPos.deprecatedNode());
     if ((isListElement(refNode.get()) || (isLegacyAppleStyleSpan(refNode.get()) && isListElement(refNode->firstChild())))
         && blockStart && blockStart->renderer()->isListItem())
-        refNode = insertAsListItems(refNode, blockStart, insertionPos);
-    else
-        insertNodeAtAndUpdateNodesInserted(refNode, insertionPos);
+        refNode = insertAsListItems(refNode, blockStart, insertionPos, insertedNodes);
+    else {
+        insertNodeAt(refNode, insertionPos);
+        insertedNodes.respondToNodeInsertion(refNode.get());
+    }
 
     // Mutation events (bug 22634) may have already removed the inserted content
     if (!refNode->inDocument())
@@ -1008,7 +1032,8 @@
     while (node) {
         RefPtr<Node> next = node->nextSibling();
         fragment.removeNode(node.get());
-        insertNodeAfterAndUpdateNodesInserted(node, refNode.get());
+        insertNodeAfter(node, refNode.get());
+        insertedNodes.respondToNodeInsertion(node.get());
 
         // Mutation events (bug 22634) may have already removed the inserted content
         if (!node->inDocument())
@@ -1019,11 +1044,14 @@
             plainTextFragment = isPlainTextMarkup(node.get());
         node = next;
     }
-    
+
+    removeRedundantStylesAndKeepStyleSpanInline(insertedNodes);
+
+    m_firstNodeInserted = insertedNodes.firstNodeInserted();
+    m_lastLeafInserted = insertedNodes.lastLeafInserted();
+
     removeUnrenderedTextNodesAtEnds();
-    
-    removeRedundantStylesAndKeepStyleSpanInline();
-    
+
     if (!handledStyleSpans)
         handleStyleSpans();
     
@@ -1137,7 +1165,8 @@
                 insertTextIntoNode(text, text->length(), collapseWhiteSpace ? nonBreakingSpaceString() : " ");
             } else {
                 RefPtr<Node> node = document()->createEditingTextNode(collapseWhiteSpace ? nonBreakingSpaceString() : " ");
-                insertNodeAfterAndUpdateNodesInserted(node, endNode);
+                insertNodeAfter(node, endNode);
+                updateNodesInserted(node.get());
             }
         }
     
@@ -1227,30 +1256,9 @@
     return m_editAction;
 }
 
-void ReplaceSelectionCommand::insertNodeAfterAndUpdateNodesInserted(PassRefPtr<Node> insertChild, Node* refChild)
-{
-    Node* nodeToUpdate = insertChild.get(); // insertChild will be cleared when passed
-    insertNodeAfter(insertChild, refChild);
-    updateNodesInserted(nodeToUpdate);
-}
-
-void ReplaceSelectionCommand::insertNodeAtAndUpdateNodesInserted(PassRefPtr<Node> insertChild, const Position& p)
-{
-    Node* nodeToUpdate = insertChild.get(); // insertChild will be cleared when passed
-    insertNodeAt(insertChild, p);
-    updateNodesInserted(nodeToUpdate);
-}
-
-void ReplaceSelectionCommand::insertNodeBeforeAndUpdateNodesInserted(PassRefPtr<Node> insertChild, Node* refChild)
-{
-    Node* nodeToUpdate = insertChild.get(); // insertChild will be cleared when passed
-    insertNodeBefore(insertChild, refChild);
-    updateNodesInserted(nodeToUpdate);
-}
-
 // If the user is inserting a list into an existing list, instead of nesting the list,
 // we put the list items into the existing list.
-Node* ReplaceSelectionCommand::insertAsListItems(PassRefPtr<Node> prpListElement, Node* insertionBlock, const Position& insertPos)
+Node* ReplaceSelectionCommand::insertAsListItems(PassRefPtr<Node> prpListElement, Node* insertionBlock, const Position& insertPos, InsertedNodes& insertedNodes)
 {
     RefPtr<Node> listElement = prpListElement;
 
@@ -1275,10 +1283,12 @@
         ExceptionCode ec = 0;
         toContainerNode(listElement.get())->removeChild(listItem.get(), ec);
         ASSERT(!ec);
-        if (isStart || isMiddle)
+        if (isStart || isMiddle) {
             insertNodeBefore(listItem, lastNode);
-        else if (isEnd) {
+            insertedNodes.respondToNodeInsertion(listItem.get());
+        } else if (isEnd) {
             insertNodeAfter(listItem, lastNode);
+            insertedNodes.respondToNodeInsertion(listItem.get());
             lastNode = listItem.get();
         } else
             ASSERT_NOT_REACHED();
@@ -1287,7 +1297,6 @@
         lastNode = lastNode->previousSibling();
     if (isMiddle)
         insertNodeAfter(createListItemElement(document()), lastNode);
-    updateNodesInserted(lastNode);
     return lastNode;
 }
 

Modified: trunk/Source/WebCore/editing/ReplaceSelectionCommand.h (96083 => 96084)


--- trunk/Source/WebCore/editing/ReplaceSelectionCommand.h	2011-09-27 08:56:26 UTC (rev 96083)
+++ trunk/Source/WebCore/editing/ReplaceSelectionCommand.h	2011-09-27 09:00:08 UTC (rev 96084)
@@ -60,12 +60,22 @@
     virtual EditAction editingAction() const;
 
     void completeHTMLReplacement(const Position& lastPositionToSelect);
+    
+    class InsertedNodes {
+    public:
+        void respondToNodeInsertion(Node* node);
+        void willRemoveNode(Node* node);
+        Node* firstNodeInserted() const { return m_firstNodeInserted.get(); }
+        Node* lastLeafInserted() const { return m_lastNodeInserted->lastDescendant(); }
+        Node* pastLastLeaf() const { return m_firstNodeInserted ? lastLeafInserted()->traverseNextNode() : 0; }
 
-    void insertNodeAfterAndUpdateNodesInserted(PassRefPtr<Node> insertChild, Node* refChild);
-    void insertNodeAtAndUpdateNodesInserted(PassRefPtr<Node>, const Position&);
-    void insertNodeBeforeAndUpdateNodesInserted(PassRefPtr<Node> insertChild, Node* refChild);
-    Node* insertAsListItems(PassRefPtr<Node>, Node* insertionNode, const Position&);
+    private:
+        RefPtr<Node> m_firstNodeInserted;
+        RefPtr<Node> m_lastNodeInserted;
+    };
 
+    Node* insertAsListItems(PassRefPtr<Node>, Node* insertionNode, const Position&, InsertedNodes&);
+
     void updateNodesInserted(Node*);
     bool shouldRemoveEndBR(Node*, const VisiblePosition&);
     
@@ -77,7 +87,7 @@
     
     void removeUnrenderedTextNodesAtEnds();
     
-    void removeRedundantStylesAndKeepStyleSpanInline();
+    void removeRedundantStylesAndKeepStyleSpanInline(InsertedNodes&);
     void handleStyleSpans();
     void copyStyleToChildren(Node* parentNode, const CSSMutableStyleDeclaration* parentStyle);
     void handlePasteAsQuotationNode();

Modified: trunk/Source/WebCore/editing/htmlediting.cpp (96083 => 96084)


--- trunk/Source/WebCore/editing/htmlediting.cpp	2011-09-27 08:56:26 UTC (rev 96083)
+++ trunk/Source/WebCore/editing/htmlediting.cpp	2011-09-27 09:00:08 UTC (rev 96084)
@@ -923,6 +923,36 @@
     return num;
 }
 
+void updatePositionForNodeRemoval(Position& position, Node* node)
+{
+    if (position.isNull())
+        return;
+    switch (position.anchorType()) {
+    case Position::PositionIsBeforeChildren:
+        if (position.containerNode() == node)
+            position = positionInParentBeforeNode(node);
+        break;
+    case Position::PositionIsAfterChildren:
+        if (position.containerNode() == node)
+            position = positionInParentAfterNode(node);
+        break;
+    case Position::PositionIsOffsetInAnchor:
+        if (position.containerNode() == node->parentNode() && static_cast<unsigned>(position.offsetInContainerNode()) > node->nodeIndex())
+            position.moveToOffset(position.offsetInContainerNode() - 1);
+        else if (node->contains(position.containerNode()))
+            position = positionInParentBeforeNode(node);
+        break;
+    case Position::PositionIsAfterAnchor:
+        if (node->contains(position.anchorNode()))
+            position = positionInParentAfterNode(node);
+        break;
+    case Position::PositionIsBeforeAnchor:
+        if (node->contains(position.anchorNode()))
+            position = positionInParentBeforeNode(node);
+        break;
+    }
+}
+
 bool isMailBlockquote(const Node *node)
 {
     if (!node || !node->hasTagName(blockquoteTag))

Modified: trunk/Source/WebCore/editing/htmlediting.h (96083 => 96084)


--- trunk/Source/WebCore/editing/htmlediting.h	2011-09-27 08:56:26 UTC (rev 96083)
+++ trunk/Source/WebCore/editing/htmlediting.h	2011-09-27 09:00:08 UTC (rev 96084)
@@ -159,6 +159,7 @@
 // miscellaneous functions on Position
 
 unsigned numEnclosingMailBlockquotes(const Position&);
+void updatePositionForNodeRemoval(Position&, Node*);
 
 // -------------------------------------------------------------------------
 // VisiblePosition
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to