2008-12-23 Darin Adler <darin@apple.com>
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Dec 2008 21:42:46 +0000 (21:42 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Dec 2008 21:42:46 +0000 (21:42 +0000)
        Reviewed by John Sullivan.

        - improve robustness of undo/redo in HTML editing to fix the following bugs
          <https://bugs.webkit.org/show_bug.cgi?id=19703> Crash in WebCore::InsertNodeBeforeCommand::doUnapply()
          <rdar://problem/4059423> DOM operations performed on editable HTML can cause a crash later during Undo

        Major categories of improvements:

            1) Added null checks.
            2) Eliminated type casts without corresponding type checks.
            3) Avoided possible infinite loops by building up lists of nodes to operate on
               before starting to make DOM changes.
            4) Use more RefPtr.

        No test at this time, but test cases should follow in separate patches.

        * WebCore.xcodeproj/project.pbxproj: Set the role of CSSPropertyNames.h to Private so it
        can be used in other Private headers, specifically editing ones.

        * css/CSSStyleSelector.cpp:
        (WebCore::CSSStyleSelector::locateCousinList): Adopt parentElement.
        (WebCore::CSSStyleSelector::locateSharedStyle): Ditto.
        (WebCore::CSSStyleSelector::SelectorChecker::checkOneSelector): Ditto.

        * dom/Element.cpp: (WebCore::Element::cloneElement): Added.
        * dom/Element.h: Added cloneElement and an implementation of parentElement.
        * dom/Node.h: Moved parentElement from here to Element.h and changed its
        implementation so it will return 0 when the parent is not an element
        (document, document fragment, etc.).

        * editing/AppendNodeCommand.cpp:
        (WebCore::AppendNodeCommand::AppendNodeCommand): Made parent be an Element.
        Moved assertions from doApply in here.
        (WebCore::AppendNodeCommand::doApply): Simplified to just a single unchecked
        appendChild call.
        (WebCore::AppendNodeCommand::doUnapply): Simplified to just a single remove call.
        * editing/AppendNodeCommand.h: Updated.

        * editing/ApplyStyleCommand.cpp:
        (WebCore::createStyleSpanElement): Eliminate casting by creating an element in a more
        direct way with new instead of createElementNS.
        (WebCore::ApplyStyleCommand::ApplyStyleCommand): Use PassRefPtr.
        (WebCore::ApplyStyleCommand::removeCSSStyle): Use CSSPropertyID.
        (WebCore::ApplyStyleCommand::addInlineStyleIfNeeded): Use cloneElement.
        * editing/ApplyStyleCommand.h:

        * editing/BreakBlockquoteCommand.cpp:
        (WebCore::BreakBlockquoteCommand::doApply): Use Element* and cloneElement.

        * editing/CompositeEditCommand.cpp:
        (WebCore::CompositeEditCommand::applyStyledElement): Use PassRefPtr and unsigned.
        (WebCore::CompositeEditCommand::removeStyledElement): Ditto.
        (WebCore::CompositeEditCommand::insertNodeBefore): Ditto.
        (WebCore::CompositeEditCommand::insertNodeAfter): Ditto.
        (WebCore::CompositeEditCommand::insertNodeAt): Ditto.
        (WebCore::CompositeEditCommand::appendNode): Ditto.
        (WebCore::CompositeEditCommand::removeChildrenInRange): Ditto. Also use a vector to
        make the list of children in case removing them has side effects.
        (WebCore::CompositeEditCommand::removeNode): Ditto.
        (WebCore::CompositeEditCommand::removeNodePreservingChildren): Ditto.
        (WebCore::CompositeEditCommand::removeNodeAndPruneAncestors): Ditto.
        (WebCore::CompositeEditCommand::splitTextNode): Ditto.
        (WebCore::CompositeEditCommand::splitElement): Ditto.
        (WebCore::CompositeEditCommand::mergeIdenticalElements): Ditto.
        (WebCore::CompositeEditCommand::wrapContentsInDummySpan): Ditto.
        (WebCore::CompositeEditCommand::splitTextNodeContainingElement): Ditto.
        (WebCore::CompositeEditCommand::joinTextNodes): Ditto.
        (WebCore::CompositeEditCommand::inputText): Ditto.
        (WebCore::CompositeEditCommand::insertTextIntoNode): Ditto.
        (WebCore::CompositeEditCommand::deleteTextFromNode): Ditto.
        (WebCore::CompositeEditCommand::replaceTextInNode): Ditto.
        (WebCore::CompositeEditCommand::insertNodeAtTabSpanPosition): Ditto.
        (WebCore::CompositeEditCommand::removeCSSProperty): Ditto.
        (WebCore::CompositeEditCommand::removeNodeAttribute): Ditto. Implement by calling
        setNodeAttribute instead of with its own SimpleEditCommand.
        (WebCore::CompositeEditCommand::setNodeAttribute): Ditto.
        (WebCore::CompositeEditCommand::deleteInsignificantText): Ditto.
        (WebCore::CompositeEditCommand::appendBlockPlaceholder): Ditto.
        (WebCore::CompositeEditCommand::addBlockPlaceholderIfNeeded): Ditto.
        (WebCore::CompositeEditCommand::insertNewDefaultParagraphElementAt): Ditto. Don't
        bother using an undoable operation to put the break element into the paragraph
        element because there's no need to split them and redo this when doing undo/redo.
        (WebCore::CompositeEditCommand::moveParagraphs): Ditto.
        (WebCore::CompositeEditCommand::breakOutOfEmptyListItem): Ditto.
        * editing/CompositeEditCommand.h: Ditto.

        * editing/DeleteFromTextNodeCommand.cpp:
        (WebCore::DeleteFromTextNodeCommand::DeleteFromTextNodeCommand): Use unsigned.
        (WebCore::DeleteFromTextNodeCommand::doApply): Eliminated inappropriate assertions.
        (WebCore::DeleteFromTextNodeCommand::doUnapply): Ditto.
        * editing/DeleteFromTextNodeCommand.h:

        * editing/DeleteSelectionCommand.cpp:
        (WebCore::DeleteSelectionCommand::removeNode): Use PassRefPtr.
        (WebCore::DeleteSelectionCommand::deleteTextFromNode): Ditto.
        * editing/DeleteSelectionCommand.h:

        * editing/FormatBlockCommand.cpp:
        (WebCore::FormatBlockCommand::FormatBlockCommand): Use AtomicString.
        (WebCore::FormatBlockCommand::doApply): Use Element.
        * editing/FormatBlockCommand.h:

        * editing/IndentOutdentCommand.cpp:
        (WebCore::createIndentBlockquoteElement): Use new to create the element
        instead of calling a function so we have a more specific type.
        (WebCore::IndentOutdentCommand::prepareBlockquoteLevelForInsertion):
        Use RefPtr and Element.
        (WebCore::IndentOutdentCommand::indentRegion): Ditto.
        (WebCore::IndentOutdentCommand::outdentParagraph): Ditto.
        * editing/IndentOutdentCommand.h:

        * editing/InsertIntoTextNodeCommand.cpp:
        (WebCore::InsertIntoTextNodeCommand::InsertIntoTextNodeCommand):
        Use unsigned. Added an assertion.
        (WebCore::InsertIntoTextNodeCommand::doApply): Eliminated inappropriate assertions.
        (WebCore::InsertIntoTextNodeCommand::doUnapply): Ditto.
        * editing/InsertIntoTextNodeCommand.h:

        * editing/InsertLineBreakCommand.cpp:
        (WebCore::InsertLineBreakCommand::insertNodeAfterPosition): Use Element.
        (WebCore::InsertLineBreakCommand::insertNodeBeforePosition): Ditto.

        * editing/InsertListCommand.cpp:
        (WebCore::InsertListCommand::doApply): Use Element.

        * editing/InsertNodeBeforeCommand.cpp:
        (WebCore::InsertNodeBeforeCommand::InsertNodeBeforeCommand): Moved assertions
        here from doApply.
        (WebCore::InsertNodeBeforeCommand::doApply): Eliminated inappropriate assertions.
        Added a null check.
        (WebCore::InsertNodeBeforeCommand::doUnapply): Simplified to just a single remove call.

        * editing/InsertParagraphSeparatorCommand.cpp:
        (WebCore::InsertParagraphSeparatorCommand::doApply): Use Element and cloneElement.

        * editing/JoinTextNodesCommand.cpp:
        (WebCore::JoinTextNodesCommand::doApply): Eliminated inappropriate assertions.
        Added some runtime checks. Don't store anything in m_offset.
        (WebCore::JoinTextNodesCommand::doUnapply): Ditto.
        * editing/JoinTextNodesCommand.h:

        * editing/MergeIdenticalElementsCommand.cpp:
        (WebCore::MergeIdenticalElementsCommand::MergeIdenticalElementsCommand): Moved
        an assertion here from doApply.
        (WebCore::MergeIdenticalElementsCommand::doApply): Eliminated inappropriate assertions.
        Added a null check. Changed implementation to use remove to avoid null parent issue.
        Use a vector of nodes to avoid possible infinite loop if mutation happens while iterating.
        (WebCore::MergeIdenticalElementsCommand::doUnapply): Ditto.

        * editing/ModifySelectionListLevel.cpp:
        (WebCore::ModifySelectionListLevelCommand::appendSiblingNodeRange): Use Element*.
        (WebCore::IncreaseSelectionListLevelCommand::doApply): Ditto.
        * editing/ModifySelectionListLevel.h:

        * editing/RemoveCSSPropertyCommand.cpp:
        (WebCore::RemoveCSSPropertyCommand::RemoveCSSPropertyCommand): Use PassRefPtr and
        CSSPropertyID. Also renamed m_decl to m_style.
        (WebCore::RemoveCSSPropertyCommand::doApply): Eliminated inappropriate assertions.
        (WebCore::RemoveCSSPropertyCommand::doUnapply): Ditto.

        * editing/RemoveNodeAttributeCommand.cpp: Removed contents of this file. To be deleted.
        Use SetNodeAttributeCommand instead.
        * editing/RemoveNodeAttributeCommand.h: Ditto.

        * editing/RemoveNodeCommand.cpp:
        (WebCore::RemoveNodeCommand::RemoveNodeCommand): Moved assertions here from doApply.
        Don't initialize m_refChild here; rather do it in doApply.
        (WebCore::RemoveNodeCommand::doApply): Eliminated inappropriate assertions. Added
        checks and streamlined implementation.
        (WebCore::RemoveNodeCommand::doUnapply): Ditto.
        * editing/RemoveNodeCommand.h:

        * editing/RemoveNodePreservingChildrenCommand.cpp:
        (WebCore::RemoveNodePreservingChildrenCommand::doApply): Use a vector.

        * editing/ReplaceSelectionCommand.cpp:
        (WebCore::ReplacementFragment::insertFragmentForTestRendering): Removed now-unneeded cast.

        * editing/SetNodeAttributeCommand.cpp:
        (WebCore::SetNodeAttributeCommand::SetNodeAttributeCommand): Use AtomicString.
        Removed assertion that prevents us from using this to remove an attribute.
        (WebCore::SetNodeAttributeCommand::doApply): Eliminated inappropriate assertions.
        (WebCore::SetNodeAttributeCommand::doUnapply): Ditto.
        * editing/SetNodeAttributeCommand.h:

        * editing/SplitElementCommand.cpp:
        (WebCore::SplitElementCommand::SplitElementCommand): Moved assertion here from doApply.
        (WebCore::SplitElementCommand::doApply): Check some more invariants and use a vector
        to avoid possible infinite loops.
        (WebCore::SplitElementCommand::doUnapply): Ditto.

        * editing/SplitTextNodeCommand.cpp:
        (WebCore::SplitTextNodeCommand::SplitTextNodeCommand): Moved assertions and comment
        here from doApply.
        (WebCore::SplitTextNodeCommand::doApply): Check for null and failures when applying.
        (WebCore::SplitTextNodeCommand::doUnapply): Ditto.

        * editing/SplitTextNodeContainingElementCommand.cpp:
        (WebCore::SplitTextNodeContainingElementCommand::doApply): Use Element.

        * editing/WrapContentsInDummySpanCommand.cpp:
        (WebCore::WrapContentsInDummySpanCommand::doApply): Check for null and ignore failures.
        Don't reuse the dummy span. Simplified logic.
        (WebCore::WrapContentsInDummySpanCommand::doUnapply): Ditto.

        * editing/htmlediting.cpp:
        (WebCore::isBlock): Make sure this returns true only for elements.
        (WebCore::enclosingBlock): Return an Element*.
        (WebCore::enclosingTableCell): Ditto.
        (WebCore::enclosingList): Return an HTMLElement*.
        (WebCore::outermostEnclosingList): Return an HTMLElement*.
        (WebCore::createDefaultParagraphElement): Return an HTMLElement*.
        (WebCore::createBreakElement): Return an HTMLElement*.
        (WebCore::createOrderedListElement): Return an HTMLElement*.
        (WebCore::createUnorderedListElement): Return an HTMLElement*.
        (WebCore::createListItemElement): Return an HTMLElement*.
        (WebCore::createHTMLElement): Return an HTMLElement*.
        * editing/htmlediting.h:

        * editing/markup.cpp:
        (WebCore::createFragmentFromText): Use createBreakElement and use Element*.

        * page/MouseEventWithHitTestResults.cpp:
        (WebCore::MouseEventWithHitTestResults::targetNode): Use parentElement.

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

52 files changed:
WebCore/ChangeLog
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/css/CSSStyleSelector.cpp
WebCore/dom/Element.cpp
WebCore/dom/Element.h
WebCore/dom/Node.h
WebCore/editing/AppendNodeCommand.cpp
WebCore/editing/AppendNodeCommand.h
WebCore/editing/ApplyStyleCommand.cpp
WebCore/editing/ApplyStyleCommand.h
WebCore/editing/BreakBlockquoteCommand.cpp
WebCore/editing/CompositeEditCommand.cpp
WebCore/editing/CompositeEditCommand.h
WebCore/editing/DeleteFromTextNodeCommand.cpp
WebCore/editing/DeleteFromTextNodeCommand.h
WebCore/editing/DeleteSelectionCommand.cpp
WebCore/editing/DeleteSelectionCommand.h
WebCore/editing/FormatBlockCommand.cpp
WebCore/editing/FormatBlockCommand.h
WebCore/editing/IndentOutdentCommand.cpp
WebCore/editing/IndentOutdentCommand.h
WebCore/editing/InsertIntoTextNodeCommand.cpp
WebCore/editing/InsertIntoTextNodeCommand.h
WebCore/editing/InsertLineBreakCommand.cpp
WebCore/editing/InsertListCommand.cpp
WebCore/editing/InsertListCommand.h
WebCore/editing/InsertNodeBeforeCommand.cpp
WebCore/editing/InsertParagraphSeparatorCommand.cpp
WebCore/editing/JoinTextNodesCommand.cpp
WebCore/editing/JoinTextNodesCommand.h
WebCore/editing/MergeIdenticalElementsCommand.cpp
WebCore/editing/ModifySelectionListLevel.cpp
WebCore/editing/ModifySelectionListLevel.h
WebCore/editing/RemoveCSSPropertyCommand.cpp
WebCore/editing/RemoveCSSPropertyCommand.h
WebCore/editing/RemoveNodeAttributeCommand.cpp
WebCore/editing/RemoveNodeAttributeCommand.h
WebCore/editing/RemoveNodeCommand.cpp
WebCore/editing/RemoveNodeCommand.h
WebCore/editing/RemoveNodePreservingChildrenCommand.cpp
WebCore/editing/ReplaceSelectionCommand.cpp
WebCore/editing/SetNodeAttributeCommand.cpp
WebCore/editing/SetNodeAttributeCommand.h
WebCore/editing/SplitElementCommand.cpp
WebCore/editing/SplitTextNodeCommand.cpp
WebCore/editing/SplitTextNodeContainingElementCommand.cpp
WebCore/editing/WrapContentsInDummySpanCommand.cpp
WebCore/editing/WrapContentsInDummySpanCommand.h
WebCore/editing/htmlediting.cpp
WebCore/editing/htmlediting.h
WebCore/editing/markup.cpp
WebCore/page/MouseEventWithHitTestResults.cpp

index 12d5f30..a87e9fc 100644 (file)
@@ -1,5 +1,232 @@
 2008-12-23  Darin Adler  <darin@apple.com>
 
