WebCore:
authorkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 2 Nov 2004 23:22:45 +0000 (23:22 +0000)
committerkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 2 Nov 2004 23:22:45 +0000 (23:22 +0000)
        Reviewed by Hyatt

        Implemented command to insert a block in response to typing a return key (even though
        I am not turning that on by default with this patch....that will come later).

        This new command is called InsertParagraphSeparatorCommand.

        Reworked the command and function names associated with inserting content into a
        document. Before this patch, there were inputXXX and insertXXX variants, with the
        former used for more high-level actions and the latter used for lower-level stuff.
        However, this was confusing as the AppKit uses insertXXX for everything. This resulted
        in an insertXXX command going through an inputXXX WebCore step and then finally to an
        insertXXX WebCore step. To make this less confusing, I have changes all the names to
        be insertXXX, and modified the lower-level operations so that it is clear what they do.

        * khtml/editing/htmlediting.cpp:
        (khtml::EditCommandPtr::isInsertTextCommand): Name change.
        (khtml::EditCommand::isInsertTextCommand): Ditto.
        (khtml::CompositeEditCommand::inputText): Ditto.
        (khtml::CompositeEditCommand::insertTextIntoNode): Ditto.
        (khtml::CompositeEditCommand::deleteTextFromNode): Ditto.
        (khtml::CompositeEditCommand::replaceTextInNode): Ditto.
        (khtml::CompositeEditCommand::deleteInsignificantText): Name changes in implementation.
        (khtml::CompositeEditCommand::isLastVisiblePositionInNode): Ditto.
        (khtml::DeleteFromTextNodeCommand::DeleteFromTextNodeCommand): Class name change, was DeleteTextCommand.
        (khtml::DeleteFromTextNodeCommand::~DeleteFromTextNodeCommand): Ditto.
        (khtml::DeleteFromTextNodeCommand::doApply): Ditto.
        (khtml::DeleteFromTextNodeCommand::doUnapply): Ditto.
        (khtml::DeleteSelectionCommand::performGeneralDelete): Ditto.
        (khtml::DeleteSelectionCommand::fixupWhitespace): Ditto.
        (khtml::DeleteSelectionCommand::moveNodesAfterNode): Ditto.
        (khtml::InsertIntoTextNode::InsertIntoTextNode): Class name change.
        (khtml::InsertIntoTextNode::~InsertIntoTextNode): Ditto.
        (khtml::InsertIntoTextNode::doApply): Ditto.
        (khtml::InsertIntoTextNode::doUnapply): Ditto.
        (khtml::InsertLineBreakCommand::InsertLineBreakCommand): Class name change, was InsertNewlineCommand.
        (khtml::InsertLineBreakCommand::insertNodeAfterPosition):
        (khtml::InsertLineBreakCommand::insertNodeBeforePosition):
        (khtml::InsertLineBreakCommand::doApply):
        (khtml::InsertNodeBeforeCommand::InsertNodeBeforeCommand): Code moved. No changes.
        (khtml::InsertNodeBeforeCommand::~InsertNodeBeforeCommand): Ditto.
        (khtml::InsertNodeBeforeCommand::doApply): Ditto.
        (khtml::InsertNodeBeforeCommand::doUnapply): Ditto.
        (khtml::InsertParagraphSeparatorCommand::InsertParagraphSeparatorCommand): New command.
        (khtml::InsertParagraphSeparatorCommand::doApply):
        (khtml::InsertParagraphSeparatorInQuotedContentCommand::InsertParagraphSeparatorInQuotedContentCommand):
        Class name change, was InsertNewlineCommandInQuotedContentCommand.
        (khtml::InsertParagraphSeparatorInQuotedContentCommand::~InsertParagraphSeparatorInQuotedContentCommand): Ditto.
        (khtml::InsertParagraphSeparatorInQuotedContentCommand::isMailBlockquote): Ditto.
        (khtml::InsertParagraphSeparatorInQuotedContentCommand::doApply): Ditto.
        (khtml::InsertTextCommand::InsertTextCommand): Class name change, was InputTextCommand.
        (khtml::InsertTextCommand::doApply): Ditto.
        (khtml::InsertTextCommand::deleteCharacter): Ditto.
        (khtml::InsertTextCommand::prepareForTextInsertion): Ditto.
        (khtml::InsertTextCommand::input): Ditto.
        (khtml::InsertTextCommand::insertSpace): Ditto.
        (khtml::InsertTextCommand::isInsertTextCommand): Ditto.
        (khtml::TypingCommand::insertLineBreak): Name change, was insertNewline.
        (khtml::TypingCommand::insertParagraphSeparatorInQuotedContent): Name change, was insertNewlineInQuotedContent.
        (khtml::TypingCommand::insertParagraphSeparator): New function.
        (khtml::TypingCommand::doApply): Name changes, as above.
        (khtml::TypingCommand::insertText): Ditto.
        (khtml::TypingCommand::deleteKeyPressed): Ditto.
        (khtml::TypingCommand::preservesTypingStyle): Ditto.
        * khtml/editing/htmlediting.h:
        (khtml::DeleteFromTextNodeCommand::node): Name change.
        (khtml::DeleteFromTextNodeCommand::offset): Ditto.
        (khtml::DeleteFromTextNodeCommand::count): Ditto.
        (khtml::InsertIntoTextNode::text): Ditto.
        (khtml::InsertNodeBeforeCommand::insertChild): Ditto.
        (khtml::InsertNodeBeforeCommand::refChild): Ditto.
        (khtml::TypingCommand::): Ditto.
        * khtml/editing/jsediting.cpp: Name changes, as above.
        * kwq/WebCoreBridge.h:
        * kwq/WebCoreBridge.mm:
        (-[WebCoreBridge insertLineBreak]): Name change, was insertNewline.
        (-[WebCoreBridge insertParagraphSeparator]): New function.
        (-[WebCoreBridge insertParagraphSeparatorInQuotedContent]): Name change, was insertNewlineInQuotedContent.

WebKit:

        Reviewed by Hyatt

        WebCore now implements a command to insert a block in response to typing a return key, and
        some names were improved in the course of this work.

        * WebView.subproj/WebHTMLView.m:
        (-[WebHTMLView insertNewline:]): Now calls insertLineBreak on bridge object.
        (-[WebHTMLView insertLineBreak:]): New method.
        (-[WebHTMLView insertParagraphSeparator:]): Now implemented.
        * WebView.subproj/WebView.m:

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

WebCore/ChangeLog-2005-08-23
WebCore/khtml/editing/htmlediting.cpp
WebCore/khtml/editing/htmlediting.h
WebCore/khtml/editing/jsediting.cpp
WebCore/kwq/WebCoreBridge.h
WebCore/kwq/WebCoreBridge.mm
WebKit/ChangeLog
WebKit/WebView.subproj/WebHTMLView.m
WebKit/WebView.subproj/WebView.m

