LayoutTests:
authorjusting <justing@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 7 Apr 2006 18:41:26 +0000 (18:41 +0000)
committerjusting <justing@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 7 Apr 2006 18:41:26 +0000 (18:41 +0000)
        Reviewed by harrison

        <http://bugzilla.opendarwin.org/show_bug.cgi?id=8145>
        REGRESSION: Pasting text from TextEdit with a bold word into text field results in crash

        * editing/pasteboard/8145-1-expected.checksum: Added.
        * editing/pasteboard/8145-1-expected.png: Added.
        * editing/pasteboard/8145-1-expected.txt: Added.
        * editing/pasteboard/8145-1.html: Added.
        * editing/pasteboard/8145-2-expected.checksum: Added.
        * editing/pasteboard/8145-2-expected.png: Added.
        * editing/pasteboard/8145-2-expected.txt: Added.
        * editing/pasteboard/8145-2.html: Added.
        * editing/pasteboard/8145-3-expected.checksum: Added.
        * editing/pasteboard/8145-3-expected.png: Added.
        * editing/pasteboard/8145-3-expected.txt: Added.
        * editing/pasteboard/8145-3.html: Added.
        * fast/forms/plaintext-mode-1-expected.txt:
        * fast/forms/plaintext-mode-1.html:

WebCore:

        Reviewed by harrison

        <http://bugzilla.opendarwin.org/show_bug.cgi?id=8145>
        REGRESSION: Pasting text from TextEdit with a bold word into text field results in crash

        * editing/AppendNodeCommand.cpp:
        (WebCore::AppendNodeCommand::doApply):
        Assert that the node will be placed somewhere that's contenteditable.
        * editing/InsertNodeBeforeCommand.cpp:
        (WebCore::InsertNodeBeforeCommand::doApply): Ditto
        * editing/JSEditor.cpp:
        Enabled insertHTML for plaintext-only regions since it's useful for debugging rich
        content pastes into the new text fields.
        * editing/ReplaceSelectionCommand.cpp:
        (WebCore::ReplaceSelectionCommand::doApply):
        1) After the first paragraph of the fragment has been merged with the first part of the
        paragraph where the paste occured, if the next node to be inserted is inline, we put it
        in a new paragraph because it was at the start of a paragraph in the fragment.  The change
        is to insert a paragraph separator if insertionPos.next() is null or outside of the current
        editable region.
        2) Before the paste begins, a paragraph separator is inserted in order to avoid
        nesting blocks from the fragment to be pasted inside the block where the paste will
        occur.  I made two fixes to the code that decides whether or not to insert the
        paragraph separator and added testcases for each.  Added a fixme because it appears that
        this code is also used to ensure that the aforementioned insertionPos will be at the end of
        a paragraph.  This code should only be about preventing nesting.

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

21 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/pasteboard/8145-1-expected.checksum [new file with mode: 0644]
LayoutTests/editing/pasteboard/8145-1-expected.png [new file with mode: 0644]
LayoutTests/editing/pasteboard/8145-1-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/8145-1.html [new file with mode: 0644]
LayoutTests/editing/pasteboard/8145-2-expected.checksum [new file with mode: 0644]
LayoutTests/editing/pasteboard/8145-2-expected.png [new file with mode: 0644]
LayoutTests/editing/pasteboard/8145-2-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/8145-2.html [new file with mode: 0644]
LayoutTests/editing/pasteboard/8145-3-expected.checksum [new file with mode: 0644]
LayoutTests/editing/pasteboard/8145-3-expected.png [new file with mode: 0644]
LayoutTests/editing/pasteboard/8145-3-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/8145-3.html [new file with mode: 0644]
LayoutTests/fast/forms/plaintext-mode-1-expected.txt
LayoutTests/fast/forms/plaintext-mode-1.html
WebCore/ChangeLog
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/editing/AppendNodeCommand.cpp
WebCore/editing/InsertNodeBeforeCommand.cpp
WebCore/editing/JSEditor.cpp
WebCore/editing/ReplaceSelectionCommand.cpp

