WebCore:
authorjustin.garcia@apple.com <justin.garcia@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Nov 2007 01:33:52 +0000 (01:33 +0000)
committerjustin.garcia@apple.com <justin.garcia@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Nov 2007 01:33:52 +0000 (01:33 +0000)
        Reviewed by Darin Adler.

        <rdar://problem/5573879> GMail Beta: Crash in when undoing Remove Formating

        In the new beta, Google has added some custom code on top of our RemoveFormat
        to work around a bug where fully selected lists aren't removed.  This code corrupts
        the undo stack and causes crashes.  This change fixes two problems with RemoveFormat
        so that Google doesn't have to have any custom code. After checking this in I'll
        work on bulletproofing the undo stack

        * WebCore.xcodeproj/project.pbxproj:
        * editing/CompositeEditCommand.cpp:
        (WebCore::CompositeEditCommand::insertLineBreak): Added this convenience method.
        (WebCore::CompositeEditCommand::inputText): Added code to select all inserted text, not
        just the last paragraph.  Added code to support an input string with '\n's.
        * editing/CompositeEditCommand.h:
        * editing/Editor.cpp:
        (WebCore::Editor::removeFormattingAndStyle): Moved code to its own EditCommand.
        * editing/RemoveFormatCommand.cpp: Added. Moved code from removeFormattingAndStyle here.
        (WebCore::RemoveFormatCommand::RemoveFormatCommand):
        (WebCore::RemoveFormatCommand::doApply): Added code to remove fully selected lists.
        * editing/RemoveFormatCommand.h: Added.
        (WebCore::RemoveFormatCommand::editingAction):

LayoutTests:

        Reviewed by Darin Adler.

        <rdar://problem/5573879> GMail Beta: Crash in when undoing Remove Formating

        Added to demonstrate fixes:
        * editing/execCommand/5573879.html: Added.
        * platform/mac/editing/execCommand/5573879-expected.checksum: Added.
        * platform/mac/editing/execCommand/5573879-expected.png: Added.
        * platform/mac/editing/execCommand/5573879-expected.txt: Added.

        Fixes (RemoveFormat now preserves the selection correctly):
        * platform/mac/editing/execCommand/4920742-1-expected.checksum:
        * platform/mac/editing/execCommand/4920742-1-expected.png:
        * platform/mac/editing/execCommand/4920742-1-expected.txt:
        * platform/mac/editing/execCommand/remove-formatting-2-expected.checksum:
        * platform/mac/editing/execCommand/remove-formatting-2-expected.png:
        * platform/mac/editing/execCommand/remove-formatting-2-expected.txt:
        * platform/mac/editing/execCommand/remove-formatting-expected.checksum:
        * platform/mac/editing/execCommand/remove-formatting-expected.png:
        * platform/mac/editing/execCommand/remove-formatting-expected.txt:

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

21 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/execCommand/5573879.html [new file with mode: 0644]
LayoutTests/platform/mac/editing/execCommand/4920742-1-expected.checksum
LayoutTests/platform/mac/editing/execCommand/4920742-1-expected.png
LayoutTests/platform/mac/editing/execCommand/4920742-1-expected.txt
LayoutTests/platform/mac/editing/execCommand/5573879-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/editing/execCommand/5573879-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/editing/execCommand/5573879-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/editing/execCommand/remove-formatting-2-expected.checksum
LayoutTests/platform/mac/editing/execCommand/remove-formatting-2-expected.png
LayoutTests/platform/mac/editing/execCommand/remove-formatting-2-expected.txt
LayoutTests/platform/mac/editing/execCommand/remove-formatting-expected.checksum
LayoutTests/platform/mac/editing/execCommand/remove-formatting-expected.png
LayoutTests/platform/mac/editing/execCommand/remove-formatting-expected.txt
WebCore/ChangeLog
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/editing/CompositeEditCommand.cpp
WebCore/editing/CompositeEditCommand.h
WebCore/editing/Editor.cpp
WebCore/editing/RemoveFormatCommand.cpp [new file with mode: 0644]
WebCore/editing/RemoveFormatCommand.h [new file with mode: 0644]