index 5997cd3ae5e9b521ef233f914cff636b81d90187..5cb33f6ac4d0ca1ab92c50762985da2b2f2320ee 100644 (file)
@@ -1,3 +1,84 @@
+2004-11-02  Ken Kocienda  <kocienda@apple.com>
+
+        Reviewed by Hyatt
+
+        Implemented command to insert a block in response to typing a return key (even though
+        I am not turning that on by default with this patch....that will come later). 
+        
+        This new command is called InsertParagraphSeparatorCommand.
+        
+        Reworked the command and function names associated with inserting content into a 
+        document. Before this patch, there were inputXXX and insertXXX variants, with the
+        former used for more high-level actions and the latter used for lower-level stuff.
+        However, this was confusing as the AppKit uses insertXXX for everything. This resulted
+        in an insertXXX command going through an inputXXX WebCore step and then finally to an
+        insertXXX WebCore step. To make this less confusing, I have changes all the names to
+        be insertXXX, and modified the lower-level operations so that it is clear what they do.
+        
+        * khtml/editing/htmlediting.cpp:
+        (khtml::EditCommandPtr::isInsertTextCommand): Name change.
+        (khtml::EditCommand::isInsertTextCommand): Ditto.
+        (khtml::CompositeEditCommand::inputText): Ditto.
+        (khtml::CompositeEditCommand::insertTextIntoNode): Ditto.
+        (khtml::CompositeEditCommand::deleteTextFromNode): Ditto.
+        (khtml::CompositeEditCommand::replaceTextInNode): Ditto.
+        (khtml::CompositeEditCommand::deleteInsignificantText): Name changes in implementation.
+        (khtml::CompositeEditCommand::isLastVisiblePositionInNode): Ditto.
+        (khtml::DeleteFromTextNodeCommand::DeleteFromTextNodeCommand): Class name change, was DeleteTextCommand.
+        (khtml::DeleteFromTextNodeCommand::~DeleteFromTextNodeCommand): Ditto.
+        (khtml::DeleteFromTextNodeCommand::doApply): Ditto.
+        (khtml::DeleteFromTextNodeCommand::doUnapply): Ditto.
+        (khtml::DeleteSelectionCommand::performGeneralDelete): Ditto.
+        (khtml::DeleteSelectionCommand::fixupWhitespace): Ditto.
+        (khtml::DeleteSelectionCommand::moveNodesAfterNode): Ditto.
+        (khtml::InsertIntoTextNode::InsertIntoTextNode): Class name change.
+        (khtml::InsertIntoTextNode::~InsertIntoTextNode): Ditto.
+        (khtml::InsertIntoTextNode::doApply): Ditto.
+        (khtml::InsertIntoTextNode::doUnapply): Ditto.
+        (khtml::InsertLineBreakCommand::InsertLineBreakCommand): Class name change, was InsertNewlineCommand.
+        (khtml::InsertLineBreakCommand::insertNodeAfterPosition):
+        (khtml::InsertLineBreakCommand::insertNodeBeforePosition):
+        (khtml::InsertLineBreakCommand::doApply):
+        (khtml::InsertNodeBeforeCommand::InsertNodeBeforeCommand): Code moved. No changes.
+        (khtml::InsertNodeBeforeCommand::~InsertNodeBeforeCommand): Ditto.
+        (khtml::InsertNodeBeforeCommand::doApply): Ditto.
+        (khtml::InsertNodeBeforeCommand::doUnapply): Ditto.
+        (khtml::InsertParagraphSeparatorCommand::InsertParagraphSeparatorCommand): New command.
+        (khtml::InsertParagraphSeparatorCommand::doApply):
+        (khtml::InsertParagraphSeparatorInQuotedContentCommand::InsertParagraphSeparatorInQuotedContentCommand):
+        Class name change, was InsertNewlineCommandInQuotedContentCommand.
+        (khtml::InsertParagraphSeparatorInQuotedContentCommand::~InsertParagraphSeparatorInQuotedContentCommand): Ditto.
+        (khtml::InsertParagraphSeparatorInQuotedContentCommand::isMailBlockquote): Ditto.
+        (khtml::InsertParagraphSeparatorInQuotedContentCommand::doApply): Ditto.
+        (khtml::InsertTextCommand::InsertTextCommand): Class name change, was InputTextCommand.
+        (khtml::InsertTextCommand::doApply): Ditto.
+        (khtml::InsertTextCommand::deleteCharacter): Ditto.
+        (khtml::InsertTextCommand::prepareForTextInsertion): Ditto.
+        (khtml::InsertTextCommand::input): Ditto.
+        (khtml::InsertTextCommand::insertSpace): Ditto.
+        (khtml::InsertTextCommand::isInsertTextCommand): Ditto.
+        (khtml::TypingCommand::insertLineBreak): Name change, was insertNewline.
+        (khtml::TypingCommand::insertParagraphSeparatorInQuotedContent): Name change, was insertNewlineInQuotedContent.
+        (khtml::TypingCommand::insertParagraphSeparator): New function.
+        (khtml::TypingCommand::doApply): Name changes, as above.
+        (khtml::TypingCommand::insertText): Ditto.
+        (khtml::TypingCommand::deleteKeyPressed): Ditto.
+        (khtml::TypingCommand::preservesTypingStyle): Ditto.
+        * khtml/editing/htmlediting.h:
+        (khtml::DeleteFromTextNodeCommand::node): Name change.
+        (khtml::DeleteFromTextNodeCommand::offset): Ditto.
+        (khtml::DeleteFromTextNodeCommand::count): Ditto.
+        (khtml::InsertIntoTextNode::text): Ditto.
+        (khtml::InsertNodeBeforeCommand::insertChild): Ditto.
+        (khtml::InsertNodeBeforeCommand::refChild): Ditto.
+        (khtml::TypingCommand::): Ditto.
+        * khtml/editing/jsediting.cpp: Name changes, as above.
+        * kwq/WebCoreBridge.h:
+        * kwq/WebCoreBridge.mm:
+        (-[WebCoreBridge insertLineBreak]): Name change, was insertNewline.
+        (-[WebCoreBridge insertParagraphSeparator]): New function.
+        (-[WebCoreBridge insertParagraphSeparatorInQuotedContent]): Name change, was insertNewlineInQuotedContent.
+
 2004-11-01  Kevin Decker  <kdecker@apple.com>
 
         Reviewed by rjw.
index 3e283d1e221649d4a298d67a6b5e59bff192beb8..6252d102da2a55b0fb6e08eecd2bfababf5a63bb 100644 (file)
@@ -215,10 +215,10 @@ bool EditCommandPtr::isCompositeStep() const
     return get()->isCompositeStep();
 }
 
-bool EditCommandPtr::isInputTextCommand() const
+bool EditCommandPtr::isInsertTextCommand() const
 {
     IF_IMPL_NULL_RETURN_ARG(false);        
-    return get()->isInputTextCommand();
+    return get()->isInsertTextCommand();
 }
 
 bool EditCommandPtr::isTypingCommand() const
@@ -514,7 +514,7 @@ bool EditCommand::preservesTypingStyle() const
     return false;
 }
 
-bool EditCommand::isInputTextCommand() const
+bool EditCommand::isInsertTextCommand() const
 {
     return false;
 }
@@ -657,29 +657,29 @@ void CompositeEditCommand::joinTextNodes(TextImpl *text1, TextImpl *text2)
 
 void CompositeEditCommand::inputText(const DOMString &text, bool selectInsertedText)
 {
-    InputTextCommand *impl = new InputTextCommand(document());
+    InsertTextCommand *impl = new InsertTextCommand(document());
     EditCommandPtr cmd(impl);
     applyCommandToComposite(cmd);
     impl->input(text, selectInsertedText);
 }
 
-void CompositeEditCommand::insertText(TextImpl *node, long offset, const DOMString &text)
+void CompositeEditCommand::insertTextIntoNode(TextImpl *node, long offset, const DOMString &text)
 {
-    EditCommandPtr cmd(new InsertTextCommand(document(), node, offset, text));
+    EditCommandPtr cmd(new InsertIntoTextNode(document(), node, offset, text));
     applyCommandToComposite(cmd);
 }
 
-void CompositeEditCommand::deleteText(TextImpl *node, long offset, long count)
+void CompositeEditCommand::deleteTextFromNode(TextImpl *node, long offset, long count)
 {
-    EditCommandPtr cmd(new DeleteTextCommand(document(), node, offset, count));
+    EditCommandPtr cmd(new DeleteFromTextNodeCommand(document(), node, offset, count));
     applyCommandToComposite(cmd);
 }
 
-void CompositeEditCommand::replaceText(TextImpl *node, long offset, long count, const DOMString &replacementText)
+void CompositeEditCommand::replaceTextInNode(TextImpl *node, long offset, long count, const DOMString &replacementText)
 {
-    EditCommandPtr deleteCommand(new DeleteTextCommand(document(), node, offset, count));
+    EditCommandPtr deleteCommand(new DeleteFromTextNodeCommand(document(), node, offset, count));
     applyCommandToComposite(deleteCommand);
-    EditCommandPtr insertCommand(new InsertTextCommand(document(), node, offset, replacementText));
+    EditCommandPtr insertCommand(new InsertIntoTextNode(document(), node, offset, replacementText));
     applyCommandToComposite(insertCommand);
 }
 
@@ -817,14 +817,14 @@ void CompositeEditCommand::deleteInsignificantText(TextImpl *textNode, int start
     if (str) {
         // Replace the text between start and end with our pruned version.
         if (str->l > 0) {
-            replaceText(textNode, start, end - start, str);
+            replaceTextInNode(textNode, start, end - start, str);
         }
         else {
             // 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 long)end - start < textNode->length());
-            deleteText(textNode, start, end - start);
+            deleteTextFromNode(textNode, start, end - start);
         }
         str->deref();
     }
@@ -904,6 +904,15 @@ bool CompositeEditCommand::removeBlockPlaceholderIfNeeded(NodeImpl *node)
     return false;
 }
 
+bool CompositeEditCommand::isLastVisiblePositionInNode(const VisiblePosition &pos, const NodeImpl *node) const
+{
+    if (pos.isNull())
+        return false;
+        
+    VisiblePosition next = pos.next();
+    return next.isNull() || !next.deepEquivalent().node()->isAncestor(node);
+}
+
 //==========================================================================================
 // Concrete commands
 //------------------------------------------------------------------------------------------