index 920340d..bf40982 100644 (file)
@@ -1,3 +1,25 @@
+2006-04-07  Justin Garcia  <justin.garcia@apple.com>
+
+        Reviewed by harrison
+        
+        <http://bugzilla.opendarwin.org/show_bug.cgi?id=8145>
+        REGRESSION: Pasting text from TextEdit with a bold word into text field results in crash
+
+        * editing/pasteboard/8145-1-expected.checksum: Added.
+        * editing/pasteboard/8145-1-expected.png: Added.
+        * editing/pasteboard/8145-1-expected.txt: Added.
+        * editing/pasteboard/8145-1.html: Added.
+        * editing/pasteboard/8145-2-expected.checksum: Added.
+        * editing/pasteboard/8145-2-expected.png: Added.
+        * editing/pasteboard/8145-2-expected.txt: Added.
+        * editing/pasteboard/8145-2.html: Added.
+        * editing/pasteboard/8145-3-expected.checksum: Added.
+        * editing/pasteboard/8145-3-expected.png: Added.
+        * editing/pasteboard/8145-3-expected.txt: Added.
+        * editing/pasteboard/8145-3.html: Added.
+        * fast/forms/plaintext-mode-1-expected.txt:
+        * fast/forms/plaintext-mode-1.html:
+
 2006-04-07  Maciej Stachowiak  <mjs@apple.com>
 
         Reviewed by Anders.
