LayoutTests:
authorjusting <justing@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 25 Mar 2006 10:17:39 +0000 (10:17 +0000)
committerjusting <justing@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 25 Mar 2006 10:17:39 +0000 (10:17 +0000)
        Reviewed by harrison

        <http://bugzilla.opendarwin.org/show_bug.cgi?id=7683>
        TinyMCE: execCommand("Unlink") unimplemented

        * editing/editing.js:
        * editing/execCommand/createLink-expected.checksum: Removed.
        * editing/execCommand/createLink-expected.png: Removed.
        * editing/execCommand/createLink-expected.txt:
        * editing/execCommand/createLink.html:
        * editing/execCommand/unlink-expected.txt: Added.
        * editing/execCommand/unlink.html: Added.

WebCore:

        Reviewed by harrison

        <http://bugzilla.opendarwin.org/show_bug.cgi?id=7683>
        TinyMCE: execCommand("Unlink") unimplemented

        Added code to push partially selected anchor elements down before
        creating or removing links to create fully selected chunks that can be removed.
        Changed __create_link_command_h__ to CreateLinkCommand_h
        Gave styled element application/removal its own ApplyStyleCommand constructor.
        Still need to add new EditActions (7974).

        * WebCore.xcodeproj/project.pbxproj:
        * editing/ApplyStyleCommand.cpp:
        (WebCore::ApplyStyleCommand::ApplyStyleCommand):
        (WebCore::ApplyStyleCommand::applyBlockStyle):
        (WebCore::ApplyStyleCommand::addInlineStyleIfNeeded):
        * editing/ApplyStyleCommand.h:
        * editing/CompositeEditCommand.cpp:
        (WebCore::CompositeEditCommand::applyStyle):
        (WebCore::CompositeEditCommand::applyStyledElement):
        (WebCore::CompositeEditCommand::removeStyledElement):
        (WebCore::enclosingAnchorElement):
        (WebCore::CompositeEditCommand::pushAnchorElementDown):
        (WebCore::CompositeEditCommand::pushPartiallySelectedAnchorElementsDown):
        * editing/CompositeEditCommand.h:
        * editing/CreateLinkCommand.cpp:
        (WebCore::CreateLinkCommand::doApply):
        * editing/CreateLinkCommand.h:
        * editing/JSEditor.cpp:
        * editing/Selection.cpp:
        (WebCore::Selection::selectionFromContentsOfNode):
        * editing/Selection.h:
        * editing/UnlinkCommand.cpp: Added.
        (WebCore::UnlinkCommand::UnlinkCommand):
        (WebCore::UnlinkCommand::doApply):
        * editing/UnlinkCommand.h: Added.
        * page/Frame.cpp:
        (WebCore::Frame::selectContentsOfNode):
        (WebCore::Frame::computeAndSetTypingStyle):
        (WebCore::Frame::applyStyle):
        (WebCore::Frame::applyParagraphStyle):

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

22 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/editing.js
LayoutTests/editing/execCommand/createLink-expected.checksum [deleted file]
LayoutTests/editing/execCommand/createLink-expected.png [deleted file]
LayoutTests/editing/execCommand/createLink-expected.txt
LayoutTests/editing/execCommand/createLink.html
LayoutTests/editing/execCommand/unlink-expected.txt [new file with mode: 0644]
LayoutTests/editing/execCommand/unlink.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/editing/ApplyStyleCommand.cpp
WebCore/editing/ApplyStyleCommand.h
WebCore/editing/CompositeEditCommand.cpp
WebCore/editing/CompositeEditCommand.h
WebCore/editing/CreateLinkCommand.cpp
WebCore/editing/CreateLinkCommand.h
WebCore/editing/JSEditor.cpp
WebCore/editing/Selection.cpp
WebCore/editing/Selection.h
WebCore/editing/UnlinkCommand.cpp [new file with mode: 0644]
WebCore/editing/UnlinkCommand.h [new file with mode: 0644]
WebCore/page/Frame.cpp

index 2c24d767072798407a0a3b5c61d91bd42b61f01b..3576050654fbaf2c0dc0b4b944a3a328f793fa11 100644 (file)
@@ -1,3 +1,18 @@
+2006-03-25  Justin Garcia  <justin.garcia@apple.com>
+
+        Reviewed by harrison
+        
+        <http://bugzilla.opendarwin.org/show_bug.cgi?id=7683>
+        TinyMCE: execCommand("Unlink") unimplemented
+
+        * editing/editing.js:
+        * editing/execCommand/createLink-expected.checksum: Removed.
+        * editing/execCommand/createLink-expected.png: Removed.
+        * editing/execCommand/createLink-expected.txt:
+        * editing/execCommand/createLink.html:
+        * editing/execCommand/unlink-expected.txt: Added.
+        * editing/execCommand/unlink.html: Added.
+
 2006-03-24  Justin Garcia  <justin.garcia@apple.com>
 
         Reviewed by harrison
index 19dd1c46361da935a36ca1290d495d06c563eaea..0ee507726c0a1667d8ba9230b3cc982b74683bed 100644 (file)
@@ -565,10 +565,21 @@ function createLinkCommand(url) {
     if (commandDelay > 0) {
         window.setTimeout(execCreateLinkCommand, commandCount * commandDelay, url);
         commandCount++;
-    }
-    else {
+    } else
         execCreateLinkCommand(url);
-    }
+}
+
+//-------------------------------------------------------------------------------------------------------
+
+function execUnlinkCommand() {
+    document.execCommand("Unlink");
+}
+function unlinkCommand() {
+    if (commandDelay > 0) {
+        window.setTimeout(execUnlinkCommand, commandCount * commandDelay);
+        commandCount++;
+    } else
+        execUnlinkCommand();
 }
 
 //-------------------------------------------------------------------------------------------------------
diff --git a/LayoutTests/editing/execCommand/createLink-expected.checksum b/LayoutTests/editing/execCommand/createLink-expected.checksum
deleted file mode 100644 (file)
index afa96d7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-37f870a43e281e15227a3bc47347325d
\ No newline at end of file
diff --git a/LayoutTests/editing/execCommand/createLink-expected.png b/LayoutTests/editing/execCommand/createLink-expected.png
deleted file mode 100644 (file)
index c714f42..0000000
Binary files a/LayoutTests/editing/execCommand/createLink-expected.png and /dev/null differ
index 02b6733df4260bebbef6e2f82bb9409d6faf21af..577072e458ee4f3ea0817715ee325df9d5c36cce 100644 (file)
@@ -12,7 +12,7 @@ EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 4 of #text > A > DIV > LI > OL > BODY > HTML > #document to 14 of #text > A > DIV > LI > OL > BODY > HTML > #document toDOMRange:range from 0 of #text > A > DIV > LI > OL > BODY > HTML > #document to 10 of #text > A > DIV > LI > OL > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > A > DIV > LI > OL > BODY > HTML > #document to 10 of #text > A > DIV > LI > OL > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
 EDITING DELEGATE: shouldEndEditingInDOMRange:range from 0 of DIV > LI > OL > BODY > HTML > #document to 3 of DIV > LI > OL > BODY > HTML > #document
