#include "config.h"
#include "core/editing/CompositeEditCommand.h"
-#include "HTMLNames.h"
-#include "bindings/v8/ExceptionStatePlaceholder.h"
+#include "bindings/core/v8/ExceptionStatePlaceholder.h"
+#include "core/HTMLNames.h"
#include "core/dom/Document.h"
#include "core/dom/DocumentFragment.h"
#include "core/dom/DocumentMarkerController.h"
+#include "core/dom/ElementTraversal.h"
#include "core/dom/NodeTraversal.h"
#include "core/dom/Range.h"
-#include "core/events/ScopedEventQueue.h"
#include "core/dom/Text.h"
#include "core/editing/AppendNodeCommand.h"
#include "core/editing/ApplyStyleCommand.h"
#include "core/editing/WrapContentsInDummySpanCommand.h"
#include "core/editing/htmlediting.h"
#include "core/editing/markup.h"
+#include "core/events/ScopedEventQueue.h"
+#include "core/frame/LocalFrame.h"
+#include "core/html/HTMLBRElement.h"
+#include "core/html/HTMLDivElement.h"
#include "core/html/HTMLElement.h"
-#include "core/frame/Frame.h"
+#include "core/html/HTMLLIElement.h"
+#include "core/html/HTMLQuoteElement.h"
+#include "core/html/HTMLSpanElement.h"
#include "core/rendering/InlineTextBox.h"
#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderListItem.h"
#include "core/rendering/RenderText.h"
-using namespace std;
-
-namespace WebCore {
+namespace blink {
using namespace HTMLNames;
-PassRefPtr<EditCommandComposition> EditCommandComposition::create(Document* document,
+PassRefPtrWillBeRawPtr<EditCommandComposition> EditCommandComposition::create(Document* document,
const VisibleSelection& startingSelection, const VisibleSelection& endingSelection, EditAction editAction)
{
- return adoptRef(new EditCommandComposition(document, startingSelection, endingSelection, editAction));
+ return adoptRefWillBeNoop(new EditCommandComposition(document, startingSelection, endingSelection, editAction));
}
EditCommandComposition::EditCommandComposition(Document* document, const VisibleSelection& startingSelection, const VisibleSelection& endingSelection, EditAction editAction)
{
}
+bool EditCommandComposition::belongsTo(const LocalFrame& frame) const
+{
+ ASSERT(m_document);
+ return m_document->frame() == &frame;
+}
+
void EditCommandComposition::unapply()
{
ASSERT(m_document);
- RefPtr<Frame> frame = m_document->frame();
+ RefPtrWillBeRawPtr<LocalFrame> frame = m_document->frame();
ASSERT(frame);
// Changes to the document may have been made since the last editing operation that require a layout, as in <rdar://problem/5658603>.
void EditCommandComposition::reapply()
{
ASSERT(m_document);
- RefPtr<Frame> frame = m_document->frame();
+ RefPtrWillBeRawPtr<LocalFrame> frame = m_document->frame();
ASSERT(frame);
// Changes to the document may have been made since the last editing operation that require a layout, as in <rdar://problem/5658603>.
m_document->updateLayoutIgnorePendingStylesheets();
{
- size_t size = m_commands.size();
- for (size_t i = 0; i != size; ++i)
- m_commands[i]->doReapply();
+ for (const auto& command : m_commands)
+ command->doReapply();
}
frame->editor().reappliedEditing(this);
m_endingRootEditableElement = selection.rootEditableElement();
}
+void EditCommandComposition::trace(Visitor* visitor)
+{
+ visitor->trace(m_document);
+ visitor->trace(m_startingSelection);
+ visitor->trace(m_endingSelection);
+ visitor->trace(m_commands);
+ visitor->trace(m_startingRootEditableElement);
+ visitor->trace(m_endingRootEditableElement);
+ UndoStep::trace(visitor);
+}
+
CompositeEditCommand::CompositeEditCommand(Document& document)
: EditCommand(document)
{
// if one is necessary (like for the creation of VisiblePositions).
document().updateLayoutIgnorePendingStylesheets();
- Frame* frame = document().frame();
+ LocalFrame* frame = document().frame();
ASSERT(frame);
{
- EventQueueScope scope;
+ EventQueueScope eventQueueScope;
doApply();
}
return command->m_composition.get();
}
-bool CompositeEditCommand::isCreateLinkCommand() const
-{
- return false;
-}
-
bool CompositeEditCommand::preservesTypingStyle() const
{
return false;
return false;
}
-bool CompositeEditCommand::shouldRetainAutocorrectionIndicator() const
-{
- return false;
-}
-
void CompositeEditCommand::setShouldRetainAutocorrectionIndicator(bool)
{
}
//
// sugary-sweet convenience functions to help create and apply edit commands in composite commands
//
-void CompositeEditCommand::applyCommandToComposite(PassRefPtr<EditCommand> prpCommand)
+void CompositeEditCommand::applyCommandToComposite(PassRefPtrWillBeRawPtr<EditCommand> prpCommand)
{
- RefPtr<EditCommand> command = prpCommand;
+ RefPtrWillBeRawPtr<EditCommand> command = prpCommand;
command->setParent(this);
command->doApply();
if (command->isSimpleEditCommand()) {
m_commands.append(command.release());
}
-void CompositeEditCommand::applyCommandToComposite(PassRefPtr<CompositeEditCommand> command, const VisibleSelection& selection)
+void CompositeEditCommand::applyCommandToComposite(PassRefPtrWillBeRawPtr<CompositeEditCommand> command, const VisibleSelection& selection)
{
command->setParent(this);
if (selection != command->endingSelection()) {
applyCommandToComposite(ApplyStyleCommand::create(document(), style, start, end, editingAction));
}
-void CompositeEditCommand::applyStyledElement(PassRefPtr<Element> element)
+void CompositeEditCommand::applyStyledElement(PassRefPtrWillBeRawPtr<Element> element)
{
applyCommandToComposite(ApplyStyleCommand::create(element, false));
}
-void CompositeEditCommand::removeStyledElement(PassRefPtr<Element> element)
+void CompositeEditCommand::removeStyledElement(PassRefPtrWillBeRawPtr<Element> element)
{
applyCommandToComposite(ApplyStyleCommand::create(element, true));
}
applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(), useDefaultParagraphElement, pasteBlockqutoeIntoUnquotedArea));
}
-void CompositeEditCommand::insertLineBreak()
-{
- applyCommandToComposite(InsertLineBreakCommand::create(document()));
-}
-
bool CompositeEditCommand::isRemovableBlock(const Node* node)
{
- if (!node->hasTagName(divTag))
+ ASSERT(node);
+ if (!isHTMLDivElement(*node))
return false;
- Node* parentNode = node->parentNode();
+ const HTMLDivElement& element = toHTMLDivElement(*node);
+ ContainerNode* parentNode = element.parentNode();
if (parentNode && parentNode->firstChild() != parentNode->lastChild())
return false;
- if (!toElement(node)->hasAttributes())
+ if (!element.hasAttributes())
return true;
return false;
}
-void CompositeEditCommand::insertNodeBefore(PassRefPtr<Node> insertChild, PassRefPtr<Node> refChild, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
+void CompositeEditCommand::insertNodeBefore(PassRefPtrWillBeRawPtr<Node> insertChild, PassRefPtrWillBeRawPtr<Node> refChild, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
{
- ASSERT(!refChild->hasTagName(bodyTag));
+ ASSERT(!isHTMLBodyElement(*refChild));
applyCommandToComposite(InsertNodeBeforeCommand::create(insertChild, refChild, shouldAssumeContentIsAlwaysEditable));
}
-void CompositeEditCommand::insertNodeAfter(PassRefPtr<Node> insertChild, PassRefPtr<Node> refChild)
+void CompositeEditCommand::insertNodeAfter(PassRefPtrWillBeRawPtr<Node> insertChild, PassRefPtrWillBeRawPtr<Node> refChild)
{
ASSERT(insertChild);
ASSERT(refChild);
- ASSERT(!refChild->hasTagName(bodyTag));
+ ASSERT(!isHTMLBodyElement(*refChild));
ContainerNode* parent = refChild->parentNode();
ASSERT(parent);
ASSERT(!parent->isShadowRoot());
}
}
-void CompositeEditCommand::insertNodeAt(PassRefPtr<Node> insertChild, const Position& editingPosition)
+void CompositeEditCommand::insertNodeAt(PassRefPtrWillBeRawPtr<Node> insertChild, const Position& editingPosition)
{
- ASSERT(isEditablePosition(editingPosition));
+ ASSERT(isEditablePosition(editingPosition, ContentIsEditable, DoNotUpdateStyle));
// For editing positions like [table, 0], insert before the table,
// likewise for replaced elements, brs, etc.
Position p = editingPosition.parentAnchoredEquivalent();
insertNodeAfter(insertChild, refChild);
}
-void CompositeEditCommand::appendNode(PassRefPtr<Node> node, PassRefPtr<ContainerNode> parent)
+void CompositeEditCommand::appendNode(PassRefPtrWillBeRawPtr<Node> node, PassRefPtrWillBeRawPtr<ContainerNode> parent)
{
ASSERT(canHaveChildrenForEditing(parent.get()));
applyCommandToComposite(AppendNodeCommand::create(parent, node));
}
-void CompositeEditCommand::removeChildrenInRange(PassRefPtr<Node> node, unsigned from, unsigned to)
+void CompositeEditCommand::removeChildrenInRange(PassRefPtrWillBeRawPtr<Node> node, unsigned from, unsigned to)
{
- Vector<RefPtr<Node> > children;
- Node* child = node->childNode(from);
+ WillBeHeapVector<RefPtrWillBeMember<Node>> children;
+ Node* child = NodeTraversal::childAt(*node, from);
for (unsigned i = from; child && i < to; i++, child = child->nextSibling())
children.append(child);
removeNode(children[i].release());
}
-void CompositeEditCommand::removeNode(PassRefPtr<Node> node, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
+void CompositeEditCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
{
if (!node || !node->nonShadowBoundaryParentNode())
return;
applyCommandToComposite(RemoveNodeCommand::create(node, shouldAssumeContentIsAlwaysEditable));
}
-void CompositeEditCommand::removeNodePreservingChildren(PassRefPtr<Node> node, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
+void CompositeEditCommand::removeNodePreservingChildren(PassRefPtrWillBeRawPtr<Node> node, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
{
applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node, shouldAssumeContentIsAlwaysEditable));
}
-void CompositeEditCommand::removeNodeAndPruneAncestors(PassRefPtr<Node> node, Node* excludeNode)
+void CompositeEditCommand::removeNodeAndPruneAncestors(PassRefPtrWillBeRawPtr<Node> node, Node* excludeNode)
{
ASSERT(node.get() != excludeNode);
- RefPtr<ContainerNode> parent = node->parentNode();
+ RefPtrWillBeRawPtr<ContainerNode> parent = node->parentNode();
removeNode(node);
prune(parent.release(), excludeNode);
}
-void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pastLastNodeToMove, PassRefPtr<Element> prpNewParent)
+void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pastLastNodeToMove, PassRefPtrWillBeRawPtr<Element> prpNewParent)
{
NodeVector nodesToRemove;
- RefPtr<Element> newParent = prpNewParent;
+ RefPtrWillBeRawPtr<Element> newParent = prpNewParent;
for (; node && node != pastLastNodeToMove; node = node->nextSibling())
nodesToRemove.append(node);
}
}
-void CompositeEditCommand::updatePositionForNodeRemovalPreservingChildren(Position& position, Node* node)
+void CompositeEditCommand::updatePositionForNodeRemovalPreservingChildren(Position& position, Node& node)
{
int offset = (position.anchorType() == Position::PositionIsOffsetInAnchor) ? position.offsetInContainerNode() : 0;
updatePositionForNodeRemoval(position, node);
position.moveToOffset(offset);
}
-HTMLElement* CompositeEditCommand::replaceElementWithSpanPreservingChildrenAndAttributes(PassRefPtr<HTMLElement> node)
+HTMLSpanElement* CompositeEditCommand::replaceElementWithSpanPreservingChildrenAndAttributes(PassRefPtrWillBeRawPtr<HTMLElement> node)
{
// It would also be possible to implement all of ReplaceNodeWithSpanCommand
// as a series of existing smaller edit commands. Someone who wanted to
// reduce the number of edit commands could do so here.
- RefPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpanCommand::create(node);
+ RefPtrWillBeRawPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpanCommand::create(node);
applyCommandToComposite(command);
// Returning a raw pointer here is OK because the command is retained by
// applyCommandToComposite (thus retaining the span), and the span is also
return command->spanElement();
}
-void CompositeEditCommand::prune(PassRefPtr<Node> node, Node* excludeNode)
+void CompositeEditCommand::prune(PassRefPtrWillBeRawPtr<Node> node, Node* excludeNode)
{
- if (RefPtr<Node> highestNodeToRemove = highestNodeToRemoveInPruning(node.get(), excludeNode))
+ if (RefPtrWillBeRawPtr<Node> highestNodeToRemove = highestNodeToRemoveInPruning(node.get(), excludeNode))
removeNode(highestNodeToRemove.release());
}
-void CompositeEditCommand::splitTextNode(PassRefPtr<Text> node, unsigned offset)
+void CompositeEditCommand::splitTextNode(PassRefPtrWillBeRawPtr<Text> node, unsigned offset)
{
applyCommandToComposite(SplitTextNodeCommand::create(node, offset));
}
-void CompositeEditCommand::splitElement(PassRefPtr<Element> element, PassRefPtr<Node> atChild)
+void CompositeEditCommand::splitElement(PassRefPtrWillBeRawPtr<Element> element, PassRefPtrWillBeRawPtr<Node> atChild)
{
applyCommandToComposite(SplitElementCommand::create(element, atChild));
}
-void CompositeEditCommand::mergeIdenticalElements(PassRefPtr<Element> prpFirst, PassRefPtr<Element> prpSecond)
+void CompositeEditCommand::mergeIdenticalElements(PassRefPtrWillBeRawPtr<Element> prpFirst, PassRefPtrWillBeRawPtr<Element> prpSecond)
{
- RefPtr<Element> first = prpFirst;
- RefPtr<Element> second = prpSecond;
+ RefPtrWillBeRawPtr<Element> first = prpFirst;
+ RefPtrWillBeRawPtr<Element> second = prpSecond;
ASSERT(!first->isDescendantOf(second.get()) && second != first);
if (first->nextSibling() != second) {
removeNode(second);
applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second));
}
-void CompositeEditCommand::wrapContentsInDummySpan(PassRefPtr<Element> element)
+void CompositeEditCommand::wrapContentsInDummySpan(PassRefPtrWillBeRawPtr<Element> element)
{
applyCommandToComposite(WrapContentsInDummySpanCommand::create(element));
}
-void CompositeEditCommand::splitTextNodeContainingElement(PassRefPtr<Text> text, unsigned offset)
+void CompositeEditCommand::splitTextNodeContainingElement(PassRefPtrWillBeRawPtr<Text> text, unsigned offset)
{
applyCommandToComposite(SplitTextNodeContainingElementCommand::create(text, offset));
}
-void CompositeEditCommand::insertTextIntoNode(PassRefPtr<Text> node, unsigned offset, const String& text)
+void CompositeEditCommand::insertTextIntoNode(PassRefPtrWillBeRawPtr<Text> node, unsigned offset, const String& text)
{
if (!text.isEmpty())
applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset, text));
}
-void CompositeEditCommand::deleteTextFromNode(PassRefPtr<Text> node, unsigned offset, unsigned count)
+void CompositeEditCommand::deleteTextFromNode(PassRefPtrWillBeRawPtr<Text> node, unsigned offset, unsigned count)
{
applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, count));
}
-void CompositeEditCommand::replaceTextInNode(PassRefPtr<Text> prpNode, unsigned offset, unsigned count, const String& replacementText)
+void CompositeEditCommand::replaceTextInNode(PassRefPtrWillBeRawPtr<Text> prpNode, unsigned offset, unsigned count, const String& replacementText)
{
- RefPtr<Text> node(prpNode);
+ RefPtrWillBeRawPtr<Text> node(prpNode);
applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, count));
if (!replacementText.isEmpty())
applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset, replacementText));
{
Position start = endingSelection().start();
Position end = endingSelection().end();
- if (start.containerNode() != end.containerNode() || !start.containerNode()->isTextNode() || isTabSpanTextNode(start.containerNode()))
+ if (start.containerNode() != end.containerNode() || !start.containerNode()->isTextNode() || isTabHTMLSpanElementTextNode(start.containerNode()))
return Position();
- RefPtr<Text> textNode = start.containerText();
+ RefPtrWillBeRawPtr<Text> textNode = start.containerText();
replaceTextInNode(textNode, start.offsetInContainerNode(), end.offsetInContainerNode() - start.offsetInContainerNode(), text);
return Position(textNode.release(), start.offsetInContainerNode() + text.length());
}
-static void copyMarkers(const Vector<DocumentMarker*>& markerPointers, Vector<DocumentMarker>& markers)
+static void copyMarkerTypesAndDescriptions(const DocumentMarkerVector& markerPointers, Vector<DocumentMarker::MarkerType>& types, Vector<String>& descriptions)
{
size_t arraySize = markerPointers.size();
- markers.reserveCapacity(arraySize);
- for (size_t i = 0; i < arraySize; ++i)
- markers.append(*markerPointers[i]);
+ types.reserveCapacity(arraySize);
+ descriptions.reserveCapacity(arraySize);
+ for (const auto& markerPointer : markerPointers) {
+ types.append(markerPointer->type());
+ descriptions.append(markerPointer->description());
+ }
}
-void CompositeEditCommand::replaceTextInNodePreservingMarkers(PassRefPtr<Text> prpNode, unsigned offset, unsigned count, const String& replacementText)
+void CompositeEditCommand::replaceTextInNodePreservingMarkers(PassRefPtrWillBeRawPtr<Text> prpNode, unsigned offset, unsigned count, const String& replacementText)
{
- RefPtr<Text> node(prpNode);
- DocumentMarkerController* markerController = document().markers();
- Vector<DocumentMarker> markers;
- copyMarkers(markerController->markersInRange(Range::create(document(), node.get(), offset, node.get(), offset + count).get(), DocumentMarker::AllMarkers()), markers);
+ RefPtrWillBeRawPtr<Text> node(prpNode);
+ DocumentMarkerController& markerController = document().markers();
+ Vector<DocumentMarker::MarkerType> types;
+ Vector<String> descriptions;
+ copyMarkerTypesAndDescriptions(markerController.markersInRange(Range::create(document(), node.get(), offset, node.get(), offset + count).get(), DocumentMarker::AllMarkers()), types, descriptions);
replaceTextInNode(node, offset, count, replacementText);
- RefPtr<Range> newRange = Range::create(document(), node.get(), offset, node.get(), offset + replacementText.length());
- for (size_t i = 0; i < markers.size(); ++i)
- markerController->addMarker(newRange.get(), markers[i].type(), markers[i].description());
+ RefPtrWillBeRawPtr<Range> newRange = Range::create(document(), node.get(), offset, node.get(), offset + replacementText.length());
+ ASSERT(types.size() == descriptions.size());
+ for (size_t i = 0; i < types.size(); ++i)
+ markerController.addMarker(newRange.get(), types[i], descriptions[i]);
}
Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos)
{
- if (!isTabSpanTextNode(pos.anchorNode()))
+ if (!isTabHTMLSpanElementTextNode(pos.anchorNode()))
return pos;
switch (pos.anchorType()) {
case Position::PositionIsOffsetInAnchor:
break;
case Position::PositionIsBeforeAnchor:
- return positionInParentBeforeNode(pos.anchorNode());
+ return positionInParentBeforeNode(*pos.anchorNode());
case Position::PositionIsAfterAnchor:
- return positionInParentAfterNode(pos.anchorNode());
+ return positionInParentAfterNode(*pos.anchorNode());
}
- Node* tabSpan = tabSpanNode(pos.containerNode());
+ HTMLSpanElement* tabSpan = tabSpanElement(pos.containerNode());
+ ASSERT(tabSpan);
if (pos.offsetInContainerNode() <= caretMinOffset(pos.containerNode()))
- return positionInParentBeforeNode(tabSpan);
+ return positionInParentBeforeNode(*tabSpan);
if (pos.offsetInContainerNode() >= caretMaxOffset(pos.containerNode()))
- return positionInParentAfterNode(tabSpan);
+ return positionInParentAfterNode(*tabSpan);
splitTextNodeContainingElement(toText(pos.containerNode()), pos.offsetInContainerNode());
- return positionInParentBeforeNode(tabSpan);
+ return positionInParentBeforeNode(*tabSpan);
}
-void CompositeEditCommand::insertNodeAtTabSpanPosition(PassRefPtr<Node> node, const Position& pos)
+void CompositeEditCommand::insertNodeAtTabSpanPosition(PassRefPtrWillBeRawPtr<Node> node, const Position& pos)
{
// insert node before, after, or at split of tab span
insertNodeAt(node, positionOutsideTabSpan(pos));
}
-void CompositeEditCommand::deleteSelection(bool smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements, bool sanitizeMarkup)
+void CompositeEditCommand::deleteSelection(bool smartDelete, bool mergeBlocksAfterDelete, bool expandForSpecialElements, bool sanitizeMarkup)
{
if (endingSelection().isRange())
- applyCommandToComposite(DeleteSelectionCommand::create(document(), smartDelete, mergeBlocksAfterDelete, replace, expandForSpecialElements, sanitizeMarkup));
+ applyCommandToComposite(DeleteSelectionCommand::create(document(), smartDelete, mergeBlocksAfterDelete, expandForSpecialElements, sanitizeMarkup));
}
-void CompositeEditCommand::deleteSelection(const VisibleSelection &selection, bool smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements, bool sanitizeMarkup)
+void CompositeEditCommand::deleteSelection(const VisibleSelection &selection, bool smartDelete, bool mergeBlocksAfterDelete, bool expandForSpecialElements, bool sanitizeMarkup)
{
if (selection.isRange())
- applyCommandToComposite(DeleteSelectionCommand::create(selection, smartDelete, mergeBlocksAfterDelete, replace, expandForSpecialElements, sanitizeMarkup));
+ applyCommandToComposite(DeleteSelectionCommand::create(selection, smartDelete, mergeBlocksAfterDelete, expandForSpecialElements, sanitizeMarkup));
}
-void CompositeEditCommand::removeCSSProperty(PassRefPtr<Element> element, CSSPropertyID property)
+void CompositeEditCommand::removeCSSProperty(PassRefPtrWillBeRawPtr<Element> element, CSSPropertyID property)
{
applyCommandToComposite(RemoveCSSPropertyCommand::create(document(), element, property));
}
-void CompositeEditCommand::removeNodeAttribute(PassRefPtr<Element> element, const QualifiedName& attribute)
+void CompositeEditCommand::removeElementAttribute(PassRefPtrWillBeRawPtr<Element> element, const QualifiedName& attribute)
{
setNodeAttribute(element, attribute, AtomicString());
}
-void CompositeEditCommand::setNodeAttribute(PassRefPtr<Element> element, const QualifiedName& attribute, const AtomicString& value)
+void CompositeEditCommand::setNodeAttribute(PassRefPtrWillBeRawPtr<Element> element, const QualifiedName& attribute, const AtomicString& value)
{
applyCommandToComposite(SetNodeAttributeCommand::create(element, attribute, value));
}
if (textNode->length() == 0)
return false;
- RenderObject* renderer = textNode->renderer();
+ RenderText* renderer = textNode->renderer();
if (renderer && !renderer->style()->collapseWhiteSpace())
return false;
rebalanceWhitespaceOnTextSubstring(toText(node), position.offsetInContainerNode(), position.offsetInContainerNode());
}
-void CompositeEditCommand::rebalanceWhitespaceOnTextSubstring(PassRefPtr<Text> prpTextNode, int startOffset, int endOffset)
+void CompositeEditCommand::rebalanceWhitespaceOnTextSubstring(PassRefPtrWillBeRawPtr<Text> prpTextNode, int startOffset, int endOffset)
{
- RefPtr<Text> textNode = prpTextNode;
+ RefPtrWillBeRawPtr<Text> textNode = prpTextNode;
String text = textNode->data();
ASSERT(!text.isEmpty());
if (textNode->length() == 0)
return;
- RenderObject* renderer = textNode->renderer();
+ RenderText* renderer = textNode->renderer();
if (renderer && !renderer->style()->collapseWhiteSpace())
return;
if (!isCollapsibleWhitespace(visiblePosition.characterAfter()))
return;
Position pos = visiblePosition.deepEquivalent().downstream();
- if (!pos.containerNode() || !pos.containerNode()->isTextNode() || pos.containerNode()->hasTagName(brTag))
+ if (!pos.containerNode() || !pos.containerNode()->isTextNode())
return;
replaceTextInNodePreservingMarkers(pos.containerText(), pos.offsetInContainerNode(), 1, nonBreakingSpaceString());
}
rebalanceWhitespaceAt(selection.end());
}
-void CompositeEditCommand::deleteInsignificantText(PassRefPtr<Text> textNode, unsigned start, unsigned end)
+void CompositeEditCommand::deleteInsignificantText(PassRefPtrWillBeRawPtr<Text> textNode, unsigned start, unsigned end)
{
if (!textNode || start >= end)
return;
document().updateLayout();
- RenderText* textRenderer = toRenderText(textNode->renderer());
+ RenderText* textRenderer = textNode->renderer();
if (!textRenderer)
return;
return;
unsigned removed = 0;
- InlineTextBox* prevBox = 0;
+ InlineTextBox* prevBox = nullptr;
String str;
// This loop structure works to process all gaps preceding a box,
bool indicesIntersect = start <= gapEnd && end >= gapStart;
int gapLen = gapEnd - gapStart;
if (indicesIntersect && gapLen > 0) {
- gapStart = max(gapStart, start);
- gapEnd = min(gapEnd, end);
+ gapStart = std::max(gapStart, start);
if (str.isNull())
str = textNode->data().substring(start, end - start);
// remove text in the gap
if (comparePositions(start, end) >= 0)
return;
- Vector<RefPtr<Text> > nodes;
- for (Node* node = start.deprecatedNode(); node; node = NodeTraversal::next(node)) {
- if (node->isTextNode())
- nodes.append(toText(node));
- if (node == end.deprecatedNode())
+ WillBeHeapVector<RefPtrWillBeMember<Text>> nodes;
+ for (Node& node : NodeTraversal::startsAt(start.deprecatedNode())) {
+ if (node.isTextNode())
+ nodes.append(toText(&node));
+ if (&node == end.deprecatedNode())
break;
}
- for (size_t i = 0; i < nodes.size(); ++i) {
- Text* textNode = nodes[i].get();
+ for (const auto& node : nodes) {
+ Text* textNode = node.get();
int startOffset = textNode == start.deprecatedNode() ? start.deprecatedEditingOffset() : 0;
int endOffset = textNode == end.deprecatedNode() ? end.deprecatedEditingOffset() : static_cast<int>(textNode->length());
deleteInsignificantText(textNode, startOffset, endOffset);
deleteInsignificantText(pos, end);
}
-PassRefPtr<Node> CompositeEditCommand::appendBlockPlaceholder(PassRefPtr<Element> container)
+PassRefPtrWillBeRawPtr<HTMLBRElement> CompositeEditCommand::appendBlockPlaceholder(PassRefPtrWillBeRawPtr<Element> container)
{
if (!container)
- return 0;
+ return nullptr;
document().updateLayoutIgnorePendingStylesheets();
// Should assert isRenderBlockFlow || isInlineFlow when deletion improves. See 4244964.
ASSERT(container->renderer());
- RefPtr<Node> placeholder = createBlockPlaceholderElement(document());
+ RefPtrWillBeRawPtr<HTMLBRElement> placeholder = createBlockPlaceholderElement(document());
appendNode(placeholder, container);
return placeholder.release();
}
-PassRefPtr<Node> CompositeEditCommand::insertBlockPlaceholder(const Position& pos)
+PassRefPtrWillBeRawPtr<HTMLBRElement> CompositeEditCommand::insertBlockPlaceholder(const Position& pos)
{
if (pos.isNull())
- return 0;
+ return nullptr;
// Should assert isRenderBlockFlow || isInlineFlow when deletion improves. See 4244964.
ASSERT(pos.deprecatedNode()->renderer());
- RefPtr<Node> placeholder = createBlockPlaceholderElement(document());
+ RefPtrWillBeRawPtr<HTMLBRElement> placeholder = createBlockPlaceholderElement(document());
insertNodeAt(placeholder, pos);
return placeholder.release();
}
-PassRefPtr<Node> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element* container)
+PassRefPtrWillBeRawPtr<HTMLBRElement> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element* container)
{
if (!container)
- return 0;
+ return nullptr;
document().updateLayoutIgnorePendingStylesheets();
RenderObject* renderer = container->renderer();
if (!renderer || !renderer->isRenderBlockFlow())
- return 0;
+ return nullptr;
// append the placeholder to make sure it follows
// any unrendered blocks
- RenderBlock* block = toRenderBlock(renderer);
- if (block->height() == 0 || (block->isListItem() && block->isEmpty()))
+ RenderBlockFlow* block = toRenderBlockFlow(renderer);
+ if (block->height() == 0 || (block->isListItem() && toRenderListItem(block)->isEmpty()))
return appendBlockPlaceholder(container);
- return 0;
+ return nullptr;
}
// Assumes that the position is at a placeholder and does the removal without much checking.
ASSERT(lineBreakExistsAtPosition(p));
// We are certain that the position is at a line break, but it may be a br or a preserved newline.
- if (p.anchorNode()->hasTagName(brTag)) {
+ if (isHTMLBRElement(*p.anchorNode())) {
removeNode(p.anchorNode());
return;
}
deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1);
}
-PassRefPtr<Node> CompositeEditCommand::insertNewDefaultParagraphElementAt(const Position& position)
+PassRefPtrWillBeRawPtr<HTMLElement> CompositeEditCommand::insertNewDefaultParagraphElementAt(const Position& position)
{
- RefPtr<Element> paragraphElement = createDefaultParagraphElement(document());
+ RefPtrWillBeRawPtr<HTMLElement> paragraphElement = createDefaultParagraphElement(document());
paragraphElement->appendChild(createBreakElement(document()));
insertNodeAt(paragraphElement, position);
return paragraphElement.release();
// If the paragraph is not entirely within it's own block, create one and move the paragraph into
// it, and return that block. Otherwise return 0.
-PassRefPtr<Node> CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessary(const Position& pos)
+PassRefPtrWillBeRawPtr<HTMLElement> CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessary(const Position& pos)
{
- if (pos.isNull())
- return 0;
-
- document().updateLayoutIgnorePendingStylesheets();
+ ASSERT(isEditablePosition(pos, ContentIsEditable, DoNotUpdateStyle));
// It's strange that this function is responsible for verifying that pos has not been invalidated
// by an earlier call to this function. The caller, applyBlockStyle, should do this.
// If there are no VisiblePositions in the same block as pos then
// upstreamStart will be outside the paragraph
if (comparePositions(pos, upstreamStart) < 0)
- return 0;
+ return nullptr;
// Perform some checks to see if we need to perform work in this function.
if (isBlock(upstreamStart.deprecatedNode())) {
if (!upstreamEnd.deprecatedNode()->isDescendantOf(upstreamStart.deprecatedNode())) {
// If the paragraph end is a descendant of paragraph start, then we need to run
// the rest of this function. If not, we can bail here.
- return 0;
+ return nullptr;
}
} else if (enclosingBlock(upstreamEnd.deprecatedNode()) != upstreamStart.deprecatedNode()) {
- // The visibleEnd. It must be an ancestor of the paragraph start.
+ // It should be an ancestor of the paragraph start.
// We can bail as we have a full block to work with.
- ASSERT(upstreamStart.deprecatedNode()->isDescendantOf(enclosingBlock(upstreamEnd.deprecatedNode())));
- return 0;
+ return nullptr;
} else if (isEndOfEditableOrNonEditableContent(visibleEnd)) {
// At the end of the editable region. We can bail here as well.
- return 0;
+ return nullptr;
}
}
- RefPtr<Node> newBlock = insertNewDefaultParagraphElementAt(upstreamStart);
+ if (visibleParagraphEnd.isNull())
+ return nullptr;
+
+ RefPtrWillBeRawPtr<HTMLElement> newBlock = insertNewDefaultParagraphElementAt(upstreamStart);
- bool endWasBr = visibleParagraphEnd.deepEquivalent().deprecatedNode()->hasTagName(brTag);
+ bool endWasBr = isHTMLBRElement(*visibleParagraphEnd.deepEquivalent().deprecatedNode());
+ // Inserting default paragraph element can change visible position. We
+ // should update visible positions before use them.
+ visiblePos = VisiblePosition(pos, VP_DEFAULT_AFFINITY);
+ visibleParagraphStart = VisiblePosition(startOfParagraph(visiblePos));
+ visibleParagraphEnd = VisiblePosition(endOfParagraph(visiblePos));
moveParagraphs(visibleParagraphStart, visibleParagraphEnd, VisiblePosition(firstPositionInNode(newBlock.get())));
- if (newBlock->lastChild() && newBlock->lastChild()->hasTagName(brTag) && !endWasBr)
+ if (newBlock->lastChild() && isHTMLBRElement(*newBlock->lastChild()) && !endWasBr)
removeNode(newBlock->lastChild());
return newBlock.release();
}
-void CompositeEditCommand::pushAnchorElementDown(Node* anchorNode)
+void CompositeEditCommand::pushAnchorElementDown(Element* anchorNode)
{
if (!anchorNode)
return;
ASSERT(anchorNode->isLink());
setEndingSelection(VisibleSelection::selectionFromContentsOfNode(anchorNode));
- applyStyledElement(toElement(anchorNode));
+ applyStyledElement(anchorNode);
// Clones of anchorNode have been pushed down, now remove it.
if (anchorNode->inDocument())
removeNodePreservingChildren(anchorNode);
// Clone the paragraph between start and end under blockElement,
// preserving the hierarchy up to outerNode.
-void CompositeEditCommand::cloneParagraphUnderNewElement(Position& start, Position& end, Node* passedOuterNode, Element* blockElement)
+void CompositeEditCommand::cloneParagraphUnderNewElement(const Position& start, const Position& end, Node* passedOuterNode, Element* blockElement)
{
+ ASSERT(comparePositions(start, end) <= 0);
+ ASSERT(passedOuterNode);
+ ASSERT(blockElement);
+
// First we clone the outerNode
- RefPtr<Node> lastNode;
- RefPtr<Node> outerNode = passedOuterNode;
+ RefPtrWillBeRawPtr<Node> lastNode = nullptr;
+ RefPtrWillBeRawPtr<Node> outerNode = passedOuterNode;
if (outerNode->isRootEditableElement()) {
lastNode = blockElement;
} else {
- lastNode = outerNode->cloneNode(isTableElement(outerNode.get()));
+ lastNode = outerNode->cloneNode(isRenderedHTMLTableElement(outerNode.get()));
appendNode(lastNode, blockElement);
}
- if (start.deprecatedNode() != outerNode && lastNode->isElementNode()) {
- Vector<RefPtr<Node> > ancestors;
+ if (start.anchorNode() != outerNode && lastNode->isElementNode() && start.anchorNode()->isDescendantOf(outerNode.get())) {
+ WillBeHeapVector<RefPtrWillBeMember<Node>> ancestors;
// Insert each node from innerNode to outerNode (excluded) in a list.
for (Node* n = start.deprecatedNode(); n && n != outerNode; n = n->parentNode())
for (size_t i = ancestors.size(); i != 0; --i) {
Node* item = ancestors[i - 1].get();
- RefPtr<Node> child = item->cloneNode(isTableElement(item));
+ RefPtrWillBeRawPtr<Node> child = item->cloneNode(isRenderedHTMLTableElement(item));
appendNode(child, toElement(lastNode));
lastNode = child.release();
}
}
+ // Scripts specified in javascript protocol may remove |outerNode|
+ // during insertion, e.g. <iframe src="javascript:...">
+ if (!outerNode->inDocument())
+ return;
+
// Handle the case of paragraphs with more than one node,
// cloning all the siblings until end.deprecatedNode() is reached.
// If end is not a descendant of outerNode we need to
// find the first common ancestor to increase the scope
// of our nextSibling traversal.
- while (!end.deprecatedNode()->isDescendantOf(outerNode.get())) {
+ while (outerNode && !end.deprecatedNode()->isDescendantOf(outerNode.get())) {
outerNode = outerNode->parentNode();
}
- RefPtr<Node> startNode = start.deprecatedNode();
- for (RefPtr<Node> node = NodeTraversal::nextSkippingChildren(startNode.get(), outerNode.get()); node; node = NodeTraversal::nextSkippingChildren(node.get(), outerNode.get())) {
+ if (!outerNode)
+ return;
+
+ RefPtrWillBeRawPtr<Node> startNode = start.deprecatedNode();
+ for (RefPtrWillBeRawPtr<Node> node = NodeTraversal::nextSkippingChildren(*startNode, outerNode.get()); node; node = NodeTraversal::nextSkippingChildren(*node, outerNode.get())) {
// Move lastNode up in the tree as much as node was moved up in the
// tree by NodeTraversal::nextSkippingChildren, so that the relative depth between
// node and the original start node is maintained in the clone.
- while (startNode->parentNode() != node->parentNode()) {
+ while (startNode && lastNode && startNode->parentNode() != node->parentNode()) {
startNode = startNode->parentNode();
lastNode = lastNode->parentNode();
}
- RefPtr<Node> clonedNode = node->cloneNode(true);
+ if (!lastNode || !lastNode->parentNode())
+ return;
+
+ RefPtrWillBeRawPtr<Node> clonedNode = node->cloneNode(true);
insertNodeAfter(clonedNode, lastNode);
lastNode = clonedNode.release();
if (node == end.deprecatedNode() || end.deprecatedNode()->isDescendantOf(node.get()))
return;
// Normally deletion will leave a br as a placeholder.
- if (node->hasTagName(brTag)) {
+ if (isHTMLBRElement(*node)) {
removeNodeAndPruneAncestors(node, destinationNode);
// If the selection to move was empty and in an empty block that
// The blockElement parameter is the element to move the paragraph to,
// outerNode is the top element of the paragraph hierarchy.
-void CompositeEditCommand::moveParagraphWithClones(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, Element* blockElement, Node* outerNode)
+void CompositeEditCommand::moveParagraphWithClones(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, HTMLElement* blockElement, Node* outerNode)
{
ASSERT(outerNode);
ASSERT(blockElement);
// We upstream() the end and downstream() the start so that we don't include collapsed whitespace in the move.
// When we paste a fragment, spaces after the end and before the start are treated as though they were rendered.
Position start = startOfParagraphToMove.deepEquivalent().downstream();
- Position end = endOfParagraphToMove.deepEquivalent().upstream();
+ Position end = startOfParagraphToMove == endOfParagraphToMove ? start : endOfParagraphToMove.deepEquivalent().upstream();
+ if (comparePositions(start, end) > 0)
+ end = start;
cloneParagraphUnderNewElement(start, end, outerNode, blockElement);
setEndingSelection(VisibleSelection(start, end, DOWNSTREAM));
- deleteSelection(false, false, false, false);
+ deleteSelection(false, false, false);
// There are bugs in deletion when it removes a fully selected table/list.
// It expands and removes the entire table/list, but will let content
beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent());
afterParagraph = VisiblePosition(afterParagraph.deepEquivalent());
- if (beforeParagraph.isNotNull() && !isTableElement(beforeParagraph.deepEquivalent().deprecatedNode())
+ if (beforeParagraph.isNotNull() && !isRenderedTableElement(beforeParagraph.deepEquivalent().deprecatedNode())
&& ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforeParagraph)) || beforeParagraph == afterParagraph)) {
// FIXME: Trim text between beforeParagraph and afterParagraph if they aren't equal.
insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquivalent());
void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& destination, bool preserveSelection, bool preserveStyle, Node* constrainingAncestor)
{
- if (startOfParagraphToMove == destination)
+ if (startOfParagraphToMove == destination || startOfParagraphToMove.isNull())
return;
int startIndex = -1;
bool endInParagraph = comparePositions(visibleEnd, endOfParagraphToMove) <= 0;
startIndex = 0;
- if (startInParagraph) {
- RefPtr<Range> startRange = Range::create(document(), startOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent(), visibleStart.deepEquivalent().parentAnchoredEquivalent());
- startIndex = TextIterator::rangeLength(startRange.get(), true);
- }
+ if (startInParagraph)
+ startIndex = TextIterator::rangeLength(startOfParagraphToMove.toParentAnchoredPosition(), visibleStart.toParentAnchoredPosition(), true);
endIndex = 0;
- if (endInParagraph) {
- RefPtr<Range> endRange = Range::create(document(), startOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent(), visibleEnd.deepEquivalent().parentAnchoredEquivalent());
- endIndex = TextIterator::rangeLength(endRange.get(), true);
- }
+ if (endInParagraph)
+ endIndex = TextIterator::rangeLength(startOfParagraphToMove.toParentAnchoredPosition(), visibleEnd.toParentAnchoredPosition(), true);
}
}
// start and end can't be used directly to create a Range; they are "editing positions"
Position startRangeCompliant = start.parentAnchoredEquivalent();
Position endRangeCompliant = end.parentAnchoredEquivalent();
- RefPtr<Range> range = Range::create(document(), startRangeCompliant.deprecatedNode(), startRangeCompliant.deprecatedEditingOffset(), endRangeCompliant.deprecatedNode(), endRangeCompliant.deprecatedEditingOffset());
+ RefPtrWillBeRawPtr<Range> range = Range::create(document(), startRangeCompliant.deprecatedNode(), startRangeCompliant.deprecatedEditingOffset(), endRangeCompliant.deprecatedNode(), endRangeCompliant.deprecatedEditingOffset());
// FIXME: This is an inefficient way to preserve style on nodes in the paragraph to move. It
// shouldn't matter though, since moved paragraphs will usually be quite small.
- RefPtr<DocumentFragment> fragment = startOfParagraphToMove != endOfParagraphToMove ?
- createFragmentFromMarkup(document(), createMarkup(range.get(), 0, DoNotAnnotateForInterchange, true, DoNotResolveURLs, constrainingAncestor), "") : 0;
+ RefPtrWillBeRawPtr<DocumentFragment> fragment = startOfParagraphToMove != endOfParagraphToMove ?
+ createFragmentFromMarkup(document(), createMarkup(range.get(), 0, DoNotAnnotateForInterchange, true, DoNotResolveURLs, constrainingAncestor), "") : nullptr;
// A non-empty paragraph's style is moved when we copy and move it. We don't move
// anything if we're given an empty paragraph, but an empty paragraph can have style
// too, <div><b><br></b></div> for example. Save it so that we can preserve it later.
- RefPtr<EditingStyle> styleInEmptyParagraph;
+ RefPtrWillBeRawPtr<EditingStyle> styleInEmptyParagraph = nullptr;
if (startOfParagraphToMove == endOfParagraphToMove && preserveStyle) {
styleInEmptyParagraph = EditingStyle::create(startOfParagraphToMove.deepEquivalent());
styleInEmptyParagraph->mergeTypingStyle(&document());
setEndingSelection(VisibleSelection(start, end, DOWNSTREAM));
document().frame()->spellChecker().clearMisspellingsAndBadGrammar(endingSelection());
- deleteSelection(false, false, false, false);
+ deleteSelection(false, false, false);
ASSERT(destination.deepEquivalent().inDocument());
cleanupAfterDeletion(destination);
document().updateLayoutIgnorePendingStylesheets();
}
- RefPtr<Range> startToDestinationRange(Range::create(document(), firstPositionInNode(document().documentElement()), destination.deepEquivalent().parentAnchoredEquivalent()));
- destinationIndex = TextIterator::rangeLength(startToDestinationRange.get(), true);
+ destinationIndex = TextIterator::rangeLength(firstPositionInNode(document().documentElement()), destination.toParentAnchoredPosition(), true);
setEndingSelection(VisibleSelection(destination, originalIsDirectional));
ASSERT(endingSelection().isCaretOrRange());
applyStyle(styleInEmptyParagraph.get());
if (preserveSelection && startIndex != -1) {
- // Fragment creation (using createMarkup) incorrectly uses regular
- // spaces instead of nbsps for some spaces that were rendered (11475), which
- // causes spaces to be collapsed during the move operation. This results
- // in a call to rangeFromLocationAndLength with a location past the end
- // of the document (which will return null).
- RefPtr<Range> start = PlainTextRange(destinationIndex + startIndex).createRangeForSelection(*document().documentElement());
- RefPtr<Range> end = PlainTextRange(destinationIndex + endIndex).createRangeForSelection(*document().documentElement());
- if (start && end)
- setEndingSelection(VisibleSelection(start->startPosition(), end->startPosition(), DOWNSTREAM, originalIsDirectional));
+ if (Element* documentElement = document().documentElement()) {
+ // Fragment creation (using createMarkup) incorrectly uses regular
+ // spaces instead of nbsps for some spaces that were rendered (11475), which
+ // causes spaces to be collapsed during the move operation. This results
+ // in a call to rangeFromLocationAndLength with a location past the end
+ // of the document (which will return null).
+ RefPtrWillBeRawPtr<Range> start = PlainTextRange(destinationIndex + startIndex).createRangeForSelection(*documentElement);
+ RefPtrWillBeRawPtr<Range> end = PlainTextRange(destinationIndex + endIndex).createRangeForSelection(*documentElement);
+ if (start && end)
+ setEndingSelection(VisibleSelection(start->startPosition(), end->startPosition(), DOWNSTREAM, originalIsDirectional));
+ }
}
}
// FIXME: Send an appropriate shouldDeleteRange call.
bool CompositeEditCommand::breakOutOfEmptyListItem()
{
- RefPtr<Node> emptyListItem = enclosingEmptyListItem(endingSelection().visibleStart());
+ RefPtrWillBeRawPtr<Node> emptyListItem = enclosingEmptyListItem(endingSelection().visibleStart());
if (!emptyListItem)
return false;
- RefPtr<EditingStyle> style = EditingStyle::create(endingSelection().start());
+ RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(endingSelection().start());
style->mergeTypingStyle(&document());
- RefPtr<ContainerNode> listNode = emptyListItem->parentNode();
+ RefPtrWillBeRawPtr<ContainerNode> listNode = emptyListItem->parentNode();
// FIXME: Can't we do something better when the immediate parent wasn't a list node?
if (!listNode
- || (!listNode->hasTagName(ulTag) && !listNode->hasTagName(olTag))
- || !listNode->rendererIsEditable()
+ || (!isHTMLUListElement(*listNode) && !isHTMLOListElement(*listNode))
+ || !listNode->hasEditableStyle()
|| listNode == emptyListItem->rootEditableElement())
return false;
- RefPtr<Element> newBlock = 0;
+ RefPtrWillBeRawPtr<HTMLElement> newBlock = nullptr;
if (ContainerNode* blockEnclosingList = listNode->parentNode()) {
- if (blockEnclosingList->hasTagName(liTag)) { // listNode is inside another list item
- if (visiblePositionAfterNode(blockEnclosingList) == visiblePositionAfterNode(listNode.get())) {
+ if (isHTMLLIElement(*blockEnclosingList)) { // listNode is inside another list item
+ if (visiblePositionAfterNode(*blockEnclosingList) == visiblePositionAfterNode(*listNode)) {
// If listNode appears at the end of the outer list item, then move listNode outside of this list item
// e.g. <ul><li>hello <ul><li><br></li></ul> </li></ul> should become <ul><li>hello</li> <ul><li><br></li></ul> </ul> after this section
// If listNode does NOT appear at the end, then we should consider it as a regular paragraph.
newBlock = createListItemElement(document());
}
// If listNode does NOT appear at the end of the outer list item, then behave as if in a regular paragraph.
- } else if (blockEnclosingList->hasTagName(olTag) || blockEnclosingList->hasTagName(ulTag)) {
+ } else if (isHTMLOListElement(*blockEnclosingList) || isHTMLUListElement(*blockEnclosingList)) {
newBlock = createListItemElement(document());
}
}
if (!newBlock)
newBlock = createDefaultParagraphElement(document());
- RefPtr<Node> previousListNode = emptyListItem->isElementNode() ? toElement(emptyListItem)->previousElementSibling(): emptyListItem->previousSibling();
- RefPtr<Node> nextListNode = emptyListItem->isElementNode() ? toElement(emptyListItem)->nextElementSibling(): emptyListItem->nextSibling();
- if (isListItem(nextListNode.get()) || isListElement(nextListNode.get())) {
+ RefPtrWillBeRawPtr<Node> previousListNode = emptyListItem->isElementNode() ? ElementTraversal::previousSibling(*emptyListItem): emptyListItem->previousSibling();
+ RefPtrWillBeRawPtr<Node> nextListNode = emptyListItem->isElementNode() ? ElementTraversal::nextSibling(*emptyListItem): emptyListItem->nextSibling();
+ if (isListItem(nextListNode.get()) || isHTMLListElement(nextListNode.get())) {
// If emptyListItem follows another list item or nested list, split the list node.
- if (isListItem(previousListNode.get()) || isListElement(previousListNode.get()))
+ if (isListItem(previousListNode.get()) || isHTMLListElement(previousListNode.get()))
splitElement(toElement(listNode), emptyListItem);
// If emptyListItem is followed by other list item or nested list, then insert newBlock before the list node.
// When emptyListItem does not follow any list item or nested list, insert newBlock after the enclosing list node.
// Remove the enclosing node if emptyListItem is the only child; otherwise just remove emptyListItem.
insertNodeAfter(newBlock, listNode);
- removeNode(isListItem(previousListNode.get()) || isListElement(previousListNode.get()) ? emptyListItem.get() : listNode.get());
+ removeNode(isListItem(previousListNode.get()) || isHTMLListElement(previousListNode.get()) ? emptyListItem.get() : listNode.get());
}
appendBlockPlaceholder(newBlock);
return false;
VisiblePosition caret(endingSelection().visibleStart());
- Node* highestBlockquote = highestEnclosingNodeOfType(caret.deepEquivalent(), &isMailBlockquote);
+ HTMLQuoteElement* highestBlockquote = toHTMLQuoteElement(highestEnclosingNodeOfType(caret.deepEquivalent(), &isMailHTMLBlockquoteElement));
if (!highestBlockquote)
return false;
VisiblePosition previous(caret.previous(CannotCrossEditingBoundary));
// Only move forward if there's nothing before the caret, or if there's unquoted content before it.
- if (enclosingNodeOfType(previous.deepEquivalent(), &isMailBlockquote))
+ if (enclosingNodeOfType(previous.deepEquivalent(), &isMailHTMLBlockquoteElement))
return false;
- RefPtr<Node> br = createBreakElement(document());
+ RefPtrWillBeRawPtr<HTMLBRElement> br = createBreakElement(document());
// We want to replace this quoted paragraph with an unquoted one, so insert a br
// to hold the caret before the highest blockquote.
insertNodeBefore(br, highestBlockquote);
Position caretPos(caret.deepEquivalent().downstream());
// A line break is either a br or a preserved newline.
- ASSERT(caretPos.deprecatedNode()->hasTagName(brTag) || (caretPos.deprecatedNode()->isTextNode() && caretPos.deprecatedNode()->renderer()->style()->preserveNewline()));
+ ASSERT(isHTMLBRElement(caretPos.deprecatedNode()) || (caretPos.deprecatedNode()->isTextNode() && caretPos.deprecatedNode()->renderer()->style()->preserveNewline()));
- if (caretPos.deprecatedNode()->hasTagName(brTag))
+ if (isHTMLBRElement(*caretPos.deprecatedNode()))
removeNodeAndPruneAncestors(caretPos.deprecatedNode());
else if (caretPos.deprecatedNode()->isTextNode()) {
ASSERT(caretPos.deprecatedEditingOffset() == 0);
return original;
VisiblePosition visiblePos(original);
- Node* enclosingAnchor = enclosingAnchorElement(original);
+ Element* enclosingAnchor = enclosingAnchorElement(original);
Position result = original;
if (!enclosingAnchor)
if (lineBreakExistsAtVisiblePosition(visiblePos) && downstream.deprecatedNode()->isDescendantOf(enclosingAnchor))
return original;
- result = positionInParentAfterNode(enclosingAnchor);
+ result = positionInParentAfterNode(*enclosingAnchor);
}
// If visually just before an anchor, insert *outside* the anchor unless it's the first
// VisiblePosition in a paragraph, to match NSTextView.
if (!enclosingAnchor)
return original;
- result = positionInParentBeforeNode(enclosingAnchor);
+ result = positionInParentBeforeNode(*enclosingAnchor);
}
}
// Splits the tree parent by parent until we reach the specified ancestor. We use VisiblePositions
// to determine if the split is necessary. Returns the last split node.
-PassRefPtr<Node> CompositeEditCommand::splitTreeToNode(Node* start, Node* end, bool shouldSplitAncestor)
+PassRefPtrWillBeRawPtr<Node> CompositeEditCommand::splitTreeToNode(Node* start, Node* end, bool shouldSplitAncestor)
{
ASSERT(start);
ASSERT(end);
ASSERT(start != end);
- RefPtr<Node> node;
if (shouldSplitAncestor && end->parentNode())
end = end->parentNode();
-
- RefPtr<Node> endNode = end;
- for (node = start; node && node->parentNode() != endNode; node = node->parentNode()) {
- if (!node->parentNode()->isElementNode())
+ if (!start->isDescendantOf(end))
+ return end;
+
+ RefPtrWillBeRawPtr<Node> endNode = end;
+ RefPtrWillBeRawPtr<Node> node = nullptr;
+ for (node = start; node->parentNode() != endNode; node = node->parentNode()) {
+ Element* parentElement = node->parentElement();
+ if (!parentElement)
break;
// Do not split a node when doing so introduces an empty node.
- VisiblePosition positionInParent = firstPositionInNode(node->parentNode());
- VisiblePosition positionInNode = firstPositionInOrBeforeNode(node.get());
+ VisiblePosition positionInParent(firstPositionInNode(parentElement));
+ VisiblePosition positionInNode(firstPositionInOrBeforeNode(node.get()));
if (positionInParent != positionInNode)
- splitElement(toElement(node->parentNode()), node);
+ splitElement(parentElement, node);
}
return node.release();
}
-PassRefPtr<Element> createBlockPlaceholderElement(Document& document)
+void CompositeEditCommand::trace(Visitor* visitor)
{
- RefPtr<Element> breakNode = document.createElement(brTag, false);
- return breakNode.release();
+ visitor->trace(m_commands);
+ visitor->trace(m_composition);
+ EditCommand::trace(visitor);
}
-} // namespace WebCore
+} // namespace blink