@@ -1321,6 +1330,48 @@ Position ApplyStyleCommand::positionInsertionPoint(Position pos)
     return pos;
 }
 
+//------------------------------------------------------------------------------------------
+// DeleteFromTextNodeCommand
+
+DeleteFromTextNodeCommand::DeleteFromTextNodeCommand(DocumentImpl *document, TextImpl *node, long offset, long count)
+    : EditCommand(document), m_node(node), m_offset(offset), m_count(count)
+{
+    ASSERT(m_node);
+    ASSERT(m_offset >= 0);
+    ASSERT(m_offset < (long)m_node->length());
+    ASSERT(m_count >= 0);
+    
+    m_node->ref();
+}
+
+DeleteFromTextNodeCommand::~DeleteFromTextNodeCommand()
+{
+    ASSERT(m_node);
+    m_node->deref();
+}
+
+void DeleteFromTextNodeCommand::doApply()
+{
+    ASSERT(m_node);
+
+    int exceptionCode = 0;
+    m_text = m_node->substringData(m_offset, m_count, exceptionCode);
+    ASSERT(exceptionCode == 0);
+    
+    m_node->deleteData(m_offset, m_count, exceptionCode);
+    ASSERT(exceptionCode == 0);
+}
+
+void DeleteFromTextNodeCommand::doUnapply()
+{
+    ASSERT(m_node);
+    ASSERT(!m_text.isEmpty());
+
+    int exceptionCode = 0;
+    m_node->insertData(m_offset, m_text, exceptionCode);
+    ASSERT(exceptionCode == 0);
+}
+
 //------------------------------------------------------------------------------------------
 // DeleteSelectionCommand
 
@@ -1459,7 +1510,7 @@ void DeleteSelectionCommand::performGeneralDelete()
             // Delete any insignificant text from this node.
             TextImpl *text = static_cast<TextImpl *>(m_startNode);
             if (text->length() > (unsigned)m_startNode->caretMaxOffset())
-                deleteText(text, m_startNode->caretMaxOffset(), text->length() - m_startNode->caretMaxOffset());
+                deleteTextFromNode(text, m_startNode->caretMaxOffset(), text->length() - m_startNode->caretMaxOffset());
         }
         // shift the start node to the next
         NodeImpl *old = m_startNode;
@@ -1479,7 +1530,7 @@ void DeleteSelectionCommand::performGeneralDelete()
         else if (m_downstreamEnd.offset() - startOffset > 0) {
             // in a text node that needs to be trimmed
             TextImpl *text = static_cast<TextImpl *>(m_startNode);
-            deleteText(text, startOffset, m_downstreamEnd.offset() - startOffset);
+            deleteTextFromNode(text, startOffset, m_downstreamEnd.offset() - startOffset);
             m_trailingWhitespaceValid = false;
         }
     }
@@ -1489,7 +1540,7 @@ void DeleteSelectionCommand::performGeneralDelete()
         if (startOffset > 0) {
             // in a text node that needs to be trimmed
             TextImpl *text = static_cast<TextImpl *>(node);
-            deleteText(text, startOffset, text->length() - startOffset);
+            deleteTextFromNode(text, startOffset, text->length() - startOffset);
             node = node->traverseNextNode();
         }
         
@@ -1526,7 +1577,7 @@ void DeleteSelectionCommand::performGeneralDelete()
                 // in a text node that needs to be trimmed
                 TextImpl *text = static_cast<TextImpl *>(m_downstreamEnd.node());
                 if (m_downstreamEnd.offset() > 0) {
-                    deleteText(text, 0, m_downstreamEnd.offset());
+                    deleteTextFromNode(text, 0, m_downstreamEnd.offset());
                     m_trailingWhitespaceValid = false;
                 }
             }