index c29d1ed..45fe41c 100644 (file)
@@ -1,3 +1,26 @@
+2007-11-28  Justin Garcia  <justin.garcia@apple.com>
+
+        Reviewed by Darin Adler.
+        
+        <rdar://problem/5573879> GMail Beta: Crash in when undoing Remove Formating
+
+        Added to demonstrate fixes:
+        * editing/execCommand/5573879.html: Added.
+        * platform/mac/editing/execCommand/5573879-expected.checksum: Added.
+        * platform/mac/editing/execCommand/5573879-expected.png: Added.
+        * platform/mac/editing/execCommand/5573879-expected.txt: Added.
+        
+        Fixes (RemoveFormat now preserves the selection correctly):
+        * platform/mac/editing/execCommand/4920742-1-expected.checksum:
+        * platform/mac/editing/execCommand/4920742-1-expected.png:
+        * platform/mac/editing/execCommand/4920742-1-expected.txt:
+        * platform/mac/editing/execCommand/remove-formatting-2-expected.checksum:
+        * platform/mac/editing/execCommand/remove-formatting-2-expected.png:
+        * platform/mac/editing/execCommand/remove-formatting-2-expected.txt:
+        * platform/mac/editing/execCommand/remove-formatting-expected.checksum:
+        * platform/mac/editing/execCommand/remove-formatting-expected.png:
+        * platform/mac/editing/execCommand/remove-formatting-expected.txt:
+
 2007-11-28  Timothy Hatcher  <timothy@apple.com>
 
         Make this test not depend on the screen size.
diff --git a/LayoutTests/editing/execCommand/5573879.html b/LayoutTests/editing/execCommand/5573879.html
new file mode 100644 (file)
index 0000000..e204d3e
--- /dev/null
@@ -0,0 +1,10 @@
+<p>This tests to make sure that RemoveFormat destroys lists if they are fully selected.  You should see foo\nbar below.</p>
+<div id="div" contenteditable="true"><ul><li>foo</li><li>bar</li></ul></div>
+
+<script>
+div = document.getElementById("div");
+div.focus();
+
+document.execCommand("SelectAll");
+document.execCommand("RemoveFormat");
+</script>
index b246c62..8fcf677 100644 (file)
Binary files a/LayoutTests/platform/mac/editing/execCommand/4920742-1-expected.png and b/LayoutTests/platform/mac/editing/execCommand/4920742-1-expected.png differ
index 07d590d..19455d5 100644 (file)
@@ -13,11 +13,11 @@ layer at (0,0) size 800x600
             text run at (126,18) width 185: "It should be on the last line."
       RenderBlock {DIV} at (0,52) size 784x54
         RenderBlock (anonymous) at (0,0) size 784x0