+        Reviewed by John Sullivan.
+
+        - improve robustness of undo/redo in HTML editing to fix the following bugs
+          <https://bugs.webkit.org/show_bug.cgi?id=19703> Crash in WebCore::InsertNodeBeforeCommand::doUnapply()
+          <rdar://problem/4059423> DOM operations performed on editable HTML can cause a crash later during Undo
+
+        Major categories of improvements:
+
+            1) Added null checks.
+            2) Eliminated type casts without corresponding type checks.
+            3) Avoided possible infinite loops by building up lists of nodes to operate on
+               before starting to make DOM changes.
+            4) Use more RefPtr.
+
+        No test at this time, but test cases should follow in separate patches.
+
+        * WebCore.xcodeproj/project.pbxproj: Set the role of CSSPropertyNames.h to Private so it
+        can be used in other Private headers, specifically editing ones.
+
+        * css/CSSStyleSelector.cpp:
+        (WebCore::CSSStyleSelector::locateCousinList): Adopt parentElement.
+        (WebCore::CSSStyleSelector::locateSharedStyle): Ditto.
+        (WebCore::CSSStyleSelector::SelectorChecker::checkOneSelector): Ditto.
+
+        * dom/Element.cpp: (WebCore::Element::cloneElement): Added.
+        * dom/Element.h: Added cloneElement and an implementation of parentElement.
+        * dom/Node.h: Moved parentElement from here to Element.h and changed its
+        implementation so it will return 0 when the parent is not an element
+        (document, document fragment, etc.).
+
+        * editing/AppendNodeCommand.cpp:
+        (WebCore::AppendNodeCommand::AppendNodeCommand): Made parent be an Element.
+        Moved assertions from doApply in here.
+        (WebCore::AppendNodeCommand::doApply): Simplified to just a single unchecked
+        appendChild call.
+        (WebCore::AppendNodeCommand::doUnapply): Simplified to just a single remove call.
+        * editing/AppendNodeCommand.h: Updated.
+
+        * editing/ApplyStyleCommand.cpp:
+        (WebCore::createStyleSpanElement): Eliminate casting by creating an element in a more
+        direct way with new instead of createElementNS.
+        (WebCore::ApplyStyleCommand::ApplyStyleCommand): Use PassRefPtr.
+        (WebCore::ApplyStyleCommand::removeCSSStyle): Use CSSPropertyID.
+        (WebCore::ApplyStyleCommand::addInlineStyleIfNeeded): Use cloneElement.
+        * editing/ApplyStyleCommand.h:
+
+        * editing/BreakBlockquoteCommand.cpp:
+        (WebCore::BreakBlockquoteCommand::doApply): Use Element* and cloneElement.
+
+        * editing/CompositeEditCommand.cpp:
+        (WebCore::CompositeEditCommand::applyStyledElement): Use PassRefPtr and unsigned.
+        (WebCore::CompositeEditCommand::removeStyledElement): Ditto.
+        (WebCore::CompositeEditCommand::insertNodeBefore): Ditto.
+        (WebCore::CompositeEditCommand::insertNodeAfter): Ditto.
+        (WebCore::CompositeEditCommand::insertNodeAt): Ditto.
+        (WebCore::CompositeEditCommand::appendNode): Ditto.
+        (WebCore::CompositeEditCommand::removeChildrenInRange): Ditto. Also use a vector to
+        make the list of children in case removing them has side effects.
+        (WebCore::CompositeEditCommand::removeNode): Ditto.
+        (WebCore::CompositeEditCommand::removeNodePreservingChildren): Ditto.
+        (WebCore::CompositeEditCommand::removeNodeAndPruneAncestors): Ditto.
+        (WebCore::CompositeEditCommand::splitTextNode): Ditto.
+        (WebCore::CompositeEditCommand::splitElement): Ditto.
+        (WebCore::CompositeEditCommand::mergeIdenticalElements): Ditto.
+        (WebCore::CompositeEditCommand::wrapContentsInDummySpan): Ditto.
+        (WebCore::CompositeEditCommand::splitTextNodeContainingElement): Ditto.
+        (WebCore::CompositeEditCommand::joinTextNodes): Ditto.
+        (WebCore::CompositeEditCommand::inputText): Ditto.
+        (WebCore::CompositeEditCommand::insertTextIntoNode): Ditto.
+        (WebCore::CompositeEditCommand::deleteTextFromNode): Ditto.
+        (WebCore::CompositeEditCommand::replaceTextInNode): Ditto.
+        (WebCore::CompositeEditCommand::insertNodeAtTabSpanPosition): Ditto.
+        (WebCore::CompositeEditCommand::removeCSSProperty): Ditto.
+        (WebCore::CompositeEditCommand::removeNodeAttribute): Ditto. Implement by calling
+        setNodeAttribute instead of with its own SimpleEditCommand.
+        (WebCore::CompositeEditCommand::setNodeAttribute): Ditto.
+        (WebCore::CompositeEditCommand::deleteInsignificantText): Ditto.
+        (WebCore::CompositeEditCommand::appendBlockPlaceholder): Ditto.
+        (WebCore::CompositeEditCommand::addBlockPlaceholderIfNeeded): Ditto.
+        (WebCore::CompositeEditCommand::insertNewDefaultParagraphElementAt): Ditto. Don't
+        bother using an undoable operation to put the break element into the paragraph
+        element because there's no need to split them and redo this when doing undo/redo.
+        (WebCore::CompositeEditCommand::moveParagraphs): Ditto.
+        (WebCore::CompositeEditCommand::breakOutOfEmptyListItem): Ditto.
+        * editing/CompositeEditCommand.h: Ditto.
+
+        * editing/DeleteFromTextNodeCommand.cpp:
+        (WebCore::DeleteFromTextNodeCommand::DeleteFromTextNodeCommand): Use unsigned.
+        (WebCore::DeleteFromTextNodeCommand::doApply): Eliminated inappropriate assertions.
+        (WebCore::DeleteFromTextNodeCommand::doUnapply): Ditto.
+        * editing/DeleteFromTextNodeCommand.h:
+
+        * editing/DeleteSelectionCommand.cpp:
+        (WebCore::DeleteSelectionCommand::removeNode): Use PassRefPtr.
+        (WebCore::DeleteSelectionCommand::deleteTextFromNode): Ditto.
+        * editing/DeleteSelectionCommand.h:
+
+        * editing/FormatBlockCommand.cpp:
+        (WebCore::FormatBlockCommand::FormatBlockCommand): Use AtomicString.
+        (WebCore::FormatBlockCommand::doApply): Use Element.
+        * editing/FormatBlockCommand.h:
+
+        * editing/IndentOutdentCommand.cpp:
+        (WebCore::createIndentBlockquoteElement): Use new to create the element
+        instead of calling a function so we have a more specific type.
+        (WebCore::IndentOutdentCommand::prepareBlockquoteLevelForInsertion):
+        Use RefPtr and Element.
+        (WebCore::IndentOutdentCommand::indentRegion): Ditto.
+        (WebCore::IndentOutdentCommand::outdentParagraph): Ditto.
+        * editing/IndentOutdentCommand.h:
+
+        * editing/InsertIntoTextNodeCommand.cpp:
+        (WebCore::InsertIntoTextNodeCommand::InsertIntoTextNodeCommand):
+        Use unsigned. Added an assertion.
+        (WebCore::InsertIntoTextNodeCommand::doApply): Eliminated inappropriate assertions.
+        (WebCore::InsertIntoTextNodeCommand::doUnapply): Ditto.
+        * editing/InsertIntoTextNodeCommand.h:
+
+        * editing/InsertLineBreakCommand.cpp:
+        (WebCore::InsertLineBreakCommand::insertNodeAfterPosition): Use Element.
+        (WebCore::InsertLineBreakCommand::insertNodeBeforePosition): Ditto.
+
+        * editing/InsertListCommand.cpp:
+        (WebCore::InsertListCommand::doApply): Use Element.
+
+        * editing/InsertNodeBeforeCommand.cpp:
+        (WebCore::InsertNodeBeforeCommand::InsertNodeBeforeCommand): Moved assertions
+        here from doApply.
+        (WebCore::InsertNodeBeforeCommand::doApply): Eliminated inappropriate assertions.
+        Added a null check.
+        (WebCore::InsertNodeBeforeCommand::doUnapply): Simplified to just a single remove call.
+
+        * editing/InsertParagraphSeparatorCommand.cpp:
+        (WebCore::InsertParagraphSeparatorCommand::doApply): Use Element and cloneElement.
+
+        * editing/JoinTextNodesCommand.cpp:
+        (WebCore::JoinTextNodesCommand::doApply): Eliminated inappropriate assertions.
+        Added some runtime checks. Don't store anything in m_offset.
+        (WebCore::JoinTextNodesCommand::doUnapply): Ditto.
+        * editing/JoinTextNodesCommand.h:
+
+        * editing/MergeIdenticalElementsCommand.cpp:
+        (WebCore::MergeIdenticalElementsCommand::MergeIdenticalElementsCommand): Moved
+        an assertion here from doApply.
+        (WebCore::MergeIdenticalElementsCommand::doApply): Eliminated inappropriate assertions.
+        Added a null check. Changed implementation to use remove to avoid null parent issue.
+        Use a vector of nodes to avoid possible infinite loop if mutation happens while iterating.
+        (WebCore::MergeIdenticalElementsCommand::doUnapply): Ditto.
+
+        * editing/ModifySelectionListLevel.cpp:
+        (WebCore::ModifySelectionListLevelCommand::appendSiblingNodeRange): Use Element*.
+        (WebCore::IncreaseSelectionListLevelCommand::doApply): Ditto.
+        * editing/ModifySelectionListLevel.h:
+
+        * editing/RemoveCSSPropertyCommand.cpp:
+        (WebCore::RemoveCSSPropertyCommand::RemoveCSSPropertyCommand): Use PassRefPtr and
+        CSSPropertyID. Also renamed m_decl to m_style.
+        (WebCore::RemoveCSSPropertyCommand::doApply): Eliminated inappropriate assertions.
+        (WebCore::RemoveCSSPropertyCommand::doUnapply): Ditto.
+
+        * editing/RemoveNodeAttributeCommand.cpp: Removed contents of this file. To be deleted.
+        Use SetNodeAttributeCommand instead.
+        * editing/RemoveNodeAttributeCommand.h: Ditto.
+
+        * editing/RemoveNodeCommand.cpp:
+        (WebCore::RemoveNodeCommand::RemoveNodeCommand): Moved assertions here from doApply.
+        Don't initialize m_refChild here; rather do it in doApply.
+        (WebCore::RemoveNodeCommand::doApply): Eliminated inappropriate assertions. Added
+        checks and streamlined implementation.
+        (WebCore::RemoveNodeCommand::doUnapply): Ditto.
+        * editing/RemoveNodeCommand.h:
+
+        * editing/RemoveNodePreservingChildrenCommand.cpp:
+        (WebCore::RemoveNodePreservingChildrenCommand::doApply): Use a vector.
+
+        * editing/ReplaceSelectionCommand.cpp:
+        (WebCore::ReplacementFragment::insertFragmentForTestRendering): Removed now-unneeded cast.
+
+        * editing/SetNodeAttributeCommand.cpp:
+        (WebCore::SetNodeAttributeCommand::SetNodeAttributeCommand): Use AtomicString.
+        Removed assertion that prevents us from using this to remove an attribute.
+        (WebCore::SetNodeAttributeCommand::doApply): Eliminated inappropriate assertions.
+        (WebCore::SetNodeAttributeCommand::doUnapply): Ditto.
+        * editing/SetNodeAttributeCommand.h:
+
+        * editing/SplitElementCommand.cpp:
+        (WebCore::SplitElementCommand::SplitElementCommand): Moved assertion here from doApply.
+        (WebCore::SplitElementCommand::doApply): Check some more invariants and use a vector
+        to avoid possible infinite loops.
+        (WebCore::SplitElementCommand::doUnapply): Ditto.
+
+        * editing/SplitTextNodeCommand.cpp:
+        (WebCore::SplitTextNodeCommand::SplitTextNodeCommand): Moved assertions and comment
+        here from doApply.
+        (WebCore::SplitTextNodeCommand::doApply): Check for null and failures when applying.
+        (WebCore::SplitTextNodeCommand::doUnapply): Ditto.
+
+        * editing/SplitTextNodeContainingElementCommand.cpp:
+        (WebCore::SplitTextNodeContainingElementCommand::doApply): Use Element.
+
+        * editing/WrapContentsInDummySpanCommand.cpp:
+        (WebCore::WrapContentsInDummySpanCommand::doApply): Check for null and ignore failures.
+        Don't reuse the dummy span. Simplified logic.
+        (WebCore::WrapContentsInDummySpanCommand::doUnapply): Ditto.
+
+        * editing/htmlediting.cpp:
+        (WebCore::isBlock): Make sure this returns true only for elements.
+        (WebCore::enclosingBlock): Return an Element*.
+        (WebCore::enclosingTableCell): Ditto.
+        (WebCore::enclosingList): Return an HTMLElement*.
+        (WebCore::outermostEnclosingList): Return an HTMLElement*.
+        (WebCore::createDefaultParagraphElement): Return an HTMLElement*.
+        (WebCore::createBreakElement): Return an HTMLElement*.
+        (WebCore::createOrderedListElement): Return an HTMLElement*.
+        (WebCore::createUnorderedListElement): Return an HTMLElement*.
+        (WebCore::createListItemElement): Return an HTMLElement*.
+        (WebCore::createHTMLElement): Return an HTMLElement*.
+        * editing/htmlediting.h:
+
+        * editing/markup.cpp:
+        (WebCore::createFragmentFromText): Use createBreakElement and use Element*.
+
+        * page/MouseEventWithHitTestResults.cpp:
+        (WebCore::MouseEventWithHitTestResults::targetNode): Use parentElement.
+
+2008-12-23  Darin Adler  <darin@apple.com>
+
         Reviewed by Dan Bernstein.
 
         * dom/Node.h: Tweak comments and order of bits that Sam moved
index 0b14cb8..050ff96 100644 (file)
                6550B6A6099DF0270090D781 /* Text.h in Headers */ = {isa = PBXBuildFile; fileRef = 6550B69C099DF0270090D781 /* Text.h */; settings = {ATTRIBUTES = (Private, ); }; };
                65653F2D0D9727D200CA9723 /* SVGAltGlyphElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65653F2A0D9727D200CA9723 /* SVGAltGlyphElement.cpp */; };
                65653F2E0D9727D200CA9723 /* SVGAltGlyphElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 65653F2B0D9727D200CA9723 /* SVGAltGlyphElement.h */; };
-               656580F409D12B20000E61D7 /* CSSPropertyNames.h in Headers */ = {isa = PBXBuildFile; fileRef = 656580EF09D12B20000E61D7 /* CSSPropertyNames.h */; };
+               656580F409D12B20000E61D7 /* CSSPropertyNames.h in Headers */ = {isa = PBXBuildFile; fileRef = 656580EF09D12B20000E61D7 /* CSSPropertyNames.h */; settings = {ATTRIBUTES = (Private, ); }; };
                6565815109D13043000E61D7 /* CSSValueKeywords.h in Headers */ = {isa = PBXBuildFile; fileRef = 6565814809D13043000E61D7 /* CSSValueKeywords.h */; };
                656581B209D14EE6000E61D7 /* UserAgentStyleSheets.h in Headers */ = {isa = PBXBuildFile; fileRef = 656581AE09D14EE6000E61D7 /* UserAgentStyleSheets.h */; };
                656581FE09D1508D000E61D7 /* SVGElementFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 656581E709D1508D000E61D7 /* SVGElementFactory.h */; };
index bafe5e1..7a9c020 100644 (file)
@@ -905,7 +905,7 @@ Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned depth)
                 r = r->previousSibling();
             }
             if (!r && depth < cStyleSearchThreshold)
-                r = locateCousinList(static_cast<Element*>(parent->parentNode()), depth + 1);
+                r = locateCousinList(parent->parentElement(), depth + 1);
             while (r) {
                 if (r->renderStyle() == st)
                     return r->lastChild();
@@ -998,7 +998,7 @@ RenderStyle* CSSStyleSelector::locateSharedStyle()
             for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
         }
         if (!n) 
