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();