-        RenderBlock {DIV} at (0,0) size 784x18
+        RenderBlock {DIV} at (0,0) size 784x54
           RenderText {#text} at (0,0) size 21x18
             text run at (0,0) width 21: "foo"
-        RenderBlock {DIV} at (0,18) size 784x18
-          RenderBR {BR} at (0,0) size 0x18
-        RenderBlock {DIV} at (0,36) size 784x18
-          RenderBR {BR} at (0,0) size 0x18
-caret: position 0 of child 0 {BR} of child 2 {DIV} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
+          RenderBR {BR} at (21,14) size 0x0
+          RenderBR {BR} at (0,18) size 0x18
+          RenderBR {BR} at (0,36) size 0x18
+selection start: position 0 of child 0 {#text} of child 0 {DIV} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
+selection end:   position 1 of child 2 {BR} of child 0 {DIV} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
diff --git a/LayoutTests/platform/mac/editing/execCommand/5573879-expected.checksum b/LayoutTests/platform/mac/editing/execCommand/5573879-expected.checksum
new file mode 100644 (file)
index 0000000..e22b826
--- /dev/null
@@ -0,0 +1 @@
+730cd49434a57952e12a9b5e755eb01a
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/editing/execCommand/5573879-expected.png b/LayoutTests/platform/mac/editing/execCommand/5573879-expected.png
new file mode 100644 (file)
index 0000000..c99d7d5
Binary files /dev/null and b/LayoutTests/platform/mac/editing/execCommand/5573879-expected.png differ
diff --git a/LayoutTests/platform/mac/editing/execCommand/5573879-expected.txt b/LayoutTests/platform/mac/editing/execCommand/5573879-expected.txt
new file mode 100644 (file)
index 0000000..da1c527
--- /dev/null
@@ -0,0 +1,18 @@
+layer at (0,0) size 800x600
+  RenderView 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 784x18
+        RenderText {#text} at (0,0) size 720x18
+          text run at (0,0) width 518: "This tests to make sure that RemoveFormat destroys lists if they are fully selected. "
+          text run at (518,0) width 202: "You should see foo\\nbar below."
+      RenderBlock {DIV} at (0,34) size 784x36
+        RenderBlock {DIV} at (0,0) size 784x36
+          RenderText {#text} at (0,0) size 21x18
+            text run at (0,0) width 21: "foo"
+          RenderBR {BR} at (21,14) size 0x0
+          RenderText {#text} at (0,18) size 20x18
+            text run at (0,18) width 20: "bar"
+selection start: position 0 of child 0 {#text} of child 0 {DIV} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
+selection end:   position 3 of child 2 {#text} of child 0 {DIV} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
index 6fd72ce..102ab96 100644 (file)
Binary files a/LayoutTests/platform/mac/editing/execCommand/remove-formatting-2-expected.png and b/LayoutTests/platform/mac/editing/execCommand/remove-formatting-2-expected.png differ
index 57eb008..b4478a6 100644 (file)
@@ -3,10 +3,7 @@ EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 4 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 4 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
 layer at (0,0) size 800x600
index 3978188..3a023bd 100644 (file)
Binary files a/LayoutTests/platform/mac/editing/execCommand/remove-formatting-expected.png and b/LayoutTests/platform/mac/editing/execCommand/remove-formatting-expected.png differ
index 20f434a..0316daf 100644 (file)
@@ -4,25 +4,9 @@ EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotificatio
 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document toDOMRange:range from 0 of #text > B > DIV > BODY > HTML > #document to 3 of #text > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 9 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-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
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 11 of #text > DIV > DIV > BODY > HTML > #document to 11 of #text > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 11 of #text > DIV > DIV > BODY > HTML > #document to 11 of #text > DIV > DIV > BODY > HTML > #document 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
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > DIV > DIV > BODY > HTML > #document to 9 of #text > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
 layer at (0,0) size 800x600
   RenderView at (0,0) size 800x600
 layer at (0,0) size 800x600
@@ -36,15 +20,14 @@ layer at (0,0) size 800x600
             text run at (329,0) width 418: "It demonstrates a bug: everything in the editable region below"
             text run at (0,18) width 576: "should be selected, as everything was selected before Remove Format was performed."
       RenderBlock {DIV} at (0,52) size 784x54
-        RenderBlock (anonymous) at (0,0) size 784x18
-          RenderText {#text} at (0,0) size 63x18
-            text run at (0,0) width 63: "foobarbaz"
-        RenderBlock {DIV} at (0,18) size 784x18
-          RenderText {#text} at (0,0) size 71x18
-            text run at (0,0) width 71: "foo\x{9}bar\x{9}baz"
-        RenderBlock {DIV} at (0,36) size 784x18
-          RenderText {#text} at (0,0) size 63x18
-            text run at (0,0) width 63: "foobarbaz"
+        RenderText {#text} at (0,0) size 63x18
+          text run at (0,0) width 63: "foobarbaz"
+        RenderBR {BR} at (63,14) size 0x0
+        RenderText {#text} at (0,18) size 71x18
+          text run at (0,18) width 71: "foo\x{9}bar\x{9}baz"
+        RenderBR {BR} at (71,32) size 0x0
+        RenderText {#text} at (0,36) size 63x18
+          text run at (0,36) width 63: "foobarbaz"
       RenderBlock {UL} at (0,122) size 784x0
-selection start: position 0 of child 0 {#text} of child 3 {DIV} of child 2 {DIV} of child 1 {BODY} of child 0 {HTML} of document
-selection end:   position 9 of child 0 {#text} of child 3 {DIV} of child 2 {DIV} of child 1 {BODY} of child 0 {HTML} of document
+selection start: position 0 of child 0 {#text} of child 2 {DIV} of child 1 {BODY} of child 0 {HTML} of document
+selection end:   position 9 of child 4 {#text} of child 2 {DIV} of child 1 {BODY} of child 0 {HTML} of document
index cfc4a25..2ad1ce1 100644 (file)
@@ -1,3 +1,29 @@
+2007-11-28  Justin Garcia  <justin.garcia@apple.com>
+
+        Reviewed by Darin Adler.
+
+        <rdar://problem/5573879> GMail Beta: Crash in when undoing Remove Formating
+        
+        In the new beta, Google has added some custom code on top of our RemoveFormat
+        to work around a bug where fully selected lists aren't removed.  This code corrupts
+        the undo stack and causes crashes.  This change fixes two problems with RemoveFormat
+        so that Google doesn't have to have any custom code. After checking this in I'll 
+        work on bulletproofing the undo stack
+
+        * WebCore.xcodeproj/project.pbxproj: 
+        * editing/CompositeEditCommand.cpp:
+        (WebCore::CompositeEditCommand::insertLineBreak): Added this convenience method.
+        (WebCore::CompositeEditCommand::inputText): Added code to select all inserted text, not
+        just the last paragraph.  Added code to support an input string with '\n's.
+        * editing/CompositeEditCommand.h:
+        * editing/Editor.cpp:
+        (WebCore::Editor::removeFormattingAndStyle): Moved code to its own EditCommand.
+        * editing/RemoveFormatCommand.cpp: Added. Moved code from removeFormattingAndStyle here.
+        (WebCore::RemoveFormatCommand::RemoveFormatCommand):
+        (WebCore::RemoveFormatCommand::doApply): Added code to remove fully selected lists.
+        * editing/RemoveFormatCommand.h: Added.
+        (WebCore::RemoveFormatCommand::editingAction):
+
 2007-11-28  Dan Bernstein  <mitz@apple.com>
 
         Reviewed by Dave Hyatt.
index dcc3e49..27419bf 100644 (file)
                C6D74AE409AA290A000B0A52 /* ModifySelectionListLevel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D74AE309AA290A000B0A52 /* ModifySelectionListLevel.cpp */; };
                D05CED290A40BB2C00C5AF38 /* FormatBlockCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D05CED270A40BB2C00C5AF38 /* FormatBlockCommand.cpp */; };
                D05CED2A0A40BB2C00C5AF38 /* FormatBlockCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = D05CED280A40BB2C00C5AF38 /* FormatBlockCommand.h */; };
+               D06C0D8F0CFD11460065F43F /* RemoveFormatCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = D06C0D8D0CFD11460065F43F /* RemoveFormatCommand.h */; };
+               D06C0D900CFD11460065F43F /* RemoveFormatCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D06C0D8E0CFD11460065F43F /* RemoveFormatCommand.cpp */; };
                D07DEAB90A36554A00CA30F8 /* InsertListCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D07DEAB70A36554A00CA30F8 /* InsertListCommand.cpp */; };
                D07DEABA0A36554A00CA30F8 /* InsertListCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = D07DEAB80A36554A00CA30F8 /* InsertListCommand.h */; };
                D086FE9809D53AAB005BC74D /* UnlinkCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = D086FE9609D53AAB005BC74D /* UnlinkCommand.h */; };
                C6D74AE309AA290A000B0A52 /* ModifySelectionListLevel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModifySelectionListLevel.cpp; sourceTree = "<group>"; };
                D05CED270A40BB2C00C5AF38 /* FormatBlockCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FormatBlockCommand.cpp; sourceTree = "<group>"; };
                D05CED280A40BB2C00C5AF38 /* FormatBlockCommand.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FormatBlockCommand.h; sourceTree = "<group>"; };
+               D06C0D8D0CFD11460065F43F /* RemoveFormatCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoveFormatCommand.h; sourceTree = "<group>"; };
+               D06C0D8E0CFD11460065F43F /* RemoveFormatCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoveFormatCommand.cpp; sourceTree = "<group>"; };
                D07DEAB70A36554A00CA30F8 /* InsertListCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = InsertListCommand.cpp; sourceTree = "<group>"; };
                D07DEAB80A36554A00CA30F8 /* InsertListCommand.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = InsertListCommand.h; sourceTree = "<group>"; };
                D086FE9609D53AAB005BC74D /* UnlinkCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnlinkCommand.h; sourceTree = "<group>"; };
                93309D86099E64910056E581 /* editing */ = {
                        isa = PBXGroup;
                        children = (
+                               D06C0D8D0CFD11460065F43F /* RemoveFormatCommand.h */,
+                               D06C0D8E0CFD11460065F43F /* RemoveFormatCommand.cpp */,
                                ED501DC90B249F3900AE18D9 /* mac */,
                                93309D87099E64910056E581 /* AppendNodeCommand.cpp */,
                                93309D88099E64910056E581 /* AppendNodeCommand.h */,
                                93309DF8099E64920056E581 /* markup.h in Headers */,
                                93309E1E099E64920056E581 /* visible_units.h in Headers */,
                                E1BE512E0CF6C512002EA959 /* XSLTUnicodeSort.h in Headers */,
+                               D06C0D8F0CFD11460065F43F /* RemoveFormatCommand.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                93309DF7099E64920056E581 /* markup.cpp in Sources */,
                                93309E1D099E64920056E581 /* visible_units.cpp in Sources */,
                                E1BE512D0CF6C512002EA959 /* XSLTUnicodeSort.cpp in Sources */,
+                               D06C0D900CFD11460065F43F /* RemoveFormatCommand.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 8bbe162..a630d38 100644 (file)
@@ -40,6 +40,7 @@
 #include "HTMLNames.h"
 #include "InlineTextBox.h"
 #include "InsertIntoTextNodeCommand.h"
+#include "InsertLineBreakCommand.h"
 #include "InsertNodeBeforeCommand.h"
 #include "InsertParagraphSeparatorCommand.h"
 #include "InsertTextCommand.h"
@@ -122,6 +123,11 @@ void CompositeEditCommand::insertParagraphSeparator(bool useDefaultParagraphElem
     applyCommandToComposite(new InsertParagraphSeparatorCommand(document(), useDefaultParagraphElement));
 }
 
+void CompositeEditCommand::insertLineBreak()
+{
+    applyCommandToComposite(new InsertLineBreakCommand(document()));
+}
+
 void CompositeEditCommand::insertNodeBefore(Node* insertChild, Node* refChild)
 {
     ASSERT(!refChild->hasTagName(bodyTag));
@@ -262,9 +268,29 @@ void CompositeEditCommand::joinTextNodes(Text *text1, Text *text2)
 
 void CompositeEditCommand::inputText(const String &text, bool selectInsertedText)
 {
-    RefPtr<InsertTextCommand> command = new InsertTextCommand(document());
-    applyCommandToComposite(command);
-    command->input(text, selectInsertedText);
+    int offset = 0;
+    int length = text.length();
+    RefPtr<Range> startRange = new Range(document(), Position(document()->documentElement(), 0), endingSelection().start());
+    int startIndex = TextIterator::rangeLength(startRange.get());
+    int newline;
+    do {
+        newline = text.find('\n', offset);
+        if (newline != offset) {
+            RefPtr<InsertTextCommand> command = new InsertTextCommand(document());
+            applyCommandToComposite(command);
+            int substringLength = newline == -1 ? length - offset : newline - offset;
+            command->input(text.substring(offset, substringLength), false);
+        }
+        if (newline != -1)
+            insertLineBreak();
+            
+        offset = newline + 1;
+    } while (newline != -1 && offset != length);
+    
+    if (selectInsertedText) {
+        RefPtr<Range> selectedRange = TextIterator::rangeFromLocationAndLength(document()->documentElement(), startIndex, length);
+        setEndingSelection(Selection(selectedRange.get()));
+    }
 }
 
 void CompositeEditCommand::insertTextIntoNode(Text *node, int offset, const String &text)
index 23e7f71..e099fcf 100644 (file)
@@ -58,6 +58,7 @@ protected:
     void insertNodeAt(Node* insertChild, const Position&);
     void insertNodeBefore(Node* insertChild, Node* refChild);
     void insertParagraphSeparator(bool useDefaultParagraphElement = false);
+    void insertLineBreak();
     void insertTextIntoNode(Text* node, int offset, const String& text);
     void joinTextNodes(Text*, Text*);
     void rebalanceWhitespace();
index d2c2035..de27ff5 100644 (file)
@@ -61,6 +61,7 @@
 #include "Page.h"
 #include "Pasteboard.h"
 #include "Range.h"
+#include "RemoveFormatCommand.h"
 #include "ReplaceSelectionCommand.h"
 #include "SelectionController.h"
 #include "Sound.h"
@@ -581,27 +582,7 @@ void Editor::decreaseSelectionListLevel()
 
 void Editor::removeFormattingAndStyle()
 {
-    Document* document = m_frame->document();
-    
-    // Make a plain text string from the selection to remove formatting like tables and lists.
-    String string = plainText(m_frame->selectionController()->selection().toRange().get());
-
-    // Get the default style for this editable root, it's the style that we'll give the
-    // content that we're operating on.
-    Node* root = m_frame->selectionController()->rootEditableElement();
-    RefPtr<CSSComputedStyleDeclaration> computedStyle = new CSSComputedStyleDeclaration(root);
-    RefPtr<CSSMutableStyleDeclaration> defaultStyle = computedStyle->copyInheritableProperties();
-    
-    // Delete the selected content.
-    // FIXME: We should be able to leave this to insertText, but its delete operation
-    // doesn't preserve the style we're about to set.
-    deleteSelectionWithSmartDelete(false);
-    // Normally, deleting a fully selected anchor and then inserting text will re-create
-    // the removed anchor, but we don't want that behavior here. 
-    setRemovedAnchor(0);
-    // Insert the content with the default style.
-    m_frame->setTypingStyle(defaultStyle.get());
-    TypingCommand::insertText(document, string, true);
+    applyCommand(new RemoveFormatCommand(m_frame->document()));
 }
 
 void Editor::setLastEditCommand(PassRefPtr<EditCommand> lastEditCommand) 
diff --git a/WebCore/editing/RemoveFormatCommand.cpp b/WebCore/editing/RemoveFormatCommand.cpp
new file mode 100644 (file)
index 0000000..57f526a
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2007 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "RemoveFormatCommand.h"
+
+#include "CSSComputedStyleDeclaration.h"
+#include "Editor.h"
+#include "Frame.h"
+#include "HTMLNames.h"
+#include "Selection.h"
+#include "SelectionController.h"
+#include "TextIterator.h"
+#include "TypingCommand.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RemoveFormatCommand::RemoveFormatCommand(Document* document)
+    : CompositeEditCommand(document)
+{
+}
+
+void RemoveFormatCommand::doApply()
+{
+    Frame* frame = document()->frame();
+    
+    // Make a plain text string from the selection to remove formatting like tables and lists.
+    String string = plainText(frame->selectionController()->selection().toRange().get());
+
+    // Get the default style for this editable root, it's the style that we'll give the
+    // content that we're operating on.
+    Node* root = frame->selectionController()->rootEditableElement();
+    RefPtr<CSSComputedStyleDeclaration> computedStyle = new CSSComputedStyleDeclaration(root);
+    RefPtr<CSSMutableStyleDeclaration> defaultStyle = computedStyle->copyInheritableProperties();
+    
+    // Delete the selected content.
+    // FIXME: We should be able to leave this to insertText, but its delete operation
+    // doesn't preserve the style we're about to set.
+    deleteSelection();
+    
+    // Delete doesn't remove fully selected lists.
+    while (breakOutOfEmptyListItem())
+        ;
+    
+    // Normally, deleting a fully selected anchor and then inserting text will re-create
+    // the removed anchor, but we don't want that behavior here. 
+    frame->editor()->setRemovedAnchor(0);
+    // Insert the content with the default style.
+    frame->setTypingStyle(defaultStyle.get());
+    
+    inputText(string, true);
+}
+
+}
diff --git a/WebCore/editing/RemoveFormatCommand.h b/WebCore/editing/RemoveFormatCommand.h
new file mode 100644 (file)
index 0000000..a6df271
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2007 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef RemoveFormatCommand_h
+#define RemoveFormatCommand_h
+
+#include "CompositeEditCommand.h"
+
+namespace WebCore {
+
+class RemoveFormatCommand : public CompositeEditCommand {
+public:
+    RemoveFormatCommand(Document*);
+    virtual void doApply();
+    virtual EditAction editingAction() const { return EditActionUnspecified; }
+};
+
+} // namespace WebCore
+
+#endif // RemoveFormatCommand_h