Index: Source/core/editing/ReplaceSelectionCommand.cpp |
diff --git a/Source/core/editing/ReplaceSelectionCommand.cpp b/Source/core/editing/ReplaceSelectionCommand.cpp |
index 3980379427ed3f56d5633071b8aca6f6f1b0b343..d4cf82ff5627b03daf140f65e103462bbe104915 100644 |
--- a/Source/core/editing/ReplaceSelectionCommand.cpp |
+++ b/Source/core/editing/ReplaceSelectionCommand.cpp |
@@ -53,6 +53,8 @@ |
#include "core/html/HTMLElement.h" |
#include "core/html/HTMLInputElement.h" |
#include "core/html/HTMLLIElement.h" |
+#include "core/html/HTMLQuoteElement.h" |
+#include "core/html/HTMLSelectElement.h" |
#include "core/html/HTMLSpanElement.h" |
#include "core/rendering/RenderObject.h" |
#include "core/rendering/RenderText.h" |
@@ -82,13 +84,13 @@ public: |
bool hasInterchangeNewlineAtEnd() const { return m_hasInterchangeNewlineAtEnd; } |
void removeNode(PassRefPtrWillBeRawPtr<Node>); |
- void removeNodePreservingChildren(PassRefPtrWillBeRawPtr<Node>); |
+ void removeNodePreservingChildren(PassRefPtrWillBeRawPtr<ContainerNode>); |
private: |
- PassRefPtrWillBeRawPtr<Element> insertFragmentForTestRendering(Node* rootEditableNode); |
- void removeUnrenderedNodes(Node*); |
+ PassRefPtrWillBeRawPtr<HTMLElement> insertFragmentForTestRendering(Element* rootEditableElement); |
+ void removeUnrenderedNodes(ContainerNode*); |
void restoreAndRemoveTestRenderingNodesToFragment(Element*); |
- void removeInterchangeNodes(Node*); |
+ void removeInterchangeNodes(ContainerNode*); |
void insertNodeBefore(PassRefPtrWillBeRawPtr<Node>, Node* refNode); |
@@ -98,16 +100,16 @@ private: |
bool m_hasInterchangeNewlineAtEnd; |
}; |
-static bool isInterchangeNewlineNode(const Node *node) |
+static bool isInterchangeHTMLBRElement(const Node* node) |
{ |
DEFINE_STATIC_LOCAL(String, interchangeNewlineClassString, (AppleInterchangeNewline)); |
- if (!isHTMLBRElement(node) || toElement(node)->getAttribute(classAttr) != interchangeNewlineClassString) |
+ if (!isHTMLBRElement(node) || toHTMLBRElement(node)->getAttribute(classAttr) != interchangeNewlineClassString) |
return false; |
UseCounter::count(node->document(), UseCounter::EditingAppleInterchangeNewline); |
return true; |
} |
-static bool isInterchangeConvertedSpaceSpan(const Node *node) |
+static bool isHTMLInterchangeConvertedSpaceSpan(const Node* node) |
{ |
DEFINE_STATIC_LOCAL(String, convertedSpaceSpanClassString, (AppleConvertedSpace)); |
if (!node->isHTMLElement() || toHTMLElement(node)->getAttribute(classAttr) != convertedSpaceSpanClassString) |
@@ -126,8 +128,8 @@ static Position positionAvoidingPrecedingNodes(Position pos) |
// same. E.g., |
// <div>foo^</div>^ |
// The two positions above are the same visual position, but we want to stay in the same block. |
- Node* enclosingBlockNode = enclosingBlock(pos.containerNode()); |
- for (Position nextPosition = pos; nextPosition.containerNode() != enclosingBlockNode; pos = nextPosition) { |
+ Element* enclosingBlockElement = enclosingBlock(pos.containerNode()); |
+ for (Position nextPosition = pos; nextPosition.containerNode() != enclosingBlockElement; pos = nextPosition) { |
if (lineBreakExistsAtPosition(pos)) |
break; |
@@ -135,7 +137,7 @@ static Position positionAvoidingPrecedingNodes(Position pos) |
nextPosition = positionInParentAfterNode(*pos.containerNode()); |
if (nextPosition == pos |
- || enclosingBlock(nextPosition.containerNode()) != enclosingBlockNode |
+ || enclosingBlock(nextPosition.containerNode()) != enclosingBlockElement |
|| VisiblePosition(pos) != VisiblePosition(nextPosition)) |
break; |
} |
@@ -158,21 +160,21 @@ ReplacementFragment::ReplacementFragment(Document* document, DocumentFragment* f |
if (!editableRoot) |
return; |
- Node* shadowAncestorNode; |
+ Element* shadowAncestorElement; |
if (editableRoot->isInShadowTree()) |
- shadowAncestorNode = editableRoot->shadowHost(); |
+ shadowAncestorElement = editableRoot->shadowHost(); |
else |
- shadowAncestorNode = editableRoot.get(); |
+ shadowAncestorElement = editableRoot.get(); |
- if (!editableRoot->getAttributeEventListener(EventTypeNames::webkitBeforeTextInserted) && |
+ if (!editableRoot->getAttributeEventListener(EventTypeNames::webkitBeforeTextInserted) |
// FIXME: Remove these checks once textareas and textfields actually register an event handler. |
- !(shadowAncestorNode && shadowAncestorNode->renderer() && shadowAncestorNode->renderer()->isTextControl()) && |
- editableRoot->rendererIsRichlyEditable()) { |
+ && !(shadowAncestorElement && shadowAncestorElement->renderer() && shadowAncestorElement->renderer()->isTextControl()) |
+ && editableRoot->rendererIsRichlyEditable()) { |
removeInterchangeNodes(m_fragment.get()); |
return; |
} |
- RefPtrWillBeRawPtr<Element> holder = insertFragmentForTestRendering(editableRoot.get()); |
+ RefPtrWillBeRawPtr<HTMLElement> holder = insertFragmentForTestRendering(editableRoot.get()); |
if (!holder) { |
removeInterchangeNodes(m_fragment.get()); |
return; |
@@ -207,17 +209,17 @@ bool ReplacementFragment::isEmpty() const |
return (!m_fragment || !m_fragment->hasChildren()) && !m_hasInterchangeNewlineAtStart && !m_hasInterchangeNewlineAtEnd; |
} |
-Node *ReplacementFragment::firstChild() const |
+Node* ReplacementFragment::firstChild() const |
{ |
return m_fragment ? m_fragment->firstChild() : 0; |
} |
-Node *ReplacementFragment::lastChild() const |
+Node* ReplacementFragment::lastChild() const |
{ |
return m_fragment ? m_fragment->lastChild() : 0; |
} |
-void ReplacementFragment::removeNodePreservingChildren(PassRefPtrWillBeRawPtr<Node> node) |
+void ReplacementFragment::removeNodePreservingChildren(PassRefPtrWillBeRawPtr<ContainerNode> node) |
{ |
if (!node) |
return; |
@@ -253,10 +255,10 @@ void ReplacementFragment::insertNodeBefore(PassRefPtrWillBeRawPtr<Node> node, No |
parent->insertBefore(node, refNode); |
} |
-PassRefPtrWillBeRawPtr<Element> ReplacementFragment::insertFragmentForTestRendering(Node* rootEditableElement) |
+PassRefPtrWillBeRawPtr<HTMLElement> ReplacementFragment::insertFragmentForTestRendering(Element* rootEditableElement) |
{ |
ASSERT(m_document); |
- RefPtrWillBeRawPtr<Element> holder = createDefaultParagraphElement(*m_document.get()); |
+ RefPtrWillBeRawPtr<HTMLElement> holder = createDefaultParagraphElement(*m_document.get()); |
holder->appendChild(m_fragment); |
rootEditableElement->appendChild(holder.get()); |
@@ -278,7 +280,7 @@ void ReplacementFragment::restoreAndRemoveTestRenderingNodesToFragment(Element* |
removeNode(holder); |
} |
-void ReplacementFragment::removeUnrenderedNodes(Node* holder) |
+void ReplacementFragment::removeUnrenderedNodes(ContainerNode* holder) |
{ |
WillBeHeapVector<RefPtrWillBeMember<Node> > unrendered; |
@@ -291,7 +293,7 @@ void ReplacementFragment::removeUnrenderedNodes(Node* holder) |
removeNode(unrendered[i]); |
} |
-void ReplacementFragment::removeInterchangeNodes(Node* container) |
+void ReplacementFragment::removeInterchangeNodes(ContainerNode* container) |
{ |
m_hasInterchangeNewlineAtStart = false; |
m_hasInterchangeNewlineAtEnd = false; |
@@ -300,7 +302,7 @@ void ReplacementFragment::removeInterchangeNodes(Node* container) |
// either the first node in the fragment or the first leaf in the fragment. |
Node* node = container->firstChild(); |
while (node) { |
- if (isInterchangeNewlineNode(node)) { |
+ if (isInterchangeHTMLBRElement(node)) { |
m_hasInterchangeNewlineAtStart = true; |
removeNode(node); |
break; |
@@ -313,7 +315,7 @@ void ReplacementFragment::removeInterchangeNodes(Node* container) |
// either the last node in the fragment or the last leaf in the fragment. |
node = container->lastChild(); |
while (node) { |
- if (isInterchangeNewlineNode(node)) { |
+ if (isInterchangeHTMLBRElement(node)) { |
m_hasInterchangeNewlineAtEnd = true; |
removeNode(node); |
break; |
@@ -324,9 +326,10 @@ void ReplacementFragment::removeInterchangeNodes(Node* container) |
node = container->firstChild(); |
while (node) { |
RefPtrWillBeRawPtr<Node> next = NodeTraversal::next(*node); |
- if (isInterchangeConvertedSpaceSpan(node)) { |
- next = NodeTraversal::nextSkippingChildren(*node); |
- removeNodePreservingChildren(node); |
+ if (isHTMLInterchangeConvertedSpaceSpan(node)) { |
+ HTMLElement& element = toHTMLElement(*node); |
+ next = NodeTraversal::nextSkippingChildren(element); |
+ removeNodePreservingChildren(&element); |
} |
node = next.get(); |
} |
@@ -428,15 +431,18 @@ bool ReplaceSelectionCommand::shouldMergeEnd(bool selectionEndWasEndOfParagraph) |
&& shouldMerge(endOfInsertedContent, next); |
} |
-static bool isMailPasteAsQuotationNode(const Node* node) |
+static bool isMailPasteAsQuotationHTMLBlockQuoteElement(const Node* node) |
{ |
- if (!node || !node->hasTagName(blockquoteTag) || toElement(node)->getAttribute(classAttr) != ApplePasteAsQuotation) |
+ if (!node || !node->isHTMLElement()) |
+ return false; |
+ const HTMLElement& element = toHTMLElement(*node); |
+ if (!element.hasTagName(blockquoteTag) || element.getAttribute(classAttr) != ApplePasteAsQuotation) |
return false; |
UseCounter::count(node->document(), UseCounter::EditingApplePasteAsQuotation); |
return true; |
} |
-static bool isHeaderElement(const Node* a) |
+static bool isHTMLHeaderElement(const Node* a) |
{ |
if (!a || !a->isHTMLElement()) |
return false; |
@@ -450,9 +456,9 @@ static bool isHeaderElement(const Node* a) |
|| element.hasTagName(h6Tag); |
} |
-static bool haveSameTagName(Node* a, Node* b) |
+static bool haveSameTagName(Element* a, Element* b) |
{ |
- return a && b && a->isElementNode() && b->isElementNode() && toElement(a)->tagName() == toElement(b)->tagName(); |
+ return a && b && a->tagName() == b->tagName(); |
} |
bool ReplaceSelectionCommand::shouldMerge(const VisiblePosition& source, const VisiblePosition& destination) |
@@ -464,11 +470,11 @@ bool ReplaceSelectionCommand::shouldMerge(const VisiblePosition& source, const V |
Node* destinationNode = destination.deepEquivalent().deprecatedNode(); |
Element* sourceBlock = enclosingBlock(sourceNode); |
Element* destinationBlock = enclosingBlock(destinationNode); |
- return !enclosingNodeOfType(source.deepEquivalent(), &isMailPasteAsQuotationNode) |
+ return !enclosingNodeOfType(source.deepEquivalent(), &isMailPasteAsQuotationHTMLBlockQuoteElement) |
&& sourceBlock && (!sourceBlock->hasTagName(blockquoteTag) || isMailHTMLBlockquoteElement(sourceBlock)) |
&& enclosingListChild(sourceBlock) == enclosingListChild(destinationNode) |
&& enclosingTableCell(source.deepEquivalent()) == enclosingTableCell(destination.deepEquivalent()) |
- && (!isHeaderElement(sourceBlock) || haveSameTagName(sourceBlock, destinationBlock)) |
+ && (!isHTMLHeaderElement(sourceBlock) || haveSameTagName(sourceBlock, destinationBlock)) |
// Don't merge to or from a position before or after a block because it would |
// be a no-op and cause infinite recursion. |
&& !isBlock(sourceNode) && !isBlock(destinationNode); |
@@ -506,7 +512,7 @@ void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(Insert |
EditingStyle::DoNotExtractMatchingStyle)) { |
// e.g. <font size="3" style="font-size: 20px;"> is converted to <font style="font-size: 20px;"> |
for (size_t i = 0; i < attributes.size(); i++) |
- removeNodeAttribute(element, attributes[i]); |
+ removeElementAttribute(htmlElement, attributes[i]); |
} |
} |
@@ -514,8 +520,10 @@ void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(Insert |
// If Mail wraps the fragment with a Paste as Quotation blockquote, or if you're pasting into a quoted region, |
// styles from blockquoteNode are allowed to override those from the source document, see <rdar://problem/4930986> and <rdar://problem/5089327>. |
- Node* blockquoteNode = !context || isMailPasteAsQuotationNode(context) ? context : enclosingNodeOfType(firstPositionInNode(context), isMailHTMLBlockquoteElement, CanCrossEditingBoundary); |
- if (blockquoteNode) |
+ HTMLQuoteElement* blockquoteElement = !context || isMailPasteAsQuotationHTMLBlockQuoteElement(context) ? |
+ toHTMLQuoteElement(context) : |
+ toHTMLQuoteElement(enclosingNodeOfType(firstPositionInNode(context), isMailHTMLBlockquoteElement, CanCrossEditingBoundary)); |
+ if (blockquoteElement) |
newInlineStyle->removeStyleFromRulesAndContext(element, document().documentElement()); |
newInlineStyle->removeStyleFromRulesAndContext(element, context); |
@@ -527,7 +535,7 @@ void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(Insert |
removeNodePreservingChildren(element); |
continue; |
} |
- removeNodeAttribute(element, styleAttr); |
+ removeElementAttribute(element, styleAttr); |
} else if (newInlineStyle->style()->propertyCount() != inlineStyle->propertyCount()) { |
setNodeAttribute(element, styleAttr, AtomicString(newInlineStyle->style()->asText())); |
} |
@@ -542,11 +550,11 @@ void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(Insert |
} |
if (element->parentNode() && element->parentNode()->rendererIsRichlyEditable()) |
- removeNodeAttribute(element, contenteditableAttr); |
+ removeElementAttribute(element, contenteditableAttr); |
// WebKit used to not add display: inline and float: none on copy. |
// Keep this code around for backward compatibility |
- if (isLegacyAppleStyleSpan(element)) { |
+ if (isLegacyAppleHTMLSpanElement(element)) { |
if (!element->hasChildren()) { |
insertedNodes.willRemoveNodePreservingChildren(*element); |
removeNodePreservingChildren(element); |
@@ -635,38 +643,39 @@ void ReplaceSelectionCommand::makeInsertedContentRoundTrippableWithHTMLTreeBuild |
if (!node->isHTMLElement()) |
continue; |
- if (isProhibitedParagraphChild(toHTMLElement(node)->localName())) { |
- if (HTMLElement* paragraphElement = toHTMLElement(enclosingElementWithTag(positionInParentBeforeNode(*node), pTag))) |
- moveNodeOutOfAncestor(node, paragraphElement); |
+ HTMLElement& element = toHTMLElement(*node); |
+ if (isProhibitedParagraphChild(element.localName())) { |
+ if (HTMLElement* paragraphElement = toHTMLElement(enclosingElementWithTag(positionInParentBeforeNode(element), pTag))) |
+ moveElementOutOfAncestor(&element, paragraphElement); |
} |
- if (isHeaderElement(node.get())) { |
- if (HTMLElement* headerElement = toHTMLElement(highestEnclosingNodeOfType(positionInParentBeforeNode(*node), isHeaderElement))) |
- moveNodeOutOfAncestor(node, headerElement); |
+ if (isHTMLHeaderElement(&element)) { |
+ if (HTMLElement* headerElement = toHTMLElement(highestEnclosingNodeOfType(positionInParentBeforeNode(element), isHTMLHeaderElement))) |
+ moveElementOutOfAncestor(&element, headerElement); |
} |
} |
} |
-void ReplaceSelectionCommand::moveNodeOutOfAncestor(PassRefPtrWillBeRawPtr<Node> prpNode, PassRefPtrWillBeRawPtr<ContainerNode> prpAncestor) |
+void ReplaceSelectionCommand::moveElementOutOfAncestor(PassRefPtrWillBeRawPtr<Element> prpElement, PassRefPtrWillBeRawPtr<ContainerNode> prpAncestor) |
{ |
- RefPtrWillBeRawPtr<Node> node = prpNode; |
- RefPtrWillBeRawPtr<Node> ancestor = prpAncestor; |
+ RefPtrWillBeRawPtr<Element> element = prpElement; |
+ RefPtrWillBeRawPtr<ContainerNode> ancestor = prpAncestor; |
if (!ancestor->parentNode()->hasEditableStyle()) |
return; |
- VisiblePosition positionAtEndOfNode(lastPositionInOrAfterNode(node.get())); |
+ VisiblePosition positionAtEndOfNode(lastPositionInOrAfterNode(element.get())); |
VisiblePosition lastPositionInParagraph(lastPositionInNode(ancestor.get())); |
if (positionAtEndOfNode == lastPositionInParagraph) { |
- removeNode(node); |
+ removeNode(element); |
if (ancestor->nextSibling()) |
- insertNodeBefore(node, ancestor->nextSibling()); |
+ insertNodeBefore(element, ancestor->nextSibling()); |
else |
- appendNode(node, ancestor->parentNode()); |
+ appendNode(element, ancestor->parentNode()); |
} else { |
- RefPtrWillBeRawPtr<Node> nodeToSplitTo = splitTreeToNode(node.get(), ancestor.get(), true); |
- removeNode(node); |
- insertNodeBefore(node, nodeToSplitTo); |
+ RefPtrWillBeRawPtr<Node> nodeToSplitTo = splitTreeToNode(element.get(), ancestor.get(), true); |
+ removeNode(element); |
+ insertNodeBefore(element, nodeToSplitTo); |
} |
if (!ancestor->hasChildren()) |
removeNode(ancestor.release()); |
@@ -701,7 +710,7 @@ void ReplaceSelectionCommand::removeUnrenderedTextNodesAtEnds(InsertedNodes& ins |
VisiblePosition ReplaceSelectionCommand::positionAtEndOfInsertedContent() const |
{ |
// FIXME: Why is this hack here? What's special about <select> tags? |
- Element* enclosingSelect = enclosingElementWithTag(m_endOfInsertedContent, selectTag); |
+ HTMLSelectElement* enclosingSelect = toHTMLSelectElement(enclosingElementWithTag(m_endOfInsertedContent, selectTag)); |
return VisiblePosition(enclosingSelect ? lastPositionInOrAfterNode(enclosingSelect) : m_endOfInsertedContent); |
} |
@@ -735,21 +744,21 @@ static bool handleStyleSpansBeforeInsertion(ReplacementFragment& fragment, const |
// Handling the case where we are doing Paste as Quotation or pasting into quoted content is more complicated (see handleStyleSpans) |
// and doesn't receive the optimization. |
- if (isMailPasteAsQuotationNode(topNode) || enclosingNodeOfType(firstPositionInOrBeforeNode(topNode), isMailHTMLBlockquoteElement, CanCrossEditingBoundary)) |
+ if (isMailPasteAsQuotationHTMLBlockQuoteElement(topNode) || enclosingNodeOfType(firstPositionInOrBeforeNode(topNode), isMailHTMLBlockquoteElement, CanCrossEditingBoundary)) |
return false; |
// Either there are no style spans in the fragment or a WebKit client has added content to the fragment |
// before inserting it. Look for and handle style spans after insertion. |
- if (!isLegacyAppleStyleSpan(topNode)) |
+ if (!isLegacyAppleHTMLSpanElement(topNode)) |
return false; |
- Node* wrappingStyleSpan = topNode; |
+ HTMLSpanElement* wrappingStyleSpan = toHTMLSpanElement(topNode); |
RefPtrWillBeRawPtr<EditingStyle> styleAtInsertionPos = EditingStyle::create(insertionPos.parentAnchoredEquivalent()); |
String styleText = styleAtInsertionPos->style()->asText(); |
// FIXME: This string comparison is a naive way of comparing two styles. |
// We should be taking the diff and check that the diff is empty. |
- if (styleText != toElement(wrappingStyleSpan)->getAttribute(styleAttr)) |
+ if (styleText != wrappingStyleSpan->getAttribute(styleAttr)) |
return false; |
fragment.removeNodePreservingChildren(wrappingStyleSpan); |
@@ -766,13 +775,13 @@ static bool handleStyleSpansBeforeInsertion(ReplacementFragment& fragment, const |
// or at copy time. |
void ReplaceSelectionCommand::handleStyleSpans(InsertedNodes& insertedNodes) |
{ |
- HTMLElement* wrappingStyleSpan = 0; |
+ HTMLSpanElement* wrappingStyleSpan = 0; |
// The style span that contains the source document's default style should be at |
// the top of the fragment, but Mail sometimes adds a wrapper (for Paste As Quotation), |
// so search for the top level style span instead of assuming it's at the top. |
for (Node* node = insertedNodes.firstNodeInserted(); node; node = NodeTraversal::next(*node)) { |
- if (isLegacyAppleStyleSpan(node)) { |
- wrappingStyleSpan = toHTMLElement(node); |
+ if (isLegacyAppleHTMLSpanElement(node)) { |
+ wrappingStyleSpan = toHTMLSpanElement(node); |
break; |
} |
} |
@@ -786,9 +795,11 @@ void ReplaceSelectionCommand::handleStyleSpans(InsertedNodes& insertedNodes) |
ContainerNode* context = wrappingStyleSpan->parentNode(); |
// If Mail wraps the fragment with a Paste as Quotation blockquote, or if you're pasting into a quoted region, |
- // styles from blockquoteNode are allowed to override those from the source document, see <rdar://problem/4930986> and <rdar://problem/5089327>. |
- Node* blockquoteNode = isMailPasteAsQuotationNode(context) ? context : enclosingNodeOfType(firstPositionInNode(context), isMailHTMLBlockquoteElement, CanCrossEditingBoundary); |
- if (blockquoteNode) |
+ // styles from blockquoteElement are allowed to override those from the source document, see <rdar://problem/4930986> and <rdar://problem/5089327>. |
+ HTMLQuoteElement* blockquoteElement = isMailPasteAsQuotationHTMLBlockQuoteElement(context) ? |
+ toHTMLQuoteElement(context) : |
+ toHTMLQuoteElement(enclosingNodeOfType(firstPositionInNode(context), isMailHTMLBlockquoteElement, CanCrossEditingBoundary)); |
+ if (blockquoteElement) |
context = document().documentElement(); |
// This operation requires that only editing styles to be removed from sourceDocumentStyle. |
@@ -868,7 +879,7 @@ static Node* enclosingInline(Node* node) |
return node; |
} |
-static bool isInlineNodeWithStyle(const Node* node) |
+static bool isInlineHTMLElementWithStyle(const Node* node) |
{ |
// We don't want to skip over any block elements. |
if (isBlock(node)) |
@@ -882,25 +893,25 @@ static bool isInlineNodeWithStyle(const Node* node) |
const HTMLElement* element = toHTMLElement(node); |
const AtomicString& classAttributeValue = element->getAttribute(classAttr); |
if (classAttributeValue == AppleTabSpanClass) { |
- UseCounter::count(node->document(), UseCounter::EditingAppleTabSpanClass); |
+ UseCounter::count(element->document(), UseCounter::EditingAppleTabSpanClass); |
return true; |
} |
if (classAttributeValue == AppleConvertedSpace) { |
- UseCounter::count(node->document(), UseCounter::EditingAppleConvertedSpace); |
+ UseCounter::count(element->document(), UseCounter::EditingAppleConvertedSpace); |
return true; |
} |
if (classAttributeValue == ApplePasteAsQuotation) { |
- UseCounter::count(node->document(), UseCounter::EditingApplePasteAsQuotation); |
+ UseCounter::count(element->document(), UseCounter::EditingApplePasteAsQuotation); |
return true; |
} |
return EditingStyle::elementIsStyledSpanOrHTMLEquivalent(element); |
} |
-inline Node* nodeToSplitToAvoidPastingIntoInlineNodesWithStyle(const Position& insertionPos) |
+static inline HTMLElement* elementToSplitToAvoidPastingIntoInlineElementsWithStyle(const Position& insertionPos) |
{ |
Element* containingBlock = enclosingBlock(insertionPos.containerNode()); |
- return highestEnclosingNodeOfType(insertionPos, isInlineNodeWithStyle, CannotCrossEditingBoundary, containingBlock); |
+ return toHTMLElement(highestEnclosingNodeOfType(insertionPos, isInlineHTMLElementWithStyle, CannotCrossEditingBoundary, containingBlock)); |
} |
void ReplaceSelectionCommand::doApply() |
@@ -934,7 +945,7 @@ void ReplaceSelectionCommand::doApply() |
bool selectionEndWasEndOfParagraph = isEndOfParagraph(visibleEnd); |
bool selectionStartWasStartOfParagraph = isStartOfParagraph(visibleStart); |
- Node* enclosingBlockOfVisibleStart = enclosingBlock(visibleStart.deepEquivalent().deprecatedNode()); |
+ Element* enclosingBlockOfVisibleStart = enclosingBlock(visibleStart.deepEquivalent().deprecatedNode()); |
Position insertionPos = selection.start(); |
bool startIsInsideMailBlockquote = enclosingNodeOfType(insertionPos, isMailHTMLBlockquoteElement, CanCrossEditingBoundary); |
@@ -1011,12 +1022,12 @@ void ReplaceSelectionCommand::doApply() |
// NOTE: This would be an incorrect usage of downstream() if downstream() were changed to mean the last position after |
// p that maps to the same visible position as p (since in the case where a br is at the end of a block and collapsed |
// away, there are positions after the br which map to the same visible position as [br, 0]). |
- Node* endBR = isHTMLBRElement(*insertionPos.downstream().deprecatedNode()) ? insertionPos.downstream().deprecatedNode() : 0; |
+ HTMLBRElement* endBR = isHTMLBRElement(*insertionPos.downstream().deprecatedNode()) ? toHTMLBRElement(insertionPos.downstream().deprecatedNode()) : 0; |
VisiblePosition originalVisPosBeforeEndBR; |
if (endBR) |
originalVisPosBeforeEndBR = VisiblePosition(positionBeforeNode(endBR), DOWNSTREAM).previous(); |
- RefPtrWillBeRawPtr<Node> enclosingBlockOfInsertionPos = enclosingBlock(insertionPos.deprecatedNode()); |
+ RefPtrWillBeRawPtr<Element> enclosingBlockOfInsertionPos = enclosingBlock(insertionPos.deprecatedNode()); |
// Adjust insertionPos to prevent nesting. |
// If the start was in a Mail blockquote, we will have already handled adjusting insertionPos above. |
@@ -1065,12 +1076,12 @@ void ReplaceSelectionCommand::doApply() |
insertionPos = firstPositionInNode(insertionPos.containerNode()); |
} |
- if (RefPtrWillBeRawPtr<Node> nodeToSplitTo = nodeToSplitToAvoidPastingIntoInlineNodesWithStyle(insertionPos)) { |
- if (insertionPos.containerNode() != nodeToSplitTo->parentNode()) { |
+ if (RefPtrWillBeRawPtr<HTMLElement> elementToSplitTo = elementToSplitToAvoidPastingIntoInlineElementsWithStyle(insertionPos)) { |
+ if (insertionPos.containerNode() != elementToSplitTo->parentNode()) { |
Node* splitStart = insertionPos.computeNodeAfterPosition(); |
if (!splitStart) |
splitStart = insertionPos.containerNode(); |
- nodeToSplitTo = splitTreeToNode(splitStart, nodeToSplitTo->parentNode()).get(); |
+ RefPtrWillBeRawPtr<Node> nodeToSplitTo = splitTreeToNode(splitStart, elementToSplitTo->parentNode()).get(); |
insertionPos = positionInParentBeforeNode(*nodeToSplitTo); |
} |
} |
@@ -1096,8 +1107,8 @@ void ReplaceSelectionCommand::doApply() |
fragment.removeNode(refNode); |
- Node* blockStart = enclosingBlock(insertionPos.deprecatedNode()); |
- if ((isHTMLListElement(refNode.get()) || (isLegacyAppleStyleSpan(refNode.get()) && isHTMLListElement(refNode->firstChild()))) |
+ Element* blockStart = enclosingBlock(insertionPos.deprecatedNode()); |
+ if ((isHTMLListElement(refNode.get()) || (isLegacyAppleHTMLSpanElement(refNode.get()) && isHTMLListElement(refNode->firstChild()))) |
&& blockStart && blockStart->renderer()->isListItem()) |
refNode = insertAsListItems(toHTMLElement(refNode), blockStart, insertionPos, insertedNodes); |
else { |
@@ -1214,10 +1225,10 @@ void ReplaceSelectionCommand::doApply() |
if (selectionEndWasEndOfParagraph || !isEndOfParagraph(endOfInsertedContent) || next.isNull()) { |
if (!isStartOfParagraph(endOfInsertedContent)) { |
setEndingSelection(endOfInsertedContent); |
- Node* enclosingNode = enclosingBlock(endOfInsertedContent.deepEquivalent().deprecatedNode()); |
- if (isListItem(enclosingNode)) { |
+ Element* enclosingBlockElement = enclosingBlock(endOfInsertedContent.deepEquivalent().deprecatedNode()); |
+ if (isListItem(enclosingBlockElement)) { |
RefPtrWillBeRawPtr<HTMLLIElement> newListItem = createListItemElement(document()); |
- insertNodeAfter(newListItem, enclosingNode); |
+ insertNodeAfter(newListItem, enclosingBlockElement); |
setEndingSelection(VisiblePosition(firstPositionInNode(newListItem.get()))); |
} else { |
// Use a default paragraph element (a plain div) for the empty paragraph, using the last paragraph |
@@ -1234,12 +1245,12 @@ void ReplaceSelectionCommand::doApply() |
// Select up to the beginning of the next paragraph. |
lastPositionToSelect = next.deepEquivalent().downstream(); |
} |
- |
- } else |
+ } else { |
mergeEndIfNeeded(); |
+ } |
- if (Node* mailBlockquote = enclosingNodeOfType(positionAtStartOfInsertedContent().deepEquivalent(), isMailPasteAsQuotationNode)) |
- removeNodeAttribute(toElement(mailBlockquote), classAttr); |
+ if (HTMLQuoteElement* mailBlockquote = toHTMLQuoteElement(enclosingNodeOfType(positionAtStartOfInsertedContent().deepEquivalent(), isMailPasteAsQuotationHTMLBlockQuoteElement))) |
+ removeElementAttribute(mailBlockquote, classAttr); |
if (shouldPerformSmartReplace()) |
addSpacesForSmartReplace(); |
@@ -1252,7 +1263,7 @@ void ReplaceSelectionCommand::doApply() |
completeHTMLReplacement(lastPositionToSelect); |
} |
-bool ReplaceSelectionCommand::shouldRemoveEndBR(Node* endBR, const VisiblePosition& originalVisPosBeforeEndBR) |
+bool ReplaceSelectionCommand::shouldRemoveEndBR(HTMLBRElement* endBR, const VisiblePosition& originalVisPosBeforeEndBR) |
{ |
if (!endBR || !endBR->inDocument()) |
return false; |
@@ -1277,7 +1288,7 @@ bool ReplaceSelectionCommand::shouldPerformSmartReplace() const |
if (!m_smartReplace) |
return false; |
- Element* textControl = enclosingTextFormControl(positionAtStartOfInsertedContent().deepEquivalent()); |
+ HTMLTextFormControlElement* textControl = enclosingTextFormControl(positionAtStartOfInsertedContent().deepEquivalent()); |
if (isHTMLInputElement(textControl) && toHTMLInputElement(textControl)->isPasswordField()) |
return false; // Disable smart replace for password fields. |
@@ -1310,7 +1321,7 @@ void ReplaceSelectionCommand::addSpacesForSmartReplace() |
if (m_endOfInsertedContent.containerNode() == endNode) |
m_endOfInsertedContent.moveToOffset(m_endOfInsertedContent.offsetInContainerNode() + 1); |
} else { |
- RefPtrWillBeRawPtr<Node> node = document().createEditingTextNode(collapseWhiteSpace ? nonBreakingSpaceString() : " "); |
+ RefPtrWillBeRawPtr<Text> node = document().createEditingTextNode(collapseWhiteSpace ? nonBreakingSpaceString() : " "); |
insertNodeAfter(node, endNode); |
updateNodesInserted(node.get()); |
} |
@@ -1334,7 +1345,7 @@ void ReplaceSelectionCommand::addSpacesForSmartReplace() |
if (m_endOfInsertedContent.containerNode() == startNode && m_endOfInsertedContent.offsetInContainerNode()) |
m_endOfInsertedContent.moveToOffset(m_endOfInsertedContent.offsetInContainerNode() + 1); |
} else { |
- RefPtrWillBeRawPtr<Node> node = document().createEditingTextNode(collapseWhiteSpace ? nonBreakingSpaceString() : " "); |
+ RefPtrWillBeRawPtr<Text> node = document().createEditingTextNode(collapseWhiteSpace ? nonBreakingSpaceString() : " "); |
// Don't updateNodesInserted. Doing so would set m_endOfInsertedContent to be the node containing the leading space, |
// but m_endOfInsertedContent is supposed to mark the end of pasted content. |
insertNodeBefore(node, startNode); |
@@ -1438,7 +1449,7 @@ EditAction ReplaceSelectionCommand::editingAction() const |
// 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(PassRefPtrWillBeRawPtr<HTMLElement> prpListElement, Node* insertionBlock, const Position& insertPos, InsertedNodes& insertedNodes) |
+Node* ReplaceSelectionCommand::insertAsListItems(PassRefPtrWillBeRawPtr<HTMLElement> prpListElement, Element* insertionBlock, const Position& insertPos, InsertedNodes& insertedNodes) |
{ |
RefPtrWillBeRawPtr<HTMLElement> listElement = prpListElement; |
@@ -1503,7 +1514,7 @@ bool ReplaceSelectionCommand::performTrivialReplace(const ReplacementFragment& f |
return false; |
// e.g. when "bar" is inserted after "foo" in <div><u>foo</u></div>, "bar" should not be underlined. |
- if (nodeToSplitToAvoidPastingIntoInlineNodesWithStyle(endingSelection().start())) |
+ if (elementToSplitToAvoidPastingIntoInlineElementsWithStyle(endingSelection().start())) |
return false; |
RefPtrWillBeRawPtr<Node> nodeAfterInsertionPos = endingSelection().end().downstream().anchorNode(); |
@@ -1516,7 +1527,7 @@ bool ReplaceSelectionCommand::performTrivialReplace(const ReplacementFragment& f |
return false; |
if (nodeAfterInsertionPos && nodeAfterInsertionPos->parentNode() && isHTMLBRElement(*nodeAfterInsertionPos) |
- && shouldRemoveEndBR(nodeAfterInsertionPos.get(), VisiblePosition(positionBeforeNode(nodeAfterInsertionPos.get())))) |
+ && shouldRemoveEndBR(toHTMLBRElement(nodeAfterInsertionPos.get()), VisiblePosition(positionBeforeNode(nodeAfterInsertionPos.get())))) |
removeNodeAndPruneAncestors(nodeAfterInsertionPos.get()); |
VisibleSelection selectionAfterReplace(m_selectReplacement ? start : end, end); |