@@ -1542,14 +1593,14 @@ void DeleteSelectionCommand::fixupWhitespace()
     if (m_leadingWhitespace.isNotNull() && (m_trailingWhitespace.isNotNull() || !m_leadingWhitespace.isRenderedCharacter())) {
         LOG(Editing, "replace leading");
         TextImpl *textNode = static_cast<TextImpl *>(m_leadingWhitespace.node());
-        replaceText(textNode, m_leadingWhitespace.offset(), 1, nonBreakingSpaceString());
+        replaceTextInNode(textNode, m_leadingWhitespace.offset(), 1, nonBreakingSpaceString());
     }
     else if (m_trailingWhitespace.isNotNull()) {
         if (m_trailingWhitespaceValid) {
             if (!m_trailingWhitespace.isRenderedCharacter()) {
                 LOG(Editing, "replace trailing [valid]");
                 TextImpl *textNode = static_cast<TextImpl *>(m_trailingWhitespace.node());
-                replaceText(textNode, m_trailingWhitespace.offset(), 1, nonBreakingSpaceString());
+                replaceTextInNode(textNode, m_trailingWhitespace.offset(), 1, nonBreakingSpaceString());
             }
         }
         else {
@@ -1558,7 +1609,7 @@ void DeleteSelectionCommand::fixupWhitespace()
             if (isWS(pos) && !pos.isRenderedCharacter()) {
                 LOG(Editing, "replace trailing [invalid]");
                 TextImpl *textNode = static_cast<TextImpl *>(pos.node());
-                replaceText(textNode, pos.offset(), 1, nonBreakingSpaceString());
+                replaceTextInNode(textNode, pos.offset(), 1, nonBreakingSpaceString());
                 // need to adjust ending position since the trailing position is not valid.
                 m_endingPosition = pos;
             }
@@ -1602,7 +1653,10 @@ void DeleteSelectionCommand::moveNodesAfterNode()
         NodeImpl *moveNode = node;
         node = node->nextSibling();
         removeNode(moveNode);
-        insertNodeAfter(moveNode, refNode);
+        if (refNode->isBlockFlow())
+            appendNode(moveNode, refNode);
+        else
+            insertNodeAfter(moveNode, refNode);
         refNode = moveNode;
     }
 
@@ -1619,7 +1673,7 @@ void DeleteSelectionCommand::moveNodesAfterNode()
     // and 'Two'. This is undesirable. We fix this up by adding a BR before the 'Three'.
     // This may not be ideal, but it is better than nothing.
     document()->updateLayout();
-    if (startBlock->renderer() && startBlock->renderer()->height() == 0) {
+    if (!startBlock->renderer() || !startBlock->renderer()->firstChild()) {
         removeNode(startBlock);
         if (refNode->renderer() && refNode->renderer()->inlineBox() && refNode->renderer()->inlineBox()->nextOnLineExists()) {
             int exceptionCode = 0;
@@ -1757,56 +1811,56 @@ bool DeleteSelectionCommand::preservesTypingStyle() const
 }
 
 //------------------------------------------------------------------------------------------
-// DeleteTextCommand
+// InsertIntoTextNode
 
-DeleteTextCommand::DeleteTextCommand(DocumentImpl *document, TextImpl *node, long offset, long count)
-    : EditCommand(document), m_node(node), m_offset(offset), m_count(count)
+InsertIntoTextNode::InsertIntoTextNode(DocumentImpl *document, TextImpl *node, long offset, const DOMString &text)
+    : EditCommand(document), m_node(node), m_offset(offset)
 {
     ASSERT(m_node);
     ASSERT(m_offset >= 0);
-    ASSERT(m_offset < (long)m_node->length());
-    ASSERT(m_count >= 0);
+    ASSERT(!text.isEmpty());
     
     m_node->ref();
+    m_text = text.copy(); // make a copy to ensure that the string never changes
 }
 
-DeleteTextCommand::~DeleteTextCommand()
+InsertIntoTextNode::~InsertIntoTextNode()
 {
-    ASSERT(m_node);
-    m_node->deref();
+    if (m_node)
+        m_node->deref();
 }
 
-void DeleteTextCommand::doApply()
+void InsertIntoTextNode::doApply()
 {
     ASSERT(m_node);
+    ASSERT(m_offset >= 0);
+    ASSERT(!m_text.isEmpty());
 
     int exceptionCode = 0;
-    m_text = m_node->substringData(m_offset, m_count, exceptionCode);
-    ASSERT(exceptionCode == 0);
-    
-    m_node->deleteData(m_offset, m_count, exceptionCode);
+    m_node->insertData(m_offset, m_text, exceptionCode);
     ASSERT(exceptionCode == 0);
 }
 
-void DeleteTextCommand::doUnapply()
+void InsertIntoTextNode::doUnapply()
 {
     ASSERT(m_node);
+    ASSERT(m_offset >= 0);
     ASSERT(!m_text.isEmpty());
 
     int exceptionCode = 0;
-    m_node->insertData(m_offset, m_text, exceptionCode);
+    m_node->deleteData(m_offset, m_text.length(), exceptionCode);
     ASSERT(exceptionCode == 0);
 }
 
 //------------------------------------------------------------------------------------------
-// InputNewlineCommand
+// InsertLineBreakCommand
 
-InputNewlineCommand::InputNewlineCommand(DocumentImpl *document) 
+InsertLineBreakCommand::InsertLineBreakCommand(DocumentImpl *document) 
     : CompositeEditCommand(document)
 {
 }
 
-void InputNewlineCommand::insertNodeAfterPosition(NodeImpl *node, const Position &pos)
+void InsertLineBreakCommand::insertNodeAfterPosition(NodeImpl *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
@@ -1819,7 +1873,7 @@ void InputNewlineCommand::insertNodeAfterPosition(NodeImpl *node, const Position
         insertNodeAfter(node, pos.node());
 }
 
-void InputNewlineCommand::insertNodeBeforePosition(NodeImpl *node, const Position &pos)
+void InsertLineBreakCommand::insertNodeBeforePosition(NodeImpl *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
@@ -1832,7 +1886,7 @@ void InputNewlineCommand::insertNodeBeforePosition(NodeImpl *node, const Positio
         insertNodeBefore(node, pos.node());
 }
 
-void InputNewlineCommand::doApply()
+void InsertLineBreakCommand::doApply()
 {
     deleteSelection();
     Selection selection = endingSelection();
@@ -1904,7 +1958,7 @@ void InputNewlineCommand::doApply()
         // Do the split
         TextImpl *textNode = static_cast<TextImpl *>(pos.node());
         TextImpl *textBeforeNode = document()->createTextNode(textNode->substringData(0, selection.start().offset(), exceptionCode));
-        deleteText(textNode, 0, pos.offset());
+        deleteTextFromNode(textNode, 0, pos.offset());
         insertNodeBefore(textBeforeNode, textNode);
         insertNodeBefore(nodeToInsert, textNode);
         Position endingPosition = Position(textNode, 0);
@@ -1914,7 +1968,7 @@ void InputNewlineCommand::doApply()
         if (!endingPosition.isRenderedCharacter()) {
             // Clear out all whitespace and insert one non-breaking space
             deleteInsignificantTextDownstream(endingPosition);
-            insertText(textNode, 0, nonBreakingSpaceString());
+            insertTextIntoNode(textNode, 0, nonBreakingSpaceString());
         }
         
         setEndingSelection(endingPosition);
@@ -1922,22 +1976,188 @@ void InputNewlineCommand::doApply()
 }
 
 //------------------------------------------------------------------------------------------
-// InputNewlineInQuotedContentCommand
+// InsertNodeBeforeCommand
+
+InsertNodeBeforeCommand::InsertNodeBeforeCommand(DocumentImpl *document, NodeImpl *insertChild, NodeImpl *refChild)
+    : EditCommand(document), m_insertChild(insertChild), m_refChild(refChild)
+{
+    ASSERT(m_insertChild);
+    m_insertChild->ref();
+
+    ASSERT(m_refChild);
+    m_refChild->ref();
+}
+
+InsertNodeBeforeCommand::~InsertNodeBeforeCommand()
+{
+    ASSERT(m_insertChild);
+    m_insertChild->deref();
+
+    ASSERT(m_refChild);
+    m_refChild->deref();
+}
+
+void InsertNodeBeforeCommand::doApply()
+{
+    ASSERT(m_insertChild);
+    ASSERT(m_refChild);
+    ASSERT(m_refChild->parentNode());
+
+    int exceptionCode = 0;
+    m_refChild->parentNode()->insertBefore(m_insertChild, m_refChild, exceptionCode);
+    ASSERT(exceptionCode == 0);
+}
+
+void InsertNodeBeforeCommand::doUnapply()
+{
+    ASSERT(m_insertChild);
+    ASSERT(m_refChild);
+    ASSERT(m_refChild->parentNode());
+
+    int exceptionCode = 0;
+    m_refChild->parentNode()->removeChild(m_insertChild, exceptionCode);
+    ASSERT(exceptionCode == 0);
+}
+
+//------------------------------------------------------------------------------------------
+// InsertParagraphSeparatorCommand
+
+InsertParagraphSeparatorCommand::InsertParagraphSeparatorCommand(DocumentImpl *document) 
+    : CompositeEditCommand(document)
+{
+    ancestors.setAutoDelete(true);
+    clonedNodes.setAutoDelete(true);
+}
+
+void InsertParagraphSeparatorCommand::doApply()
+{
+    Selection selection = endingSelection();
+    if (selection.isNone())
+        return;
+    
+    // Delete the current selection.
+    // If the selection is a range and the start and end nodes are in different blocks, 
+    // then this command bails after the delete, but takes the one additional step of
+    // moving the selection downstream so it is in the ending block (if that block is
+    // still around, that is).
+    Position pos = selection.start();
+    if (selection.isRange()) {
+        NodeImpl *startBlockBeforeDelete = selection.start().node()->enclosingBlockFlowElement();
+        NodeImpl *endBlockBeforeDelete = selection.end().node()->enclosingBlockFlowElement();
+        bool doneAfterDelete = startBlockBeforeDelete != endBlockBeforeDelete;
+        deleteSelection(false, false);
+        if (doneAfterDelete) {
+            document()->updateLayout();
+            setEndingSelection(endingSelection().start().downstream());
+            return;
+        }
+        pos = endingSelection().start().upstream();
+    }
+    
+    // Find the start block.
+    NodeImpl *startNode = pos.node();
+    NodeImpl *startBlock = startNode->enclosingBlockFlowElement();
+    if (!startBlock || !startBlock->parentNode())
+        return;
+
+    // Build up list of ancestors in between the start node and the start block.
+    for (NodeImpl *n = startNode->parentNode(); n && n != startBlock; n = n->parentNode())
+        ancestors.prepend(n);
+
+    // Make new block to represent the newline.
+    // If the start block is the body, just make a P tag, otherwise, make a shallow clone
+    // of the the start block.
+    NodeImpl *addedBlock = 0;
+    if (startBlock->id() == ID_BODY) {
+        int exceptionCode = 0;
+        addedBlock = document()->createHTMLElement("P", exceptionCode);
+        ASSERT(exceptionCode == 0);
+        appendNode(addedBlock, startBlock);
+    }
+    else {
+        addedBlock = startBlock->cloneNode(false);
+        insertNodeAfter(addedBlock, startBlock);
+    }
+    clonedNodes.append(addedBlock);
+
+    if (!isLastVisiblePositionInNode(VisiblePosition(pos), startBlock)) {
+        // Split at pos if in the middle of a text node.
+        if (startNode->isTextNode()) {
+            TextImpl *textNode = static_cast<TextImpl *>(startNode);
+            bool atEnd = (unsigned long)pos.offset() >= textNode->length();
+            if (pos.offset() > 0 && !atEnd) {
+                SplitTextNodeCommand *splitCommand = new SplitTextNodeCommand(document(), textNode, pos.offset());
+                EditCommandPtr cmd(splitCommand);
+                applyCommandToComposite(cmd);
+                startNode = splitCommand->node();
+                pos = Position(startNode, 0);
+            }
+            else if (atEnd) {
+                startNode = startNode->traverseNextNode();
+                ASSERT(startNode);
+            }
+        }
+        else if (pos.offset() > 0) {
+            startNode = startNode->traverseNextNode();
+            ASSERT(startNode);
+        }
+
+        // Make clones of ancestors in between the start node and the start block.
+        NodeImpl *parent = addedBlock;
+        for (QPtrListIterator<NodeImpl> it(ancestors); it.current(); ++it) {
+            NodeImpl *child = it.current()->cloneNode(false); // shallow clone
+            clonedNodes.append(child);
+            appendNode(child, parent);
+            parent = child;
+        }
+
+        // Move the start node and the siblings of the start node.
+        NodeImpl *n = startNode;
+        if (n->id() == ID_BR)
+            n = n->nextSibling();
+        while (n && n != addedBlock) {
+            NodeImpl *next = n->nextSibling();
+            removeNode(n);
+            appendNode(n, parent);
+            n = next;
+        }
+        
+        // Move everything after the start node.
+        NodeImpl *leftParent = ancestors.last();
+        while (leftParent && leftParent != startBlock) {
+            parent = parent->parentNode();
+            NodeImpl *n = leftParent->nextSibling();
+            while (n) {
+                NodeImpl *next = n->nextSibling();
+                removeNode(n);
+                appendNode(n, parent);
+                n = next;
+            }
+            leftParent = leftParent->parentNode();
+        }
+    }
+    
+    // Put the selection right at the start of the added block.
+    setEndingSelection(Position(addedBlock, 0));
+}
+
+//------------------------------------------------------------------------------------------
+// InsertParagraphSeparatorInQuotedContentCommand
 
-InputNewlineInQuotedContentCommand::InputNewlineInQuotedContentCommand(DocumentImpl *document)
+InsertParagraphSeparatorInQuotedContentCommand::InsertParagraphSeparatorInQuotedContentCommand(DocumentImpl *document)
     : CompositeEditCommand(document)
 {
     ancestors.setAutoDelete(true);
     clonedNodes.setAutoDelete(true);
 }
 
-InputNewlineInQuotedContentCommand::~InputNewlineInQuotedContentCommand()
+InsertParagraphSeparatorInQuotedContentCommand::~InsertParagraphSeparatorInQuotedContentCommand()
 {
     if (m_breakNode)
         m_breakNode->deref();
 }
 
-bool InputNewlineInQuotedContentCommand::isMailBlockquote(const NodeImpl *node) const
+bool InsertParagraphSeparatorInQuotedContentCommand::isMailBlockquote(const NodeImpl *node) const
 {
     if (!node || !node->renderer() || !node->isElementNode() && node->id() != ID_BLOCKQUOTE)
         return false;
@@ -1945,16 +2165,7 @@ bool InputNewlineInQuotedContentCommand::isMailBlockquote(const NodeImpl *node)
     return static_cast<const ElementImpl *>(node)->getAttribute("type") == "cite";
 }
 
-bool InputNewlineInQuotedContentCommand::isLastVisiblePositionInBlockquote(const VisiblePosition &pos, const NodeImpl *blockquote) const
-{
-    if (pos.isNull())
-        return false;
-        
-    VisiblePosition next = pos.next();
-    return next.isNull() || !next.deepEquivalent().node()->isAncestor(blockquote);
-}
-
-void InputNewlineInQuotedContentCommand::doApply()
+void InsertParagraphSeparatorInQuotedContentCommand::doApply()
 {
     Selection selection = endingSelection();
     if (selection.isNone())
@@ -1988,7 +2199,7 @@ void InputNewlineInQuotedContentCommand::doApply()
     ASSERT(exceptionCode == 0);
     insertNodeAfter(m_breakNode, topBlockquote);
 
-    if (!isLastVisiblePositionInBlockquote(VisiblePosition(pos), topBlockquote)) {
+    if (!isLastVisiblePositionInNode(VisiblePosition(pos), topBlockquote)) {
         // Split at pos if in the middle of a text node.
         if (startNode->isTextNode()) {
             TextImpl *textNode = static_cast<TextImpl *>(startNode);
@@ -2067,18 +2278,18 @@ void InputNewlineInQuotedContentCommand::doApply()
 }
 
 //------------------------------------------------------------------------------------------
-// InputTextCommand
+// InsertTextCommand
 
-InputTextCommand::InputTextCommand(DocumentImpl *document) 
+InsertTextCommand::InsertTextCommand(DocumentImpl *document) 
     : CompositeEditCommand(document), m_charactersAdded(0)
 {
 }
 
-void InputTextCommand::doApply()
+void InsertTextCommand::doApply()
 {
 }
 
-void InputTextCommand::deleteCharacter()
+void InsertTextCommand::deleteCharacter()
 {
     ASSERT(state() == Applied);
 
@@ -2099,7 +2310,7 @@ void InputTextCommand::deleteCharacter()
     }
 }
 
-Position InputTextCommand::prepareForTextInsertion(bool adjustDownstream)
+Position InsertTextCommand::prepareForTextInsertion(bool adjustDownstream)
 {
     // Prepare for text input by looking at the current position.
     // It may be necessary to insert a text node to receive characters.
@@ -2168,7 +2379,7 @@ Position InputTextCommand::prepareForTextInsertion(bool adjustDownstream)
     return pos;
 }
 
-void InputTextCommand::input(const DOMString &text, bool selectInsertedText)
+void InsertTextCommand::input(const DOMString &text, bool selectInsertedText)
 {
     Selection selection = endingSelection();
     bool adjustDownstream = selection.start().downstream(StayInBlock).isFirstRenderedPositionOnLine();
@@ -2226,9 +2437,9 @@ void InputTextCommand::input(const DOMString &text, bool selectInsertedText)
             // convert the nbsp to a regular space.
             // EDIT FIXME: This needs to be improved some day to convert back only
             // those nbsp's added by the editor to make rendering come out right.
-            replaceText(textNode, offset - 1, 1, " ");
+            replaceTextInNode(textNode, offset - 1, 1, " ");
         }
-        insertText(textNode, offset, text);
+        insertTextIntoNode(textNode, offset, text);
         if (selectInsertedText)
             setEndingSelection(Selection(Position(textNode, offset), Position(textNode, offset + text.length())));
         else
@@ -2237,7 +2448,7 @@ void InputTextCommand::input(const DOMString &text, bool selectInsertedText)
     }
 }
 
-void InputTextCommand::insertSpace(TextImpl *textNode, unsigned long offset)
+void InsertTextCommand::insertSpace(TextImpl *textNode, unsigned long offset)
 {
     ASSERT(textNode);
 
@@ -2261,12 +2472,12 @@ void InputTextCommand::insertSpace(TextImpl *textNode, unsigned long offset)
         if (downstream.offset() < (long)text.length() && isWS(text[downstream.offset()]))
             count--; // leave this WS in
         if (count > 0)
-            deleteText(textNode, offset, count);
+            deleteTextFromNode(textNode, offset, count);
     }
 
     if (offset > 0 && offset <= text.length() - 1 && !isWS(text[offset]) && !isWS(text[offset - 1])) {
         // insert a "regular" space
-        insertText(textNode, offset, " ");
+        insertTextIntoNode(textNode, offset, " ");
         return;
     }
 
@@ -2274,105 +2485,19 @@ void InputTextCommand::insertSpace(TextImpl *textNode, unsigned long offset)
         // DOM looks like this:
         // nbsp nbsp caret
         // insert a space between the two nbsps
-        insertText(textNode, offset - 1, " ");
+        insertTextIntoNode(textNode, offset - 1, " ");
         return;
     }
 
     // insert an nbsp
-    insertText(textNode, offset, nonBreakingSpaceString());
+    insertTextIntoNode(textNode, offset, nonBreakingSpaceString());
 }
 
-bool InputTextCommand::isInputTextCommand() const
+bool InsertTextCommand::isInsertTextCommand() const
 {
     return true;
 }
 
-//------------------------------------------------------------------------------------------
-// InsertNodeBeforeCommand
-
-InsertNodeBeforeCommand::InsertNodeBeforeCommand(DocumentImpl *document, NodeImpl *insertChild, NodeImpl *refChild)
-    : EditCommand(document), m_insertChild(insertChild), m_refChild(refChild)
-{
-    ASSERT(m_insertChild);
-    m_insertChild->ref();
-
-    ASSERT(m_refChild);
-    m_refChild->ref();
-}
-
-InsertNodeBeforeCommand::~InsertNodeBeforeCommand()
-{
-    ASSERT(m_insertChild);
-    m_insertChild->deref();
-
-    ASSERT(m_refChild);
-    m_refChild->deref();
-}
-
-void InsertNodeBeforeCommand::doApply()
-{
-    ASSERT(m_insertChild);
-    ASSERT(m_refChild);
-    ASSERT(m_refChild->parentNode());
-
-    int exceptionCode = 0;
-    m_refChild->parentNode()->insertBefore(m_insertChild, m_refChild, exceptionCode);
-    ASSERT(exceptionCode == 0);
-}
-
-void InsertNodeBeforeCommand::doUnapply()
-{
-    ASSERT(m_insertChild);
-    ASSERT(m_refChild);
-    ASSERT(m_refChild->parentNode());
-
-    int exceptionCode = 0;
-    m_refChild->parentNode()->removeChild(m_insertChild, exceptionCode);
-    ASSERT(exceptionCode == 0);
-}
-
-//------------------------------------------------------------------------------------------
-// InsertTextCommand
-
-InsertTextCommand::InsertTextCommand(DocumentImpl *document, TextImpl *node, long offset, const DOMString &text)
-    : EditCommand(document), m_node(node), m_offset(offset)
-{
-    ASSERT(m_node);
-    ASSERT(m_offset >= 0);
-    ASSERT(!text.isEmpty());
-    
-    m_node->ref();
-    m_text = text.copy(); // make a copy to ensure that the string never changes
-}
-
-InsertTextCommand::~InsertTextCommand()
-{
-    if (m_node)
-        m_node->deref();
-}
-
-void InsertTextCommand::doApply()
-{
-    ASSERT(m_node);
-    ASSERT(m_offset >= 0);
-    ASSERT(!m_text.isEmpty());
-
-    int exceptionCode = 0;
-    m_node->insertData(m_offset, m_text, exceptionCode);
-    ASSERT(exceptionCode == 0);
-}
-
-void InsertTextCommand::doUnapply()
-{
-    ASSERT(m_node);
-    ASSERT(m_offset >= 0);
-    ASSERT(!m_text.isEmpty());
-
-    int exceptionCode = 0;
-    m_node->deleteData(m_offset, m_text.length(), exceptionCode);
-    ASSERT(exceptionCode == 0);
-}
-
 //------------------------------------------------------------------------------------------
 // JoinTextNodesCommand
 
@@ -2888,7 +3013,7 @@ void TypingCommand::insertText(DocumentImpl *document, const DOMString &text, bo
     }
 }
 
-void TypingCommand::insertNewline(DocumentImpl *document)
+void TypingCommand::insertLineBreak(DocumentImpl *document)
 {
     ASSERT(document);
     
@@ -2897,15 +3022,15 @@ void TypingCommand::insertNewline(DocumentImpl *document)
     
     EditCommandPtr lastEditCommand = part->lastEditCommand();
     if (isOpenForMoreTypingCommand(lastEditCommand)) {
-        static_cast<TypingCommand *>(lastEditCommand.get())->insertNewline();
+        static_cast<TypingCommand *>(lastEditCommand.get())->insertLineBreak();
     }
     else {
-        EditCommandPtr cmd(new TypingCommand(document, InsertNewline));
+        EditCommandPtr cmd(new TypingCommand(document, InsertLineBreak));
         cmd.apply();
     }
 }
 
-void TypingCommand::insertNewlineInQuotedContent(DocumentImpl *document)
+void TypingCommand::insertParagraphSeparatorInQuotedContent(DocumentImpl *document)
 {
     ASSERT(document);
     
@@ -2914,10 +3039,27 @@ void TypingCommand::insertNewlineInQuotedContent(DocumentImpl *document)
     
     EditCommandPtr lastEditCommand = part->lastEditCommand();
     if (isOpenForMoreTypingCommand(lastEditCommand)) {
-        static_cast<TypingCommand *>(lastEditCommand.get())->insertNewlineInQuotedContent();
+        static_cast<TypingCommand *>(lastEditCommand.get())->insertParagraphSeparatorInQuotedContent();
     }
     else {
-        EditCommandPtr cmd(new TypingCommand(document, InsertNewlineInQuotedContent));
+        EditCommandPtr cmd(new TypingCommand(document, InsertParagraphSeparatorInQuotedContent));
+        cmd.apply();
+    }
+}
+
+void TypingCommand::insertParagraphSeparator(DocumentImpl *document)
+{
+    ASSERT(document);
+    
+    KHTMLPart *part = document->part();
+    ASSERT(part);
+    
+    EditCommandPtr lastEditCommand = part->lastEditCommand();
+    if (isOpenForMoreTypingCommand(lastEditCommand)) {
+        static_cast<TypingCommand *>(lastEditCommand.get())->insertParagraphSeparator();
+    }
+    else {
+        EditCommandPtr cmd(new TypingCommand(document, InsertParagraphSeparator));
         cmd.apply();
     }
 }
@@ -2943,14 +3085,17 @@ void TypingCommand::doApply()
         case DeleteKey:
             deleteKeyPressed();
             return;
-        case InsertText:
-            insertText(m_textToInsert, m_selectInsertedText);
+        case InsertLineBreak:
+            insertLineBreak();
             return;
-        case InsertNewline:
-            insertNewline();
+        case InsertParagraphSeparator:
+            insertParagraphSeparator();
             return;
-        case InsertNewlineInQuotedContent:
-            insertNewlineInQuotedContent();
+        case InsertParagraphSeparatorInQuotedContent:
+            insertParagraphSeparatorInQuotedContent();
+            return;
+        case InsertText:
+            insertText(m_textToInsert, m_selectInsertedText);
             return;
     }
 
@@ -2992,19 +3137,19 @@ void TypingCommand::insertText(const DOMString &text, bool selectInsertedText)
     // FIXME: Improve typing style.
     // See this bug: <rdar://problem/3769899> Implementation of typing style needs improvement
     if (document()->part()->typingStyle() || m_cmds.count() == 0) {
-        InputTextCommand *impl = new InputTextCommand(document());
+        InsertTextCommand *impl = new InsertTextCommand(document());
         EditCommandPtr cmd(impl);
         applyCommandToComposite(cmd);
         impl->input(text, selectInsertedText);
     }
     else {
         EditCommandPtr lastCommand = m_cmds.last();
-        if (lastCommand.isInputTextCommand()) {
-            InputTextCommand *impl = static_cast<InputTextCommand *>(lastCommand.get());
+        if (lastCommand.isInsertTextCommand()) {
+            InsertTextCommand *impl = static_cast<InsertTextCommand *>(lastCommand.get());
             impl->input(text, selectInsertedText);
         }
         else {
-            InputTextCommand *impl = new InputTextCommand(document());
+            InsertTextCommand *impl = new InsertTextCommand(document());
             EditCommandPtr cmd(impl);
             applyCommandToComposite(cmd);
             impl->input(text, selectInsertedText);
@@ -3013,16 +3158,23 @@ void TypingCommand::insertText(const DOMString &text, bool selectInsertedText)
     typingAddedToOpenCommand();
 }
 
-void TypingCommand::insertNewline()
+void TypingCommand::insertLineBreak()
+{
+    EditCommandPtr cmd(new InsertLineBreakCommand(document()));
+    applyCommandToComposite(cmd);
+    typingAddedToOpenCommand();
+}
+
+void TypingCommand::insertParagraphSeparator()
 {
-    EditCommandPtr cmd(new InputNewlineCommand(document()));
+    EditCommandPtr cmd(new InsertParagraphSeparatorCommand(document()));
     applyCommandToComposite(cmd);
     typingAddedToOpenCommand();
 }
 
-void TypingCommand::insertNewlineInQuotedContent()
+void TypingCommand::insertParagraphSeparatorInQuotedContent()
 {
-    EditCommandPtr cmd(new InputNewlineInQuotedContentCommand(document()));
+    EditCommandPtr cmd(new InsertParagraphSeparatorInQuotedContentCommand(document()));
     applyCommandToComposite(cmd);
     typingAddedToOpenCommand();
 }
@@ -3074,14 +3226,14 @@ void TypingCommand::deleteKeyPressed()
     }
     else {
         EditCommandPtr lastCommand = m_cmds.last();
-        if (lastCommand.isInputTextCommand()) {
-            InputTextCommand &cmd = static_cast<InputTextCommand &>(lastCommand);
+        if (lastCommand.isInsertTextCommand()) {
+            InsertTextCommand &cmd = static_cast<InsertTextCommand &>(lastCommand);
             cmd.deleteCharacter();
             if (cmd.charactersAdded() == 0) {
                 removeCommand(lastCommand);
             }
         }
-        else if (lastCommand.isInputNewlineCommand()) {
+        else if (lastCommand.isInsertLineBreakCommand()) {
             lastCommand.unapply();
             removeCommand(lastCommand);
         }
@@ -3111,9 +3263,10 @@ bool TypingCommand::preservesTypingStyle() const
     switch (m_commandType) {
         case DeleteKey:
             return true;
+        case InsertLineBreak:
+        case InsertParagraphSeparator:
+        case InsertParagraphSeparatorInQuotedContent:
         case InsertText:
-        case InsertNewline:
-        case InsertNewlineInQuotedContent:
             return false;
     }
     ASSERT_NOT_REACHED();
index b488e2802727a7f48a902ad369ffebe3935c9dbd..91f70383b128fa830e4aa814fcb0ffbaacda605a 100644 (file)
@@ -78,8 +78,8 @@ public:
     EditCommandPtr parent() const;
     void setParent(const EditCommandPtr &) const;
 
-    bool isInputTextCommand() const;
-    bool isInputNewlineCommand() const;
+    bool isInsertTextCommand() const;
+    bool isInsertLineBreakCommand() const;
     bool isTypingCommand() const;
 
     static EditCommandPtr &emptyCommand();
@@ -150,7 +150,7 @@ public:
     DOM::CSSStyleDeclarationImpl *typingStyle() const { return m_typingStyle; };
     void setTypingStyle(DOM::CSSStyleDeclarationImpl *);
     
-    virtual bool isInputTextCommand() const;
+    virtual bool isInsertTextCommand() const;
     virtual bool isTypingCommand() const;
 
 private:
@@ -186,19 +186,19 @@ protected:
     void deleteKeyPressed();
     void deleteSelection(bool smartDelete=false, bool mergeBlocksAfterDelete=true);
     void deleteSelection(const khtml::Selection &selection, bool smartDelete=false, bool mergeBlocksAfterDelete=true);
-    void deleteText(DOM::TextImpl *node, long offset, long count);
+    void deleteTextFromNode(DOM::TextImpl *node, long offset, long count);
     void inputText(const DOM::DOMString &text, bool selectInsertedText = false);
     void insertNodeAfter(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
     void insertNodeAt(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild, long offset);
     void insertNodeBefore(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
-    void insertText(DOM::TextImpl *node, long offset, const DOM::DOMString &text);
+    void insertTextIntoNode(DOM::TextImpl *node, long offset, const DOM::DOMString &text);
     void joinTextNodes(DOM::TextImpl *text1, DOM::TextImpl *text2);
     void removeCSSProperty(DOM::CSSStyleDeclarationImpl *, int property);
     void removeFullySelectedNode(DOM::NodeImpl *);
     void removeNodeAttribute(DOM::ElementImpl *, int attribute);
     void removeNode(DOM::NodeImpl *removeChild);
     void removeNodePreservingChildren(DOM::NodeImpl *node);
-    void replaceText(DOM::TextImpl *node, long offset, long count, const DOM::DOMString &replacementText);
+    void replaceTextInNode(DOM::TextImpl *node, long offset, long count, const DOM::DOMString &replacementText);
     void setNodeAttribute(DOM::ElementImpl *, int attribute, const DOM::DOMString &);
     void splitTextNode(DOM::TextImpl *text, long offset);
 
@@ -211,6 +211,8 @@ protected:
     void insertBlockPlaceholderIfNeeded(DOM::NodeImpl *);
     bool removeBlockPlaceholderIfNeeded(DOM::NodeImpl *);
 
+    bool isLastVisiblePositionInNode(const VisiblePosition &, const DOM::NodeImpl *) const;
+
     QValueList<EditCommandPtr> m_cmds;
 };
 
@@ -271,6 +273,29 @@ private:
     DOM::CSSStyleDeclarationImpl *m_style;
 };
 
+//------------------------------------------------------------------------------------------
+// DeleteFromTextNodeCommand
+
+class DeleteFromTextNodeCommand : public EditCommand
+{
+public:
+    DeleteFromTextNodeCommand(DOM::DocumentImpl *document, DOM::TextImpl *node, long offset, long count);
+    virtual ~DeleteFromTextNodeCommand();
+       
+    virtual void doApply();
+    virtual void doUnapply();
+
+    DOM::TextImpl *node() const { return m_node; }
+    long offset() const { return m_offset; }
+    long count() const { return m_count; }
+
+private:
+    DOM::TextImpl *m_node;
+    long m_offset;
+    long m_count;
+    DOM::DOMString m_text;
+};
+
 //------------------------------------------------------------------------------------------
 // DeleteSelectionCommand
 
@@ -318,35 +343,54 @@ private:
 };
 
 //------------------------------------------------------------------------------------------
-// DeleteTextCommand
+// InsertIntoTextNode
 
-class DeleteTextCommand : public EditCommand
+class InsertIntoTextNode : public EditCommand
 {
 public:
-    DeleteTextCommand(DOM::DocumentImpl *document, DOM::TextImpl *node, long offset, long count);
-    virtual ~DeleteTextCommand();
+    InsertIntoTextNode(DOM::DocumentImpl *document, DOM::TextImpl *, long, const DOM::DOMString &);
+    virtual ~InsertIntoTextNode();
        
     virtual void doApply();
     virtual void doUnapply();
 
     DOM::TextImpl *node() const { return m_node; }
     long offset() const { return m_offset; }
-    long count() const { return m_count; }
+    DOM::DOMString text() const { return m_text; }
 
 private:
     DOM::TextImpl *m_node;
     long m_offset;
-    long m_count;
     DOM::DOMString m_text;
 };
 
 //------------------------------------------------------------------------------------------
-// InputNewlineCommand
+// InsertNodeBeforeCommand
+
+class InsertNodeBeforeCommand : public EditCommand
+{
+public:
+    InsertNodeBeforeCommand(DOM::DocumentImpl *, DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
+    virtual ~InsertNodeBeforeCommand();
+
+    virtual void doApply();
+    virtual void doUnapply();
+
+    DOM::NodeImpl *insertChild() const { return m_insertChild; }
+    DOM::NodeImpl *refChild() const { return m_refChild; }
+
+private:
+    DOM::NodeImpl *m_insertChild;
+    DOM::NodeImpl *m_refChild; 
+};
+
+//------------------------------------------------------------------------------------------
+// InsertLineBreakCommand
 
-class InputNewlineCommand : public CompositeEditCommand
+class InsertLineBreakCommand : public CompositeEditCommand
 {
 public:
-    InputNewlineCommand(DOM::DocumentImpl *document);
+    InsertLineBreakCommand(DOM::DocumentImpl *document);
 
     virtual void doApply();
 
@@ -356,19 +400,33 @@ private:
 };
 
 //------------------------------------------------------------------------------------------
-// InputNewlineInQuotedContentCommand
+// InsertParagraphSeparatorCommand
 
-class InputNewlineInQuotedContentCommand : public CompositeEditCommand
+class InsertParagraphSeparatorCommand : public CompositeEditCommand
 {
 public:
-    InputNewlineInQuotedContentCommand(DOM::DocumentImpl *);
-    virtual ~InputNewlineInQuotedContentCommand();
+    InsertParagraphSeparatorCommand(DOM::DocumentImpl *document);
+
+    virtual void doApply();
+
+private:
+    QPtrList<DOM::NodeImpl> ancestors;
+    QPtrList<DOM::NodeImpl> clonedNodes;
+};
+
+//------------------------------------------------------------------------------------------
+// InsertParagraphSeparatorInQuotedContentCommand
+
+class InsertParagraphSeparatorInQuotedContentCommand : public CompositeEditCommand
+{
+public:
+    InsertParagraphSeparatorInQuotedContentCommand(DOM::DocumentImpl *);
+    virtual ~InsertParagraphSeparatorInQuotedContentCommand();
        
     virtual void doApply();
     
 private:
     bool isMailBlockquote(const DOM::NodeImpl *) const;
-    bool isLastVisiblePositionInBlockquote(const VisiblePosition &pos, const DOM::NodeImpl *) const;
 
     QPtrList<DOM::NodeImpl> ancestors;
     QPtrList<DOM::NodeImpl> clonedNodes;
@@ -376,12 +434,12 @@ private:
 };
 
 //------------------------------------------------------------------------------------------
-// InputTextCommand
+// InsertTextCommand
 
-class InputTextCommand : public CompositeEditCommand
+class InsertTextCommand : public CompositeEditCommand
 {
 public:
-    InputTextCommand(DOM::DocumentImpl *document);
+    InsertTextCommand(DOM::DocumentImpl *document);
 
     virtual void doApply();
 
@@ -391,7 +449,7 @@ public:
     unsigned long charactersAdded() const { return m_charactersAdded; }
     
 private:
-    virtual bool isInputTextCommand() const;
+    virtual bool isInsertTextCommand() const;
 
     DOM::Position prepareForTextInsertion(bool adjustDownstream);
     void insertSpace(DOM::TextImpl *textNode, unsigned long offset);
@@ -399,48 +457,6 @@ private:
     unsigned long m_charactersAdded;
 };
 
-//------------------------------------------------------------------------------------------
-// InsertNodeBeforeCommand
-
-class InsertNodeBeforeCommand : public EditCommand
-{
-public:
-    InsertNodeBeforeCommand(DOM::DocumentImpl *, DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
-    virtual ~InsertNodeBeforeCommand();
-
-    virtual void doApply();
-    virtual void doUnapply();
-
-    DOM::NodeImpl *insertChild() const { return m_insertChild; }
-    DOM::NodeImpl *refChild() const { return m_refChild; }
-
-private:
-    DOM::NodeImpl *m_insertChild;
-    DOM::NodeImpl *m_refChild; 
-};
-
-//------------------------------------------------------------------------------------------
-// InsertTextCommand
-
-class InsertTextCommand : public EditCommand
-{
-public:
-    InsertTextCommand(DOM::DocumentImpl *document, DOM::TextImpl *, long, const DOM::DOMString &);
-    virtual ~InsertTextCommand();
-       
-    virtual void doApply();
-    virtual void doUnapply();
-
-    DOM::TextImpl *node() const { return m_node; }
-    long offset() const { return m_offset; }
-    DOM::DOMString text() const { return m_text; }
-
-private:
-    DOM::TextImpl *m_node;
-    long m_offset;
-    DOM::DOMString m_text;
-};
-
 //------------------------------------------------------------------------------------------
 // JoinTextNodesCommand
 
@@ -626,14 +642,21 @@ private:
 class TypingCommand : public CompositeEditCommand
 {
 public:
-    enum ETypingCommand { DeleteKey, InsertText, InsertNewline, InsertNewlineInQuotedContent };
+    enum ETypingCommand { 
+        DeleteKey, 
+        InsertText, 
+        InsertLineBreak, 
+        InsertParagraphSeparator,
+        InsertParagraphSeparatorInQuotedContent,
+    };
 
     TypingCommand(DOM::DocumentImpl *document, ETypingCommand, const DOM::DOMString &text = "", bool selectInsertedText = false);
 
-    static void deleteKeyPressed(DOM::DocumentImpl *document);
-    static void insertText(DOM::DocumentImpl *document, const DOM::DOMString &text, bool selectInsertedText = false);
-    static void insertNewline(DOM::DocumentImpl *document);
-    static void insertNewlineInQuotedContent(DOM::DocumentImpl *document);
+    static void deleteKeyPressed(DOM::DocumentImpl *);
+    static void insertText(DOM::DocumentImpl *, const DOM::DOMString &, bool selectInsertedText = false);
+    static void insertLineBreak(DOM::DocumentImpl *);
+    static void insertParagraphSeparator(DOM::DocumentImpl *);
+    static void insertParagraphSeparatorInQuotedContent(DOM::DocumentImpl *);
     static bool isOpenForMoreTypingCommand(const EditCommandPtr &);
     static void closeTyping(const EditCommandPtr &);
     
@@ -643,8 +666,9 @@ public:
     void closeTyping() { m_openForMoreTyping = false; }
 
     void insertText(const DOM::DOMString &text, bool selectInsertedText);
-    void insertNewline();
-    void insertNewlineInQuotedContent();
+    void insertLineBreak();
+    void insertParagraphSeparatorInQuotedContent();
+    void insertParagraphSeparator();
     void deleteKeyPressed();
 
 private:
index f2cfba5f8de115d3d295490a6acf5fd1be397d2e..07fde0544002b8902fcad1cc2367f9195058be33 100644 (file)
@@ -228,14 +228,14 @@ bool execIndent(KHTMLPart *part, bool userInterface, const DOMString &value)
 
 bool execInsertNewline(KHTMLPart *part, bool userInterface, const DOMString &value)
 {
-    TypingCommand::insertNewline(part->xmlDocImpl());
+    TypingCommand::insertLineBreak(part->xmlDocImpl());
     return true;
 }
 
 bool execInsertParagraph(KHTMLPart *part, bool userInterface, const DOMString &value)
 {
-    // FIXME: Implement.
-    return false;
+    TypingCommand::insertParagraphSeparator(part->xmlDocImpl());
+    return true;
 }
 
 bool execInsertText(KHTMLPart *part, bool userInterface, const DOMString &value)
index dca453a6b3d53a333be45b3a92828198263104d8..2041a7e0e0c6b52c8799f6b59a8cdf84c45ec8bd 100644 (file)
@@ -332,9 +332,10 @@ typedef enum {
 - (void)replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace;
 - (void)replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace;
 
+- (void)insertLineBreak;
+- (void)insertParagraphSeparator;
+- (void)insertParagraphSeparatorInQuotedContent;
 - (void)insertText:(NSString *)text selectInsertedText:(BOOL)selectInsertedText;
-- (void)insertNewline;
-- (void)insertNewlineInQuotedContent;
 
 - (void)setSelectionToDragCaret;
 - (void)moveSelectionToDragCaret:(DOMDocumentFragment *)selectionFragment smartMove:(BOOL)smartMove;
index 447479d2a1cb823885b42aa5b7212174950b27db..96f1bf742dc1d67190e97ef50a4aacabff1b14bd 100644 (file)
@@ -1555,16 +1555,25 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
     [self replaceSelectionWithFragment:[self documentFragmentWithText:text] selectReplacement:selectReplacement smartReplace:smartReplace];
 }
 
-- (void)insertNewline
+- (void)insertLineBreak
 {
     if (!_part || !_part->xmlDocImpl())
         return;
     
-    TypingCommand::insertNewline(_part->xmlDocImpl());
+    TypingCommand::insertLineBreak(_part->xmlDocImpl());
     [self ensureSelectionVisible];
 }
 
-- (void)insertNewlineInQuotedContent
+- (void)insertParagraphSeparator
+{
+    if (!_part || !_part->xmlDocImpl())
+        return;
+    
+    TypingCommand::insertParagraphSeparator(_part->xmlDocImpl());
+    [self ensureSelectionVisible];
+}
+
+- (void)insertParagraphSeparatorInQuotedContent
 {
     if (!_part || !_part->xmlDocImpl())
         return;
@@ -1573,7 +1582,7 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
     if (selection.isNone())
         return;
     
-    TypingCommand::insertNewlineInQuotedContent(_part->xmlDocImpl());
+    TypingCommand::insertParagraphSeparatorInQuotedContent(_part->xmlDocImpl());
     [self ensureSelectionVisible];
 }
 
index 19bce6543bd25a998a65a3244f74370be296e34b..348d282b8a12d99ba131490aa4370e0d011fd632 100644 (file)
@@ -1,3 +1,16 @@
+2004-11-02  Ken Kocienda  <kocienda@apple.com>
+
+        Reviewed by Hyatt
+
+        WebCore now implements a command to insert a block in response to typing a return key, and
+        some names were improved in the course of this work.
+
+        * WebView.subproj/WebHTMLView.m:
+        (-[WebHTMLView insertNewline:]): Now calls insertLineBreak on bridge object.
+        (-[WebHTMLView insertLineBreak:]): New method.
+        (-[WebHTMLView insertParagraphSeparator:]): Now implemented.
+        * WebView.subproj/WebView.m: 
+
 === Safari-169 ===
 
 2004-10-29  Chris Blumenberg  <cblu@apple.com>
index 67e88e516e24ba3812afa80d826806937a7235e6..08bd4993b1333d0dbfb78de4b8fa92f490a1ab62 100644 (file)
@@ -3533,7 +3533,19 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
     // Perhaps we should make this delegate call sensitive to the real DOM operation we actually do.
     WebBridge *bridge = [self _bridge];
     if ([self _shouldReplaceSelectionWithText:@"\n" givenAction:WebViewInsertActionTyped]) {
-        [bridge insertNewline];
+        [bridge insertLineBreak];
+    }
+}
+
+- (void)insertLineBreak:(id)sender
+{
+    if (![self _canEdit])
+        return;
+        
+    // Perhaps we should make this delegate call sensitive to the real DOM operation we actually do.
+    WebBridge *bridge = [self _bridge];
+    if ([self _shouldReplaceSelectionWithText:@"\n" givenAction:WebViewInsertActionTyped]) {
+        [bridge insertLineBreak];
     }
 }
 
@@ -3542,8 +3554,11 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
     if (![self _canEdit])
         return;
 
-    // FIXME: Should this do something different? Do we have the equivalent of a paragraph separator?
-    [self insertNewline:sender];
+    // Perhaps we should make this delegate call sensitive to the real DOM operation we actually do.
+    WebBridge *bridge = [self _bridge];
+    if ([self _shouldReplaceSelectionWithText:@"\n" givenAction:WebViewInsertActionTyped]) {
+        [bridge insertParagraphSeparator];
+    }
 }
 
 - (void)_changeWordCaseWithSelector:(SEL)selector
index 712380cee54e980a65098b9e6ad51361a96a33f8..9861dedbbc9bdf23979414677d8ac5eabd5ae7e6 100644 (file)
@@ -2838,7 +2838,7 @@ FORWARD(yankAndSelect)
 
 - (void)_insertNewlineInQuotedContent;
 {
-    [[self _bridgeForCurrentSelection] insertNewlineInQuotedContent];
+    [[self _bridgeForCurrentSelection] insertParagraphSeparatorInQuotedContent];
 }
 
 @end