@@ -21,10 +21,10 @@ EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > LI > OL > B
 EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > A > SPAN > A > DIV > LI > OL > BODY > HTML > #document to 121 of #text > A > DIV > LI > OL > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > A > SPAN > DIV > LI > OL > BODY > HTML > #document to 121 of #text > A > DIV > LI > OL > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-EDITING DELEGATE: shouldEndEditingInDOMRange:range from 0 of DIV > LI > OL > BODY > HTML > #document to 3 of DIV > LI > OL > BODY > HTML > #document
+EDITING DELEGATE: shouldEndEditingInDOMRange:range from 0 of DIV > LI > OL > BODY > HTML > #document to 4 of DIV > LI > OL > BODY > HTML > #document
 EDITING DELEGATE: webViewDidEndEditing:WebViewDidEndEditingNotification
 EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > LI > OL > BODY > HTML > #document to 13 of DIV > LI > OL > BODY > HTML > #document
 EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
@@ -34,158 +34,26 @@ EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotificatio
 EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > A > P > DIV > LI > OL > BODY > HTML > #document to 10 of #text > A > DIV > LI > OL > 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 784x580
-      RenderBlock {P} at (0,0) size 784x14
-        RenderText {TEXT} at (0,0) size 260x14
-          text run at (0,0) width 226: "This is a test of execCommand(CreateLink, ...). "
-          text run at (226,0) width 34: "It tests:"
-      RenderBlock {OL} at (0,26) size 784x56
-        RenderListItem {LI} at (40,0) size 744x14
-          RenderListMarker at (0,0) size 0x11
-          RenderText {TEXT} at (0,0) size 279x14
-            text run at (0,0) width 279: "Creating a link from a selection that is completely unlinked."
-        RenderListItem {LI} at (40,14) size 744x14
-          RenderListMarker at (0,0) size 0x11
-          RenderText {TEXT} at (0,0) size 287x14
-            text run at (0,0) width 287: "Creating a link from a selection that is inside an existing link."
-        RenderListItem {LI} at (40,28) size 744x14
-          RenderListMarker at (0,0) size 0x11
-          RenderText {TEXT} at (0,0) size 254x14
-            text run at (0,0) width 254: "Creating a link from a selection that is partially linked."
-        RenderListItem {LI} at (40,42) size 744x14
-          RenderListMarker at (0,0) size 0x11
-          RenderText {TEXT} at (0,0) size 380x14
-            text run at (0,0) width 380: "Creating a link from a selection that contains lists, tables, styled text, and images."
-      RenderBlock {OL} at (0,94) size 784x256
-        RenderListItem {LI} at (40,0) size 744x14
-          RenderBlock {DIV} at (0,0) size 744x14
-            RenderListMarker at (0,0) size 0x11
-            RenderInline {A} at (0,0) size 447x14 [color=#0000EE]
-              RenderText {TEXT} at (0,0) size 447x14
-                text run at (0,0) width 149: "This paragraph starts unlinked. "
-                text run at (149,0) width 298: "The entire paragraph should end up being a link to google.com."
-        RenderListItem {LI} at (40,14) size 744x14
-          RenderBlock {DIV} at (0,0) size 744x14
-            RenderListMarker at (0,0) size 0x11
-            RenderInline {A} at (0,0) size 21x14 [color=#0000EE]
-              RenderText {TEXT} at (0,0) size 21x14
-                text run at (0,0) width 21: "This"
-            RenderInline {A} at (0,0) size 50x14 [color=#0000EE]
-              RenderText {TEXT} at (21,0) size 50x14
-                text run at (21,0) width 50: " paragraph"
-            RenderInline {A} at (0,0) size 519x14 [color=#0000EE]
-              RenderText {TEXT} at (71,0) size 519x14
-                text run at (71,0) width 157: " starts out as a link to apple.com. "
-                text run at (228,0) width 362: "The second word in the paragraph should end up being a link to google.com."
-        RenderListItem {LI} at (40,28) size 744x14
-          RenderBlock {DIV} at (0,0) size 744x14
-            RenderListMarker at (0,0) size 0x11
-            RenderText {TEXT} at (0,0) size 114x14
-              text run at (0,0) width 114: "This line starts out with "
-            RenderInline {A} at (0,0) size 27x14 [color=#0000EE]
-              RenderInline {B} at (0,0) size 6x14
-                RenderText {TEXT} at (114,0) size 6x14
-                  text run at (114,0) width 6: "a"
-              RenderInline {SPAN} at (0,0) size 21x14
-                RenderInline {A} at (0,0) size 21x14
-                  RenderText {TEXT} at (120,0) size 21x14
-                    text run at (120,0) width 21: " link"
-            RenderInline {A} at (0,0) size 547x14 [color=#0000EE]
-              RenderText {TEXT} at (141,0) size 547x14
-                text run at (141,0) width 70: " in the middle. "
-                text run at (211,0) width 477: "The second half of this paragraph, starting after the bold 'a' should end up being a link to google.com."
-        RenderListItem {LI} at (40,54) size 744x202
-          RenderBlock {DIV} at (0,0) size 744x202
-            RenderBlock {P} at (0,0) size 744x14
-              RenderListMarker at (0,0) size 0x11
-              RenderInline {A} at (0,0) size 24x14 [color=#0000EE]
-                RenderText {TEXT} at (0,0) size 24x14
-                  text run at (0,0) width 24: "This "
-              RenderInline {I} at (0,0) size 71x14
-                RenderInline {A} at (0,0) size 71x14 [color=#0000EE]
-                  RenderText {TEXT} at (24,0) size 71x14
-                    text run at (24,0) width 71: "editable region"
-              RenderInline {A} at (0,0) size 497x14 [color=#0000EE]
-                RenderText {TEXT} at (95,0) size 497x14
-                  text run at (95,0) width 216: " contains lists, tables, styled text, and images. "
-                  text run at (311,0) width 281: "The entire region should end up being a link to google.com."
-            RenderBlock {UL} at (0,26) size 744x28
-              RenderListItem {LI} at (40,0) size 704x14
-                RenderListMarker at (0,0) size 0x11
-                RenderInline {A} at (0,0) size 30x14 [color=#0000EE]
-                  RenderText {TEXT} at (0,0) size 30x14
-                    text run at (0,0) width 30: "Item 1"
-              RenderListItem {LI} at (40,14) size 704x14
-                RenderListMarker at (0,0) size 0x11
-                RenderInline {A} at (0,0) size 30x14 [color=#0000EE]
-                  RenderText {TEXT} at (0,0) size 30x14
-                    text run at (0,0) width 30: "Item 2"
-            RenderTable {TABLE} at (0,54) size 46x28 [border: (1px outset #808080)]
-              RenderTableSection {TBODY} at (1,1) size 0x26
-                RenderTableRow {TR} at (0,0) size 0x0
-                  RenderTableCell {TD} at (2,2) size 12x22 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
-                    RenderInline {A} at (0,0) size 8x18 [color=#0000EE]
-                      RenderText {TEXT} at (2,2) size 8x18
-                        text run at (2,2) width 8: "1"
-                  RenderTableCell {TD} at (16,2) size 12x22 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
-                    RenderInline {A} at (0,0) size 8x18 [color=#0000EE]
-                      RenderText {TEXT} at (2,2) size 8x18
-                        text run at (2,2) width 8: "2"
-                  RenderTableCell {TD} at (30,2) size 12x22 [border: (1px inset #808080)] [r=0 c=2 rs=1 cs=1]
-                    RenderInline {A} at (0,0) size 8x18 [color=#0000EE]
-                      RenderText {TEXT} at (2,2) size 8x18
-                        text run at (2,2) width 8: "3"
-            RenderBlock (anonymous) at (0,82) size 744x120
-              RenderInline {A} at (0,0) size 24x120 [color=#0000EE]
-                RenderBR {BR} at (0,0) size 0x14
-                RenderText {TEXT} at (0,106) size 24x14
-                  text run at (0,106) width 24: "This "
-              RenderInline {B} at (0,0) size 18x14
-                RenderInline {A} at (0,0) size 18x14 [color=#0000EE]
-                  RenderText {TEXT} at (24,106) size 18x14
-                    text run at (24,106) width 18: "line"
-              RenderInline {A} at (0,0) size 45x14 [color=#0000EE]
-                RenderText {TEXT} at (42,106) size 45x14
-                  text run at (42,106) width 45: " contains "
-              RenderInline {A} at (0,0) size 124x14 [color=#0000EE]
-                RenderImage {IMG} at (87,14) size 76x103
-                RenderText {TEXT} at (163,106) size 48x14
-                  text run at (163,106) width 48: " an image."
-      RenderBlock {P} at (0,362) size 784x14
-        RenderText {TEXT} at (0,0) size 211x14
-          text run at (0,0) width 211: "innerHTML of editable regions after the test:"
-      RenderBlock {OL} at (0,388) size 784x168
-        RenderListItem {LI} at (40,0) size 744x14
-          RenderListMarker at (0,0) size 0x11
-          RenderText {TEXT} at (0,0) size 650x14
-            text run at (0,0) width 326: "<A href=\"http://www.google.com/\">This paragraph starts unlinked. "
-            text run at (326,0) width 324: "The entire paragraph should end up being a link to google.com.</A>"
-        RenderListItem {LI} at (40,14) size 744x28
-          RenderListMarker at (0,0) size 0x11
-          RenderText {TEXT} at (0,0) size 740x28
-            text run at (0,0) width 740: "<A href=\"http://www.apple.com/\">This</A><A href=\"http://www.google.com/\"> paragraph</A><A href=\"http://www.apple.com/\"> starts out as a link to"
-            text run at (0,14) width 54: "apple.com. "
-            text run at (54,14) width 388: "The second word in the paragraph should end up being a link to google.com.</A>"
-        RenderListItem {LI} at (40,42) size 744x28
-          RenderListMarker at (0,0) size 0x11
-          RenderText {TEXT} at (0,0) size 740x28
-            text run at (0,0) width 740: "<A href=\"http://www.apple.com/\">This</A><A href=\"http://www.google.com/\"> paragraph</A><A href=\"http://www.apple.com/\"> starts out as a link to"
-            text run at (0,14) width 54: "apple.com. "
-            text run at (54,14) width 388: "The second word in the paragraph should end up being a link to google.com.</A>"
-        RenderListItem {LI} at (40,70) size 744x98
-          RenderListMarker at (0,0) size 0x11
-          RenderText {TEXT} at (0,0) size 736x98
-            text run at (0,0) width 736: "<P><A href=\"http://www.google.com/\">This </A><I><A href=\"http://www.google.com/\">editable region</A></I><A href=\"http://www.google.com/\">"
-            text run at (0,14) width 213: "contains lists, tables, styled text, and images. "
-            text run at (213,14) width 408: "The entire region should end up being a link to google.com.</A></P> <UL> <LI><A"
-            text run at (0,28) width 615: "href=\"http://www.google.com/\">Item 1</A></LI> <LI><A href=\"http://www.google.com/\">Item 2</A></LI> </UL> <TABLE"
-            text run at (0,42) width 736: "border=\"1\"><TBODY><TR><TD><A href=\"http://www.google.com/\">1</A></TD><TD><A href=\"http://www.google.com/\">2</A></TD><TD><A"
-            text run at (0,56) width 670: "href=\"http://www.google.com/\">3</A></TD></TR></TBODY></TABLE> <A href=\"http://www.google.com/\"><BR> This </A><B><A"
-            text run at (0,70) width 682: "href=\"http://www.google.com/\">line</A></B><A href=\"http://www.google.com/\"> contains </A><A href=\"http://www.google.com/\"><IMG"
-            text run at (0,84) width 206: "src=\"../resources/abe.jpg\"> an image. </A>"
-selection start: position 0 of child 0 {TEXT} of child 0 {A} of child 1 {P} of child 0 {DIV} of child 7 {LI} of child 5 {OL} of child 1 {BODY} of child 0 {HTML} of document
-selection end:   position 10 of child 1 {TEXT} of child 10 {A} of child 0 {DIV} of child 7 {LI} of child 5 {OL} of child 1 {BODY} of child 0 {HTML} of document
+This is a test of execCommand(CreateLink, ...). It tests:
+
+Creating a link from a selection that is completely unlinked.
+Creating a link from a selection that is inside an existing link.
+Creating a link from a selection that is partially linked.
+Creating a link from a selection that contains lists, tables, styled text, and images.
+This paragraph starts unlinked. The entire paragraph should end up being a link to google.com.
+This paragraph starts out as a link to apple.com. The second word in the paragraph should end up being a link to google.com.
+This line starts out with a link in the middle. The second half of this paragraph, starting after the bold 'a' should end up being a link to google.com.
+This editable region contains lists, tables, styled text, and images. The entire region should end up being a link to google.com.
+
+Item 1
+Item 2
+1      2       3
+
+This line contains  an image.
+innerHTML of editable regions after the test:
+
+<A href="http://www.google.com/">This paragraph starts unlinked. The entire paragraph should end up being a link to google.com.</A>
+<A href="http://www.apple.com/">This</A><A href="http://www.google.com/"> paragraph</A><A href="http://www.apple.com/"> starts out as a link to apple.com. The second word in the paragraph should end up being a link to google.com.</A>
+<A href="http://www.apple.com/">This</A><A href="http://www.google.com/"> paragraph</A><A href="http://www.apple.com/"> starts out as a link to apple.com. The second word in the paragraph should end up being a link to google.com.</A>
+<P><A href="http://www.google.com/">This </A><I><A href="http://www.google.com/">editable region</A></I><A href="http://www.google.com/"> contains lists, tables, styled text, and images. The entire region should end up being a link to google.com.</A></P> <UL> <LI><A href="http://www.google.com/">Item 1</A></LI> <LI><A href="http://www.google.com/">Item 2</A></LI> </UL> <TABLE border="1"><TBODY><TR><TD><A href="http://www.google.com/">1</A></TD><TD><A href="http://www.google.com/">2</A></TD><TD><A href="http://www.google.com/">3</A></TD></TR></TBODY></TABLE> <A href="http://www.google.com/"><BR> This </A><B><A href="http://www.google.com/">line</A></B><A href="http://www.google.com/"> contains </A><A href="http://www.google.com/"><IMG src="../resources/abe.jpg"> an image. </A>
+
index 29239ffcc811440dfb683f15fa627f2e3fe1cd4d..0416785f7a243ba6567d5677d894ee3096ca5dce 100644 (file)
@@ -15,6 +15,9 @@ function editingTest() {
     var s = window.getSelection();
     var d;
     
+    if (window.layoutTestController)
+        window.layoutTestController.dumpAsText();
+    
     // Fully select the line in the first div.
     d = document.getElementById("test1");
     s.setPosition(d, 0);
diff --git a/LayoutTests/editing/execCommand/unlink-expected.txt b/LayoutTests/editing/execCommand/unlink-expected.txt
new file mode 100644 (file)
index 0000000..ebd0b4b
--- /dev/null
@@ -0,0 +1,65 @@
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > LI > OL > BODY > HTML > #document to 1 of DIV > LI > OL > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > DIV > LI > OL > BODY > HTML > #document to 45 of #text > DIV > LI > OL > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldEndEditingInDOMRange:range from 0 of DIV > LI > OL > BODY > HTML > #document to 1 of DIV > LI > OL > BODY > HTML > #document
+EDITING DELEGATE: webViewDidEndEditing:WebViewDidEndEditingNotification
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > LI > OL > BODY > HTML > #document to 1 of DIV > LI > OL > 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 0 of #text > DIV > LI > OL > BODY > HTML > #document to 7 of #text > DIV > LI > OL > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldEndEditingInDOMRange:range from 0 of DIV > LI > OL > BODY > HTML > #document to 3 of DIV > LI > OL > BODY > HTML > #document
+EDITING DELEGATE: webViewDidEndEditing:WebViewDidEndEditingNotification
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > LI > OL > BODY > HTML > #document to 3 of DIV > LI > OL > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > SPAN > DIV > LI > OL > BODY > HTML > #document to 87 of #text > DIV > LI > OL > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldEndEditingInDOMRange:range from 0 of DIV > LI > OL > BODY > HTML > #document to 4 of DIV > LI > OL > BODY > HTML > #document
+EDITING DELEGATE: webViewDidEndEditing:WebViewDidEndEditingNotification
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > LI > OL > BODY > HTML > #document to 13 of DIV > LI > OL > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of P > DIV > LI > OL > BODY > HTML > #document to 0 of P > DIV > LI > OL > BODY > HTML > #document toDOMRange:range from 0 of #text > P > DIV > LI > OL > BODY > HTML > #document to 10 of #text > DIV > LI > OL > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > A > P > DIV > LI > OL > BODY > HTML > #document to 10 of #text > A > DIV > LI > OL > 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 > P > DIV > LI > OL > BODY > HTML > #document to 0 of TD > TR > TBODY > TABLE > DIV > LI > OL > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+This is a test of execCommand("Unlink"). It tests:
+
+Completely unlinking a link.
+Unlinking a single word inside of a link.
+Unlinking a selection containing linked and unlinked text.
+Unlinking a selection that partially selects a linked table.
+The editable regions below describe what their content should be after the test.
+
+This paragraph should should end up unlinked.
+The second word in this paragraph should end up being unlinked, everything else should be a link.
+This paragraph starts with a link in the middle. Only the 'a' in the previous sentence should be linked after the test.
+This editable region contains lists, tables, styled text, and images. Everything in this region that is not selected should be a link, nothing that is selected should be a link.
+
+Item 1
+Item 2
+1      2       3
+
+This line contains  an image.
+The innerHTML of editable regions after the test:
+
+This paragraph should should end up unlinked.
+<A href="http://www.apple.com/">The</A> second<A href="http://www.apple.com/"> word in this paragraph should end up being unlinked, everything else should be a link.</A>
+This paragraph starts with <I><A href="http://www.google.com">a</A></I><SPAN id="test3start"> link</SPAN> in the middle. Only the 'a' in the previous sentence should be linked after the test.
+<P>This <I>editable region</I> contains lists, tables, styled text, and images. Everything in this region that is not selected should be a link, nothing that is selected should be a link.</P> <UL> <LI>Item 1</LI> <LI>Item 2</LI> </UL> <TABLE border="1"><TBODY><TR><TD>1</TD><TD>2</TD><TD><SPAN id="test4end"><A href="http://www.google.com/">3</A></SPAN></TD></TR></TBODY></TABLE> <A href="http://www.google.com/"><BR> This </A><B><A href="http://www.google.com/">line</A></B><A href="http://www.google.com/"> contains </A><A href="http://www.google.com/"><IMG src="../resources/abe.jpg"> an image. </A>
+
diff --git a/LayoutTests/editing/execCommand/unlink.html b/LayoutTests/editing/execCommand/unlink.html
new file mode 100644 (file)
index 0000000..d6f08b3
--- /dev/null
@@ -0,0 +1,94 @@
+<html>
+<head>
+<script src=../editing.js language="JavaScript" type="text/JavaScript"></script>
+<script>
+function log(message) {
+    var console = document.getElementById("console");
+    var li = document.createElement("li");
+    var text = document.createTextNode(message);
+    li.appendChild(text);
+    console.appendChild(li);
+}
+
+function editingTest() {
+        
+    var s = window.getSelection();
+    var d;
+    
+    if (window.layoutTestController)
+        window.layoutTestController.dumpAsText();
+    
+    // Fully select the line in the first div.
+    d = document.getElementById("test1");
+    s.setPosition(d, 0);
+    extendSelectionForwardByLineCommand();
+    unlinkCommand();
+    
+    log(d.innerHTML);
+
+    // Select the second word in the second div  
+    d = document.getElementById("test2");
+    s.setPosition(d, 0);
+    moveSelectionForwardByWordCommand();
+    extendSelectionForwardByWordCommand();
+    unlinkCommand();
+    
+    log(d.innerHTML);
+    
+    // Select part of a link (and a bit of trailing non-linked text)
+    d = document.getElementById("test3");
+    var e = document.getElementById("test3start");
+    s.setPosition(e, 0);
+    extendSelectionForwardByLineCommand();
+    unlinkCommand();
+    
+    log(d.innerHTML);
+    
+    // Link an editable region containing lists, tables, images, etc.
+    d = document.getElementById("test4");
+    s.setPosition(d, 0);
+    selectAllCommand();
+    createLinkCommand("http://www.google.com/");
+    // Now unlink a portion of it
+    var end = document.getElementById("test4end");
+    s.setBaseAndExtent(d, 0, end, 0);
+    unlinkCommand();
+    
+    log(d.innerHTML);
+    
+}
+</script>
+</head>
+
+<body style="font-size: 12px;">
+<p>This is a test of execCommand("Unlink").  It tests:</p>
+<ol>
+<li>Completely unlinking a link.</li>
+<li>Unlinking a single word inside of a link.</li>
+<li>Unlinking a selection containing linked and unlinked text.</li>
+<li>Unlinking a selection that partially selects a linked table.</li>
+</ol>
+<p>The editable regions below describe what their content should be after the test.</p>
+<ol>
+<li><div id="test1" contenteditable="true"><a href="http://www.apple.com/">This paragraph should should end up unlinked.</a></div></li>
+<li><div id="test2" contenteditable="true"><a href="http://www.apple.com/">The second word in this paragraph should end up being unlinked, everything else should be a link.</a></div></li>
+<li><div id="test3" contenteditable="true">This paragraph starts with <a href="http://www.google.com"><i>a</i><span id="test3start"> link</span></a> in the middle.  Only the 'a' in the previous sentence should be linked after the test.</div></li>
+<li><div id="test4" contenteditable="true">
+<p>This <i>editable region</i> contains lists, tables, styled text, and images.  Everything in this region that is not selected should be a link, nothing that is selected should be a link.</p>
+<ul>
+<li>Item 1</li>
+<li>Item 2</li>
+</ul>
+<table border=1><tr><td>1</td><td>2</td><td><span id="test4end">3</span></td></tr></table>
+<br>
+This <b>line</b> contains <img src="../resources/abe.jpg"> an image.
+</div></li>
+</ol>
+<p>The innerHTML of editable regions after the test:</p>
+<ol id="console"></ol>
+<script>
+runEditingTest();
+</script>
+</body>
+
+</html>
\ No newline at end of file
index 9ffadcc0b1a44937b29eeb8d03666b6621fcc0e3..39b469645152328d57a45b518142ef59361e7fa9 100644 (file)
@@ -1,3 +1,47 @@
+2006-03-25  Justin Garcia  <justin.garcia@apple.com>
+
+        Reviewed by harrison
+        
+        <http://bugzilla.opendarwin.org/show_bug.cgi?id=7683>
+        TinyMCE: execCommand("Unlink") unimplemented
+        
+        Added code to push partially selected anchor elements down before 
+        creating or removing links to create fully selected chunks that can be removed.
+        Changed __create_link_command_h__ to CreateLinkCommand_h
+        Gave styled element application/removal its own ApplyStyleCommand constructor.
+        Still need to add new EditActions (7974).
+        
+        * WebCore.xcodeproj/project.pbxproj:
+        * editing/ApplyStyleCommand.cpp:
+        (WebCore::ApplyStyleCommand::ApplyStyleCommand):
+        (WebCore::ApplyStyleCommand::applyBlockStyle):
+        (WebCore::ApplyStyleCommand::addInlineStyleIfNeeded):
+        * editing/ApplyStyleCommand.h:
+        * editing/CompositeEditCommand.cpp:
+        (WebCore::CompositeEditCommand::applyStyle):
+        (WebCore::CompositeEditCommand::applyStyledElement):
+        (WebCore::CompositeEditCommand::removeStyledElement):
+        (WebCore::enclosingAnchorElement):
+        (WebCore::CompositeEditCommand::pushAnchorElementDown):
+        (WebCore::CompositeEditCommand::pushPartiallySelectedAnchorElementsDown):
+        * editing/CompositeEditCommand.h:
+        * editing/CreateLinkCommand.cpp:
+        (WebCore::CreateLinkCommand::doApply):
+        * editing/CreateLinkCommand.h:
+        * editing/JSEditor.cpp:
+        * editing/Selection.cpp:
+        (WebCore::Selection::selectionFromContentsOfNode):
+        * editing/Selection.h:
+        * editing/UnlinkCommand.cpp: Added.
+        (WebCore::UnlinkCommand::UnlinkCommand):
+        (WebCore::UnlinkCommand::doApply):
+        * editing/UnlinkCommand.h: Added.
+        * page/Frame.cpp:
+        (WebCore::Frame::selectContentsOfNode):
+        (WebCore::Frame::computeAndSetTypingStyle):
+        (WebCore::Frame::applyStyle):
+        (WebCore::Frame::applyParagraphStyle):
+
 2006-03-24  Justin Garcia  <justin.garcia@apple.com>
 
         Reviewed by harrison
index 7129c22217a8de5b8ab9baadcc29dc0271ae7bae..bb7fc1a1c07539564d85b3892b06e7bdcdbf9643 100644 (file)
                BCFB2F77097A2E1A00BA703D /* Arena.h in Headers */ = {isa = PBXBuildFile; fileRef = BCFB2F75097A2E1A00BA703D /* Arena.h */; };
                C6D74AD509AA282E000B0A52 /* ModifySelectionListLevelCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = C6D74AD309AA282E000B0A52 /* ModifySelectionListLevelCommand.h */; };
                C6D74AE409AA290A000B0A52 /* ModifySelectionListLevelCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D74AE309AA290A000B0A52 /* ModifySelectionListLevelCommand.cpp */; };
+               D086FE9809D53AAB005BC74D /* UnlinkCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = D086FE9609D53AAB005BC74D /* UnlinkCommand.h */; };
+               D086FE9909D53AAB005BC74D /* UnlinkCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D086FE9709D53AAB005BC74D /* UnlinkCommand.cpp */; };
                D0B0556809C6700100307E43 /* CreateLinkCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = D0B0556609C6700100307E43 /* CreateLinkCommand.h */; };
                D0B0556909C6700100307E43 /* CreateLinkCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0B0556709C6700100307E43 /* CreateLinkCommand.cpp */; };
                DD763BB20992C2C900740B8E /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DD763BB10992C2C900740B8E /* libxml2.dylib */; };
                BEF7EEA105FF8F0D009717EE /* KWQEditCommand.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KWQEditCommand.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                C6D74AD309AA282E000B0A52 /* ModifySelectionListLevelCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModifySelectionListLevelCommand.h; sourceTree = "<group>"; };
                C6D74AE309AA290A000B0A52 /* ModifySelectionListLevelCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModifySelectionListLevelCommand.cpp; sourceTree = "<group>"; };
+               D086FE9609D53AAB005BC74D /* UnlinkCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnlinkCommand.h; sourceTree = "<group>"; };
+               D086FE9709D53AAB005BC74D /* UnlinkCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnlinkCommand.cpp; sourceTree = "<group>"; };
                D0B0556609C6700100307E43 /* CreateLinkCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CreateLinkCommand.h; sourceTree = "<group>"; };
                D0B0556709C6700100307E43 /* CreateLinkCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CreateLinkCommand.cpp; sourceTree = "<group>"; };
                DD763BB10992C2C900740B8E /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = /usr/lib/libxml2.dylib; sourceTree = "<absolute>"; };
                                93309DD3099E64910056E581 /* VisibleRange.h */,
                                93309DD4099E64910056E581 /* WrapContentsInDummySpanCommand.cpp */,
                                93309DD5099E64910056E581 /* WrapContentsInDummySpanCommand.h */,
+                               D086FE9609D53AAB005BC74D /* UnlinkCommand.h */,
+                               D086FE9709D53AAB005BC74D /* UnlinkCommand.cpp */,
                        );
                        path = editing;
                        sourceTree = "<group>";
                                65DF323A09D1DE65000BE325 /* JSCanvasGradient.h in Headers */,
                                65DF323C09D1DE65000BE325 /* JSCanvasPattern.h in Headers */,
                                65DF323E09D1DE65000BE325 /* JSCanvasRenderingContext2D.h in Headers */,
+                               D086FE9809D53AAB005BC74D /* UnlinkCommand.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                65DF323B09D1DE65000BE325 /* JSCanvasPattern.cpp in Sources */,
                                65DF323D09D1DE65000BE325 /* JSCanvasRenderingContext2D.cpp in Sources */,
                                65DF326109D1E199000BE325 /* UserAgentStyleSheetsData.cpp in Sources */,
+                               D086FE9909D53AAB005BC74D /* UnlinkCommand.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 58211caf0402ea78b3378336bf8d0dedf5886595..8ae53a2c4816b0b34c24dd5826b262aa3ded235e 100644 (file)
@@ -257,7 +257,7 @@ PassRefPtr<HTMLElement> createStyleSpanElement(Document* document)
     return static_pointer_cast<HTMLElement>(styleElement.release());
 }
 
-ApplyStyleCommand::ApplyStyleCommand(Document* document, CSSStyleDeclaration* style, Element* element, EditAction editingAction, EPropertyLevel propertyLevel)
+ApplyStyleCommand::ApplyStyleCommand(Document* document, CSSStyleDeclaration* style, EditAction editingAction, EPropertyLevel propertyLevel)
     : CompositeEditCommand(document)
     , m_style(style->makeMutable())
     , m_editingAction(editingAction)
@@ -265,11 +265,12 @@ ApplyStyleCommand::ApplyStyleCommand(Document* document, CSSStyleDeclaration* st
     , m_start(endingSelection().start().downstream())
     , m_end(endingSelection().end().upstream())
     , m_useEndingSelection(true)
-    , m_styledInlineElement(element)
+    , m_styledInlineElement(0)
+    , m_removeOnly(false)
 {
 }
 
-ApplyStyleCommand::ApplyStyleCommand(Document* document, CSSStyleDeclaration* style, Element* element, const Position& start, const Position& end, EditAction editingAction, EPropertyLevel propertyLevel)
+ApplyStyleCommand::ApplyStyleCommand(Document* document, CSSStyleDeclaration* style, const Position& start, const Position& end, EditAction editingAction, EPropertyLevel propertyLevel)
     : CompositeEditCommand(document)
     , m_style(style->makeMutable())
     , m_editingAction(editingAction)
@@ -277,7 +278,21 @@ ApplyStyleCommand::ApplyStyleCommand(Document* document, CSSStyleDeclaration* st
     , m_start(start)
     , m_end(end)
     , m_useEndingSelection(false)
+    , m_styledInlineElement(0)
+    , m_removeOnly(false)
+{
+}
+
+ApplyStyleCommand::ApplyStyleCommand(Document* document, Element* element, bool removeOnly, EditAction editingAction)
+    : CompositeEditCommand(document)
+    , m_style(new CSSMutableStyleDeclaration())
+    , m_editingAction(editingAction)
+    , m_propertyLevel(PropertyDefault)
+    , m_start(endingSelection().start().downstream())
+    , m_end(endingSelection().end().upstream())
+    , m_useEndingSelection(true)
     , m_styledInlineElement(element)
+    , m_removeOnly(removeOnly)
 {
 }
 
@@ -373,6 +388,9 @@ void ApplyStyleCommand::applyBlockStyle(CSSMutableStyleDeclaration *style)
         }
     }
     
+    if (m_removeOnly)
+        return;
+    
     // apply specified styles to the block flow elements in the selected range
     prevBlock = 0;
     for (DeprecatedPtrListIterator<Node> it(nodes); it.current(); ++it) {
@@ -1203,6 +1221,9 @@ void ApplyStyleCommand::addBlockStyleIfNeeded(CSSMutableStyleDeclaration *style,
 
 void ApplyStyleCommand::addInlineStyleIfNeeded(CSSMutableStyleDeclaration *style, Node *startNode, Node *endNode)
 {
+    if (m_removeOnly)
+        return;
+        
     StyleChange styleChange(style, Position(startNode, 0), StyleChange::styleModeForParseMode(document()->inCompatMode()));
     ExceptionCode ec = 0;
     
index 2673a1ced8bac4e63908c3c81a458ca37f351dd8..6f0925edfdaae77afa27a4415c60aaf426a4d20c 100644 (file)
@@ -38,8 +38,9 @@ class ApplyStyleCommand : public CompositeEditCommand
 public:
     enum EPropertyLevel { PropertyDefault, ForceBlockProperties };
 
-    ApplyStyleCommand(Document*, CSSStyleDeclaration*, Element*, EditAction = EditActionChangeAttributes, EPropertyLevel = PropertyDefault);
-    ApplyStyleCommand(Document*, CSSStyleDeclaration*, Element*, const Position& start, const Position& end, EditAction = EditActionChangeAttributes, EPropertyLevel = PropertyDefault);
+    ApplyStyleCommand(Document*, CSSStyleDeclaration*, EditAction = EditActionChangeAttributes, EPropertyLevel = PropertyDefault);
+    ApplyStyleCommand(Document*, CSSStyleDeclaration*, const Position& start, const Position& end, EditAction = EditActionChangeAttributes, EPropertyLevel = PropertyDefault);
+    ApplyStyleCommand(Document*, Element*, bool = false, EditAction = EditActionChangeAttributes);
 
     virtual void doApply();
     virtual EditAction editingAction() const;
@@ -91,6 +92,7 @@ private:
     Position m_end;
     bool m_useEndingSelection;
     RefPtr<Element> m_styledInlineElement;
+    bool m_removeOnly;
 };
 
 bool isStyleSpan(const Node*);
index e463a3cf534edd9c11a7696b8a0966a19950f1f1..c5672ab5bc5fec78f5c533f1a2bda5cdfe62c658 100644 (file)
@@ -103,13 +103,25 @@ void CompositeEditCommand::applyCommandToComposite(EditCommandPtr &cmd)
 
 void CompositeEditCommand::applyStyle(CSSStyleDeclaration *style, EditAction editingAction)
 {
-    EditCommandPtr cmd(new ApplyStyleCommand(document(), style, 0, editingAction));
+    EditCommandPtr cmd(new ApplyStyleCommand(document(), style, editingAction));
     applyCommandToComposite(cmd);
 }
 
 void CompositeEditCommand::applyStyle(CSSStyleDeclaration *style, Position start, Position end, EditAction editingAction)
 {
-    EditCommandPtr cmd(new ApplyStyleCommand(document(), style, 0, start, end, editingAction));
+    EditCommandPtr cmd(new ApplyStyleCommand(document(), style, start, end, editingAction));
+    applyCommandToComposite(cmd);
+}
+
+void CompositeEditCommand::applyStyledElement(Element* element)
+{
+    EditCommandPtr cmd(new ApplyStyleCommand(document(), element, false));
+    applyCommandToComposite(cmd);
+}
+
+void CompositeEditCommand::removeStyledElement(Element* element)
+{
+    EditCommandPtr cmd(new ApplyStyleCommand(document(), element, true));
     applyCommandToComposite(cmd);
 }
 
@@ -586,6 +598,49 @@ void CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessary(const Posi
     }
 }
 
+Node* enclosingAnchorElement(Node* node)
+{
+    while (node && !(node->isElementNode() && node->isLink()))
+        node = node->parentNode();
+    
+    return node;
+}
+
+void CompositeEditCommand::pushAnchorElementDown(Node* anchorNode)
+{
+    if (!anchorNode)
+        return;
+    
+    ASSERT(anchorNode->isLink());
+    
+    setEndingSelection(Selection::selectionFromContentsOfNode(anchorNode));
+    applyStyledElement(static_cast<Element*>(anchorNode));
+}
+
+// We must push partially selected anchors down before creating or removing
+// links from a selection to create fully selected chunks that can be removed.
+// ApplyStyleCommand doesn't do this for us because styles can be nested.
+// Anchors cannot be nested.
+void CompositeEditCommand::pushPartiallySelectedAnchorElementsDown()
+{
+    Selection originalSelection = endingSelection();
+    VisiblePosition visibleStart(originalSelection.start());
+    VisiblePosition visibleEnd(originalSelection.end());
+    
+    Node* startAnchor = enclosingAnchorElement(originalSelection.start().node());
+    VisiblePosition startOfStartAnchor(Position(startAnchor, 0));
+    if (startAnchor && startOfStartAnchor != visibleStart)
+        pushAnchorElementDown(startAnchor);
+
+    Node* endAnchor = enclosingAnchorElement(originalSelection.end().node());
+    VisiblePosition endOfEndAnchor(Position(endAnchor, 0));
+    if (endAnchor && endOfEndAnchor != visibleEnd)
+        pushAnchorElementDown(endAnchor);
+
+    ASSERT(originalSelection.start().node()->inDocument() && originalSelection.end().node()->inDocument());
+    setEndingSelection(originalSelection);
+}
+
 PassRefPtr<Element> createBlockPlaceholderElement(Document* document)
 {
     ExceptionCode ec = 0;
index 5c521ed187d2647c1a5b0603a7f0f35e23fba1da..2e160e85678cadd2c8d7683d270c87cf59956f84 100644 (file)
@@ -54,6 +54,8 @@ protected:
     void applyCommandToComposite(EditCommandPtr &);
     void applyStyle(WebCore::CSSStyleDeclaration *style, EditAction editingAction=EditActionChangeAttributes);
     void applyStyle(WebCore::CSSStyleDeclaration *style, WebCore::Position start, WebCore::Position end, EditAction editingAction=EditActionChangeAttributes);
+    void applyStyledElement(Element*);
+    void removeStyledElement(Element*);
     void deleteKeyPressed();
     void deleteSelection(bool smartDelete=false, bool mergeBlocksAfterDelete=true);
     void deleteSelection(const Selection &selection, bool smartDelete=false, bool mergeBlocksAfterDelete=true);
@@ -94,6 +96,9 @@ protected:
     WebCore::Node *findBlockPlaceholder(WebCore::Node *);
 
     void moveParagraphContentsToNewBlockIfNecessary(const WebCore::Position &);
+    
+    void pushAnchorElementDown(WebCore::Node*);
+    void pushPartiallySelectedAnchorElementsDown();
 
     DeprecatedValueList<EditCommandPtr> m_cmds;
 };
index 0a107521298e40bc9a147c64b403610527263290..b2af2f7c353d8f403ad1b9345d50ed0698f2e8a9 100644 (file)
@@ -26,8 +26,6 @@
 #include "config.h"
 #include "CreateLinkCommand.h"
 
-#include "css_valueimpl.h"
-#include "Document.h"
 #include "html_inlineimpl.h"
 #include <kxmlcore/Assertions.h>
 
@@ -41,10 +39,11 @@ CreateLinkCommand::CreateLinkCommand(Document* document, const String& url)
 
 void CreateLinkCommand::doApply()
 {
+    pushPartiallySelectedAnchorElementsDown();
+
     HTMLAnchorElement* anchorElement = new HTMLAnchorElement(document());
     anchorElement->setHref(m_url);
-    EditCommandPtr cmd(new ApplyStyleCommand(document(), new CSSMutableStyleDeclaration(), static_cast<Element*>(anchorElement)));
-    applyCommandToComposite(cmd);
+    applyStyledElement(anchorElement);
 }
 
 }
index 45ce4a2d3f3eff3fae609bf2c9f8b82923c4a1a8..4379c7a881776c68f15e78deb12c5a5f1a1b9e7d 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
-#ifndef __create_link_command_h__
-#define __create_link_command_h__
+#ifndef CreateLinkCommand_h
+#define CreateLinkCommand_h
 
-#include "ApplyStyleCommand.h"
+#include "CompositeEditCommand.h"
 
 namespace WebCore {
 
@@ -35,7 +35,6 @@ class CreateLinkCommand : public CompositeEditCommand
 public:
     CreateLinkCommand(WebCore::Document*, const String&);
     virtual void doApply();
-    
 private:
     String m_url;
 
@@ -43,4 +42,4 @@ private:
 
 } // namespace WebCore
 
-#endif // __create_link_command_h__
+#endif // CreateLinkCommand_h
index f192f18beb58891eec918df7684a15b568cf0afd..65b9f919d746e71f078bc502ba377a5c88aa3f7e 100644 (file)
@@ -27,6 +27,7 @@
 #include "JSEditor.h"
 
 #include "CreateLinkCommand.h"
+#include "UnlinkCommand.h"
 #include "Document.h"
 #include "Frame.h"
 #include "SelectionController.h"
@@ -406,6 +407,12 @@ bool execUndo(Frame *frame, bool userInterface, const String &value)
     return true;
 }
 
+bool execUnlink(Frame *frame, bool userInterface, const String &value)
+{
+    EditCommandPtr(new UnlinkCommand(frame->document())).apply();
+    return true;
+}
+
 bool execUnselect(Frame *frame, bool userInterface, const String &value)
 {
     // FIXME: 6498 Should just be able to call m_frame->selection().clear()
@@ -589,6 +596,7 @@ CommandMap *createCommandDictionary()
         { "Transpose", { execTranspose, enabled, stateNone, valueNull } },
         { "Underline", { execUnderline, enabledAnySelection, stateUnderline, valueNull } },
         { "Undo", { execUndo, enabledUndo, stateNone, valueNull } },
+        { "Unlink", { execUnlink, enabledRangeSelection, stateNone, valueNull } },
         { "Unselect", { execUnselect, enabledAnySelection, stateNone, valueNull } }
 
         //
@@ -644,7 +652,6 @@ CommandMap *createCommandDictionary()
         // Stop (not supported)
         // StopImage (not supported)
         // Unbookmark (not supported)
-        // Unlink (not supported)
     };
 
     CommandMap *commandMap = new CommandMap;
index f60b249c1fd82fefcd02117d20d7b8c5dcbadb23..c5cb4c23175858c8263b576112dfaa1d36471ed1 100644 (file)
@@ -63,6 +63,11 @@ Selection::Selection(const Position &base, const Position &extent, EAffinity aff
     validate();
 }
 
+Selection Selection::selectionFromContentsOfNode(Node* node)
+{
+    return Selection(Position(node, 0), Position(node, maxDeepOffset(node)), DOWNSTREAM);
+}
+
 PassRefPtr<Range> Selection::toRange() const
 {
     if (isNone())
index 46db1e72dbf65c6ab789cd6bf5144d7f34fc445a..3bcb87a677af25290a45e5b5c29a857a885908a3 100644 (file)
@@ -44,6 +44,8 @@ public:
     Selection();
     Selection(const Position &, EAffinity);
     Selection(const Position &, const Position &, EAffinity);
+    
+    static Selection selectionFromContentsOfNode(Node*);
 
     EState state() const { return m_state; }
 
diff --git a/WebCore/editing/UnlinkCommand.cpp b/WebCore/editing/UnlinkCommand.cpp
new file mode 100644 (file)
index 0000000..41c6930
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2006 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 "UnlinkCommand.h"
+
+#include "html_inlineimpl.h"
+#include <kxmlcore/Assertions.h>
+
+namespace WebCore {
+
+UnlinkCommand::UnlinkCommand(Document* document)
+    : CompositeEditCommand(document)
+{
+}
+
+void UnlinkCommand::doApply()
+{
+    pushPartiallySelectedAnchorElementsDown();
+
+    HTMLAnchorElement* anchorElement = new HTMLAnchorElement(document());
+    removeStyledElement(anchorElement);
+}
+
+}
diff --git a/WebCore/editing/UnlinkCommand.h b/WebCore/editing/UnlinkCommand.h
new file mode 100644 (file)
index 0000000..a9d5211
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2006 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 UnlinkCommand_h
+#define UnlinkCommand_h
+
+#include "CompositeEditCommand.h"
+
+namespace WebCore {
+
+class UnlinkCommand : public CompositeEditCommand
+{
+public:
+    UnlinkCommand(WebCore::Document*);
+    virtual void doApply();
+private:
+
+};
+
+} // namespace khtml
+
+#endif // UnlinkCommand_h
\ No newline at end of file
index 09668929c84620e4099c77e964e4659751f8e4a6..6725fdf86fee857ecd78a1ed46b66b635f8f0fdc 100644 (file)
@@ -1908,7 +1908,7 @@ void Frame::selectAll()
 
 bool Frame::selectContentsOfNode(Node* node)
 {
-    SelectionController sel = SelectionController(Position(node, 0), Position(node, maxDeepOffset(node)), DOWNSTREAM);    
+    SelectionController sel = SelectionController(Selection::selectionFromContentsOfNode(node));    
     if (shouldChangeSelection(sel)) {
         setSelection(sel);
         return true;
@@ -2131,7 +2131,7 @@ void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction edit
     RefPtr<CSSMutableStyleDeclaration> blockStyle = mutableStyle->copyBlockProperties();
     blockStyle->diff(mutableStyle.get());
     if (document() && blockStyle->length() > 0) {
-        EditCommandPtr cmd(new ApplyStyleCommand(document(), blockStyle.get(), 0, editingAction));
+        EditCommandPtr cmd(new ApplyStyleCommand(document(), blockStyle.get(), editingAction));
         cmd.apply();
     }
     
@@ -2151,7 +2151,7 @@ void Frame::applyStyle(CSSStyleDeclaration *style, EditAction editingAction)
         }
         case Selection::RANGE:
             if (document() && style) {
-                EditCommandPtr cmd(new ApplyStyleCommand(document(), style, 0, editingAction));
+                EditCommandPtr cmd(new ApplyStyleCommand(document(), style, editingAction));
                 cmd.apply();
             }
             break;
@@ -2167,7 +2167,7 @@ void Frame::applyParagraphStyle(CSSStyleDeclaration *style, EditAction editingAc
         case Selection::CARET:
         case Selection::RANGE:
             if (document() && style) {
-                EditCommandPtr cmd(new ApplyStyleCommand(document(), style, 0, editingAction, ApplyStyleCommand::ForceBlockProperties));
+                EditCommandPtr cmd(new ApplyStyleCommand(document(), style, editingAction, ApplyStyleCommand::ForceBlockProperties));
                 cmd.apply();
             }
             break;