diff --git a/LayoutTests/editing/pasteboard/8145-1-expected.checksum b/LayoutTests/editing/pasteboard/8145-1-expected.checksum
new file mode 100644 (file)
index 0000000..0b0d1f9
--- /dev/null
@@ -0,0 +1 @@
+477f32221941a5668a307333be41f785
\ No newline at end of file
diff --git a/LayoutTests/editing/pasteboard/8145-1-expected.png b/LayoutTests/editing/pasteboard/8145-1-expected.png
new file mode 100644 (file)
index 0000000..8a2db4e
Binary files /dev/null and b/LayoutTests/editing/pasteboard/8145-1-expected.png differ
diff --git a/LayoutTests/editing/pasteboard/8145-1-expected.txt b/LayoutTests/editing/pasteboard/8145-1-expected.txt
new file mode 100644 (file)
index 0000000..ac970ec
--- /dev/null
@@ -0,0 +1,27 @@
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document toDOMRange:range from 1 of DIV > DIV > BODY > HTML > #document to 1 of DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {P} at (0,0) size 784x36
+        RenderText {TEXT} at (0,0) size 427x18
+          text run at (0,0) width 427: "This is a replica of the paste that caused the crash covered by 8145. "
+        RenderInline {B} at (0,0) size 775x36
+          RenderText {TEXT} at (427,0) size 775x36
+            text run at (427,0) width 216: "It currently demonstrates 8219. "
+            text run at (643,0) width 132: "Two extra newlines"
+            text run at (0,18) width 477: "are added when pasting a single styled line into a plaintext-only region."
+      RenderBlock {DIV} at (0,52) size 784x56 [border: (1px solid #000000)]
+        RenderBlock (anonymous) at (1,1) size 782x18
+          RenderText {TEXT} at (0,0) size 71x18
+            text run at (0,0) width 71: "foo bar baz"
+        RenderBlock {DIV} at (1,19) size 782x36
+          RenderBR {BR} at (0,0) size 0x18
+          RenderBR {BR} at (0,18) size 0x18
+caret: position 0 of child 1 {BR} of child 1 {DIV} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
diff --git a/LayoutTests/editing/pasteboard/8145-1.html b/LayoutTests/editing/pasteboard/8145-1.html
new file mode 100644 (file)
index 0000000..fb365d4
--- /dev/null
@@ -0,0 +1,11 @@
+<p>This is a replica of the paste that caused the crash covered by 8145.  <b>It currently demonstrates 8219.  Two extra newlines are added when pasting a single styled line into a plaintext-only region.</b></p>
+<div id="test1" style="border: 1px solid black;" contenteditable="plaintext-only"></div>
+
+<script>
+var s = window.getSelection();
+var p = document.getElementById("test1");
+p.innerHTML = "";
+s.setPosition(p, 0);
+var html = "<p style='margin: 0; font: 12px Helvetica'>foo <b>bar</b> baz</p>" + '\n';
+document.execCommand("InsertHTML", false, html);
+</script>
\ No newline at end of file
diff --git a/LayoutTests/editing/pasteboard/8145-2-expected.checksum b/LayoutTests/editing/pasteboard/8145-2-expected.checksum
new file mode 100644 (file)
index 0000000..210a0da
--- /dev/null
@@ -0,0 +1 @@
+bb39bee29022d1b41a03b0f06b246913
\ No newline at end of file
diff --git a/LayoutTests/editing/pasteboard/8145-2-expected.png b/LayoutTests/editing/pasteboard/8145-2-expected.png
new file mode 100644 (file)
index 0000000..385b3cb
Binary files /dev/null and b/LayoutTests/editing/pasteboard/8145-2-expected.png differ
diff --git a/LayoutTests/editing/pasteboard/8145-2-expected.txt b/LayoutTests/editing/pasteboard/8145-2-expected.txt
new file mode 100644 (file)
index 0000000..e941da5
--- /dev/null
@@ -0,0 +1,35 @@
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 5 of DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 3 of #text > DIV > BODY > HTML > #document to 3 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {P} at (0,0) size 784x36
+        RenderText {TEXT} at (0,0) size 783x36
+          text run at (0,0) width 299: "This tests a change made with the fix for 8145. "
+          text run at (299,0) width 484: "The paragraph separator inserted to prevent nesting blocks from the fragment"
+          text run at (0,18) width 779: "to paste inside the block where the paste occured was incorrectly inserted when the paste occured at the start of a paragraph."
+      RenderBlock {DIV} at (0,52) size 784x74 [border: (1px solid #000000)]
+        RenderBlock (anonymous) at (1,1) size 782x18
+          RenderText {TEXT} at (0,0) size 21x18
+            text run at (0,0) width 21: "foo"
+          RenderBR {BR} at (0,0) size 0x0
+        RenderBlock {DIV} at (1,19) size 782x18
+          RenderText {TEXT} at (0,0) size 21x18
+            text run at (0,0) width 21: "foo"
+        RenderBlock (anonymous) at (1,37) size 782x36
+          RenderText {TEXT} at (0,0) size 20x18
+            text run at (0,0) width 20: "bar"
+          RenderText {TEXT} at (20,0) size 20x18
+            text run at (20,0) width 20: "bar"
+          RenderBR {BR} at (0,0) size 0x0
+          RenderText {TEXT} at (0,18) size 22x18
+            text run at (0,18) width 22: "baz"
+caret: position 3 of child 3 {TEXT} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
diff --git a/LayoutTests/editing/pasteboard/8145-2.html b/LayoutTests/editing/pasteboard/8145-2.html
new file mode 100644 (file)
index 0000000..e7aedf5
--- /dev/null
@@ -0,0 +1,13 @@
+<p>This tests a change made with the fix for 8145.  The paragraph separator inserted to prevent nesting blocks from the fragment to paste inside the block where the paste occured was incorrectly inserted when the paste occured at the start of a paragraph.</p>
+<div id="test" style="border: 1px solid black;" contenteditable="true"></div>
+
+<script>
+var s = window.getSelection();
+var p = document.getElementById("test");
+p.innerHTML = "foo<br>bar<br>baz";
+s.setPosition(p, 0);
+s.modify("move", "forward", "word");
+s.modify("move", "forward", "character");
+var html = "<div>foo</div>bar";
+document.execCommand("InsertHTML", false, html);
+</script>
\ No newline at end of file
diff --git a/LayoutTests/editing/pasteboard/8145-3-expected.checksum b/LayoutTests/editing/pasteboard/8145-3-expected.checksum
new file mode 100644 (file)
index 0000000..6683102
--- /dev/null
@@ -0,0 +1 @@
+a9092b53934344bf893ca64826364c50
\ No newline at end of file
diff --git a/LayoutTests/editing/pasteboard/8145-3-expected.png b/LayoutTests/editing/pasteboard/8145-3-expected.png
new file mode 100644 (file)
index 0000000..8b7cee4
Binary files /dev/null and b/LayoutTests/editing/pasteboard/8145-3-expected.png differ
diff --git a/LayoutTests/editing/pasteboard/8145-3-expected.txt b/LayoutTests/editing/pasteboard/8145-3-expected.txt
new file mode 100644 (file)
index 0000000..c4e3e91
--- /dev/null
@@ -0,0 +1,31 @@
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 1 of DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {P} at (0,0) size 784x54
+        RenderText {TEXT} at (0,0) size 783x54
+          text run at (0,0) width 299: "This tests a change made with the fix for 8145. "
+          text run at (299,0) width 484: "The paragraph separator inserted to prevent nesting blocks from the fragment"
+          text run at (0,18) width 766: "to paste inside the block where the paste occured was not being inserted when the fragment had an interchange newline at"
+          text run at (0,36) width 50: "the end."
+      RenderBlock {DIV} at (0,70) size 784x56 [border: (1px solid #000000)]
+        RenderBlock {DIV} at (1,1) size 782x18
+          RenderText {TEXT} at (0,0) size 5x18
+            text run at (0,0) width 5: "f"
+          RenderText {TEXT} at (5,0) size 20x18
+            text run at (5,0) width 20: "bar"
+        RenderBlock {DIV} at (1,19) size 782x18
+          RenderText {TEXT} at (0,0) size 22x18
+            text run at (0,0) width 22: "baz"
+        RenderBlock {DIV} at (1,37) size 782x18
+          RenderText {TEXT} at (0,0) size 16x18
+            text run at (0,0) width 16: "oo"
+caret: position 0 of child 0 {TEXT} of child 2 {DIV} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
diff --git a/LayoutTests/editing/pasteboard/8145-3.html b/LayoutTests/editing/pasteboard/8145-3.html
new file mode 100644 (file)
index 0000000..054721b
--- /dev/null
@@ -0,0 +1,12 @@
+<p>This tests a change made with the fix for 8145.  The paragraph separator inserted to prevent nesting blocks from the fragment to paste inside the block where the paste occured was not being inserted when the fragment had an interchange newline at the end.</p>
+<div id="test" style="border: 1px solid black;" contenteditable="true"></div>
+
+<script>
+var s = window.getSelection();
+var p = document.getElementById("test");
+p.innerHTML = "<div>foo</div>";
+s.setPosition(p, 0);
+s.modify("move", "forward", "character");
+var html = "<div>bar</div>baz<br class='Apple-interchange-newline'>";
+document.execCommand("InsertHTML", false, html);
+</script>
\ No newline at end of file
index 03bfeb3..f0f8a67 100644 (file)
@@ -21,7 +21,7 @@ Success: document.queryCommandEnabled("FontSizeDelta") == true
 Success: document.queryCommandEnabled("ForeColor") == true
 Success: document.queryCommandEnabled("ForwardDelete") == true
 Success: document.queryCommandEnabled("Indent") == false
-Success: document.queryCommandEnabled("InsertHTML") == false
+Success: document.queryCommandEnabled("InsertHTML") == true
 Success: document.queryCommandEnabled("InsertImage") == false
 Success: document.queryCommandEnabled("InsertLineBreak") == true
 Success: document.queryCommandEnabled("InsertParagraph") == true
index 00feccd..3824c16 100644 (file)
@@ -38,7 +38,7 @@ assert("document.queryCommandEnabled", "FontSizeDelta", true);
 assert("document.queryCommandEnabled", "ForeColor", true);
 assert("document.queryCommandEnabled", "ForwardDelete", true);
 assert("document.queryCommandEnabled", "Indent", false);
-assert("document.queryCommandEnabled", "InsertHTML", false);
+assert("document.queryCommandEnabled", "InsertHTML", true);
 assert("document.queryCommandEnabled", "InsertImage", false);
 assert("document.queryCommandEnabled", "InsertLineBreak", true);
 assert("document.queryCommandEnabled", "InsertParagraph", true);
index a7dbef8..2ed8fc2 100644 (file)
@@ -1,3 +1,32 @@
+2006-04-06  Justin Garcia  <justin.garcia@apple.com>
+
+        Reviewed by harrison
+        
+        <http://bugzilla.opendarwin.org/show_bug.cgi?id=8145>
+        REGRESSION: Pasting text from TextEdit with a bold word into text field results in crash
+
+        * editing/AppendNodeCommand.cpp:
+        (WebCore::AppendNodeCommand::doApply): 
+        Assert that the node will be placed somewhere that's contenteditable.
+        * editing/InsertNodeBeforeCommand.cpp:
+        (WebCore::InsertNodeBeforeCommand::doApply): Ditto
+        * editing/JSEditor.cpp: 
+        Enabled insertHTML for plaintext-only regions since it's useful for debugging rich 
+        content pastes into the new text fields.
+        * editing/ReplaceSelectionCommand.cpp:
+        (WebCore::ReplaceSelectionCommand::doApply):
+        1) After the first paragraph of the fragment has been merged with the first part of the
+        paragraph where the paste occured, if the next node to be inserted is inline, we put it 
+        in a new paragraph because it was at the start of a paragraph in the fragment.  The change
+        is to insert a paragraph separator if insertionPos.next() is null or outside of the current 
+        editable region.
+        2) Before the paste begins, a paragraph separator is inserted in order to avoid 
+        nesting blocks from the fragment to be pasted inside the block where the paste will 
+        occur.  I made two fixes to the code that decides whether or not to insert the 
+        paragraph separator and added testcases for each.  Added a fixme because it appears that
+        this code is also used to ensure that the aforementioned insertionPos will be at the end of 
+        a paragraph.  This code should only be about preventing nesting.
+
 2006-04-06  Maciej Stachowiak  <mjs@apple.com>
 
         Reviewed by Anders.
index edc6397..31101d0 100644 (file)
                6593923509AE4346002C531F /* KURL.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = KURL.cpp; path = platform/KURL.cpp; sourceTree = "<group>"; };
                6593923609AE4346002C531F /* KURL.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = KURL.h; path = platform/KURL.h; sourceTree = "<group>"; };
                6593923909AE435C002C531F /* KURLMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = KURLMac.mm; sourceTree = "<group>"; };
-               659DDC8009E198BA001BF3C6 /* JSDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JSDocument.cpp; path = JSDocument.cpp; sourceTree = "<group>"; };
-               659DDC8109E198BA001BF3C6 /* JSDocument.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JSDocument.h; path = JSDocument.h; sourceTree = "<group>"; };
+               659DDC8009E198BA001BF3C6 /* JSDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSDocument.cpp; sourceTree = "<group>"; };
+               659DDC8109E198BA001BF3C6 /* JSDocument.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSDocument.h; sourceTree = "<group>"; };
                65A21467097A329100B9050A /* Page.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Page.h; sourceTree = "<group>"; };
                65A21482097A3F5300B9050A /* FrameTree.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FrameTree.cpp; sourceTree = "<group>"; };
                65A21483097A3F5300B9050A /* FrameTree.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FrameTree.h; sourceTree = "<group>"; };
index 8311481..5f1565e 100644 (file)
@@ -45,6 +45,7 @@ void AppendNodeCommand::doApply()
     // 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_appendChild->parent());
+    ASSERT(m_parentNode->isContentEditable());
 
     ExceptionCode ec = 0;
     m_parentNode->appendChild(m_appendChild.get(), ec);
index 4076da1..5168060 100644 (file)
@@ -46,6 +46,7 @@ void InsertNodeBeforeCommand::doApply()
     // 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(m_refChild->parentNode()->isContentEditable());
 
     ExceptionCode ec = 0;
     m_refChild->parentNode()->insertBefore(m_insertChild.get(), m_refChild.get(), ec);
index eb5e4b6..ae63f27 100644 (file)
@@ -597,7 +597,7 @@ CommandMap *createCommandDictionary()
         { "ForeColor", { execForeColor, enabledAnySelection, stateNone, valueForeColor } },
         { "ForwardDelete", { execForwardDelete, enabledAnyEditableSelection, stateNone, valueNull } },
         { "Indent", { execIndent, enabledAnyRichlyEditableSelection, stateNone, valueNull } },
-        { "InsertHTML", { execInsertHTML, enabledAnyRichlyEditableSelection, stateNone, valueNull } },
+        { "InsertHTML", { execInsertHTML, enabledAnyEditableSelection, stateNone, valueNull } },
         { "InsertImage", { execInsertImage, enabledAnyRichlyEditableSelection, stateNone, valueNull } },
         { "InsertLineBreak", { execInsertLineBreak, enabledAnyEditableSelection, stateNone, valueNull } },
         { "InsertParagraph", { execInsertParagraph, enabledAnyEditableSelection, stateNone, valueNull } },
index 41c98d0..fc52f1c 100644 (file)
@@ -496,7 +496,6 @@ void ReplaceSelectionCommand::doApply()
     VisiblePosition visibleEnd(selection.end(), selection.affinity());
     bool startAtStartOfBlock = isStartOfBlock(visibleStart);
     bool startAtEndOfBlock = isEndOfBlock(visibleStart);
-    bool startAtBlockBoundary = startAtStartOfBlock || startAtEndOfBlock;
     Node *startBlock = selection.start().node()->enclosingBlockFlowElement();
     Node *endBlock = selection.end().node()->enclosingBlockFlowElement();
 
@@ -569,10 +568,14 @@ void ReplaceSelectionCommand::doApply()
                 setEndingSelection(VisiblePosition(endingSelection().start(), VP_DEFAULT_AFFINITY));
             }
         }
-        if (!fragment.hasInterchangeNewlineAtEnd() && fragment.hasMoreThanOneBlock() && 
-            !startAtBlockBoundary && !isEndOfParagraph(visibleEnd)) {
-            // The start and the end need to wind up in separate blocks.
-            // Insert a paragraph separator to make that happen.
+        // We split the current paragraph in two to avoid nesting the blocks from the fragment inside the current block.
+        // For example paste <div>foo</div><div>bar</div><div>baz</div> into <div>x^x</div>, where ^ is the caret.  
+        // As long as the  div styles are the same, visually you'd expect: <div>xbar</div><div>bar</div><div>bazx</div>, 
+        // not <div>xbar<div>bar</div><div>bazx</div></div>
+        // FIXME: If this code is really about preventing block nesting, then the check should be !isEndOfBlock(visibleStart) and we 
+        // should split the block in two, instead of inserting a paragraph separator. In the meantime, it appears that code below 
+        // depends on this split happening when the paste position is not the start or end of a paragraph.
+        if (fragment.hasMoreThanOneBlock() && !isEndOfParagraph(visibleStart) && !isStartOfParagraph(visibleStart)) {
             insertParagraphSeparator();
             setEndingSelection(VisiblePosition(endingSelection().start(), VP_DEFAULT_AFFINITY).previous());
         }
@@ -681,15 +684,31 @@ void ReplaceSelectionCommand::doApply()
         RefPtr<Node> refNode = fragment.firstChild();
         RefPtr<Node> node = refNode ? refNode->nextSibling() : 0;
         Node *insertionBlock = insertionPos.node()->enclosingBlockFlowElement();
-        bool insertionBlockIsRoot = insertionBlock == insertionBlock->rootEditableElement();
-        VisiblePosition visiblePos(insertionPos, DOWNSTREAM);
+        Node* insertionRoot = insertionPos.node()->rootEditableElement();
+        bool insertionBlockIsRoot = insertionBlock == insertionRoot;
+        VisiblePosition visibleInsertionPos(insertionPos, DOWNSTREAM);
         fragment.removeNode(refNode);
-        if (!insertionBlockIsRoot && fragment.isBlockFlow(refNode.get()) && isStartOfBlock(visiblePos))
+        if (!insertionBlockIsRoot && fragment.isBlockFlow(refNode.get()) && isStartOfBlock(visibleInsertionPos))
             insertNodeBeforeAndUpdateNodesInserted(refNode.get(), insertionBlock);
-        else if (!insertionBlockIsRoot && fragment.isBlockFlow(refNode.get()) && isEndOfBlock(visiblePos)) {
+        else if (!insertionBlockIsRoot && fragment.isBlockFlow(refNode.get()) && isEndOfBlock(visibleInsertionPos)) {
             insertNodeAfterAndUpdateNodesInserted(refNode.get(), insertionBlock);
         } else if (m_lastNodeInserted && !fragment.isBlockFlow(refNode.get())) {
-            Position pos = visiblePos.next().deepEquivalent().downstream();
+            // A non-null m_lastNodeInserted means we've done merging above.  That means everything in the first paragraph 
+            // of the fragment has been merged with everything up to the start of the paragraph where the paste was performed.  
+            // refNode is the first node in the second paragraph of the fragment to paste.  Since it's inline, we can't 
+            // insert it at insertionPos, because it wouldn't end up in its own paragraph.
+
+            // FIXME: Code above does paragraph splitting and so we are assured that visibleInsertionPos is the end of
+            // a paragraph, but the above splitting should eventually be only about preventing nesting.
+            ASSERT(isEndOfParagraph(visibleInsertionPos));
+            VisiblePosition next = visibleInsertionPos.next();
+            if (next.isNull() || next.deepEquivalent().node()->rootEditableElement() != insertionRoot) {
+                setEndingSelection(visibleInsertionPos);
+                insertParagraphSeparator();
+                next = visibleInsertionPos.next();
+            }
+            
+            Position pos = next.deepEquivalent().downstream();
             insertNodeAtAndUpdateNodesInserted(refNode.get(), pos.node(), pos.offset());
         } else {
             insertNodeAtAndUpdateNodesInserted(refNode.get(), insertionPos.node(), insertionPos.offset());
@@ -789,6 +808,7 @@ void ReplaceSelectionCommand::doApply()
             }
         }
 
+        // FIXME: This is a bad way to move a paragraph.  This could share code with DeleteSelectionCommand::mergeParagraphs().
         if (beyondEndNode) {
             updateLayout();
             RenderingInfoMap renderingInfo;