-            n = locateCousinList(static_cast<Element*>(m_element->parentNode()));
+            n = locateCousinList(m_element->parentElement());
         while (n) {
             if (canShareStyleWithElement(n))
                 return n->renderStyle();
@@ -1962,10 +1962,9 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
             }
             case CSSSelector::PseudoLastChild: {
                 // last-child matches the last child that is an element
-                if (e->parentNode() && e->parentNode()->isElementNode()) {
-                    Element* parentNode = static_cast<Element*>(e->parentNode());
+                if (Element* parentElement = e->parentElement()) {
                     bool result = false;
-                    if (parentNode->isFinishedParsingChildren()) {
+                    if (parentElement->isFinishedParsingChildren()) {
                         Node* n = e->nextSibling();
                         while (n && !n->isElementNode())
                             n = n->nextSibling();
@@ -1974,7 +1973,7 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
                     }
                     if (!m_collectRulesOnly) {
                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
-                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentNode->renderStyle();
+                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
                         if (parentStyle)
                             parentStyle->setChildrenAffectedByLastChildRules();
                         if (result && childStyle)
@@ -1986,14 +1985,13 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
             }
             case CSSSelector::PseudoLastOfType: {
                 // last-of-type matches the last element of its type
-                if (e->parentNode() && e->parentNode()->isElementNode()) {
-                    Element* parentNode = static_cast<Element*>(e->parentNode());
+                if (Element* parentElement = e->parentElement()) {
                     if (!m_collectRulesOnly) {
-                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentNode->renderStyle();
+                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
                         if (parentStyle)
                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
                     }
-                    if (!parentNode->isFinishedParsingChildren())
+                    if (!parentElement->isFinishedParsingChildren())
                         return false;
                     bool result = false;
                     const QualifiedName& type = e->tagQName();
@@ -2010,8 +2008,7 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
                 break;
             }
             case CSSSelector::PseudoOnlyChild: {
-                if (e->parentNode() && e->parentNode()->isElementNode()) {
-                    Element* parentNode = static_cast<Element*>(e->parentNode());
+                if (Element* parentElement = e->parentElement()) {
                     bool firstChild = false;
                     bool lastChild = false;
                     
@@ -2020,7 +2017,7 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
                         n = n->previousSibling();
                     if (!n)
                         firstChild = true;
-                    if (firstChild && parentNode->isFinishedParsingChildren()) {
+                    if (firstChild && parentElement->isFinishedParsingChildren()) {
                         n = e->nextSibling();
                         while (n && !n->isElementNode())
                             n = n->nextSibling();
@@ -2029,7 +2026,7 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
                     }
                     if (!m_collectRulesOnly) {
                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
-                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentNode->renderStyle();
+                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
                         if (parentStyle) {
                             parentStyle->setChildrenAffectedByFirstChildRules();
                             parentStyle->setChildrenAffectedByLastChildRules();
@@ -2045,16 +2042,15 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
             }
             case CSSSelector::PseudoOnlyOfType: {
                 // FIXME: This selector is very slow.
-                if (e->parentNode() && e->parentNode()->isElementNode()) {
-                    Element* parentNode = static_cast<Element*>(e->parentNode());
+                if (Element* parentElement = e->parentElement()) {
                     if (!m_collectRulesOnly) {
-                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentNode->renderStyle();
+                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
                         if (parentStyle) {
                             parentStyle->setChildrenAffectedByForwardPositionalRules();
                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
                         }
                     }
-                    if (!parentNode->isFinishedParsingChildren())
+                    if (!parentElement->isFinishedParsingChildren())
                         return false;
                     bool firstChild = false;
                     bool lastChild = false;
@@ -2084,7 +2080,7 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
             case CSSSelector::PseudoNthChild: {
                 if (!sel->parseNth())
                     break;
-                if (e->parentNode() && e->parentNode()->isElementNode()) {
+                if (Element* parentElement = e->parentElement()) {
                     int count = 1;
                     Node* n = e->previousSibling();
                     while (n) {
@@ -2102,7 +2098,7 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
                     
                     if (!m_collectRulesOnly) {
                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
-                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
+                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
                         if (childStyle)
                             childStyle->setChildIndex(count);
                         if (parentStyle)
@@ -2117,7 +2113,7 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
             case CSSSelector::PseudoNthOfType: {
                 if (!sel->parseNth())
                     break;
-                if (e->parentNode() && e->parentNode()->isElementNode()) {
+                if (Element* parentElement = e->parentElement()) {
                     int count = 1;
                     const QualifiedName& type = e->tagQName();
                     Node* n = e->previousSibling();
@@ -2128,7 +2124,7 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
                     }
                     
                     if (!m_collectRulesOnly) {
-                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
+                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
                         if (parentStyle)
                             parentStyle->setChildrenAffectedByForwardPositionalRules();
                     }
@@ -2141,14 +2137,13 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
             case CSSSelector::PseudoNthLastChild: {
                 if (!sel->parseNth())
                     break;
-                if (e->parentNode() && e->parentNode()->isElementNode()) {
-                    Element* parentNode = static_cast<Element*>(e->parentNode());
+                if (Element* parentElement = e->parentElement()) {
                     if (!m_collectRulesOnly) {
-                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentNode->renderStyle();
+                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
                         if (parentStyle)
                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
                     }
-                    if (!parentNode->isFinishedParsingChildren())
+                    if (!parentElement->isFinishedParsingChildren())
                         return false;
                     int count = 1;
                     Node* n = e->nextSibling();
@@ -2165,14 +2160,13 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
             case CSSSelector::PseudoNthLastOfType: {
                 if (!sel->parseNth())
                     break;
-                if (e->parentNode() && e->parentNode()->isElementNode()) {
-                    Element* parentNode = static_cast<Element*>(e->parentNode());
+                if (Element* parentElement = e->parentElement()) {
                     if (!m_collectRulesOnly) {
-                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentNode->renderStyle();
+                        RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
                         if (parentStyle)
                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
                     }
-                    if (!parentNode->isFinishedParsingChildren())
+                    if (!parentElement->isFinishedParsingChildren())
                         return false;
                     int count = 1;
                     const QualifiedName& type = e->tagQName();
index 0dc0d0b..5496589 100644 (file)
@@ -99,6 +99,11 @@ PassRefPtr<Node> Element::cloneNode(bool deep)
     return clone.release();
 }
 
+PassRefPtr<Element> Element::cloneElement()
+{
+    return static_pointer_cast<Element>(cloneNode(false));
+}
+
 void Element::removeAttribute(const QualifiedName& name, ExceptionCode& ec)
 {
     if (namedAttrMap) {
index 6ad4e47..86f45e5 100644 (file)
@@ -116,6 +116,8 @@ public:
     virtual void removedFromDocument();
     virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
 
+    PassRefPtr<Element> cloneElement();
+
     void normalizeAttributes();
 
     virtual bool isInputTypeHidden() const { return false; }
@@ -237,6 +239,12 @@ inline NamedAttrMap* Node::attributes() const
     return isElementNode() ? static_cast<const Element*>(this)->attributes() : 0;
 }
 
+inline Element* Node::parentElement() const
+{
+    Node* parent = parentNode();
+    return parent && parent->isElementNode() ? static_cast<Element*>(parent) : 0;
+}
+
 } //namespace
 
 #endif
index e848556..85c5ca1 100644 (file)
@@ -108,7 +108,7 @@ public:
     virtual void setNodeValue(const String&, ExceptionCode&);
     virtual NodeType nodeType() const = 0;
     Node* parentNode() const { return parent(); }
-    Node* parentElement() const { return parent(); } // IE extension
+    Element* parentElement() const;
     Node* previousSibling() const { return m_previous; }
     Node* nextSibling() const { return m_next; }
     virtual PassRefPtr<NodeList> childNodes();
index 6641877..06d0158 100644 (file)
 
 #include "config.h"
 #include "AppendNodeCommand.h"
+
 #include "htmlediting.h"
 
 namespace WebCore {
 
-AppendNodeCommand::AppendNodeCommand(PassRefPtr<Node> parentNode, PassRefPtr<Node> childToAppend)
-    : SimpleEditCommand(parentNode->document()), m_parentNode(parentNode), m_childToAppend(childToAppend)
+AppendNodeCommand::AppendNodeCommand(PassRefPtr<Element> parent, PassRefPtr<Node> node)
+    : SimpleEditCommand(parent->document())
+    , m_parent(parent)
+    , m_node(node)
 {
-    ASSERT(m_childToAppend);
-    ASSERT(m_parentNode);
+    ASSERT(m_parent);
+    ASSERT(m_node);
+    ASSERT(!m_node->parent());
+
+    ASSERT(enclosingNodeOfType(Position(m_parent.get(), 0), isContentEditable) || !m_parent->attached());
 }
 
 void AppendNodeCommand::doApply()
 {
-    ASSERT(m_childToAppend);
-    ASSERT(m_parentNode);
-    // If the child to append is already in a tree, appending it will remove it from it's old location
-    // in an non-undoable way.  We might eventually find it useful to do an undoable remove in this case.
-    ASSERT(!m_childToAppend->parent());
-    ASSERT(enclosingNodeOfType(Position(m_parentNode.get(), 0), &isContentEditable) || !m_parentNode->attached());
-
-    ExceptionCode ec = 0;
-    m_parentNode->appendChild(m_childToAppend.get(), ec);
-    ASSERT(ec == 0);
+    ExceptionCode ec;
+    m_parent->appendChild(m_node.get(), ec);
 }
 
 void AppendNodeCommand::doUnapply()
 {
-    ASSERT(m_childToAppend);
-    ASSERT(m_parentNode);
-
-    ExceptionCode ec = 0;
-    m_parentNode->removeChild(m_childToAppend.get(), ec);
-    ASSERT(ec == 0);
+    ExceptionCode ec;
+    m_node->remove(ec);
 }
 
 } // namespace WebCore
index 3210512..5ffb881 100644 (file)
@@ -32,19 +32,19 @@ namespace WebCore {
 
 class AppendNodeCommand : public SimpleEditCommand {
 public:
-    static PassRefPtr<AppendNodeCommand> create(PassRefPtr<Node> parentNode, PassRefPtr<Node> childToAppend)
+    static PassRefPtr<AppendNodeCommand> create(PassRefPtr<Element> parent, PassRefPtr<Node> node)
     {
-        return adoptRef(new AppendNodeCommand(parentNode, childToAppend));
+        return adoptRef(new AppendNodeCommand(parent, node));
     }
 
 private:
-    AppendNodeCommand(PassRefPtr<Node> parentNode, PassRefPtr<Node> childToAppend);
+    AppendNodeCommand(PassRefPtr<Element> parent, PassRefPtr<Node> node);
 
     virtual void doApply();
     virtual void doUnapply();
 
-    RefPtr<Node> m_parentNode;
-    RefPtr<Node> m_childToAppend;
+    RefPtr<Element> m_parent;
+    RefPtr<Node> m_node;
 };
 
 } // namespace WebCore
index 8ffd1b1..eecec4d 100644 (file)
@@ -274,11 +274,9 @@ static PassRefPtr<Element> createFontElement(Document* document)
 
 PassRefPtr<HTMLElement> createStyleSpanElement(Document* document)
 {
-    ExceptionCode ec = 0;
-    RefPtr<Element> styleElement = document->createElementNS(xhtmlNamespaceURI, "span", ec);
-    ASSERT(ec == 0);
+    RefPtr<HTMLElement> styleElement = new HTMLElement(spanTag, document);
     styleElement->setAttribute(classAttr, styleSpanClassString());
-    return static_pointer_cast<HTMLElement>(styleElement.release());
+    return styleElement.release();
 }
 
 ApplyStyleCommand::ApplyStyleCommand(Document* document, CSSStyleDeclaration* style, EditAction editingAction, EPropertyLevel propertyLevel)
@@ -307,7 +305,7 @@ ApplyStyleCommand::ApplyStyleCommand(Document* document, CSSStyleDeclaration* st
 {
 }
 
-ApplyStyleCommand::ApplyStyleCommand(Element* element, bool removeOnly, EditAction editingAction)
+ApplyStyleCommand::ApplyStyleCommand(PassRefPtr<Element> element, bool removeOnly, EditAction editingAction)
     : CompositeEditCommand(element->document())
     , m_style(CSSMutableStyleDeclaration::create())
     , m_editingAction(editingAction)
@@ -995,7 +993,7 @@ void ApplyStyleCommand::removeCSSStyle(CSSMutableStyleDeclaration *style, HTMLEl
 
     CSSMutableStyleDeclaration::const_iterator end = style->end();
     for (CSSMutableStyleDeclaration::const_iterator it = style->begin(); it != end; ++it) {
-        int propertyID = (*it).id();
+        CSSPropertyID propertyID = static_cast<CSSPropertyID>((*it).id());
         RefPtr<CSSValue> value = decl->getPropertyCSSValue(propertyID);
         if (value && (propertyID != CSSPropertyWhiteSpace || !isTabSpanNode(elem))) {
             removeCSSProperty(decl, propertyID);
@@ -1553,7 +1551,7 @@ void ApplyStyleCommand::addInlineStyleIfNeeded(CSSMutableStyleDeclaration *style
     }
     
     if (m_styledInlineElement) {
-        RefPtr<Element> clonedElement = static_pointer_cast<Element>(m_styledInlineElement->cloneNode(false));
+        RefPtr<Element> clonedElement = m_styledInlineElement->cloneElement();
         insertNodeBefore(clonedElement.get(), startNode);
         surroundNodeRangeWithElement(startNode, endNode, clonedElement.get());
     }
index 455aeac..c646233 100644 (file)
@@ -46,7 +46,7 @@ public:
     {
         return adoptRef(new ApplyStyleCommand(document, style, start, end, action, level));
     }
-    static PassRefPtr<ApplyStyleCommand> create(Element* element, bool removeOnly = false, EditAction action = EditActionChangeAttributes)
+    static PassRefPtr<ApplyStyleCommand> create(PassRefPtr<Element> element, bool removeOnly = false, EditAction action = EditActionChangeAttributes)
     {
         return adoptRef(new ApplyStyleCommand(element, removeOnly, action));
     }
@@ -54,7 +54,7 @@ public:
 private:
     ApplyStyleCommand(Document*, CSSStyleDeclaration*, EditAction, EPropertyLevel);
     ApplyStyleCommand(Document*, CSSStyleDeclaration*, const Position& start, const Position& end, EditAction, EPropertyLevel);
-    ApplyStyleCommand(Element*, bool removeOnly, EditAction);
+    ApplyStyleCommand(PassRefPtr<Element>, bool removeOnly, EditAction);
 
     virtual void doApply();
     virtual EditAction editingAction() const;
index a172953..76a0890 100644 (file)
@@ -59,10 +59,10 @@ void BreakBlockquoteCommand::doApply()
     // startNode is the first node that we need to move to the new blockquote.
     Node* startNode = pos.node();
     // Find the top-most blockquote from the start.
-    Node* topBlockquote = 0;
+    Element* topBlockquote = 0;
     for (Node *node = startNode->parentNode(); node; node = node->parentNode()) {
         if (isMailBlockquote(node))
-            topBlockquote = node;
+            topBlockquote = static_cast<Element*>(node);
     }
     if (!topBlockquote || !topBlockquote->parentNode())
         return;
@@ -102,21 +102,21 @@ void BreakBlockquoteCommand::doApply()
     }
     
     // Build up list of ancestors in between the start node and the top blockquote.
-    Vector<Node*> ancestors;    
-    for (Node* node = startNode->parentNode(); node != topBlockquote; node = node->parentNode())
+    Vector<Element*> ancestors;    
+    for (Element* node = startNode->parentElement(); node && node != topBlockquote; node = node->parentElement())
         ancestors.append(node);
     
     // Insert a clone of the top blockquote after the break.
-    RefPtr<Node> clonedBlockquote = topBlockquote->cloneNode(false);
+    RefPtr<Element> clonedBlockquote = topBlockquote->cloneElement();
     insertNodeAfter(clonedBlockquote.get(), breakNode.get());
     
     // Clone startNode's ancestors into the cloned blockquote.
     // On exiting this loop, clonedAncestor is the lowest ancestor
     // that was cloned (i.e. the clone of either ancestors.last()
     // or clonedBlockquote if ancestors is empty).
-    RefPtr<Node> clonedAncestor = clonedBlockquote;
+    RefPtr<Element> clonedAncestor = clonedBlockquote;
     for (size_t i = ancestors.size(); i != 0; --i) {
-        RefPtr<Node> clonedChild = ancestors[i - 1]->cloneNode(false); // shallow clone
+        RefPtr<Element> clonedChild = ancestors[i - 1]->cloneElement(); // shallow clone
         // Preserve list item numbering in cloned lists.
         if (clonedChild->isElementNode() && clonedChild->hasTagName(olTag)) {
             Node* listChildNode = i > 1 ? ancestors[i - 2] : startNode;
@@ -149,11 +149,11 @@ void BreakBlockquoteCommand::doApply()
         // Throughout this loop, clonedParent is the clone of ancestor's parent.
         // This is so we can clone ancestor's siblings and place the clones
         // into the clone corresponding to the ancestor's parent.
-        Node* ancestor;
-        Node* clonedParent;
-        for (ancestor = ancestors.first(), clonedParent = clonedAncestor->parentNode();
+        Element* ancestor;
+        Element* clonedParent;
+        for (ancestor = ancestors.first(), clonedParent = clonedAncestor->parentElement();
              ancestor && ancestor != topBlockquote;
-             ancestor = ancestor->parentNode(), clonedParent = clonedParent->parentNode()) {
+             ancestor = ancestor->parentElement(), clonedParent = clonedParent->parentElement()) {
             moveNode = ancestor->nextSibling();
             while (moveNode) {
                 Node *next = moveNode->nextSibling();
index 7366537..7f4a7a3 100644 (file)
@@ -48,7 +48,6 @@
 #include "MergeIdenticalElementsCommand.h"
 #include "Range.h"
 #include "RemoveCSSPropertyCommand.h"
-#include "RemoveNodeAttributeCommand.h"
 #include "RemoveNodeCommand.h"
 #include "RemoveNodePreservingChildrenCommand.h"
 #include "ReplaceSelectionCommand.h"
@@ -108,12 +107,12 @@ void CompositeEditCommand::applyStyle(CSSStyleDeclaration* style, const Position
     applyCommandToComposite(ApplyStyleCommand::create(document(), style, start, end, editingAction));
 }
 
-void CompositeEditCommand::applyStyledElement(Element* element)
+void CompositeEditCommand::applyStyledElement(PassRefPtr<Element> element)
 {
     applyCommandToComposite(ApplyStyleCommand::create(element, false));
 }
 
-void CompositeEditCommand::removeStyledElement(Element* element)
+void CompositeEditCommand::removeStyledElement(PassRefPtr<Element> element)
 {
     applyCommandToComposite(ApplyStyleCommand::create(element, true));
 }
@@ -128,24 +127,28 @@ void CompositeEditCommand::insertLineBreak()
     applyCommandToComposite(InsertLineBreakCommand::create(document()));
 }
 
-void CompositeEditCommand::insertNodeBefore(Node* insertChild, Node* refChild)
+void CompositeEditCommand::insertNodeBefore(PassRefPtr<Node> insertChild, PassRefPtr<Node> refChild)
 {
     ASSERT(!refChild->hasTagName(bodyTag));
     applyCommandToComposite(InsertNodeBeforeCommand::create(insertChild, refChild));
 }
 
-void CompositeEditCommand::insertNodeAfter(Node* insertChild, Node* refChild)
+void CompositeEditCommand::insertNodeAfter(PassRefPtr<Node> insertChild, PassRefPtr<Node> refChild)
 {
+    ASSERT(insertChild);
+    ASSERT(refChild);
     ASSERT(!refChild->hasTagName(bodyTag));
-    if (refChild->parentNode()->lastChild() == refChild)
-        appendNode(insertChild, refChild->parentNode());
+    Element* parent = refChild->parentElement();
+    ASSERT(parent);
+    if (parent->lastChild() == refChild)
+        appendNode(insertChild, parent);
     else {
         ASSERT(refChild->nextSibling());
         insertNodeBefore(insertChild, refChild->nextSibling());
     }
 }
 
-void CompositeEditCommand::insertNodeAt(Node* insertChild, const Position& editingPosition)
+void CompositeEditCommand::insertNodeAt(PassRefPtr<Node> insertChild, const Position& editingPosition)
 {
     ASSERT(isEditablePosition(editingPosition));
     // For editing positions like [table, 0], insert before the table,
@@ -161,7 +164,7 @@ void CompositeEditCommand::insertNodeAt(Node* insertChild, const Position& editi
         if (child)
             insertNodeBefore(insertChild, child);
         else
-            appendNode(insertChild, refChild);
+            appendNode(insertChild, static_cast<Element*>(refChild));
     } else if (caretMinOffset(refChild) >= offset) {
         insertNodeBefore(insertChild, refChild);
     } else if (refChild->isTextNode() && caretMaxOffset(refChild) > offset) {
@@ -172,38 +175,39 @@ void CompositeEditCommand::insertNodeAt(Node* insertChild, const Position& editi
     }
 }
 
-void CompositeEditCommand::appendNode(Node* newChild, Node* parent)
+void CompositeEditCommand::appendNode(PassRefPtr<Node> node, PassRefPtr<Element> parent)
 {
-    ASSERT(canHaveChildrenForEditing(parent));
-    applyCommandToComposite(AppendNodeCommand::create(parent, newChild));
+    ASSERT(canHaveChildrenForEditing(parent.get()));
+    applyCommandToComposite(AppendNodeCommand::create(parent, node));
 }
 
-void CompositeEditCommand::removeChildrenInRange(Node* node, int from, int to)
+void CompositeEditCommand::removeChildrenInRange(PassRefPtr<Node> node, unsigned from, unsigned to)
 {
-    Node* nodeToRemove = node->childNode(from);
-    for (int i = from; i < to; i++) {
-        ASSERT(nodeToRemove);
-        Node* next = nodeToRemove->nextSibling();
-        removeNode(nodeToRemove);
-        nodeToRemove = next;
-    }
+    Vector<RefPtr<Node> > children;
+    Node* child = node->childNode(from);
+    for (unsigned i = from; child && i < to; i++, child = child->nextSibling())
+        children.append(child);
+
+    size_t size = children.size();
+    for (size_t i = 0; i < size; ++i)
+        removeNode(children[i].release());
 }
 
-void CompositeEditCommand::removeNode(Node* removeChild)
+void CompositeEditCommand::removeNode(PassRefPtr<Node> node)
 {
-    applyCommandToComposite(RemoveNodeCommand::create(removeChild));
+    applyCommandToComposite(RemoveNodeCommand::create(node));
 }
 
-void CompositeEditCommand::removeNodePreservingChildren(Node* removeChild)
+void CompositeEditCommand::removeNodePreservingChildren(PassRefPtr<Node> node)
 {
-    applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(removeChild));
+    applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node));
 }
 
-void CompositeEditCommand::removeNodeAndPruneAncestors(Node* node)
+void CompositeEditCommand::removeNodeAndPruneAncestors(PassRefPtr<Node> node)
 {
     RefPtr<Node> parent = node->parentNode();
     removeNode(node);
-    prune(parent);
+    prune(parent.release());
 }
 
 static bool hasARenderedDescendant(Node* node)
@@ -226,24 +230,24 @@ void CompositeEditCommand::prune(PassRefPtr<Node> node)
             return;
             
         RefPtr<Node> next = node->parentNode();
-        removeNode(node.get());
+        removeNode(node);
         node = next;
     }
 }
 
-void CompositeEditCommand::splitTextNode(Text *text, int offset)
+void CompositeEditCommand::splitTextNode(PassRefPtr<Text> node, unsigned offset)
 {
-    applyCommandToComposite(SplitTextNodeCommand::create(text, offset));
+    applyCommandToComposite(SplitTextNodeCommand::create(node, offset));
 }
 
-void CompositeEditCommand::splitElement(Element* element, Node* atChild)
+void CompositeEditCommand::splitElement(PassRefPtr<Element> element, PassRefPtr<Node> atChild)
 {
     applyCommandToComposite(SplitElementCommand::create(element, atChild));
 }
 
-void CompositeEditCommand::mergeIdenticalElements(Element* first, Element* second)
+void CompositeEditCommand::mergeIdenticalElements(PassRefPtr<Element> first, PassRefPtr<Element> second)
 {
-    ASSERT(!first->isDescendantOf(second) && second != first);
+    ASSERT(!first->isDescendantOf(second.get()) && second != first);
     if (first->nextSibling() != second) {
         removeNode(second);
         insertNodeAfter(second, first);
@@ -251,22 +255,22 @@ void CompositeEditCommand::mergeIdenticalElements(Element* first, Element* secon
     applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second));
 }
 
-void CompositeEditCommand::wrapContentsInDummySpan(Element* element)
+void CompositeEditCommand::wrapContentsInDummySpan(PassRefPtr<Element> element)
 {
     applyCommandToComposite(WrapContentsInDummySpanCommand::create(element));
 }
 
-void CompositeEditCommand::splitTextNodeContainingElement(Text *text, int offset)
+void CompositeEditCommand::splitTextNodeContainingElement(PassRefPtr<Text> text, unsigned offset)
 {
     applyCommandToComposite(SplitTextNodeContainingElementCommand::create(text, offset));
 }
 
-void CompositeEditCommand::joinTextNodes(Text *text1, Text *text2)
+void CompositeEditCommand::joinTextNodes(PassRefPtr<Text> text1, PassRefPtr<Text> text2)
 {
     applyCommandToComposite(JoinTextNodesCommand::create(text1, text2));
 }
 
-void CompositeEditCommand::inputText(const String &text, bool selectInsertedText)
+void CompositeEditCommand::inputText(const Stringtext, bool selectInsertedText)
 {
     int offset = 0;
     int length = text.length();
@@ -293,19 +297,19 @@ void CompositeEditCommand::inputText(const String &text, bool selectInsertedText
     }
 }
 
-void CompositeEditCommand::insertTextIntoNode(Text *node, int offset, const String &text)
+void CompositeEditCommand::insertTextIntoNode(PassRefPtr<Text> node, unsigned offset, const String& text)
 {
     applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset, text));
 }
 
-void CompositeEditCommand::deleteTextFromNode(Text *node, int offset, int count)
+void CompositeEditCommand::deleteTextFromNode(PassRefPtr<Text> node, unsigned offset, unsigned count)
 {
     applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, count));
 }
 
-void CompositeEditCommand::replaceTextInNode(Text *node, int offset, int count, const String &replacementText)
+void CompositeEditCommand::replaceTextInNode(PassRefPtr<Text> node, unsigned offset, unsigned count, const String& replacementText)
 {
-    applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, count));
+    applyCommandToComposite(DeleteFromTextNodeCommand::create(node.get(), offset, count));
     applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset, replacementText));
 }
 
@@ -326,11 +330,10 @@ Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos)
     return positionBeforeNode(tabSpan);
 }
 
-void CompositeEditCommand::insertNodeAtTabSpanPosition(Node* node, const Position& pos)
+void CompositeEditCommand::insertNodeAtTabSpanPosition(PassRefPtr<Node> node, const Position& pos)
 {
     // insert node before, after, or at split of tab span
-    Position insertPos = positionOutsideTabSpan(pos);
-    insertNodeAt(node, insertPos);
+    insertNodeAt(node, positionOutsideTabSpan(pos));
 }
 
 void CompositeEditCommand::deleteSelection(bool smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements)
@@ -345,19 +348,17 @@ void CompositeEditCommand::deleteSelection(const Selection &selection, bool smar
         applyCommandToComposite(DeleteSelectionCommand::create(selection, smartDelete, mergeBlocksAfterDelete, replace, expandForSpecialElements));
 }
 
-void CompositeEditCommand::removeCSSProperty(CSSStyleDeclaration *decl, int property)
+void CompositeEditCommand::removeCSSProperty(PassRefPtr<CSSMutableStyleDeclaration> style, CSSPropertyID property)
 {
-    applyCommandToComposite(RemoveCSSPropertyCommand::create(document(), decl, property));
+    applyCommandToComposite(RemoveCSSPropertyCommand::create(document(), style, property));
 }
 
-void CompositeEditCommand::removeNodeAttribute(Element* element, const QualifiedName& attribute)
+void CompositeEditCommand::removeNodeAttribute(PassRefPtr<Element> element, const QualifiedName& attribute)
 {
-    if (element->getAttribute(attribute).isNull())
-        return;
-    applyCommandToComposite(RemoveNodeAttributeCommand::create(element, attribute));
+    setNodeAttribute(element, attribute, AtomicString());;
 }
 
-void CompositeEditCommand::setNodeAttribute(Element* element, const QualifiedName& attribute, const String &value)
+void CompositeEditCommand::setNodeAttribute(PassRefPtr<Element> element, const QualifiedName& attribute, const AtomicString& value)
 {
     applyCommandToComposite(SetNodeAttributeCommand::create(element, attribute, value));
 }
@@ -457,12 +458,15 @@ void CompositeEditCommand::rebalanceWhitespace()
         rebalanceWhitespaceAt(selection.end());
 }
 
-void CompositeEditCommand::deleteInsignificantText(Text* textNode, int start, int end)
+void CompositeEditCommand::deleteInsignificantText(PassRefPtr<Text> textNode, unsigned start, unsigned end)
 {
-    if (!textNode || !textNode->renderer() || start >= end)
+    if (!textNode || start >= end)
         return;
 
     RenderText* textRenderer = static_cast<RenderText*>(textNode->renderer());
+    if (!textRenderer)
+        return;
+
     InlineTextBox* box = textRenderer->firstTextBox();
     if (!box) {
         // whole text node is empty
@@ -470,23 +474,23 @@ void CompositeEditCommand::deleteInsignificantText(Text* textNode, int start, in
         return;    
     }
     
-    int length = textNode->length();
+    unsigned length = textNode->length();
     if (start >= length || end > length)
         return;
 
-    int removed = 0;
+    unsigned removed = 0;
     InlineTextBox* prevBox = 0;
     String str;
 
     // This loop structure works to process all gaps preceding a box,
     // and also will look at the gap after the last box.
     while (prevBox || box) {
-        int gapStart = prevBox ? prevBox->m_start + prevBox->m_len : 0;
+        unsigned gapStart = prevBox ? prevBox->m_start + prevBox->m_len : 0;
         if (end < gapStart)
             // No more chance for any intersections
             break;
 
-        int gapEnd = box ? box->m_start : length;
+        unsigned gapEnd = box ? box->m_start : length;
         bool indicesIntersect = start <= gapEnd && end >= gapStart;
         int gapLen = gapEnd - gapStart;
         if (indicesIntersect && gapLen > 0) {
@@ -512,7 +516,7 @@ void CompositeEditCommand::deleteInsignificantText(Text* textNode, int start, in
             // Assert that we are not going to delete all of the text in the node.
             // If we were, that should have been done above with the call to 
             // removeNode and return.
-            ASSERT(start > 0 || (unsigned)end - start < textNode->length());
+            ASSERT(start > 0 || end - start < textNode->length());
             deleteTextFromNode(textNode, start, end - start);
         }
     }
@@ -546,16 +550,16 @@ void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos
     deleteInsignificantText(pos, end);
 }
 
-PassRefPtr<Node> CompositeEditCommand::appendBlockPlaceholder(Node* node)
+PassRefPtr<Node> CompositeEditCommand::appendBlockPlaceholder(PassRefPtr<Element> container)
 {
-    if (!node)
+    if (!container)
         return 0;
     
-    // Should assert isBlockFlow || isInlineFlow when deletion improves.  See 4244964.
-    ASSERT(node->renderer());
+    // Should assert isBlockFlow || isInlineFlow when deletion improves. See 4244964.
+    ASSERT(container->renderer());
 
     RefPtr<Node> placeholder = createBlockPlaceholderElement(document());
-    appendNode(placeholder.get(), node);
+    appendNode(placeholder, container);
     return placeholder.release();
 }
 
@@ -568,25 +572,25 @@ PassRefPtr<Node> CompositeEditCommand::insertBlockPlaceholder(const Position& po
     ASSERT(pos.node()->renderer());
 
     RefPtr<Node> placeholder = createBlockPlaceholderElement(document());
-    insertNodeAt(placeholder.get(), pos);
+    insertNodeAt(placeholder, pos);
     return placeholder.release();
 }
 
-PassRefPtr<Node> CompositeEditCommand::addBlockPlaceholderIfNeeded(Node* node)
+PassRefPtr<Node> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element* container)
 {
-    if (!node)
+    if (!container)
         return 0;
 
     updateLayout();
 
-    RenderObject *renderer = node->renderer();
+    RenderObject* renderer = container->renderer();
     if (!renderer || !renderer->isBlockFlow())
         return 0;
     
     // append the placeholder to make sure it follows
     // any unrendered blocks
     if (renderer->height() == 0 || (renderer->isListItem() && renderer->isEmpty()))
-        return appendBlockPlaceholder(node);
+        return appendBlockPlaceholder(container);
 
     return 0;
 }
@@ -613,9 +617,10 @@ void CompositeEditCommand::removePlaceholderAt(const VisiblePosition& visiblePos
 
 PassRefPtr<Node> CompositeEditCommand::insertNewDefaultParagraphElementAt(const Position& position)
 {
-    RefPtr<Node> paragraphElement = createDefaultParagraphElement(document());
-    appendNode(createBreakElement(document()).get(), paragraphElement.get());
-    insertNodeAt(paragraphElement.get(), position);
+    RefPtr<Element> paragraphElement = createDefaultParagraphElement(document());
+    ExceptionCode ec;
+    paragraphElement->appendChild(createBreakElement(document()), ec);
+    insertNodeAt(paragraphElement, position);
     return paragraphElement.release();
 }
 
@@ -834,7 +839,7 @@ void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagrap
     afterParagraph = VisiblePosition(afterParagraph.deepEquivalent());
     if (beforeParagraph.isNotNull() && (!isEndOfParagraph(beforeParagraph) || beforeParagraph == afterParagraph)) {
         // FIXME: Trim text between beforeParagraph and afterParagraph if they aren't equal.
-        insertNodeAt(createBreakElement(document()).get(), beforeParagraph.deepEquivalent());
+        insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquivalent());
         // Need an updateLayout here in case inserting the br has split a text node.
         updateLayout();
     }
@@ -843,7 +848,7 @@ void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagrap
     destinationIndex = TextIterator::rangeLength(startToDestinationRange.get(), true);
     
     setEndingSelection(destination);
-    applyCommandToComposite(ReplaceSelectionCommand::create(document(), fragment.get(), true, false, !preserveStyle, false, true));
+    applyCommandToComposite(ReplaceSelectionCommand::create(document(), fragment, true, false, !preserveStyle, false, true));
     // Restore styles from an empty paragraph to the new empty paragraph.
     if (styleInEmptyParagraph)
         applyStyle(styleInEmptyParagraph.get());
@@ -875,19 +880,19 @@ bool CompositeEditCommand::breakOutOfEmptyListItem()
     if (!listNode->isContentEditable())
         return false;
     
-    RefPtr<Node> newBlock = isListElement(listNode->parentNode()) ? createListItemElement(document()) : createDefaultParagraphElement(document());
+    RefPtr<Element> newBlock = isListElement(listNode->parentNode()) ? createListItemElement(document()) : createDefaultParagraphElement(document());
     
     if (emptyListItem->renderer()->nextSibling()) {
         if (emptyListItem->renderer()->previousSibling())
             splitElement(static_cast<Element*>(listNode), emptyListItem);
-        insertNodeBefore(newBlock.get(), listNode);
+        insertNodeBefore(newBlock, listNode);
         removeNode(emptyListItem);
     } else {
-        insertNodeAfter(newBlock.get(), listNode);
+        insertNodeAfter(newBlock, listNode);
         removeNode(emptyListItem->renderer()->previousSibling() ? emptyListItem : listNode);
     }
     
-    appendBlockPlaceholder(newBlock.get());
+    appendBlockPlaceholder(newBlock);
     setEndingSelection(Selection(Position(newBlock.get(), 0), DOWNSTREAM));
     
     computedStyle(endingSelection().start().node())->diff(style.get());
@@ -920,12 +925,12 @@ bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph()
     RefPtr<Node> 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.get(), highestBlockquote);
+    insertNodeBefore(br, highestBlockquote);
     VisiblePosition atBR(Position(br.get(), 0));
     // If the br we inserted collapsed, for example foo<br><blockquote>...</blockquote>, insert 
     // a second one.
     if (!isStartOfParagraph(atBR))
-        insertNodeBefore(createBreakElement(document()).get(), br.get());
+        insertNodeBefore(createBreakElement(document()), br);
     setEndingSelection(Selection(atBR));
     
     // If this is an empty paragraph there must be a line break here.
index 4ac003b..6bb142b 100644 (file)
@@ -27,6 +27,7 @@
 #define CompositeEditCommand_h
 
 #include "EditCommand.h"
+#include "CSSPropertyNames.h"
 #include <wtf/Vector.h>
 
 namespace WebCore {
@@ -44,50 +45,50 @@ protected:
     //
     // sugary-sweet convenience functions to help create and apply edit commands in composite commands
     //
-    void appendNode(Node* appendChild, Node* parentNode);
+    void appendNode(PassRefPtr<Node>, PassRefPtr<Element> parent);
     void applyCommandToComposite(PassRefPtr<EditCommand>);
     void applyStyle(CSSStyleDeclaration*, EditAction = EditActionChangeAttributes);
     void applyStyle(CSSStyleDeclaration*, const Position& start, const Position& end, EditAction = EditActionChangeAttributes);
-    void applyStyledElement(Element*);
-    void removeStyledElement(Element*);
+    void applyStyledElement(PassRefPtr<Element>);
+    void removeStyledElement(PassRefPtr<Element>);
     void deleteSelection(bool smartDelete = false, bool mergeBlocksAfterDelete = true, bool replace = false, bool expandForSpecialElements = true);
     void deleteSelection(const Selection&, bool smartDelete = false, bool mergeBlocksAfterDelete = true, bool replace = false, bool expandForSpecialElements = true);
-    virtual void deleteTextFromNode(Text* node, int offset, int count);
+    virtual void deleteTextFromNode(PassRefPtr<Text>, unsigned offset, unsigned count);
     void inputText(const String&, bool selectInsertedText = false);
-    void insertNodeAfter(Node* insertChild, Node* refChild);
-    void insertNodeAt(Node* insertChild, const Position&);
-    void insertNodeBefore(Node* insertChild, Node* refChild);
+    void insertNodeAfter(PassRefPtr<Node>, PassRefPtr<Node> refChild);
+    void insertNodeAt(PassRefPtr<Node>, const Position&);
+    void insertNodeAtTabSpanPosition(PassRefPtr<Node>, const Position&);
+    void insertNodeBefore(PassRefPtr<Node>, PassRefPtr<Node> refChild);
     void insertParagraphSeparator(bool useDefaultParagraphElement = false);
     void insertLineBreak();
-    void insertTextIntoNode(Text* node, int offset, const String& text);
-    void joinTextNodes(Text*, Text*);
+    void insertTextIntoNode(PassRefPtr<Text>, unsigned offset, const String& text);
+    void joinTextNodes(PassRefPtr<Text>, PassRefPtr<Text>);
+    void mergeIdenticalElements(PassRefPtr<Element>, PassRefPtr<Element>);
     void rebalanceWhitespace();
     void rebalanceWhitespaceAt(const Position&);
-    void prepareWhitespaceAtPositionForSplit(Position& position);
-    void removeCSSProperty(CSSStyleDeclaration*, int property);
-    void removeNodeAttribute(Element*, const QualifiedName& attribute);
-    void removeChildrenInRange(Node*, int from, int to);
-    virtual void removeNode(Node*);
-    void removeNodePreservingChildren(Node*);
-    void removeNodeAndPruneAncestors(Node*);
+    void prepareWhitespaceAtPositionForSplit(Position&);
+    void removeCSSProperty(PassRefPtr<CSSMutableStyleDeclaration>, CSSPropertyID);
+    void removeNodeAttribute(PassRefPtr<Element>, const QualifiedName& attribute);
+    void removeChildrenInRange(PassRefPtr<Node>, unsigned from, unsigned to);
+    virtual void removeNode(PassRefPtr<Node>);
+    void removeNodePreservingChildren(PassRefPtr<Node>);
+    void removeNodeAndPruneAncestors(PassRefPtr<Node>);
     void prune(PassRefPtr<Node>);
-    void replaceTextInNode(Text* node, int offset, int count, const String& replacementText);
+    void replaceTextInNode(PassRefPtr<Text>, unsigned offset, unsigned count, const String& replacementText);
     Position positionOutsideTabSpan(const Position&);
-    void insertNodeAtTabSpanPosition(Node*, const Position&);
-    void setNodeAttribute(Element*, const QualifiedName& attribute, const String& value);
-    void splitTextNode(Text*, int offset);
-    void splitElement(Element*, Node* atChild);
-    void mergeIdenticalElements(Element*, Element*);
-    void wrapContentsInDummySpan(Element*);
-    void splitTextNodeContainingElement(Text*, int offset);
+    void setNodeAttribute(PassRefPtr<Element>, const QualifiedName& attribute, const AtomicString& value);
+    void splitElement(PassRefPtr<Element>, PassRefPtr<Node> atChild);
+    void splitTextNode(PassRefPtr<Text>, unsigned offset);
+    void splitTextNodeContainingElement(PassRefPtr<Text>, unsigned offset);
+    void wrapContentsInDummySpan(PassRefPtr<Element>);
 
-    void deleteInsignificantText(Text*, int start, int end);
+    void deleteInsignificantText(PassRefPtr<Text>, unsigned start, unsigned end);
     void deleteInsignificantText(const Position& start, const Position& end);
     void deleteInsignificantTextDownstream(const Position&);
 
-    PassRefPtr<Node> appendBlockPlaceholder(Node*);
+    PassRefPtr<Node> appendBlockPlaceholder(PassRefPtr<Element>);
     PassRefPtr<Node> insertBlockPlaceholder(const Position&);
-    PassRefPtr<Node> addBlockPlaceholderIfNeeded(Node*);
+    PassRefPtr<Node> addBlockPlaceholderIfNeeded(Element*);
     void removePlaceholderAt(const VisiblePosition&);
 
     PassRefPtr<Node> insertNewDefaultParagraphElementAt(const Position&);
index 93a974f..e942fef 100644 (file)
 
 namespace WebCore {
 
-DeleteFromTextNodeCommand::DeleteFromTextNodeCommand(PassRefPtr<Text> node, int offset, int count)
-    : SimpleEditCommand(node->document()), m_node(node), m_offset(offset), m_count(count)
+DeleteFromTextNodeCommand::DeleteFromTextNodeCommand(PassRefPtr<Text> node, unsigned offset, unsigned count)
+    : SimpleEditCommand(node->document())
+    , m_node(node)
+    , m_offset(offset)
+    , m_count(count)
 {
     ASSERT(m_node);
-    ASSERT(m_offset >= 0);
-    ASSERT(m_offset < (int)m_node->length());
-    ASSERT(m_count >= 0);
+    ASSERT(m_offset <= m_node->length());
+    ASSERT(m_offset + m_count <= m_node->length());
 }
 
 void DeleteFromTextNodeCommand::doApply()
@@ -45,20 +47,18 @@ void DeleteFromTextNodeCommand::doApply()
 
     ExceptionCode ec = 0;
     m_text = m_node->substringData(m_offset, m_count, ec);
-    ASSERT(ec == 0);
+    if (ec)
+        return;
     
     m_node->deleteData(m_offset, m_count, ec);
-    ASSERT(ec == 0);
 }
 
 void DeleteFromTextNodeCommand::doUnapply()
 {
     ASSERT(m_node);
-    ASSERT(!m_text.isEmpty());
 
-    ExceptionCode ec = 0;
+    ExceptionCode ec;
     m_node->insertData(m_offset, m_text, ec);
-    ASSERT(ec == 0);
 }
 
 } // namespace WebCore
index b3bf10b..0d145f5 100644 (file)
@@ -34,20 +34,20 @@ class Text;
 
 class DeleteFromTextNodeCommand : public SimpleEditCommand {
 public:
-    static PassRefPtr<DeleteFromTextNodeCommand> create(PassRefPtr<Text> node, int offset, int count)
+    static PassRefPtr<DeleteFromTextNodeCommand> create(PassRefPtr<Text> node, unsigned offset, unsigned count)
     {
         return adoptRef(new DeleteFromTextNodeCommand(node, offset, count));
     }
 
 private:
-    DeleteFromTextNodeCommand(PassRefPtr<Text>, int offset, int count);
+    DeleteFromTextNodeCommand(PassRefPtr<Text>, unsigned offset, unsigned count);
 
     virtual void doApply();
     virtual void doUnapply();
 
     RefPtr<Text> m_node;
-    int m_offset;
-    int m_count;
+    unsigned m_offset;
+    unsigned m_count;
     String m_text;
 };
 
index 51ad9da..738ce64 100644 (file)
@@ -317,7 +317,7 @@ static void updatePositionForNodeRemoval(Node* node, Position& position)
         position = positionBeforeNode(node);
 }
 
-void DeleteSelectionCommand::removeNode(Node *node)
+void DeleteSelectionCommand::removeNode(PassRefPtr<Node> node)
 {
     if (!node)
         return;
@@ -344,12 +344,12 @@ void DeleteSelectionCommand::removeNode(Node *node)
         }
     }
     
-    if (isTableStructureNode(node) || node == node->rootEditableElement()) {
+    if (isTableStructureNode(node.get()) || node == node->rootEditableElement()) {
         // Do not remove an element of table structure; remove its contents.
         // Likewise for the root editable element.
-        Node *child = node->firstChild();
+        Nodechild = node->firstChild();
         while (child) {
-            Node *remove = child;
+            Noderemove = child;
             child = child->nextSibling();
             removeNode(remove);
         }
@@ -368,9 +368,9 @@ void DeleteSelectionCommand::removeNode(Node *node)
         m_needPlaceholder = true;
     
     // FIXME: Update the endpoints of the range being deleted.
-    updatePositionForNodeRemoval(node, m_endingPosition);
-    updatePositionForNodeRemoval(node, m_leadingWhitespace);
-    updatePositionForNodeRemoval(node, m_trailingWhitespace);
+    updatePositionForNodeRemoval(node.get(), m_endingPosition);
+    updatePositionForNodeRemoval(node.get(), m_leadingWhitespace);
+    updatePositionForNodeRemoval(node.get(), m_trailingWhitespace);
     
     CompositeEditCommand::removeNode(node);
 }
@@ -386,12 +386,12 @@ void updatePositionForTextRemoval(Node* node, int offset, int count, Position& p
     }
 }
 
-void DeleteSelectionCommand::deleteTextFromNode(Text *node, int offset, int count)
+void DeleteSelectionCommand::deleteTextFromNode(PassRefPtr<Text> node, unsigned offset, unsigned count)
 {
     // FIXME: Update the endpoints of the range being deleted.
-    updatePositionForTextRemoval(node, offset, count, m_endingPosition);
-    updatePositionForTextRemoval(node, offset, count, m_leadingWhitespace);
-    updatePositionForTextRemoval(node, offset, count, m_trailingWhitespace);
+    updatePositionForTextRemoval(node.get(), offset, count, m_endingPosition);
+    updatePositionForTextRemoval(node.get(), offset, count, m_leadingWhitespace);
+    updatePositionForTextRemoval(node.get(), offset, count, m_trailingWhitespace);
     
     CompositeEditCommand::deleteTextFromNode(node, offset, count);
 }
index 230814b..0f9f2f7 100644 (file)
@@ -62,8 +62,8 @@ private:
     void calculateEndingPosition();
     void calculateTypingStyleAfterDelete();
     void clearTransientState();
-    virtual void removeNode(Node*);
-    virtual void deleteTextFromNode(Text*, int, int);
+    virtual void removeNode(PassRefPtr<Node>);
+    virtual void deleteTextFromNode(PassRefPtr<Text>, unsigned, unsigned);
 
     bool m_hasSelectionToDelete;
     bool m_smartDelete;
index 64f7c2d..6a4ee7e 100644 (file)
@@ -36,7 +36,7 @@ namespace WebCore {
 
 using namespace HTMLNames;
 
-FormatBlockCommand::FormatBlockCommand(Document* document, const String& tagName) 
+FormatBlockCommand::FormatBlockCommand(Document* document, const AtomicString& tagName) 
     : CompositeEditCommand(document), m_tagName(tagName)
 {
 }
@@ -107,21 +107,21 @@ void FormatBlockCommand::doApply()
     VisiblePosition paragraphEnd = endOfParagraph(endingSelection().visibleStart());
     VisiblePosition blockStart = startOfBlock(endingSelection().visibleStart());
     VisiblePosition blockEnd = endOfBlock(endingSelection().visibleStart());
-    RefPtr<Node> blockNode = createElement(document(), m_tagName);
-    RefPtr<Node> placeholder = createBreakElement(document());
+    RefPtr<Element> blockNode = createHTMLElement(document(), m_tagName);
+    RefPtr<Element> placeholder = createBreakElement(document());
     
     Node* root = endingSelection().start().node()->rootEditableElement();
     if (validBlockTag(refNode->nodeName().lower()) && 
         paragraphStart == blockStart && paragraphEnd == blockEnd && 
         refNode != root && !root->isDescendantOf(refNode))
         // Already in a valid block tag that only contains the current paragraph, so we can swap with the new tag
-        insertNodeBefore(blockNode.get(), refNode);
+        insertNodeBefore(blockNode, refNode);
     else {
         // Avoid inserting inside inline elements that surround paragraphStart with upstream().
         // This is only to avoid creating bloated markup.
-        insertNodeAt(blockNode.get(), paragraphStart.deepEquivalent().upstream());
+        insertNodeAt(blockNode, paragraphStart.deepEquivalent().upstream());
     }
-    appendNode(placeholder.get(), blockNode.get());
+    appendNode(placeholder, blockNode);
     
     VisiblePosition destination(Position(placeholder.get(), 0));
     if (paragraphStart == paragraphEnd && !lineBreakExistsAtPosition(paragraphStart)) {
index 0e84bc1..1c8d814 100644 (file)
@@ -32,19 +32,19 @@ namespace WebCore {
 
 class FormatBlockCommand : public CompositeEditCommand {
 public:
-    static PassRefPtr<FormatBlockCommand> create(Document* document, const String& tagName)
+    static PassRefPtr<FormatBlockCommand> create(Document* document, const AtomicString& tagName)
     {
         return adoptRef(new FormatBlockCommand(document, tagName));
     }
 
 private:
-    FormatBlockCommand(Document*, const String& tagName);
+    FormatBlockCommand(Document*, const AtomicString& tagName);
 
     virtual void doApply();
     virtual EditAction editingAction() const { return EditActionFormatBlock; }
 
     bool modifyRange();
-    String m_tagName;
+    AtomicString m_tagName;
 };
 
 } // namespace WebCore
index f27dc79..03c59d3 100644 (file)
  */
 
 #include "config.h"
-#include "Element.h"
 #include "IndentOutdentCommand.h"
-#include "InsertListCommand.h"
+
 #include "Document.h"
-#include "htmlediting.h"
-#include "HTMLElement.h"
+#include "Element.h"
+#include "HTMLBlockquoteElement.h"
 #include "HTMLNames.h"
 #include "InsertLineBreakCommand.h"
+#include "InsertListCommand.h"
 #include "Range.h"
 #include "SplitElementCommand.h"
 #include "TextIterator.h"
+#include "htmlediting.h"
 #include "visible_units.h"
 #include <wtf/StdLibExtras.h>
 
@@ -48,12 +49,12 @@ static String indentBlockquoteString()
     return string;
 }
 
-static PassRefPtr<Element> createIndentBlockquoteElement(Document* document)
+static PassRefPtr<HTMLBlockquoteElement> createIndentBlockquoteElement(Document* document)
 {
-    RefPtr<Element> indentBlockquoteElement = createElement(document, "blockquote");
-    indentBlockquoteElement->setAttribute(classAttr, indentBlockquoteString());
-    indentBlockquoteElement->setAttribute(styleAttr, "margin: 0 0 0 40px; border: none; padding: 0px;");
-    return indentBlockquoteElement.release();
+    RefPtr<HTMLBlockquoteElement> element = new HTMLBlockquoteElement(blockquoteTag, document);
+    element->setAttribute(classAttr, indentBlockquoteString());
+    element->setAttribute(styleAttr, "margin: 0 0 0 40px; border: none; padding: 0px;");
+    return element.release();
 }
 
 static bool isIndentBlockquote(const Node* node)
@@ -72,32 +73,33 @@ static bool isListOrIndentBlockquote(const Node* node)
 
 IndentOutdentCommand::IndentOutdentCommand(Document* document, EIndentType typeOfAction, int marginInPixels)
     : CompositeEditCommand(document), m_typeOfAction(typeOfAction), m_marginInPixels(marginInPixels)
-{}
+{
+}
 
 // This function is a workaround for moveParagraph's tendency to strip blockquotes. It updates lastBlockquote to point to the
 // correct level for the current paragraph, and returns a pointer to a placeholder br where the insertion should be performed.
-Node* IndentOutdentCommand::prepareBlockquoteLevelForInsertion(VisiblePosition& currentParagraph, Node** lastBlockquote)
+PassRefPtr<Element> IndentOutdentCommand::prepareBlockquoteLevelForInsertion(VisiblePosition& currentParagraph, RefPtr<Element>& lastBlockquote)
 {
     int currentBlockquoteLevel = 0;
     int lastBlockquoteLevel = 0;
     Node* node = currentParagraph.deepEquivalent().node();
     while ((node = enclosingNodeOfType(Position(node->parentNode(), 0), &isIndentBlockquote)))
         currentBlockquoteLevel++;
-    node = *lastBlockquote;
+    node = lastBlockquote.get();
     while ((node = enclosingNodeOfType(Position(node->parentNode(), 0), &isIndentBlockquote)))
         lastBlockquoteLevel++;
     while (currentBlockquoteLevel > lastBlockquoteLevel) {
-        RefPtr<Node> newBlockquote = createIndentBlockquoteElement(document());
-        appendNode(newBlockquote.get(), *lastBlockquote);
-        *lastBlockquote = newBlockquote.get();
+        RefPtr<Element> newBlockquote = createIndentBlockquoteElement(document());
+        appendNode(newBlockquotelastBlockquote);
+        lastBlockquote = newBlockquote;
         lastBlockquoteLevel++;
     }
     while (currentBlockquoteLevel < lastBlockquoteLevel) {
-        *lastBlockquote = enclosingNodeOfType(Position((*lastBlockquote)->parentNode(), 0), &isIndentBlockquote);
+        lastBlockquote = static_cast<Element*>(enclosingNodeOfType(Position(lastBlockquote->parentNode(), 0), isIndentBlockquote));
         lastBlockquoteLevel--;
     }
-    RefPtr<Node> placeholder = createBreakElement(document());
-    appendNode(placeholder.get(), *lastBlockquote);
+    RefPtr<Element> placeholder = createBreakElement(document());
+    appendNode(placeholderlastBlockquote);
     // Add another br before the placeholder if it collapsed.
     VisiblePosition visiblePos(Position(placeholder.get(), 0));
     if (!isStartOfParagraph(visiblePos))
@@ -120,57 +122,57 @@ void IndentOutdentCommand::indentRegion()
     // and there's nothing to move.
     Position start = startOfSelection.deepEquivalent().downstream();
     if (start.node() == editableRootForPosition(start)) {
-        RefPtr<Node> blockquote = createIndentBlockquoteElement(document());
-        insertNodeAt(blockquote.get(), start);
-        RefPtr<Node> placeholder = createBreakElement(document());
-        appendNode(placeholder.get(), blockquote.get());
+        RefPtr<Element> blockquote = createIndentBlockquoteElement(document());
+        insertNodeAt(blockquote, start);
+        RefPtr<Element> placeholder = createBreakElement(document());
+        appendNode(placeholder, blockquote);
         setEndingSelection(Selection(Position(placeholder.get(), 0), DOWNSTREAM));
         return;
     }
     
-    Node* previousListNode = 0;
-    Node* newListNode = 0;
-    Node* newBlockquote = 0;
+    RefPtr<Element> previousListNode;
+    RefPtr<Element> newListNode;
+    RefPtr<Element> newBlockquote;
     VisiblePosition endOfCurrentParagraph = endOfParagraph(startOfSelection);
     VisiblePosition endAfterSelection = endOfParagraph(endOfParagraph(endOfSelection).next());
     while (endOfCurrentParagraph != endAfterSelection) {
         // Iterate across the selected paragraphs...
         VisiblePosition endOfNextParagraph = endOfParagraph(endOfCurrentParagraph.next());
-        Node* listNode = enclosingList(endOfCurrentParagraph.deepEquivalent().node());
-        Node* insertionPoint;
+        RefPtr<Element> listNode = enclosingList(endOfCurrentParagraph.deepEquivalent().node());
+        RefPtr<Element> insertionPoint;
         if (listNode) {
-            RefPtr<Node> placeholder = createBreakElement(document());
-            insertionPoint = placeholder.get();
+            RefPtr<Element> placeholder = createBreakElement(document());
+            insertionPoint = placeholder;
             newBlockquote = 0;
-            RefPtr<Node> listItem = createListItemElement(document());
+            RefPtr<Element> listItem = createListItemElement(document());
             if (listNode == previousListNode) {
                 // The previous paragraph was inside the same list, so add this list item to the list we already created
-                appendNode(listItem.get(), newListNode);
-                appendNode(placeholder.get(), listItem.get());
+                appendNode(listItem, newListNode);
+                appendNode(placeholder, listItem);
             } else {
                 // Clone the list element, insert it before the current paragraph, and move the paragraph into it.
-                RefPtr<Node> clonedList = static_cast<Element*>(listNode)->cloneNode(false);
-                insertNodeBefore(clonedList.get(), enclosingListChild(endOfCurrentParagraph.deepEquivalent().node()));
-                appendNode(listItem.get(), clonedList.get());
-                appendNode(placeholder.get(), listItem.get());
-                newListNode = clonedList.get();
+                RefPtr<Element> clonedList = listNode->cloneElement();
+                insertNodeBefore(clonedList, enclosingListChild(endOfCurrentParagraph.deepEquivalent().node()));
+                appendNode(listItem, clonedList);
+                appendNode(placeholder, listItem);
+                newListNode = clonedList;
                 previousListNode = listNode;
             }
         } else if (newBlockquote)
             // The previous paragraph was put into a new blockquote, so move this paragraph there as well
-            insertionPoint = prepareBlockquoteLevelForInsertion(endOfCurrentParagraph, &newBlockquote);
+            insertionPoint = prepareBlockquoteLevelForInsertion(endOfCurrentParagraph, newBlockquote);
         else {
             // Create a new blockquote and insert it as a child of the root editable element. We accomplish
             // this by splitting all parents of the current paragraph up to that point.
-            RefPtr<Node> blockquote = createIndentBlockquoteElement(document());
+            RefPtr<Element> blockquote = createIndentBlockquoteElement(document());
             Position start = startOfParagraph(endOfCurrentParagraph).deepEquivalent();
             
             Node* enclosingCell = enclosingNodeOfType(start, &isTableCell);
             Node* nodeToSplitTo = enclosingCell ? enclosingCell : editableRootForPosition(start);
             RefPtr<Node> startOfNewBlock = splitTreeToNode(start.node(), nodeToSplitTo);
-            insertNodeBefore(blockquote.get(), startOfNewBlock.get());
-            newBlockquote = blockquote.get();
-            insertionPoint = prepareBlockquoteLevelForInsertion(endOfCurrentParagraph, &newBlockquote);
+            insertNodeBefore(blockquote, startOfNewBlock);
+            newBlockquote = blockquote;
+            insertionPoint = prepareBlockquoteLevelForInsertion(endOfCurrentParagraph, newBlockquote);
             // Don't put the next paragraph in the blockquote we just created for this paragraph unless 
             // the next paragraph is in the same cell.
             if (enclosingCell && enclosingCell != enclosingNodeOfType(endOfNextParagraph.deepEquivalent(), &isTableCell))
@@ -223,9 +225,9 @@ void IndentOutdentCommand::outdentParagraph()
         visibleStartOfParagraph = VisiblePosition(visibleStartOfParagraph.deepEquivalent());
         visibleEndOfParagraph = VisiblePosition(visibleEndOfParagraph.deepEquivalent());
         if (visibleStartOfParagraph.isNotNull() && !isStartOfParagraph(visibleStartOfParagraph))
-            insertNodeAt(createBreakElement(document()).get(), visibleStartOfParagraph.deepEquivalent());
+            insertNodeAt(createBreakElement(document()), visibleStartOfParagraph.deepEquivalent());
         if (visibleEndOfParagraph.isNotNull() && !isEndOfParagraph(visibleEndOfParagraph))
-            insertNodeAt(createBreakElement(document()).get(), visibleEndOfParagraph.deepEquivalent());
+            insertNodeAt(createBreakElement(document()), visibleEndOfParagraph.deepEquivalent());
         return;
     }
     Node* enclosingBlockFlow = enclosingBlockFlowElement(visibleStartOfParagraph);
@@ -233,7 +235,7 @@ void IndentOutdentCommand::outdentParagraph()
     if (enclosingBlockFlow != enclosingNode)
         splitBlockquoteNode = splitTreeToNode(enclosingBlockFlowElement(visibleStartOfParagraph), enclosingNode, true);
     RefPtr<Node> placeholder = createBreakElement(document());
-    insertNodeBefore(placeholder.get(), splitBlockquoteNode.get());
+    insertNodeBefore(placeholder, splitBlockquoteNode);
     moveParagraph(startOfParagraph(visibleStartOfParagraph), endOfParagraph(visibleEndOfParagraph), VisiblePosition(Position(placeholder.get(), 0)), true);
 }
 
index c2ba1ea..bb1a1d2 100644 (file)
@@ -49,7 +49,7 @@ private:
     void indentRegion();
     void outdentRegion();
     void outdentParagraph();
-    Node* prepareBlockquoteLevelForInsertion(VisiblePosition&, Node**);
+    PassRefPtr<Element> prepareBlockquoteLevelForInsertion(VisiblePosition&, RefPtr<Element>&);
 
     EIndentType m_typeOfAction;
     int m_marginInPixels;
index 9d5ea6e..4905fae 100644 (file)
 
 namespace WebCore {
 
-InsertIntoTextNodeCommand::InsertIntoTextNodeCommand(PassRefPtr<Text> node, int offset, const String& text)
+InsertIntoTextNodeCommand::InsertIntoTextNodeCommand(PassRefPtr<Text> node, unsigned offset, const String& text)
     : SimpleEditCommand(node->document())
     , m_node(node)
     , m_offset(offset)
     , m_text(text)
 {
     ASSERT(m_node);
-    ASSERT(offset >= 0);
-    ASSERT(!text.isEmpty());
+    ASSERT(m_offset <= m_node->length());
+    ASSERT(!m_text.isEmpty());
 }
 
 void InsertIntoTextNodeCommand::doApply()
 {
-    ExceptionCode ec = 0;
+    ExceptionCode ec;
     m_node->insertData(m_offset, m_text, ec);
-    ASSERT(ec == 0);
 }
 
 void InsertIntoTextNodeCommand::doUnapply()
 {
-    ExceptionCode ec = 0;
+    ExceptionCode ec;
     m_node->deleteData(m_offset, m_text.length(), ec);
-    ASSERT(ec == 0);
 }
 
 } // namespace WebCore
index aed5da8..49cb58b 100644 (file)
@@ -34,19 +34,19 @@ class Text;
 
 class InsertIntoTextNodeCommand : public SimpleEditCommand {
 public:
-    static PassRefPtr<InsertIntoTextNodeCommand> create(PassRefPtr<Text> node, int offset, const String& text)
+    static PassRefPtr<InsertIntoTextNodeCommand> create(PassRefPtr<Text> node, unsigned offset, const String& text)
     {
         return adoptRef(new InsertIntoTextNodeCommand(node, offset, text));
     }
 
 private:
-    InsertIntoTextNodeCommand(PassRefPtr<Text> node, int offset, const String& text);
+    InsertIntoTextNodeCommand(PassRefPtr<Text> node, unsigned offset, const String& text);
 
     virtual void doApply();
     virtual void doUnapply();
 
     RefPtr<Text> m_node;
-    int m_offset;
+    unsigned m_offset;
     String m_text;
 };
 
index d6b4f56..15750fe 100644 (file)
@@ -51,24 +51,24 @@ bool InsertLineBreakCommand::preservesTypingStyle() const
     return true;
 }
 
-void InsertLineBreakCommand::insertNodeAfterPosition(Node *node, const Position &pos)
+void InsertLineBreakCommand::insertNodeAfterPosition(Node* node, const Position& pos)
 {
     // Insert the BR after the caret position. In the case the
     // position is a block, do an append. We don't want to insert
     // the BR *after* the block.
-    Node *cb = pos.node()->enclosingBlockFlowElement();
+    Element* cb = pos.node()->enclosingBlockFlowElement();
     if (cb == pos.node())
         appendNode(node, cb);
     else
         insertNodeAfter(node, pos.node());
 }
 
-void InsertLineBreakCommand::insertNodeBeforePosition(Node *node, const Position &pos)
+void InsertLineBreakCommand::insertNodeBeforePosition(Node* node, const Position& pos)
 {
     // Insert the BR after the caret position. In the case the
     // position is a block, do an append. We don't want to insert
     // the BR *before* the block.
-    Node *cb = pos.node()->enclosingBlockFlowElement();
+    Element* cb = pos.node()->enclosingBlockFlowElement();
     if (cb == pos.node())
         appendNode(node, cb);
     else
index 7433516..20c63b8 100644 (file)
@@ -37,19 +37,19 @@ namespace WebCore {
 
 using namespace HTMLNames;
 
-PassRefPtr<Node> InsertListCommand::insertList(Document* document, Type type)
+PassRefPtr<HTMLElement> InsertListCommand::insertList(Document* document, Type type)
 {
     RefPtr<InsertListCommand> insertCommand = new InsertListCommand(document, type, "");
     insertCommand->apply();
     return insertCommand->m_listElement;
 }
 
-Node* InsertListCommand::fixOrphanedListChild(Node* node)
+HTMLElement* InsertListCommand::fixOrphanedListChild(Node* node)
 {
-    RefPtr<Element> listElement = createUnorderedListElement(document());
-    insertNodeBefore(listElement.get(), node);
+    RefPtr<HTMLElement> listElement = createUnorderedListElement(document());
+    insertNodeBefore(listElement, node);
     removeNode(node);
-    appendNode(node, listElement.get());
+    appendNode(node, listElement);
     m_listElement = listElement;
     return listElement.get();
 }
@@ -137,7 +137,7 @@ void InsertListCommand::doApply()
     bool switchListType = false;
     if (listChildNode) {
         // Remove the list chlild.
-        Node* listNode = enclosingList(listChildNode);
+        HTMLElement* listNode = enclosingList(listChildNode);
         if (!listNode)
             listNode = fixOrphanedListChild(listChildNode);
         if (!listNode->hasTagName(listTag))
@@ -168,12 +168,12 @@ void InsertListCommand::doApply()
         // When removing a list, we must always create a placeholder to act as a point of insertion
         // for the list content being removed.
         RefPtr<Element> placeholder = createBreakElement(document());
-        RefPtr<Node> nodeToInsert = placeholder;
+        RefPtr<Element> nodeToInsert = placeholder;
         // If the content of the list item will be moved into another list, put it in a list item
         // so that we don't create an orphaned list child.
         if (enclosingList(listNode)) {
             nodeToInsert = createListItemElement(document());
-            appendNode(placeholder.get(), nodeToInsert.get());
+            appendNode(placeholder, nodeToInsert);
         }
         
         if (nextListChild && previousListChild) {
@@ -184,18 +184,18 @@ void InsertListCommand::doApply()
             // FIXME: We appear to split at nextListChild as opposed to listChildNode so that when we remove
             // listChildNode below in moveParagraphs, previousListChild will be removed along with it if it is 
             // unrendered. But we ought to remove nextListChild too, if it is unrendered.
-            splitElement(static_cast<Element*>(listNode), splitTreeToNode(nextListChild, listNode).get());
-            insertNodeBefore(nodeToInsert.get(), listNode);
+            splitElement(listNode, splitTreeToNode(nextListChild, listNode));
+            insertNodeBefore(nodeToInsert, listNode);
         } else if (nextListChild || listChildNode->parentNode() != listNode) {
             // Just because listChildNode has no previousListChild doesn't mean there isn't any content
             // in listNode that comes before listChildNode, as listChildNode could have ancestors
             // between it and listNode. So, we split up to listNode before inserting the placeholder
             // where we're about to move listChildNode to.
             if (listChildNode->parentNode() != listNode)
-                splitElement(static_cast<Element *>(listNode), splitTreeToNode(listChildNode, listNode).get());
-            insertNodeBefore(nodeToInsert.get(), listNode);
+                splitElement(listNode, splitTreeToNode(listChildNode, listNode).get());
+            insertNodeBefore(nodeToInsert, listNode);
         } else
-            insertNodeAfter(nodeToInsert.get(), listNode);
+            insertNodeAfter(nodeToInsert, listNode);
         
         VisiblePosition insertionPoint = VisiblePosition(Position(placeholder.get(), 0));
         moveParagraphs(start, end, insertionPoint, true);
@@ -208,11 +208,11 @@ void InsertListCommand::doApply()
         // Check for adjoining lists.
         VisiblePosition previousPosition = start.previous(true);
         VisiblePosition nextPosition = end.next(true);
-        RefPtr<Element> listItemElement = createListItemElement(document());
-        RefPtr<Element> placeholder = createBreakElement(document());
-        appendNode(placeholder.get(), listItemElement.get());
-        Node* previousList = outermostEnclosingList(previousPosition.deepEquivalent().node());
-        Node* nextList = outermostEnclosingList(nextPosition.deepEquivalent().node());
+        RefPtr<HTMLElement> listItemElement = createListItemElement(document());
+        RefPtr<HTMLElement> placeholder = createBreakElement(document());
+        appendNode(placeholder, listItemElement);
+        Element* previousList = outermostEnclosingList(previousPosition.deepEquivalent().node());
+        Element* nextList = outermostEnclosingList(nextPosition.deepEquivalent().node());
         Node* startNode = start.deepEquivalent().node();
         Node* previousCell = enclosingTableCell(previousPosition.deepEquivalent());
         Node* nextCell = enclosingTableCell(nextPosition.deepEquivalent());
@@ -223,16 +223,16 @@ void InsertListCommand::doApply()
             nextList = 0;
         // Place list item into adjoining lists.
         if (previousList)
-            appendNode(listItemElement.get(), previousList);
+            appendNode(listItemElement, previousList);
         else if (nextList)
-            insertNodeAt(listItemElement.get(), Position(nextList, 0));
+            insertNodeAt(listItemElement, Position(nextList, 0));
         else {
             // Create the list.
-            RefPtr<Element> listElement = m_type == OrderedList ? createOrderedListElement(document()) : createUnorderedListElement(document());
+            RefPtr<HTMLElement> listElement = m_type == OrderedList ? createOrderedListElement(document()) : createUnorderedListElement(document());
             m_listElement = listElement;
             if (!m_id.isEmpty())
-                static_cast<HTMLElement*>(listElement.get())->setId(m_id);
-            appendNode(listItemElement.get(), listElement.get());
+                listElement->setId(m_id);
+            appendNode(listItemElement, listElement);
             
             if (start == end && isBlock(start.deepEquivalent().node())) {
                 // Inserting the list into an empty paragraph that isn't held open 
@@ -254,7 +254,7 @@ void InsertListCommand::doApply()
             if (listChild && listChild->hasTagName(liTag))
                 insertionPos = positionBeforeNode(listChild);
                 
-            insertNodeAt(listElement.get(), insertionPos);
+            insertNodeAt(listElement, insertionPos);
         }
         moveParagraph(start, end, VisiblePosition(Position(placeholder.get(), 0)), true);
         if (nextList && previousList)
index e9a8da9..b39f2b5 100644 (file)
@@ -30,6 +30,8 @@
 
 namespace WebCore {
 
+class HTMLElement;
+
 class InsertListCommand : public CompositeEditCommand {
 public:
     enum Type { OrderedList, UnorderedList };
@@ -39,7 +41,7 @@ public:
         return adoptRef(new InsertListCommand(document, listType, listID));
     }
 
-    static PassRefPtr<Node> insertList(Document*, Type);
+    static PassRefPtr<HTMLElement> insertList(Document*, Type);
     
     virtual bool preservesTypingStyle() const { return true; }
 
@@ -49,9 +51,9 @@ private:
     virtual void doApply();
     virtual EditAction editingAction() const { return EditActionInsertList; }
 
-    Node* fixOrphanedListChild(Node*);
+    HTMLElement* fixOrphanedListChild(Node*);
     bool modifyRange();
-    RefPtr<Node> m_listElement;
+    RefPtr<HTMLElement> m_listElement;
     Type m_type;
     String m_id;
     bool m_forceCreateList;
index 2315597..c3acd9d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2008 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 namespace WebCore {
 
 InsertNodeBeforeCommand::InsertNodeBeforeCommand(PassRefPtr<Node> insertChild, PassRefPtr<Node> refChild)
-    : SimpleEditCommand(refChild->document()), m_insertChild(insertChild), m_refChild(refChild)
+    : SimpleEditCommand(refChild->document())
+    , m_insertChild(insertChild)
+    , m_refChild(refChild)
 {
     ASSERT(m_insertChild);
+    ASSERT(!m_insertChild->parentNode());
     ASSERT(m_refChild);
+    ASSERT(m_refChild->parentNode());
+
+    ASSERT(enclosingNodeOfType(Position(m_refChild->parentNode(), 0), isContentEditable) || !m_refChild->parentNode()->attached());
 }
 
 void InsertNodeBeforeCommand::doApply()
 {
-    ASSERT(m_insertChild);
-    ASSERT(m_refChild);
-    ASSERT(m_refChild->parentNode());
-    // If the child to insert is already in a tree, inserting it will remove it from it's old location
-    // in an non-undoable way.  We might eventually find it useful to do an undoable remove in this case.
-    ASSERT(!m_insertChild->parent());
-    ASSERT(enclosingNodeOfType(Position(m_refChild->parentNode(), 0), &isContentEditable) || !m_refChild->parentNode()->attached());
+    Node* parent = m_refChild->parentNode();
+    if (!parent)
+        return;
 
-    ExceptionCode ec = 0;
-    m_refChild->parentNode()->insertBefore(m_insertChild.get(), m_refChild.get(), ec);
-    ASSERT(ec == 0);
+    ExceptionCode ec;
+    parent->insertBefore(m_insertChild.get(), m_refChild.get(), ec);
 }
 
 void InsertNodeBeforeCommand::doUnapply()
 {
-    ASSERT(m_insertChild);
-    ASSERT(m_refChild);
-    ASSERT(m_refChild->parentNode());
-
-    ExceptionCode ec = 0;
-    m_refChild->parentNode()->removeChild(m_insertChild.get(), ec);
-    ASSERT(ec == 0);
+    ExceptionCode ec;
+    m_insertChild->remove(ec);
 }
 
 }
index bcd2bfa..8d82836 100644 (file)
@@ -119,13 +119,16 @@ void InsertParagraphSeparatorCommand::doApply()
     }
     
     // FIXME: The rangeCompliantEquivalent conversion needs to be moved into enclosingBlock.
-    Node* startBlock = enclosingBlock(rangeCompliantEquivalent(pos).node());
+    Node* startBlockNode = enclosingBlock(rangeCompliantEquivalent(pos).node());
     Position canonicalPos = VisiblePosition(pos).deepEquivalent();
-    if (!startBlock || !startBlock->parentNode() || 
-        isTableCell(startBlock) ||
-        startBlock->hasTagName(formTag) || 
-        canonicalPos.node()->renderer() && canonicalPos.node()->renderer()->isTable() ||
-        canonicalPos.node()->hasTagName(hrTag)) {
+    Element* startBlock = static_cast<Element*>(startBlockNode);
+    if (!startBlockNode
+            || !startBlockNode->isElementNode()
+            || !startBlock->parentNode()
+            || isTableCell(startBlock)
+            || startBlock->hasTagName(formTag)
+            || canonicalPos.node()->renderer() && canonicalPos.node()->renderer()->isTable()
+            || canonicalPos.node()->hasTagName(hrTag)) {
         applyCommandToComposite(InsertLineBreakCommand::create(document()));
         return;
     }
@@ -157,14 +160,14 @@ void InsertParagraphSeparatorCommand::doApply()
     bool nestNewBlock = false;
 
     // Create block to be inserted.
-    RefPtr<Node> blockToInsert;
+    RefPtr<Element> blockToInsert;
     if (startBlock == startBlock->rootEditableElement()) {
-        blockToInsert = static_pointer_cast<Node>(createDefaultParagraphElement(document()));
+        blockToInsert = createDefaultParagraphElement(document());
         nestNewBlock = true;
     } else if (shouldUseDefaultParagraphElement(startBlock)) 
-        blockToInsert = static_pointer_cast<Node>(createDefaultParagraphElement(document()));
+        blockToInsert = createDefaultParagraphElement(document());
     else
-        blockToInsert = startBlock->cloneNode(false);
+        blockToInsert = startBlock->cloneElement();
     
     //---------------------------------------------------------------------
     // Handle case when position is in the last visible position in its block,
@@ -174,15 +177,15 @@ void InsertParagraphSeparatorCommand::doApply()
             if (isFirstInBlock && !lineBreakExistsAtPosition(visiblePos)) {
                 // The block is empty.  Create an empty block to
                 // represent the paragraph that we're leaving.
-                RefPtr<Node> extraBlock = createDefaultParagraphElement(document());
-                appendNode(extraBlock.get(), startBlock);
-                appendBlockPlaceholder(extraBlock.get());
+                RefPtr<Element> extraBlock = createDefaultParagraphElement(document());
+                appendNode(extraBlock, startBlock);
+                appendBlockPlaceholder(extraBlock);
             }
-            appendNode(blockToInsert.get(), startBlock);
+            appendNode(blockToInsert, startBlock);
         } else
-            insertNodeAfter(blockToInsert.get(), startBlock);
+            insertNodeAfter(blockToInsert, startBlock);
 
-        appendBlockPlaceholder(blockToInsert.get());
+        appendBlockPlaceholder(blockToInsert);
         setEndingSelection(Selection(Position(blockToInsert.get(), 0), DOWNSTREAM));
         applyStyleAfterInsertion(startBlock);
         return;
@@ -231,10 +234,11 @@ void InsertParagraphSeparatorCommand::doApply()
     startNode = pos.node();
 
     // Build up list of ancestors in between the start node and the start block.
-    Vector<Node*> ancestors;
-    if (startNode != startBlock)
-        for (Node* n = startNode->parentNode(); n && n != startBlock; n = n->parentNode())
+    Vector<Element*> ancestors;
+    if (startNode != startBlock) {
+        for (Element* n = startNode->parentElement(); n && n != startBlock; n = n->parentElement())
             ancestors.append(n);
+    }
 
     // Make sure we do not cause a rendered space to become unrendered.
     // FIXME: We need the affinity for pos, but pos.downstream() does not give it
@@ -268,10 +272,10 @@ void InsertParagraphSeparatorCommand::doApply()
     updateLayout();
     
     // Make clones of ancestors in between the start node and the start block.
-    RefPtr<Node> parent = blockToInsert;
+    RefPtr<Element> parent = blockToInsert;
     for (size_t i = ancestors.size(); i != 0; --i) {
-        RefPtr<Node> child = ancestors[i - 1]->cloneNode(false); // shallow clone
-        appendNode(child.get(), parent.get());
+        RefPtr<Element> child = ancestors[i - 1]->cloneElement(); // shallow clone
+        appendNode(child, parent);
         parent = child.release();
     }
 
@@ -297,9 +301,11 @@ void InsertParagraphSeparatorCommand::doApply()
 
     // Move everything after the start node.
     if (!ancestors.isEmpty()) {
-        Node* leftParent = ancestors.first();
+        Element* leftParent = ancestors.first();
         while (leftParent && leftParent != startBlock) {
-            parent = parent->parentNode();
+            parent = parent->parentElement();
+            if (!parent)
+                break;
             Node* n = leftParent->nextSibling();
             while (n && n != blockToInsert) {
                 Node* next = n->nextSibling();
@@ -307,7 +313,7 @@ void InsertParagraphSeparatorCommand::doApply()
                 appendNode(n, parent.get());
                 n = next;
             }
-            leftParent = leftParent->parentNode();
+            leftParent = leftParent->parentElement();
         }
     }
 
index dddf43c..f981481 100644 (file)
@@ -42,35 +42,33 @@ JoinTextNodesCommand::JoinTextNodesCommand(PassRefPtr<Text> text1, PassRefPtr<Te
 
 void JoinTextNodesCommand::doApply()
 {
-    ASSERT(m_text1);
-    ASSERT(m_text2);
-    ASSERT(m_text1->nextSibling() == m_text2);
+    if (m_text1->nextSibling() != m_text2)
+        return;
 
     ExceptionCode ec = 0;
     m_text2->insertData(0, m_text1->data(), ec);
-    ASSERT(ec == 0);
+    if (ec)
+        return;
 
-    m_text2->parentNode()->removeChild(m_text1.get(), ec);
-    ASSERT(ec == 0);
-
-    m_offset = m_text1->length();
+    m_text1->remove(ec);
 }
 
 void JoinTextNodesCommand::doUnapply()
 {
-    ASSERT(m_text2);
-    ASSERT(m_offset > 0);
+    if (m_text1->parentNode())
+        return;
+
+    Node* parent = m_text2->parentNode();
+    if (!parent)
+        return;
 
     ExceptionCode ec = 0;
 
-    m_text2->deleteData(0, m_offset, ec);
-    ASSERT(ec == 0);
+    parent->insertBefore(m_text1.get(), m_text2.get(), ec);
+    if (ec)
+        return;
 
-    m_text2->parentNode()->insertBefore(m_text1.get(), m_text2.get(), ec);
-    ASSERT(ec == 0);
-        
-    ASSERT(m_text2->previousSibling()->isTextNode());
-    ASSERT(m_text2->previousSibling() == m_text1);
+    m_text2->deleteData(0, m_text1->length(), ec);
 }
 
 } // namespace WebCore
index 6fb5c56..6bdc6e6 100644 (file)
@@ -47,7 +47,6 @@ private:
 
     RefPtr<Text> m_text1;
     RefPtr<Text> m_text2;
-    unsigned m_offset;
 };
 
 } // namespace WebCore
index 1819b92..99ba286 100644 (file)
 namespace WebCore {
 
 MergeIdenticalElementsCommand::MergeIdenticalElementsCommand(PassRefPtr<Element> first, PassRefPtr<Element> second)
-    : SimpleEditCommand(first->document()), m_element1(first), m_element2(second)
+    : SimpleEditCommand(first->document())
+    , m_element1(first)
+    , m_element2(second)
 {
     ASSERT(m_element1);
     ASSERT(m_element2);
+    ASSERT(m_element1->nextSibling() == m_element2);
 }
 
 void MergeIdenticalElementsCommand::doApply()
 {
-    ASSERT(m_element1);
-    ASSERT(m_element2);
-    ASSERT(m_element1->nextSibling() == m_element2);
-    
+    if (m_element1->nextSibling() != m_element2)
+        return;
+
+    m_atChild = m_element2->firstChild();
+
     ExceptionCode ec = 0;
 
-    if (!m_atChild)
-        m_atChild = m_element2->firstChild();
+    Vector<RefPtr<Node> > children;
+    for (Node* child = m_element1->firstChild(); child; child = child->nextSibling())
+        children.append(child);
 
-    while (m_element1->lastChild()) {
-        m_element2->insertBefore(m_element1->lastChild(), m_element2->firstChild(), ec);
-        ASSERT(ec == 0);
-    }
+    size_t size = children.size();
+    for (size_t i = 0; i < size; ++i)
+        m_element2->insertBefore(children[i].release(), m_atChild.get(), ec);
 
-    m_element2->parentNode()->removeChild(m_element1.get(), ec);
-    ASSERT(ec == 0);
+    m_element1->remove(ec);
 }
 
 void MergeIdenticalElementsCommand::doUnapply()
@@ -62,16 +65,25 @@ void MergeIdenticalElementsCommand::doUnapply()
     ASSERT(m_element1);
     ASSERT(m_element2);
 
+    RefPtr<Node> atChild = m_atChild.release();
+
+    Node* parent = m_element2->parent();
+    if (!parent)
+        return;
+
     ExceptionCode ec = 0;
 
-    m_element2->parent()->insertBefore(m_element1.get(), m_element2.get(), ec);
-    ASSERT(ec == 0);
+    parent->insertBefore(m_element1.get(), m_element2.get(), ec);
+    if (ec)
+        return;
+
+    Vector<RefPtr<Node> > children;
+    for (Node* child = m_element2->firstChild(); child && child != atChild; child = child->nextSibling())
+        children.append(child);
 
-    while (m_element2->firstChild() != m_atChild) {
-        ASSERT(m_element2->firstChild());
-        m_element1->appendChild(m_element2->firstChild(), ec);
-        ASSERT(ec == 0);
-    }
+    size_t size = children.size();
+    for (size_t i = 0; i < size; ++i)
+        m_element1->appendChild(children[i].release(), ec);
 }
 
 } // namespace WebCore
index 0b1123b..7c14868 100644 (file)
@@ -119,7 +119,7 @@ void ModifySelectionListLevelCommand::insertSiblingNodeRangeAfter(Node* startNod
     }
 }
 
-void ModifySelectionListLevelCommand::appendSiblingNodeRange(Node* startNode, Node* endNode, Node* newParent)
+void ModifySelectionListLevelCommand::appendSiblingNodeRange(Node* startNode, Node* endNode, Element* newParent)
 {
     Node* node = startNode;
     while (1) {
@@ -178,14 +178,16 @@ void IncreaseSelectionListLevelCommand::doApply()
     Node* previousItem = startListChild->renderer()->previousSibling()->element();
     if (isListElement(previousItem)) {
         // move nodes up into preceding list
-        appendSiblingNodeRange(startListChild, endListChild, previousItem);
+        appendSiblingNodeRange(startListChild, endListChild, static_cast<Element*>(previousItem));
         m_listElement = previousItem;
     } else {
         // create a sublist for the preceding element and move nodes there
-        RefPtr<Node> newParent;
+        RefPtr<Element> newParent;
         switch (m_listType) {
             case InheritedListType:
-                newParent = startListChild->parentNode()->cloneNode(false);
+                newParent = startListChild->parentElement();
+                if (newParent)
+                    newParent = newParent->cloneElement();
                 break;
             case OrderedList:
                 newParent = createOrderedListElement(document());
@@ -258,7 +260,7 @@ void DecreaseSelectionListLevelCommand::doApply()
 
     Node* previousItem = startListChild->renderer()->previousSibling() ? startListChild->renderer()->previousSibling()->element() : 0;
     Node* nextItem = endListChild->renderer()->nextSibling() ? endListChild->renderer()->nextSibling()->element() : 0;
-    Node* listNode = startListChild->parentNode();
+    Element* listNode = startListChild->parentElement();
 
     if (!previousItem) {
         // at start of sublist, move the child(ren) to before the sublist
@@ -269,9 +271,9 @@ void DecreaseSelectionListLevelCommand::doApply()
     } else if (!nextItem) {
         // at end of list, move the child(ren) to after the sublist
         insertSiblingNodeRangeAfter(startListChild, endListChild, listNode);    
-    } else {
+    } else if (listNode) {
         // in the middle of list, split the list and move the children to the divide
-        splitElement(static_cast<Element*>(listNode), startListChild);
+        splitElement(listNode, startListChild);
         insertSiblingNodeRangeBefore(startListChild, endListChild, listNode);
     }
 }
index 1e66d10..39efff8 100644 (file)
@@ -37,7 +37,7 @@ class ModifySelectionListLevelCommand : public CompositeEditCommand {
 protected:
     ModifySelectionListLevelCommand(Document*);
     
-    void appendSiblingNodeRange(Node* startNode, Node* endNode, Node* newParent);
+    void appendSiblingNodeRange(Node* startNode, Node* endNode, Element* newParent);
     void insertSiblingNodeRangeBefore(Node* startNode, Node* endNode, Node* refNode);
     void insertSiblingNodeRangeAfter(Node* startNode, Node* endNode, Node* refNode);
 
index d4afed0..17870a7 100644 (file)
 
 namespace WebCore {
 
-RemoveCSSPropertyCommand::RemoveCSSPropertyCommand(Document* document, CSSStyleDeclaration* decl, int property)
+RemoveCSSPropertyCommand::RemoveCSSPropertyCommand(Document* document, PassRefPtr<CSSMutableStyleDeclaration> style, CSSPropertyID property)
     : SimpleEditCommand(document)
-    , m_decl(decl->makeMutable())
+    , m_style(style)
     , m_property(property)
     , m_important(false)
 {
-    ASSERT(m_decl);
+    ASSERT(m_style);
 }
 
 void RemoveCSSPropertyCommand::doApply()
 {
-    ASSERT(m_decl);
-
-    m_oldValue = m_decl->getPropertyValue(m_property);
-    ASSERT(!m_oldValue.isNull());
-
-    m_important = m_decl->getPropertyPriority(m_property);
-    m_decl->removeProperty(m_property);
+    m_oldValue = m_style->getPropertyValue(m_property);
+    m_important = m_style->getPropertyPriority(m_property);
+    m_style->removeProperty(m_property);
 }
 
 void RemoveCSSPropertyCommand::doUnapply()
 {
-    ASSERT(m_decl);
-    ASSERT(!m_oldValue.isNull());
-
-    m_decl->setProperty(m_property, m_oldValue, m_important);
+    m_style->setProperty(m_property, m_oldValue, m_important);
 }
 
 } // namespace WebCore
index 8a96b4b..fd81307 100644 (file)
 #define RemoveCSSPropertyCommand_h
 
 #include "EditCommand.h"
+#include "CSSPropertyNames.h"
 
 namespace WebCore {
 
-class CSSStyleDeclaration;
-
 class RemoveCSSPropertyCommand : public SimpleEditCommand {
 public:
-    static PassRefPtr<RemoveCSSPropertyCommand> create(Document* document, CSSStyleDeclaration* style, int property)
+    static PassRefPtr<RemoveCSSPropertyCommand> create(Document* document, PassRefPtr<CSSMutableStyleDeclaration> style, CSSPropertyID property)
     {
         return adoptRef(new RemoveCSSPropertyCommand(document, style, property));
     }
 
 private:
-    RemoveCSSPropertyCommand(Document*, CSSStyleDeclaration*, int property);
+    RemoveCSSPropertyCommand(Document*, PassRefPtr<CSSMutableStyleDeclaration>, CSSPropertyID property);
 
     virtual void doApply();
     virtual void doUnapply();
 
-    RefPtr<CSSMutableStyleDeclaration> m_decl;
-    int m_property;
+    RefPtr<CSSMutableStyleDeclaration> m_style;
+    CSSPropertyID m_property;
     String m_oldValue;
     bool m_important;
 };
index bcf1fdf..817773d 100644 (file)
@@ -1,62 +1 @@
-/*
- * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include "config.h"
-#include "RemoveNodeAttributeCommand.h"
-
-#include "Element.h"
-#include <wtf/Assertions.h>
-
-namespace WebCore {
-
-RemoveNodeAttributeCommand::RemoveNodeAttributeCommand(PassRefPtr<Element> element, const QualifiedName& attribute)
-    : SimpleEditCommand(element->document()), m_element(element), m_attribute(attribute)
-{
-    ASSERT(m_element);
-}
-
-void RemoveNodeAttributeCommand::doApply()
-{
-    ASSERT(m_element);
-
-    m_oldValue = m_element->getAttribute(m_attribute);
-    ASSERT(!m_oldValue.isNull());
-
-    ExceptionCode ec = 0;
-    m_element->removeAttribute(m_attribute, ec);
-    ASSERT(ec == 0);
-}
-
-void RemoveNodeAttributeCommand::doUnapply()
-{
-    ASSERT(m_element);
-    ASSERT(!m_oldValue.isNull());
-
-    ExceptionCode ec = 0;
-    m_element->setAttribute(m_attribute, m_oldValue.impl(), ec);
-    ASSERT(ec == 0);
-}
-
-} // namespace WebCore
+/* delete this file */
index fd9127e..8a2a98f 100644 (file)
@@ -1,54 +1 @@
-/*
- * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#ifndef RemoveNodeAttributeCommand_h
-#define RemoveNodeAttributeCommand_h
-
-#include "EditCommand.h"
-#include "QualifiedName.h"
-
-namespace WebCore {
-
-class RemoveNodeAttributeCommand : public SimpleEditCommand {
-public:
-    static PassRefPtr<RemoveNodeAttributeCommand> create(PassRefPtr<Element> element, const QualifiedName& attribute)
-    {
-        return adoptRef(new RemoveNodeAttributeCommand(element, attribute));
-    }
-    
-private:
-    RemoveNodeAttributeCommand(PassRefPtr<Element>, const QualifiedName& attribute);
-
-    virtual void doApply();
-    virtual void doUnapply();
-
-    RefPtr<Element> m_element;
-    QualifiedName m_attribute;
-    AtomicString m_oldValue;
-};
-
-} // namespace WebCore
-
-#endif // RemoveNodeAttributeCommand_h
+#error delete this file
index 2519730..62a36be 100644 (file)
 
 namespace WebCore {
 
-RemoveNodeCommand::RemoveNodeCommand(PassRefPtr<Node> removeChild)
-    : SimpleEditCommand(removeChild->document())
-    , m_removeChild(removeChild)
-    , m_parent(m_removeChild->parentNode())
-    , m_refChild(m_removeChild->nextSibling())
+RemoveNodeCommand::RemoveNodeCommand(PassRefPtr<Node> node)
+    : SimpleEditCommand(node->document())
+    , m_node(node)
 {
-    ASSERT(m_parent);
+    ASSERT(m_node);
+    ASSERT(m_node->parentNode());
 }
 
 void RemoveNodeCommand::doApply()
 {
-    ASSERT(m_parent);
-    ASSERT(m_removeChild);
+    Node* parent = m_node->parentNode();
+    if (!parent)
+        return;
 
-    ExceptionCode ec = 0;
-    m_parent->removeChild(m_removeChild.get(), ec);
-    ASSERT(ec == 0);
+    m_parent = parent;
+    m_refChild = m_node->nextSibling();
+
+    ExceptionCode ec;
+    m_node->remove(ec);
 }
 
 void RemoveNodeCommand::doUnapply()
 {
-    ASSERT(m_parent);
-    ASSERT(m_removeChild);
+    RefPtr<Node> parent = m_parent.release();
+    RefPtr<Node> refChild = m_refChild.release();
+    if (!parent)
+        return;
 
-    ExceptionCode ec = 0;
-    m_parent->insertBefore(m_removeChild.get(), m_refChild.get(), ec);
-    ASSERT(ec == 0);
+    ExceptionCode ec;
+    parent->insertBefore(m_node.get(), refChild.get(), ec);
 }
 
 }
index 802cb8b..14a798c 100644 (file)
@@ -43,7 +43,7 @@ private:
     virtual void doApply();
     virtual void doUnapply();
 
-    RefPtr<Node> m_removeChild;
+    RefPtr<Node> m_node;
     RefPtr<Node> m_parent;
     RefPtr<Node> m_refChild;    
 };
index f583865..98f4282 100644 (file)
@@ -39,11 +39,17 @@ RemoveNodePreservingChildrenCommand::RemoveNodePreservingChildrenCommand(PassRef
 
 void RemoveNodePreservingChildrenCommand::doApply()
 {
-    while (Node* curr = m_node->firstChild()) {
-        removeNode(curr);
-        insertNodeBefore(curr, m_node.get());
+    Vector<RefPtr<Node> > children;
+    for (Node* child = m_node->firstChild(); child; child = child->nextSibling())
+        children.append(child);
+
+    size_t size = children.size();
+    for (size_t i = 0; i < size; ++i) {
+        RefPtr<Node> child = children[i].release();
+        removeNode(child);
+        insertNodeBefore(child.release(), m_node);
     }
-    removeNode(m_node.get());
+    removeNode(m_node);
 }
 
 }
index 8b9fe22..0a19c5e 100644 (file)
@@ -221,7 +221,7 @@ PassRefPtr<Node> ReplacementFragment::insertFragmentForTestRendering(Node* conte
     if (!body)
         return 0;
 
-    RefPtr<StyledElement> holder = static_pointer_cast<StyledElement>(createDefaultParagraphElement(m_document.get()));
+    RefPtr<StyledElement> holder = createDefaultParagraphElement(m_document.get());
     
     ExceptionCode ec = 0;
 
index 995dd1e..d49c18c 100644 (file)
 namespace WebCore {
 
 SetNodeAttributeCommand::SetNodeAttributeCommand(PassRefPtr<Element> element, 
-        const QualifiedName& attribute, const String &value)
-    : SimpleEditCommand(element->document()), m_element(element), m_attribute(attribute), m_value(value)
+        const QualifiedName& attribute, const AtomicString& value)
+    : SimpleEditCommand(element->document())
+    , m_element(element)
+    , m_attribute(attribute)
+    , m_value(value)
 {
     ASSERT(m_element);
-    ASSERT(!m_value.isNull());
 }
 
 void SetNodeAttributeCommand::doApply()
 {
-    ASSERT(m_element);
-    ASSERT(!m_value.isNull());
-
-    ExceptionCode ec = 0;
     m_oldValue = m_element->getAttribute(m_attribute);
-    m_element->setAttribute(m_attribute, m_value.impl(), ec);
-    ASSERT(ec == 0);
+    m_element->setAttribute(m_attribute, m_value);
 }
 
 void SetNodeAttributeCommand::doUnapply()
 {
-    ASSERT(m_element);
-
-    ExceptionCode ec = 0;
-    if (m_oldValue.isNull())
-        m_element->removeAttribute(m_attribute, ec);
-    else
-        m_element->setAttribute(m_attribute, m_oldValue.impl(), ec);
-    ASSERT(ec == 0);
+    m_element->setAttribute(m_attribute, m_oldValue);
+    AtomicStringImpl* nullString = 0;
+    m_oldValue = nullString;
 }
 
 } // namespace WebCore
-
index aec79a3..899ac62 100644 (file)
@@ -39,7 +39,7 @@ public:
     }
 
 private:
-    SetNodeAttributeCommand(PassRefPtr<Element>, const QualifiedName& attribute, const String& value);
+    SetNodeAttributeCommand(PassRefPtr<Element>, const QualifiedName& attribute, const AtomicString& value);
 
     virtual void doApply();
     virtual void doUnapply();
index b056fee..69447d4 100644 (file)
 namespace WebCore {
 
 SplitElementCommand::SplitElementCommand(PassRefPtr<Element> element, PassRefPtr<Node> atChild)
-    : SimpleEditCommand(element->document()), m_element2(element), m_atChild(atChild)
+    : SimpleEditCommand(element->document())
+    , m_element2(element)
+    , m_atChild(atChild)
 {
     ASSERT(m_element2);
     ASSERT(m_atChild);
+    ASSERT(m_atChild->parentNode() == m_element2);
 }
 
 void SplitElementCommand::doApply()
 {
-    ASSERT(m_element2);
-    ASSERT(m_atChild);
-    ASSERT(m_atChild->parentNode() == m_element2);
+    RefPtr<Element> prefixElement = m_element2->cloneElement();
+
+    if (m_atChild->parentNode() != m_element2)
+        return;
+
+    Vector<RefPtr<Node> > children;
+    for (Node* node = m_element2->firstChild(); node != m_atChild; node = node->nextSibling())
+        children.append(node);
 
     ExceptionCode ec = 0;
 
-    if (!m_element1) {
-        // create only if needed.
-        // if reapplying, this object will already exist.
-        m_element1 = static_pointer_cast<Element>(m_element2->cloneNode(false));
-        ASSERT(m_element1);
-    }
-
-    m_element2->parent()->insertBefore(m_element1.get(), m_element2.get(), ec);
-    ASSERT(ec == 0);
-    
-    // Bail if we were asked to split at a bogus child, to avoid hanging below.
-    if (!m_atChild || m_atChild->parentNode() != m_element2)
+    Node* parent = m_element2->parentNode();
+    if (!parent)
         return;
-    
-    while (m_element2->firstChild() != m_atChild) {
-        ASSERT(m_element2->firstChild());
-        m_element1->appendChild(m_element2->firstChild(), ec);
-        ASSERT(ec == 0);
-    }
+    parent->insertBefore(prefixElement.get(), m_element2.get(), ec);
+    if (ec)
+        return;
+    m_element1 = prefixElement.release();
+
+    size_t size = children.size();
+    for (size_t i = 0; i < size; ++i)
+        m_element1->appendChild(children[i], ec);
 }
 
 void SplitElementCommand::doUnapply()
 {
-    ASSERT(m_element1);
-    ASSERT(m_element2);
-    ASSERT(m_atChild);
+    if (!m_element1)
+        return;
+
+    Vector<RefPtr<Node> > children;
+    for (Node* node = m_element1->firstChild(); node; node = node->nextSibling())
+        children.append(node);
 
-    ASSERT(m_element1->nextSibling() == m_element2);
-    ASSERT(m_element2->firstChild() && m_element2->firstChild() == m_atChild);
+    RefPtr<Node> refChild = m_element2->firstChild();
 
     ExceptionCode ec = 0;
 
-    while (m_element1->lastChild()) {
-        m_element2->insertBefore(m_element1->lastChild(), m_element2->firstChild(), ec);
-        ASSERT(ec == 0);
-    }
+    size_t size = children.size();
+    for (size_t i = 0; i < size; ++i)
+        m_element2->insertBefore(children[i].get(), refChild.get(), ec);
 
-    m_element2->parentNode()->removeChild(m_element1.get(), ec);
-    ASSERT(ec == 0);
+    m_element1->remove(ec);
+    m_element1 = 0;
 }
 
 } // namespace WebCore
index be6cd1d..07a54e3 100644 (file)
 namespace WebCore {
 
 SplitTextNodeCommand::SplitTextNodeCommand(PassRefPtr<Text> text, int offset)
-    : SimpleEditCommand(text->document()), m_text2(text), m_offset(offset)
+    : SimpleEditCommand(text->document())
+    , m_text2(text)
+    , m_offset(offset)
 {
+    // NOTE: Various callers rely on the fact that the original node becomes
+    // the second node (i.e. the new node is inserted before the existing one).
+    // That is not a fundamental dependency (i.e. it could be re-coded), but
+    // rather is based on how this code happens to work.
     ASSERT(m_text2);
     ASSERT(m_text2->length() > 0);
+    ASSERT(m_offset > 0);
+    ASSERT(m_offset < m_text2->length());
 }
 
 void SplitTextNodeCommand::doApply()
 {
-    ASSERT(m_text2);
-    ASSERT(m_offset > 0);
-
     ExceptionCode ec = 0;
 
-    // NOTE: Various callers rely on the fact that the original node becomes
-    // the second node (i.e. the new node is inserted before the existing one).
-    // That is not a fundamental dependency (i.e. it could be re-coded), but
-    // rather is based on how this code happens to work.
-    if (!m_text1) {
-        // create only if needed.
-        // if reapplying, this object will already exist.
-        m_text1 = document()->createTextNode(m_text2->substringData(0, m_offset, ec));
-        ASSERT(ec == 0);
-        ASSERT(m_text1);
-    }
+    String prefixText = m_text2->substringData(0, m_offset, ec);
+    if (prefixText.isEmpty())
+        return;
 
-    document()->copyMarkers(m_text2.get(), 0, m_offset, m_text1.get(), 0);
-    m_text2->deleteData(0, m_offset, ec);
-    ASSERT(ec == 0);
+    RefPtr<Text> prefixTextNode = new Text(document(), prefixText);
+    ASSERT(prefixTextNode);
+    document()->copyMarkers(m_text2.get(), 0, m_offset, prefixTextNode.get(), 0);
 
-    m_text2->parentNode()->insertBefore(m_text1.get(), m_text2.get(), ec);
-    ASSERT(ec == 0);
-        
-    ASSERT(m_text2->previousSibling()->isTextNode());
-    ASSERT(m_text2->previousSibling() == m_text1);
+    Node* parent = m_text2->parentNode();
+    if (!parent)
+        return;
+    parent->insertBefore(prefixTextNode.get(), m_text2.get(), ec);
+    if (ec)
+        return;
+
+    m_text2->deleteData(0, m_offset, ec);
+    m_text1 = prefixTextNode.release();
 }
 
 void SplitTextNodeCommand::doUnapply()
 {
-    ASSERT(m_text1);
-    ASSERT(m_text2);
-    ASSERT(m_text1->nextSibling() == m_text2);
-        
-    ExceptionCode ec = 0;
-    m_text2->insertData(0, m_text1->data(), ec);
-    ASSERT(ec == 0);
+    if (!m_text1)
+        return;
 
-    document()->copyMarkers(m_text1.get(), 0, m_offset, m_text2.get(), 0);
+    ASSERT(m_text1->document() == document());
 
-    m_text2->parentNode()->removeChild(m_text1.get(), ec);
-    ASSERT(ec == 0);
+    RefPtr<Text> prefixTextNode = m_text1.release();
+    String prefixText = prefixTextNode->data();
+
+    ExceptionCode ec = 0;
+    m_text2->insertData(0, prefixText, ec);
+    if (ec)
+        return;
 
-    m_offset = m_text1->length();
+    document()->copyMarkers(prefixTextNode.get(), 0, prefixText.length(), m_text2.get(), 0);
+    prefixTextNode->remove(ec);
 }
 
 } // namespace WebCore
index 7038a17..e716c72 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -46,14 +46,21 @@ void SplitTextNodeContainingElementCommand::doApply()
     ASSERT(m_offset > 0);
 
     splitTextNode(m_text.get(), m_offset);
-    
-    Node *parentNode = m_text->parentNode();
-    if (!parentNode->renderer() || !parentNode->renderer()->isInline()) {
-        wrapContentsInDummySpan(static_cast<Element *>(parentNode));
-        parentNode = parentNode->firstChild();
+
+    Element* parent = m_text->parentElement();
+    if (!parent)
+        return;
+
+    RenderObject* parentRenderer = parent->renderer();
+    if (!parentRenderer || !parentRenderer->isInline()) {
+        wrapContentsInDummySpan(parent);
+        Node* firstChild = parent->firstChild();
+        if (!firstChild || !firstChild->isElementNode())
+            return;
+        parent = static_cast<Element*>(firstChild);
     }
 
-    splitElement(static_cast<Element *>(parentNode), m_text.get());
+    splitElement(parent, m_text);
 }
 
 }
index 86bf440..7622c1e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 namespace WebCore {
 
 WrapContentsInDummySpanCommand::WrapContentsInDummySpanCommand(PassRefPtr<Element> element)
-    : SimpleEditCommand(element->document()), m_element(element)
+    : SimpleEditCommand(element->document())
+    , m_element(element)
 {
     ASSERT(m_element);
 }
 
 void WrapContentsInDummySpanCommand::doApply()
 {
-    ASSERT(m_element);
-
-    ExceptionCode ec = 0;
+    Vector<RefPtr<Node> > children;
+    for (Node* child = m_element->firstChild(); child; child = child->nextSibling())
+        children.append(child);
 
-    if (!m_dummySpan)
-        m_dummySpan = static_pointer_cast<HTMLElement>(createStyleSpanElement(document()));
+    RefPtr<HTMLElement> span = createStyleSpanElement(document());
  
-    while (m_element->firstChild()) {
-        m_dummySpan->appendChild(m_element->firstChild(), ec);
-        ASSERT(ec == 0);
-    }
+    ExceptionCode ec;
+
+    size_t size = children.size();
+    for (size_t i = 0; i < size; ++i)
+        span->appendChild(children[i].release(), ec);
 
-    m_element->appendChild(m_dummySpan.get(), ec);
-    ASSERT(ec == 0);
+    m_element->appendChild(span.get(), ec);
+
+    m_dummySpan = span.release();
 }
 
 void WrapContentsInDummySpanCommand::doUnapply()
 {
     ASSERT(m_element);
-    ASSERT(m_dummySpan);
 
-    ASSERT(m_element->firstChild() == m_dummySpan);
-    ASSERT(!m_element->firstChild()->nextSibling());
+    RefPtr<HTMLElement> span = m_dummySpan.release();
+    if (!span)
+        return;
+
+    Vector<RefPtr<Node> > children;
+    for (Node* child = span->firstChild(); child; child = child->nextSibling())
+        children.append(child);
 
-    ExceptionCode ec = 0;
+    ExceptionCode ec;
 
-    while (m_dummySpan->firstChild()) {
-        m_element->appendChild(m_dummySpan->firstChild(), ec);
-        ASSERT(ec == 0);
-    }
+    size_t size = children.size();
+    for (size_t i = 0; i < size; ++i)
+        m_element->appendChild(children[i].release(), ec);
 
-    m_element->removeChild(m_dummySpan.get(), ec);
-    ASSERT(ec == 0);
+    span->remove(ec);
 }
 
 } // namespace WebCore
index 63a2ae7..b12131a 100644 (file)
@@ -30,6 +30,8 @@
 
 namespace WebCore {
 
+class HTMLElement;
+
 class WrapContentsInDummySpanCommand : public SimpleEditCommand {
 public:
     static PassRefPtr<WrapContentsInDummySpanCommand> create(PassRefPtr<Element> element)
@@ -44,7 +46,7 @@ private:
     virtual void doUnapply();
 
     RefPtr<Element> m_element;
-    RefPtr<Element> m_dummySpan;
+    RefPtr<HTMLElement> m_dummySpan;
 };
 
 } // namespace WebCore
index 575114a..ab2e397 100644 (file)
 #include "CharacterNames.h"
 #include "Document.h"
 #include "EditingText.h"
-#include "HTMLElement.h"
+#include "HTMLBRElement.h"
+#include "HTMLDivElement.h"
+#include "HTMLElementFactory.h"
 #include "HTMLInterchange.h"
+#include "HTMLLIElement.h"
 #include "HTMLNames.h"
+#include "HTMLOListElement.h"
+#include "HTMLUListElement.h"
 #include "PositionIterator.h"
 #include "RenderObject.h"
 #include "RegularExpression.h"
@@ -302,7 +307,7 @@ bool isBlock(const Node* node)
 // knowing about these kinds of special cases.
 Node* enclosingBlock(Node* node)
 {
-    return enclosingNodeOfType(Position(node, 0), &isBlock);
+    return static_cast<Element*>(enclosingNodeOfType(Position(node, 0), isBlock));
 }
 
 Position rangeCompliantEquivalent(const Position& pos)
@@ -616,7 +621,7 @@ Node* highestEnclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const N
 
 Node* enclosingTableCell(const Position& p)
 {
-    return enclosingNodeOfType(p, &isTableCell);
+    return static_cast<Element*>(enclosingNodeOfType(p, isTableCell));
 }
 
 Node* enclosingAnchorElement(const Position& p)
@@ -630,7 +635,7 @@ Node* enclosingAnchorElement(const Position& p)
     return node;
 }
 
-Node* enclosingList(Node* node)
+HTMLElement* enclosingList(Node* node)
 {
     if (!node)
         return 0;
@@ -639,7 +644,7 @@ Node* enclosingList(Node* node)
     
     for (Node* n = node->parentNode(); n; n = n->parentNode()) {
         if (n->hasTagName(ulTag) || n->hasTagName(olTag))
-            return n;
+            return static_cast<HTMLElement*>(n);
         if (n == root)
             return 0;
     }
@@ -666,12 +671,12 @@ Node* enclosingListChild(Node *node)
     return 0;
 }
 
-static Node* embeddedSublist(Node* listItem)
+static HTMLElement* embeddedSublist(Node* listItem)
 {
     // Check the DOM so that we'll find collapsed sublists without renderers.
     for (Node* n = listItem->firstChild(); n; n = n->nextSibling()) {
         if (isListElement(n))
-            return n;
+            return static_cast<HTMLElement*>(n);
     }
     
     return 0;
@@ -682,7 +687,7 @@ static Node* appendedSublist(Node* listItem)
     // Check the DOM so that we'll find collapsed sublists without renderers.
     for (Node* n = listItem->nextSibling(); n; n = n->nextSibling()) {
         if (isListElement(n))
-            return n;
+            return static_cast<HTMLElement*>(n);
         if (n->renderer() && n->renderer()->isListItem())
             return 0;
     }
@@ -718,13 +723,14 @@ Node* outermostEnclosingListChild(Node* node)
     return listNode;
 }
 
-Node* outermostEnclosingList(Node* node)
+HTMLElement* outermostEnclosingList(Node* node)
 {
-    Node* listNode = 0;
-    Node* nextNode = node;
-    while ((nextNode = enclosingList(nextNode)))
-        listNode = nextNode;
-    return listNode;
+    HTMLElement* list = enclosingList(node);
+    if (!list)
+        return 0;
+    while (HTMLElement* nextList = enclosingList(list))
+        list = nextList;
+    return list;
 }
 
 Node* highestAncestor(Node* node)
@@ -755,52 +761,34 @@ bool isTableCell(const Node* node)
     return r->isTableCell();
 }
 
-PassRefPtr<Element> createDefaultParagraphElement(Document *document)
+PassRefPtr<HTMLElement> createDefaultParagraphElement(Document* document)
 {
-    ExceptionCode ec = 0;
-    RefPtr<Element> element = document->createElementNS(xhtmlNamespaceURI, "div", ec);
-    ASSERT(ec == 0);
-    return element.release();
+    return new HTMLDivElement(divTag, document);
 }
 
-PassRefPtr<Element> createBreakElement(Document *document)
+PassRefPtr<HTMLElement> createBreakElement(Document* document)
 {
-    ExceptionCode ec = 0;
-    RefPtr<Element> breakNode = document->createElementNS(xhtmlNamespaceURI, "br", ec);
-    ASSERT(ec == 0);
-    return breakNode.release();
+    return new HTMLBRElement(brTag, document);
 }
 
-PassRefPtr<Element> createOrderedListElement(Document *document)
+PassRefPtr<HTMLElement> createOrderedListElement(Document* document)
 {
-    ExceptionCode ec = 0;
-    RefPtr<Element> element = document->createElementNS(xhtmlNamespaceURI, "ol", ec);
-    ASSERT(ec == 0);
-    return element.release();
+    return new HTMLOListElement(olTag, document);
 }
 
-PassRefPtr<Element> createUnorderedListElement(Document *document)
+PassRefPtr<HTMLElement> createUnorderedListElement(Document* document)
 {
-    ExceptionCode ec = 0;
-    RefPtr<Element> element = document->createElementNS(xhtmlNamespaceURI, "ul", ec);
-    ASSERT(ec == 0);
-    return element.release();
+    return new HTMLUListElement(ulTag, document);
 }
 
-PassRefPtr<Element> createListItemElement(Document *document)
+PassRefPtr<HTMLElement> createListItemElement(Document* document)
 {
-    ExceptionCode ec = 0;
-    RefPtr<Element> breakNode = document->createElementNS(xhtmlNamespaceURI, "li", ec);
-    ASSERT(ec == 0);
-    return breakNode.release();
+    return new HTMLLIElement(liTag, document);
 }
 
-PassRefPtr<Element> createElement(Document* document, const String& tagName)
+PassRefPtr<HTMLElement> createHTMLElement(Document* document, const AtomicString& tagName)
 {
-    ExceptionCode ec = 0;
-    RefPtr<Element> breakNode = document->createElementNS(xhtmlNamespaceURI, tagName, ec);
-    ASSERT(ec == 0);
-    return breakNode.release();
+    return HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, tagName, xhtmlNamespaceURI), document, 0, false);
 }
 
 bool isTabSpanNode(const Node *node)
index 96c4dcb..634bbd4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2006 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,6 +33,7 @@ namespace WebCore {
 
 class Document;
 class Element;
+class HTMLElement;
 class Node;
 class Position;
 class Range;
@@ -76,12 +77,12 @@ Selection avoidIntersectionWithNode(const Selection&, Node*);
 bool isSpecialElement(const Node*);
 bool validBlockTag(const String&);
 
-PassRefPtr<Element> createDefaultParagraphElement(Document*);
-PassRefPtr<Element> createBreakElement(Document*);
-PassRefPtr<Element> createOrderedListElement(Document*);
-PassRefPtr<Element> createUnorderedListElement(Document*);
-PassRefPtr<Element> createListItemElement(Document*);
-PassRefPtr<Element> createElement(Document*, const String&);
+PassRefPtr<HTMLElement> createDefaultParagraphElement(Document*);
+PassRefPtr<HTMLElement> createBreakElement(Document*);
+PassRefPtr<HTMLElement> createOrderedListElement(Document*);
+PassRefPtr<HTMLElement> createUnorderedListElement(Document*);
+PassRefPtr<HTMLElement> createListItemElement(Document*);
+PassRefPtr<HTMLElement> createHTMLElement(Document*, const AtomicString&);
 
 bool isTabSpanNode(const Node*);
 bool isTabSpanTextNode(const Node*);
@@ -118,8 +119,8 @@ Node* enclosingTableCell(const Position&);
 Node* enclosingEmptyListItem(const VisiblePosition&);
 Node* enclosingAnchorElement(const Position&);
 bool isListElement(Node*);
-Node* enclosingList(Node*);
-Node* outermostEnclosingList(Node*);
+HTMLElement* enclosingList(Node*);
+HTMLElement* outermostEnclosingList(Node*);
 Node* enclosingListChild(Node*);
 Node* highestAncestor(Node*);
 bool isTableElement(Node*);
index 6674375..83445f7 100644 (file)
@@ -1104,9 +1104,7 @@ PassRefPtr<DocumentFragment> createFragmentFromText(Range* context, const String
         fragment->appendChild(document->createTextNode(string), ec);
         ASSERT(ec == 0);
         if (string.endsWith("\n")) {
-            RefPtr<Element> element;
-            element = document->createElementNS(xhtmlNamespaceURI, "br", ec);
-            ASSERT(ec == 0);
+            RefPtr<Element> element = createBreakElement(document);
             element->setAttribute(classAttr, AppleInterchangeNewline);            
             fragment->appendChild(element.release(), ec);
             ASSERT(ec == 0);
@@ -1121,8 +1119,13 @@ PassRefPtr<DocumentFragment> createFragmentFromText(Range* context, const String
     }
 
     // Break string into paragraphs. Extra line breaks turn into empty paragraphs.
-    Node* block = enclosingBlock(context->firstNode());
-    bool useClonesOfEnclosingBlock = block && !block->hasTagName(bodyTag) && !block->hasTagName(htmlTag) && block != editableRootForPosition(context->startPosition());
+    Node* blockNode = enclosingBlock(context->firstNode());
+    Element* block = static_cast<Element*>(blockNode);
+    bool useClonesOfEnclosingBlock = blockNode
+        && blockNode->isElementNode()
+        && !block->hasTagName(bodyTag)
+        && !block->hasTagName(htmlTag)
+        && block != editableRootForPosition(context->startPosition());
     
     Vector<String> list;
     string.split('\n', true, list); // true gets us empty strings in the list
@@ -1133,11 +1136,13 @@ PassRefPtr<DocumentFragment> createFragmentFromText(Range* context, const String
         RefPtr<Element> element;
         if (s.isEmpty() && i + 1 == numLines) {
             // For last line, use the "magic BR" rather than a P.
-            element = document->createElementNS(xhtmlNamespaceURI, "br", ec);
-            ASSERT(ec == 0);
+            element = createBreakElement(document);
             element->setAttribute(classAttr, AppleInterchangeNewline);            
         } else {
-            element = useClonesOfEnclosingBlock ? static_cast<Element*>(block->cloneNode(false).get()) : createDefaultParagraphElement(document);
+            if (useClonesOfEnclosingBlock)
+                element = block->cloneElement();
+            else
+                element = createDefaultParagraphElement(document);
             fillContainerFromString(element.get(), s);
         }
         fragment->appendChild(element.release(), ec);
index 0fc8c17..042269c 100644 (file)
 
 namespace WebCore {
 
-static inline Element* targetElement(Node* node)
-{
-    if (!node)
-        return 0;
-    Node* parent = node->parent();
-    if (!parent || !parent->isElementNode())
-        return 0;
-    return static_cast<Element*>(parent);
-}
-
 MouseEventWithHitTestResults::MouseEventWithHitTestResults(const PlatformMouseEvent& event, const HitTestResult& hitTestResult)
     : m_event(event)
     , m_hitTestResult(hitTestResult)
@@ -46,10 +36,12 @@ MouseEventWithHitTestResults::MouseEventWithHitTestResults(const PlatformMouseEv
 Node* MouseEventWithHitTestResults::targetNode() const
 {
     Node* node = m_hitTestResult.innerNode();
-    if (node && node->inDocument())
+    if (!node)
+        return 0;
+    if (node->inDocument())
         return node;
 
-    Element* element = targetElement(node);
+    Element* element = node->parentElement();
     if (element && element->inDocument())
         return element;