+2006-06-08 Justin Garcia <justin.garcia@apple.com>
+
+ Reviewed by levi
+
+ <http://bugzilla.opendarwin.org/show_bug.cgi?id=4468>
+ Implement execCommand(Insert{Un}OrderedList)
+
+ Added:
+ * editing/execCommand/create-list-from-range-selection-expected.checksum: Added.
+ * editing/execCommand/create-list-from-range-selection-expected.png: Added.
+ * editing/execCommand/create-list-from-range-selection-expected.txt: Added.
+ * editing/execCommand/create-list-from-range-selection.html: Added.
+ * editing/execCommand/insert-list-and-stitch-expected.checksum: Added.
+ * editing/execCommand/insert-list-and-stitch-expected.png: Added.
+ * editing/execCommand/insert-list-and-stitch-expected.txt: Added.
+ * editing/execCommand/insert-list-and-stitch.html: Added.
+ * editing/execCommand/insert-list-with-id-expected.checksum: Added.
+ * editing/execCommand/insert-list-with-id-expected.png: Added.
+ * editing/execCommand/insert-list-with-id-expected.txt: Added.
+ * editing/execCommand/insert-list-with-id.html: Added.
+ * editing/execCommand/remove-list-from-range-selection-expected.checksum: Added.
+ * editing/execCommand/remove-list-from-range-selection-expected.png: Added.
+ * editing/execCommand/remove-list-from-range-selection-expected.txt: Added.
+ * editing/execCommand/remove-list-from-range-selection.html: Added.
+ * editing/execCommand/remove-list-items-expected.checksum: Added.
+ * editing/execCommand/remove-list-items-expected.png: Added.
+ * editing/execCommand/remove-list-items-expected.txt: Added.
+ * editing/execCommand/remove-list-items.html: Added.
+ * editing/execCommand/switch-list-type-expected.checksum: Added.
+ * editing/execCommand/switch-list-type-expected.png: Added.
+ * editing/execCommand/switch-list-type-expected.txt: Added.
+ * editing/execCommand/switch-list-type.html: Added.
+
+ Fixes:
+ * editing/pasteboard/drag-drop-modifies-page-expected.txt:
+ * editing/pasteboard/paste-list-001-expected.txt:
+ * editing/selection/drag-to-contenteditable-iframe-expected.checksum:
+ * editing/selection/drag-to-contenteditable-iframe-expected.png:
+ * editing/selection/drag-to-contenteditable-iframe-expected.txt:
+ * editing/style/block-style-005-expected.txt:
+ * fast/text/textIteratorNilRenderer-expected.checksum:
+ * fast/text/textIteratorNilRenderer-expected.png:
+ * fast/text/textIteratorNilRenderer-expected.txt:
+ * editing/deleting/delete-line-016-expected.checksum:
+ * editing/deleting/delete-line-016-expected.png:
+ * editing/deleting/delete-line-016-expected.txt:
+
2006-06-08 David Harrison <harrison@apple.com>
Reviewed by Geoff and John.
-cd4b9f5df064d6eb06da38b899187641
\ No newline at end of file
+340d92c18109e711126f3aa694b08259
\ No newline at end of file
EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 2 of DIV > BODY > HTML > #document to 2 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+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
text run at (0,0) width 767: "This tests deletion of an empty line starting inside a <div> element, but ending outside that element (just before a <br>). In"
text run at (0,18) width 766: "this case, the <div> has no content inside it, but a min-height style prevents it from collapsing. If the deletion is successful,"
text run at (0,36) width 725: "the result should have two lines, and the insertion point should be on the second line, at the end of the editable area."
- RenderBlock {DIV} at (0,70) size 784x36
+ RenderBlock {DIV} at (0,70) size 784x68
RenderBlock {DIV} at (0,0) size 784x18
RenderText {#text} at (0,0) size 7x18
text run at (0,0) width 7: "a"
- RenderBlock (anonymous) at (0,18) size 784x18
+ RenderBlock {DIV} at (0,18) size 784x50
RenderBR {BR} at (0,0) size 0x18
-caret: position 0 of child 2 {BR} of child 3 {DIV} of child 1 {BODY} of child 0 {HTML} of document
+ RenderBlock (anonymous) at (0,68) size 784x0
+caret: position 0 of child 0 {BR} of child 2 {DIV} of child 3 {DIV} of child 1 {BODY} of child 0 {HTML} of document
--- /dev/null
+df73fe3bb7ebfa11d32d699f1d302fba
\ No newline at end of file
--- /dev/null
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 9 of DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 2 of #text > SPAN > LI > OL > DIV > BODY > HTML > #document to 2 of #text > SPAN > LI > OL > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+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 784x576
+ RenderBlock {P} at (0,0) size 784x18
+ RenderText {#text} at (0,0) size 632x18
+ text run at (0,0) width 632: "This tests Insert{Un}OrderedList on a range selection that contains a mix of list and non-list content."
+ RenderBlock {DIV} at (0,34) size 784x108
+ RenderBlock (anonymous) at (0,0) size 784x0
+ RenderBlock {OL} at (0,0) size 784x108
+ RenderListItem {LI} at (40,0) size 744x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 21x18
+ text run at (0,0) width 21: "asd"
+ RenderInline {SPAN} at (0,0) size 21x18
+ RenderText {#text} at (21,0) size 21x18
+ text run at (21,0) width 21: "foo"
+ RenderListItem {LI} at (40,18) size 744x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 20x18
+ text run at (0,0) width 20: "bar"
+ RenderListItem {LI} at (40,36) size 744x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 22x18
+ text run at (0,0) width 22: "baz"
+ RenderListItem {LI} at (40,54) size 744x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 21x18
+ text run at (0,0) width 21: "foo"
+ RenderListItem {LI} at (40,72) size 744x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 20x18
+ text run at (0,0) width 20: "bar"
+ RenderListItem {LI} at (40,90) size 744x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderInline {SPAN} at (0,0) size 22x18
+ RenderText {#text} at (0,0) size 22x18
+ text run at (0,0) width 22: "baz"
+ RenderBlock (anonymous) at (0,124) size 784x0
+selection start: position 2 of child 0 {#text} of child 1 {SPAN} of child 0 {LI} of child 0 {OL} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
+selection end: position 2 of child 0 {#text} of child 0 {SPAN} of child 5 {LI} of child 0 {OL} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
--- /dev/null
+<p>This tests Insert{Un}OrderedList on a range selection that contains a mix of list and non-list content.</p>
+<div id="test" contenteditable="true">asd<span id="start">foo</span><br><ul><li>bar</li></ul>baz<br>foo<ol><li>bar</li></ol><span id="end">baz</span></div>
+<script>
+var s = window.getSelection();
+var start = document.getElementById("start").firstChild;
+var end = document.getElementById("end").firstChild;
+s.setBaseAndExtent(start, 2, end, 2);
+document.execCommand("InsertOrderedList", false, "");
+</script>
--- /dev/null
+69ef56ffa5107d11ffd36615abf63a48
\ No newline at end of file
--- /dev/null
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 7 of DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of LI > OL > DIV > DIV > BODY > HTML > #document to 0 of LI > OL > 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 LI > OL > DIV > DIV > BODY > HTML > #document to 0 of LI > OL > 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 LI > OL > DIV > DIV > BODY > HTML > #document to 0 of LI > OL > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+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 784x576
+ RenderBlock {P} at (0,0) size 784x18
+ RenderText {#text} at (0,0) size 613x18
+ text run at (0,0) width 613: "The three items below should be stitched together into one ordered list when you click the button."
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {DIV} at (0,34) size 784x54
+ RenderBlock {DIV} at (0,0) size 784x54
+ RenderBlock {OL} at (0,0) size 784x54
+ RenderListItem {LI} at (40,0) size 744x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 21x18
+ text run at (0,0) width 21: "foo"
+ RenderListItem {LI} at (40,18) size 744x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 20x18
+ text run at (0,0) width 20: "bar"
+ RenderListItem {LI} at (40,36) size 744x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 22x18
+ text run at (0,0) width 22: "baz"
+ RenderBlock (anonymous) at (0,70) size 784x0
+caret: position 0 of child 0 {#text} of child 2 {LI} of child 0 {OL} of child 1 {DIV} of child 1 {DIV} of child 0 {BODY} of child 0 {HTML} of document
--- /dev/null
+<p>The three items below should be stitched together into one ordered list when you click the button.</div>
+<div contenteditable="true">
+<div id="item1">foo</div>
+<div id="item2">bar</div>
+<div id="item3">baz</div>
+</div>
+<script>
+var s = window.getSelection();
+s.setPosition(document.getElementById("item1"), 0);
+document.execCommand("InsertOrderedList", false, "");
+s.setPosition(document.getElementById("item2"), 0);
+document.execCommand("InsertOrderedList", false, "");
+s.setPosition(document.getElementById("item3"), 0);
+document.execCommand("InsertOrderedList", false, "");
+</script>
\ No newline at end of file
--- /dev/null
+574819845e52367902237bf0dea99dd9
\ No newline at end of file
--- /dev/null
+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: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of LI > OL > DIV > BODY > HTML > #document to 0 of LI > OL > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldEndEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 1 of DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidEndEditing:WebViewDidEndEditingNotification
+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 784x36
+ RenderText {#text} at (0,0) size 770x36
+ text run at (0,0) width 770: "This test makes sure Insert{Un}OrderedList properly adds an id to the inserted list when requested. The tests inserts a new"
+ text run at (0,18) width 497: "list using the command, then removes it programmatically from JS using the id."
+ RenderBlock (anonymous) at (0,52) size 784x18
+ RenderBR {BR} at (0,0) size 0x18
+ RenderBlock {DIV} at (0,70) size 784x18
+ RenderBlock (anonymous) at (0,88) size 784x18
+ RenderBR {BR} at (0,0) size 0x18
--- /dev/null
+<p>This test makes sure Insert{Un}OrderedList properly adds an id to the inserted list when requested. The tests inserts a new list using the command, then removes it programmatically from JS using the id.</p>
+<br>
+<div id="test" contenteditable="true">Foo</div>
+<br>
+<script>
+var s = window.getSelection();
+var div = document.getElementById("test");
+var id = "foo";
+s.setPosition(div, 0);
+document.execCommand("InsertOrderedList", false, id);
+div.blur();
+var list = document.getElementById(id);
+list.parentNode.removeChild(list);
+</script>
\ No newline at end of file
--- /dev/null
+6ac0c2f3a3aef772a55f5d969074a894
\ No newline at end of file
--- /dev/null
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 2 of DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 2 of #text > SPAN > DIV > BODY > HTML > #document to 2 of #text > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+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 784x576
+ RenderBlock {P} at (0,0) size 784x18
+ RenderText {#text} at (0,0) size 528x18
+ text run at (0,0) width 528: "This tests Insert{Un}OrderedList on a range selection that is entirely within one list."
+ RenderBlock {DIV} at (0,34) size 784x106
+ RenderBlock (anonymous) at (0,0) size 784x72
+ RenderInline {SPAN} at (0,0) size 75x18
+ RenderText {#text} at (0,0) size 75x18
+ text run at (0,0) width 75: "None of the"
+ RenderBR {BR} at (75,14) size 0x0
+ RenderText {#text} at (0,18) size 100x18
+ text run at (0,18) width 100: "selected content"
+ RenderBR {BR} at (100,32) size 0x0
+ RenderText {#text} at (0,36) size 61x18
+ text run at (0,36) width 61: "should be"
+ RenderBR {BR} at (61,50) size 0x0
+ RenderInline {SPAN} at (0,0) size 49x18
+ RenderText {#text} at (0,54) size 49x18
+ text run at (0,54) width 49: "in a list."
+ RenderBR {BR} at (49,68) size 0x0
+ RenderBlock {OL} at (0,88) size 784x18
+ RenderListItem {LI} at (40,0) size 744x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 316x18
+ text run at (0,0) width 316: "This should be in a list and should not be selected."
+selection start: position 2 of child 0 {#text} of child 0 {SPAN} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
+selection end: position 2 of child 0 {#text} of child 6 {SPAN} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
--- /dev/null
+<p>This tests Insert{Un}OrderedList on a range selection that is entirely within one list.</p>
+<div id="test" contenteditable="true"><ol><li><span id="start">None of the</span></li><li>selected content</li><li>should be</li><li><span id="end">in a list.</span></li></ol><ol><li>This should be in a list and should not be selected.</li></ol></div>
+<script>
+var s = window.getSelection();
+var start = document.getElementById("start").firstChild;
+var end = document.getElementById("end").firstChild;
+s.setBaseAndExtent(start, 2, end, 2);
+
+document.execCommand("InsertOrderedList", false, "foo");
+</script>
\ No newline at end of file
--- /dev/null
+784acec49fd302c45e00be85429d0a33
\ No newline at end of file
--- /dev/null
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 7 of DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of SPAN > DIV > BODY > HTML > #document to 0 of SPAN > 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 SPAN > DIV > BODY > HTML > #document to 0 of SPAN > 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 SPAN > DIV > BODY > HTML > #document to 0 of SPAN > 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 SPAN > DIV > BODY > HTML > #document to 0 of SPAN > 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 15 of DIV > BODY > HTML > #document to 15 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+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 784x36
+ RenderText {#text} at (0,0) size 738x36
+ text run at (0,0) width 738: "This test checks to see that Insert{Un}OrderedList can remove items from a list, can remove empty list when they are"
+ text run at (0,18) width 368: "emptied, and can remove content from orphaned list items."
+ RenderBlock {DIV} at (0,52) size 784x318
+ RenderBlock {OL} at (0,0) size 784x20 [border: (1px solid #FF0000)]
+ RenderListItem {LI} at (41,1) size 742x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 21x18
+ text run at (0,0) width 21: "foo"
+ RenderBlock (anonymous) at (41,19) size 742x0
+ RenderBlock (anonymous) at (0,36) size 784x18
+ RenderInline {SPAN} at (0,0) size 154x18
+ RenderText {#text} at (0,0) size 154x18
+ text run at (0,0) width 154: "This should not be a list."
+ RenderText {#text} at (154,0) size 4x18
+ text run at (154,0) width 4: " "
+ RenderBR {BR} at (158,14) size 0x0
+ RenderBlock {OL} at (0,70) size 784x56 [border: (1px solid #FF0000)]
+ RenderBlock (anonymous) at (41,1) size 742x36
+ RenderBR {BR} at (0,0) size 0x18
+ RenderText {#text} at (0,18) size 20x18
+ text run at (0,18) width 20: "bar"
+ RenderListItem {LI} at (41,37) size 742x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 22x18
+ text run at (0,0) width 22: "baz"
+ RenderBlock (anonymous) at (41,55) size 742x0
+ RenderBlock (anonymous) at (0,142) size 784x18
+ RenderInline {SPAN} at (0,0) size 170x18
+ RenderText {#text} at (0,0) size 170x18
+ text run at (0,0) width 170: "This should not be in a list."
+ RenderBR {BR} at (170,14) size 0x0
+ RenderBlock {OL} at (0,176) size 784x20 [border: (1px solid #FF0000)]
+ RenderListItem {LI} at (41,1) size 742x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 21x18
+ text run at (0,0) width 21: "foo"
+ RenderBlock (anonymous) at (0,212) size 784x18
+ RenderInline {SPAN} at (0,0) size 170x18
+ RenderText {#text} at (0,0) size 170x18
+ text run at (0,0) width 170: "This should not be in a list."
+ RenderBR {BR} at (170,14) size 0x0
+ RenderBlock {OL} at (0,246) size 784x20 [border: (1px solid #FF0000)]
+ RenderBlock (anonymous) at (41,1) size 742x0
+ RenderListItem {LI} at (41,1) size 742x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 20x18
+ text run at (0,0) width 20: "bar"
+ RenderBlock (anonymous) at (0,282) size 784x36
+ RenderInline {SPAN} at (0,0) size 170x18
+ RenderText {#text} at (0,0) size 170x18
+ text run at (0,0) width 170: "This should not be in a list."
+ RenderBR {BR} at (170,14) size 0x0
+ RenderInline {SPAN} at (0,0) size 170x18
+ RenderText {#text} at (0,18) size 170x18
+ text run at (0,18) width 170: "This should not be in a list."
+caret: position 0 of child 0 {#text} of child 15 {SPAN} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
--- /dev/null
+<p>This test checks to see that Insert{Un}OrderedList can remove items from a list, can remove empty list when they are emptied, and can remove content from orphaned list items.</p>
+<div contenteditable="true">
+<ol style="border: 1px solid red;">
+ <li>foo</li>
+ <span id="item1">This should not be a list.</span>
+ <br><br>
+ bar
+ <li>baz</li>
+ <span id="item2">This should not be in a list.</span>
+ <li>foo</li>
+ <li><span id="item3">This should not be in a list.</span></li>
+ <li>bar</li>
+</ol>
+<li><span id="item4">This should not be in a list.</span></li>
+<ul><li><span id="item5">This should not be in a list.</span></li></ul>
+</div>
+<script>
+var s = window.getSelection();
+s.setPosition(document.getElementById("item1"), 0);
+document.execCommand("InsertOrderedList", false, "");
+s.setPosition(document.getElementById("item2"), 0);
+document.execCommand("InsertOrderedList", false, "");
+s.setPosition(document.getElementById("item3"), 0);
+document.execCommand("InsertOrderedList", false, "");
+s.setPosition(document.getElementById("item4"), 0);
+document.execCommand("InsertUnorderedList", false, "");
+s.setPosition(document.getElementById("item5"), 0);
+document.execCommand("InsertUnorderedList", false, "");
+</script>
\ No newline at end of file
--- /dev/null
+1a759665d514ac0a25ee958bf4e2b581
\ No newline at end of file
--- /dev/null
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 6 of DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of LI > UL > SPAN > DIV > BODY > HTML > #document to 0 of LI > UL > SPAN > 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 LI > UL > SPAN > DIV > BODY > HTML > #document to 0 of LI > UL > SPAN > 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 LI > UL > SPAN > DIV > BODY > HTML > #document to 0 of LI > UL > SPAN > 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 LI > OL > SPAN > DIV > BODY > HTML > #document to 0 of LI > OL > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+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 784x576
+ RenderBlock {P} at (0,0) size 784x18
+ RenderText {#text} at (0,0) size 495x18
+ text run at (0,0) width 495: "This test checks to see if InsertOrderedList can switch the list type of list items."
+ RenderBlock {DIV} at (0,34) size 784x334
+ RenderBlock {OL} at (0,0) size 784x20 [border: (1px solid #FF0000)]
+ RenderListItem {LI} at (41,1) size 742x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 206x18
+ text run at (0,0) width 206: "This should be in an ordered list."
+ RenderBlock (anonymous) at (41,19) size 742x0
+ RenderBlock (anonymous) at (0,36) size 784x0
+ RenderInline {SPAN} at (0,0) size 0x0
+ RenderBlock (anonymous) at (0,36) size 784x18
+ RenderBlock {UL} at (0,0) size 784x18
+ RenderListItem {LI} at (40,0) size 744x18
+ RenderListMarker at (-17,0) size 7x18
+ RenderInline {SPAN} at (0,0) size 222x18
+ RenderText {#text} at (0,0) size 222x18
+ text run at (0,0) width 222: "This should be in an unordered list."
+ RenderText {#text} at (222,0) size 4x18
+ text run at (222,0) width 4: " "
+ RenderBlock (anonymous) at (0,70) size 784x0
+ RenderInline {SPAN} at (0,0) size 0x0
+ RenderBlock {OL} at (0,70) size 784x56 [border: (1px solid #FF0000)]
+ RenderBlock (anonymous) at (41,1) size 742x36
+ RenderBR {BR} at (0,0) size 0x18
+ RenderText {#text} at (0,18) size 206x18
+ text run at (0,18) width 206: "This should be in an ordered list."
+ RenderListItem {LI} at (41,37) size 742x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 206x18
+ text run at (0,0) width 206: "This should be in an ordered list."
+ RenderBlock (anonymous) at (41,55) size 742x0
+ RenderBlock (anonymous) at (0,142) size 784x0
+ RenderInline {SPAN} at (0,0) size 0x0
+ RenderBlock (anonymous) at (0,142) size 784x18
+ RenderBlock {UL} at (0,0) size 784x18
+ RenderListItem {LI} at (40,0) size 744x18
+ RenderListMarker at (-17,0) size 7x18
+ RenderInline {SPAN} at (0,0) size 222x18
+ RenderText {#text} at (0,0) size 222x18
+ text run at (0,0) width 222: "This should be in an unordered list."
+ RenderBlock (anonymous) at (0,176) size 784x0
+ RenderInline {SPAN} at (0,0) size 0x0
+ RenderBlock {OL} at (0,176) size 784x20 [border: (1px solid #FF0000)]
+ RenderListItem {LI} at (41,1) size 742x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 206x18
+ text run at (0,0) width 206: "This should be in an ordered list."
+ RenderBlock (anonymous) at (0,212) size 784x0
+ RenderInline {SPAN} at (0,0) size 0x0
+ RenderBlock (anonymous) at (0,212) size 784x18
+ RenderBlock {UL} at (0,0) size 784x18
+ RenderListItem {LI} at (40,0) size 744x18
+ RenderListMarker at (-17,0) size 7x18
+ RenderInline {SPAN} at (0,0) size 222x18
+ RenderText {#text} at (0,0) size 222x18
+ text run at (0,0) width 222: "This should be in an unordered list."
+ RenderBlock (anonymous) at (0,246) size 784x0
+ RenderInline {SPAN} at (0,0) size 0x0
+ RenderBlock {OL} at (0,246) size 784x20 [border: (1px solid #FF0000)]
+ RenderBlock (anonymous) at (41,1) size 742x0
+ RenderListItem {LI} at (41,1) size 742x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderText {#text} at (0,0) size 206x18
+ text run at (0,0) width 206: "This should be in an ordered list."
+ RenderBlock (anonymous) at (0,282) size 784x18
+ RenderText {#text} at (0,0) size 170x18
+ text run at (0,0) width 170: "This should not be in a list."
+ RenderBR {BR} at (170,14) size 0x0
+ RenderInline {SPAN} at (0,0) size 0x0
+ RenderBlock (anonymous) at (0,316) size 784x18
+ RenderBlock {OL} at (0,0) size 784x18
+ RenderListItem {LI} at (40,0) size 744x18
+ RenderListMarker at (-20,0) size 16x18
+ RenderInline {SPAN} at (0,0) size 206x18
+ RenderText {#text} at (0,0) size 206x18
+ text run at (0,0) width 206: "This should be in an ordered list."
+ RenderBlock (anonymous) at (0,350) size 784x0
+ RenderInline {SPAN} at (0,0) size 0x0
+caret: position 0 of child 0 {#text} of child 0 {SPAN} of child 0 {LI} of child 0 {OL} of child 10 {SPAN} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
--- /dev/null
+<p>This test checks to see if InsertOrderedList can switch the list type of list items.</p>
+<div contenteditable="true">
+<ol style="border: 1px solid red;">
+ <li>This should be in an ordered list.</li>
+ <span id="item1">This should be in an unordered list.</span>
+ <br><br>
+ This should be in an ordered list.
+ <li>This should be in an ordered list.</li>
+ <span id="item2">This should be in an unordered list.</span>
+ <li>This should be in an ordered list.</li>
+ <li><span id="item3">This should be in an unordered list.</span></li>
+ <li>This should be in an ordered list.</li>
+</ol>
+This should not be in a list.
+<li><span id="item4">This should be in an ordered list.</span></li>
+
+<script>
+var s = window.getSelection();
+s.setPosition(document.getElementById("item1"), 0);
+document.execCommand("InsertUnorderedList", false, "Moo");
+s.setPosition(document.getElementById("item2"), 0);
+document.execCommand("InsertUnorderedList", false, "Goo");
+s.setPosition(document.getElementById("item3"), 0);
+document.execCommand("InsertUnorderedList", false, "Gai");
+s.setPosition(document.getElementById("item4"), 0);
+document.execCommand("InsertOrderedList", false, "Noodles");
+</script>
\ No newline at end of file
RenderText {#text} at (0,0) size 757x18
text run at (0,0) width 757: "This test does a drag and drop such that the selection around the dragged word is no longer in the document on the drop."
RenderBlock {DIV} at (0,34) size 784x18
- RenderInline {SPAN} at (0,0) size 0x0
RenderText {#text} at (0,0) size 37x18
text run at (0,0) width 37: "world"
RenderText {#text} at (37,0) size 4x18
RenderInline {SPAN} at (0,0) size 31x18
RenderText {#text} at (41,0) size 31x18
text run at (41,0) width 31: "hello"
-selection start: position 0 of child 2 {#text} of child 3 {DIV} of child 1 {BODY} of child 0 {HTML} of document
-selection end: position 5 of child 0 {#text} of child 3 {SPAN} of child 3 {DIV} of child 1 {BODY} of child 0 {HTML} of document
+selection start: position 0 of child 1 {#text} of child 3 {DIV} of child 1 {BODY} of child 0 {HTML} of document
+selection end: position 5 of child 0 {#text} of child 2 {SPAN} of child 3 {DIV} of child 1 {BODY} of child 0 {HTML} of document
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 21 of #text > LI > OL > DIV > BODY > HTML > #document to 21 of #text > LI > OL > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted
EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 21 of #text > LI > OL > DIV > BODY > HTML > #document to 21 of #text > LI > OL > DIV > BODY > HTML > #document toDOMRange:range from 21 of #text > LI > OL > OL > DIV > BODY > HTML > #document to 21 of #text > LI > OL > OL > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-1359a67c7dc24fc1858e62d60f658a4a
\ No newline at end of file
+452b613a30dd16c4dc466d6a7c26d8e6
\ No newline at end of file
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
layer at (0,0) size 800x600
RenderView at (0,0) size 800x600
layer at (0,0) size 800x600
text run at (362,0) width 60: "\x{A9}2005 Google"
layer at (206,88) size 385x13
RenderBlock {DIV} at (3,3) size 385x13
-selection start: position 0 of child 0 {#text} of child 0 {B} of child 0 {FONT} of child 0 {TD} of child 0 {TR} of child 0 {TBODY} of child 1 {TABLE} of child 4 {DIV} of child 0 {CENTER} of child 1 {BODY} of child 0 {HTML} of document
-selection end: position 0 of child 2 {BR} of child 1 {TD} of child 0 {TR} of child 0 {TBODY} of child 2 {TABLE} of child 4 {DIV} of child 0 {CENTER} of child 1 {BODY} of child 0 {HTML} of document
+selection start: position 0 of child 4 {INPUT} of child 1 {TD} of child 0 {TR} of child 0 {TBODY} of child 2 {TABLE} of child 4 {DIV} of child 0 {CENTER} of child 1 {BODY} of child 0 {HTML} of document
+selection end: position 1 of child 2 {BR} of child 0 {FONT} of child 2 {TD} of child 0 {TR} of child 0 {TBODY} of child 2 {TABLE} of child 4 {DIV} of child 0 {CENTER} of child 1 {BODY} of child 0 {HTML} of document
-348682498d72c255547545ca349de34e
\ No newline at end of file
+e93d8592f6229d3c0681c600617c9f4d
\ No newline at end of file
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
layer at (0,0) size 800x600
RenderView at (0,0) size 800x600
layer at (0,0) size 800x600
layer at (206,88) size 385x13
RenderBlock {DIV} at (3,3) size 385x13
selection start: position 0 of child 1 {TABLE} of child 4 {DIV} of child 0 {CENTER} of child 1 {BODY} of child 0 {HTML} of document
-selection end: position 0 of child 2 {BR} of child 1 {TD} of child 0 {TR} of child 0 {TBODY} of child 2 {TABLE} of child 4 {DIV} of child 0 {CENTER} of child 1 {BODY} of child 0 {HTML} of document
+selection end: position 1 of child 3 {#text} of child 4 {FONT} of child 4 {DIV} of child 0 {CENTER} of child 1 {BODY} of child 0 {HTML} of document
-1f9431a0f9ebf8ab31ceabe91f53ad0e
\ No newline at end of file
+18c677ed78a46295f3bb9b299161feb2
\ No newline at end of file
layer at (0,0) size 200x200
RenderBlock {HTML} at (0,0) size 200x200
RenderBody {BODY} at (8,8) size 184x184 [bgcolor=#FFFFE0]
- RenderImage {IMG} at (0,0) size 76x103
+ RenderBlock (anonymous) at (0,0) size 184x103
+ RenderImage {IMG} at (0,0) size 76x103
RenderText {#text} at (208,194) size 4x18
text run at (208,194) width 4: " "
RenderImage {IMG} at (212,105) size 76x103
RenderListMarker at (-17,0) size 7x18
RenderText {#text} at (0,0) size 288x18
text run at (0,0) width 288: "Abe should be outside the frame and inside it."
-selection start: position 0 of child 0 {IMG} of child 0 {BODY} of child 0 {HTML} of document
-selection end: position 1 of child 0 {IMG} of child 0 {BODY} of child 0 {HTML} of document
+selection start: position 0 of child 3 {IMG} of child 1 {BODY} of child 0 {HTML} of document
+selection end: position 1 of child 3 {IMG} of child 1 {BODY} of child 0 {HTML} of document
RenderBR {BR} at (0,0) size 0x69
RenderBlock {DIV} at (0,138) size 784x69
RenderInline {FONT} at (0,0) size 0x55
- RenderInline {FONT} at (0,0) size 0x55
- RenderInline {SPAN} at (0,0) size 0x69
- RenderBR {BR} at (0,0) size 0x69
-caret: position 0 of child 0 {BR} of child 0 {SPAN} of child 0 {FONT} of child 0 {FONT} of child 3 {DIV} of child 3 {DIV} of child 1 {BODY} of child 0 {HTML} of document
+ RenderInline {SPAN} at (0,0) size 0x69
+ RenderBR {BR} at (0,0) size 0x69
+caret: position 0 of child 0 {BR} of child 0 {SPAN} of child 0 {FONT} of child 3 {DIV} of child 3 {DIV} of child 1 {BODY} of child 0 {HTML} of document
-0e4d863f1b1a778e924bb98fa153bf06
\ No newline at end of file
+306e8069b4223ce4121f9c8cea89f4c7
\ No newline at end of file
EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV to 0 of DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 2 of #text > TD > TR > TBODY > TABLE > FORM > CENTER > BODY > HTML > #document to 0 of INPUT > LABEL > TD > TR > TBODY > TABLE > FORM > CENTER > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 2 of #text > TD > TR > TBODY > TABLE > FORM > CENTER > BODY > HTML > #document to 0 of INPUT > TD > TR > TBODY > TABLE > FORM > CENTER > 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 to 0 of DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > TD > TR > TBODY > TABLE > FORM > CENTER > BODY > HTML > #document to 0 of INPUT > LABEL > TD > TR > TBODY > TABLE > FORM > CENTER > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > TD > TR > TBODY > TABLE > FORM > CENTER > BODY > HTML > #document to 0 of INPUT > TD > TR > TBODY > TABLE > FORM > CENTER > 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 to 0 of DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > TD > TR > TBODY > TABLE > FORM > CENTER > BODY > HTML > #document to 0 of INPUT > LABEL > TD > TR > TBODY > TABLE > FORM > CENTER > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > TD > TR > TBODY > TABLE > FORM > CENTER > BODY > HTML > #document to 0 of INPUT > TD > TR > TBODY > TABLE > FORM > CENTER > 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 to 0 of DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > TD > TR > TBODY > TABLE > FORM > CENTER > BODY > HTML > #document to 0 of INPUT > LABEL > TD > TR > TBODY > TABLE > FORM > CENTER > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > TD > TR > TBODY > TABLE > FORM > CENTER > BODY > HTML > #document to 0 of INPUT > TD > TR > TBODY > TABLE > FORM > CENTER > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
layer at (0,0) size 800x600
RenderView at (0,0) size 800x600
layer at (204,13) size 281x13
RenderBlock {DIV} at (3,3) size 281x13
selection start: position 0 of child 0 {#text} of child 0 {TD} of child 0 {TR} of child 1 {TBODY} of child 1 {TABLE} of child 1 {FORM} of child 1 {CENTER} of child 1 {BODY} of child 0 {HTML} of document
-selection end: position 0 of child 1 {INPUT} of child 3 {LABEL} of child 4 {TD} of child 0 {TR} of child 1 {TBODY} of child 1 {TABLE} of child 1 {FORM} of child 1 {CENTER} of child 1 {BODY} of child 0 {HTML} of document
+selection end: position 0 of child 1 {INPUT} of child 3 {TD} of child 0 {TR} of child 1 {TBODY} of child 1 {TABLE} of child 1 {FORM} of child 1 {CENTER} of child 1 {BODY} of child 0 {HTML} of document
+2006-06-08 Justin Garcia <justin.garcia@apple.com>
+
+ Reviewed by levi
+
+ <http://bugzilla.opendarwin.org/show_bug.cgi?id=4468>
+ Implement execCommand(Insert{Un}OrderedList)
+
+ * WebCore.xcodeproj/project.pbxproj: Added InsertListCommand.{h,cpp} to the project.
+ * dom/Position.cpp:
+ (WebCore::hasRenderedNonAnonymousDescendantsWithHeight):
+ Added. A block with height is only a candidate if this is false. This should fix the problems
+ getting carets into empty blocks.
+ (WebCore::Position::inRenderedContent):
+ * editing/AppendNodeCommand.cpp:
+ (WebCore::AppendNodeCommand::doApply):
+ * editing/CompositeEditCommand.cpp:
+ (WebCore::hasARenderedDescendant):
+ (WebCore::CompositeEditCommand::prune): A node can have DOM descendants that are rendered, yet
+ have no rendered descendants. Fixed the pruning rule to avoid removing a node like this.
+ (WebCore::CompositeEditCommand::mergeIdenticalElements): Put the two elements next to
+ each other if they aren't already, as a convenience.
+ (WebCore::CompositeEditCommand::moveParagraph): Added code to preserve the current selection.
+ (WebCore::CompositeEditCommand::moveParagraphs): Ditto.
+ * editing/CompositeEditCommand.h:
+ * editing/DeleteSelectionCommand.cpp:
+ (WebCore::DeleteSelectionCommand::initializeStartEnd): Expansion for special elements should
+ continue to happen until it is no longer possible.
+ (WebCore::DeleteSelectionCommand::handleGeneralDelete): The code to adjust the start node
+ wouldn't always avoid removing the start block.
+ * editing/InsertListCommand.cpp: Added.
+ (WebCore::InsertListCommand::fixOrphanedListChild): Puts a list item that isn't inside a list
+ into a list.
+ (WebCore::InsertListCommand::InsertListCommand):
+ (WebCore::InsertListCommand::modifyRange):
+ (WebCore::InsertListCommand::doApply):
+ * editing/InsertListCommand.h: Added.
+ (WebCore::InsertListCommand::):
+ * editing/InsertNodeBeforeCommand.cpp:
+ (WebCore::InsertNodeBeforeCommand::doApply):
+ * editing/InsertParagraphSeparatorCommand.cpp:
+ * editing/JSEditor.cpp:
+ * editing/TextIterator.cpp:
+ (WebCore::TextIterator::advance): Don't handle a node if the end of the range used to create the
+ iterator ends at the start of that node.
+ used to create the iterator.
+ * editing/VisiblePosition.cpp:
+ (WebCore::VisiblePosition::next):
+ (WebCore::VisiblePosition::previous):
+ * editing/VisiblePosition.h:
+ Added a parameter to next/previous to prevent them from going outside the current editable region.
+ * editing/htmlediting.cpp:
+ (WebCore::highestAncestor):
+ (WebCore::enclosingList):
+ (WebCore::enclosingListChild):
+ (WebCore::outermostEnclosingList):
+ (WebCore::createListItemElement):
+ * editing/htmlediting.h:
+ * page/Frame.cpp:
+ (WebCore::Frame::selectionListState): Added.
+ * page/Frame.h:
+
2006-06-08 David Harrison <harrison@apple.com>
Reviewed by Geoff and John.
2006-06-08 Alice Liu <alice.liu@apple.com>
- Reviewed by Justin.
+ Reviewed by justin.
- fixed <rdar://problem/4578115> support Range.isPointInRange
- fixed <rdar://problem/4578123> support Range.comparePoint
2006-06-08 Darin Adler <darin@apple.com>
- Reviewed by Justin.
+ Reviewed by justin.
- fix http://bugzilla.opendarwin.org/show_bug.cgi?id=8616
REGRESSION: TinyMCE: Crash on Undo
BCFE8E320A02A1D30009E61D /* WebCoreTextRenderer.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCFE8E310A02A1D30009E61D /* WebCoreTextRenderer.mm */; };
C6D74AD509AA282E000B0A52 /* ModifySelectionListLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = C6D74AD309AA282E000B0A52 /* ModifySelectionListLevel.h */; };
C6D74AE409AA290A000B0A52 /* ModifySelectionListLevel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D74AE309AA290A000B0A52 /* ModifySelectionListLevel.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 */; };
D086FE9909D53AAB005BC74D /* UnlinkCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D086FE9709D53AAB005BC74D /* UnlinkCommand.cpp */; };
D0B0556809C6700100307E43 /* CreateLinkCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = D0B0556609C6700100307E43 /* CreateLinkCommand.h */; };
BEF7EEA105FF8F0D009717EE /* KWQEditCommand.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KWQEditCommand.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
C6D74AD309AA282E000B0A52 /* ModifySelectionListLevel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModifySelectionListLevel.h; sourceTree = "<group>"; };
C6D74AE309AA290A000B0A52 /* ModifySelectionListLevel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModifySelectionListLevel.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>"; };
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>"; };
93309D9B099E64910056E581 /* InsertIntoTextNodeCommand.h */,
93309D9C099E64910056E581 /* InsertLineBreakCommand.cpp */,
93309D9D099E64910056E581 /* InsertLineBreakCommand.h */,
+ D07DEAB70A36554A00CA30F8 /* InsertListCommand.cpp */,
+ D07DEAB80A36554A00CA30F8 /* InsertListCommand.h */,
93309D9E099E64910056E581 /* InsertNodeBeforeCommand.cpp */,
93309D9F099E64910056E581 /* InsertNodeBeforeCommand.h */,
93309DA0099E64910056E581 /* InsertParagraphSeparatorCommand.cpp */,
A833C80D0A2CF25600D57664 /* XMLNames.h in Headers */,
5126E6BC0A2E3B12005C29FA /* IconDatabase.h in Headers */,
5126E6BF0A2E3B29005C29FA /* WebCoreIconDatabaseBridge.h in Headers */,
+ D07DEABA0A36554A00CA30F8 /* InsertListCommand.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A833C8520A2CF52800D57664 /* SVGElementFactory.cpp in Sources */,
5126E6BB0A2E3B12005C29FA /* IconDatabase.cpp in Sources */,
5126E6C00A2E3B29005C29FA /* WebCoreIconDatabaseBridge.mm in Sources */,
+ D07DEAB90A36554A00CA30F8 /* InsertListCommand.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
return lastVisible;
}
-static bool hasRenderedChildrenWithHeight(RenderObject *renderer)
+static bool hasRenderedNonAnonymousDescendantsWithHeight(RenderObject *renderer)
{
- if (!renderer->firstChild())
- return false;
-
- for (RenderObject *child = renderer->firstChild(); child; child = child->nextSibling())
- if (child->height())
+ RenderObject* stop = renderer->nextInPreOrderAfterChildren();
+ for (RenderObject *o = renderer->firstChild(); o && o != stop; o = o->nextInPreOrder())
+ if (o->element() && o->height())
return true;
-
+
return false;
}
if (isTableElement(node()) || editingIgnoresContent(node()))
return offset() == 0 || offset() == maxDeepOffset(node());
- if (!node()->hasTagName(htmlTag) && renderer->isBlockFlow() && !hasRenderedChildrenWithHeight(renderer) &&
+ if (!node()->hasTagName(htmlTag) && renderer->isBlockFlow() && !hasRenderedNonAnonymousDescendantsWithHeight(renderer) &&
(renderer->height() || node()->hasTagName(bodyTag)))
return offset() == 0;
// 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());
+ ASSERT(m_parentNode->isContentEditable() || !m_parentNode->attached());
ExceptionCode ec = 0;
m_parentNode->appendChild(m_appendChild.get(), ec);
prune(parent);
}
+bool hasARenderedDescendant(Node* node)
+{
+ Node* n = node->traverseNextNode(node);
+ while (n) {
+ if (n->renderer())
+ return true;
+ n = n->traverseNextNode(node);
+ }
+
+ return false;
+}
+
void CompositeEditCommand::prune(PassRefPtr<Node> node)
{
while (node) {
// If you change this rule you may have to add an updateLayout() here.
RenderObject* renderer = node->renderer();
- if (renderer && (!renderer->canHaveChildren() || renderer->firstChild()))
+ if (renderer && (!renderer->canHaveChildren() || hasARenderedDescendant(node.get()) || node->rootEditableElement() == node))
return;
RefPtr<Node> next = node->parentNode();
void CompositeEditCommand::mergeIdenticalElements(WebCore::Element *first, WebCore::Element *second)
{
+ ASSERT(!first->isAncestor(second) && second != first);
+ if (first->nextSibling() != second) {
+ removeNode(second);
+ insertNodeAfter(second, first);
+ }
EditCommandPtr cmd(new MergeIdenticalElementsCommand(document(), first, second));
applyCommandToComposite(cmd);
}
}
// This moves a paragraph preserving its style.
-void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& destination)
+void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& destination, bool preserveSelection)
+{
+ ASSERT(isStartOfParagraph(startOfParagraphToMove));
+ ASSERT(isEndOfParagraph(endOfParagraphToMove));
+ moveParagraphs(startOfParagraphToMove, endOfParagraphToMove, destination, preserveSelection);
+}
+
+// FIXME: Always preserve the selection, and pass the paragraphs to operate on using an endingSelection().
+void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& destination, bool preserveSelection)
{
if (startOfParagraphToMove == destination)
return;
- ASSERT(isStartOfParagraph(startOfParagraphToMove));
- ASSERT(isEndOfParagraph(endOfParagraphToMove));
+ int startIndex = -1;
+ int endIndex = -1;
+ int destinationIndex = -1;
+ if (preserveSelection && !endingSelection().isNone()) {
+ VisiblePosition visibleStart = endingSelection().visibleStart();
+ VisiblePosition visibleEnd = endingSelection().visibleEnd();
+
+ bool startAfterParagraph = Range::compareBoundaryPoints(visibleStart.deepEquivalent(), endOfParagraphToMove.deepEquivalent()) > 0;
+ bool endBeforeParagraph = Range::compareBoundaryPoints(visibleEnd.deepEquivalent(), startOfParagraphToMove.deepEquivalent()) < 0;
+
+ if (!startAfterParagraph && !endBeforeParagraph) {
+ bool startInParagraph = Range::compareBoundaryPoints(visibleStart.deepEquivalent(), startOfParagraphToMove.deepEquivalent()) >= 0;
+ bool endInParagraph = Range::compareBoundaryPoints(visibleEnd.deepEquivalent(), endOfParagraphToMove.deepEquivalent()) <= 0;
+
+ startIndex = startInParagraph ? TextIterator::rangeLength(new Range(document(), startOfParagraphToMove.deepEquivalent(), visibleStart.deepEquivalent())) : 0;
+ endIndex = endInParagraph ? TextIterator::rangeLength(new Range(document(), startOfParagraphToMove.deepEquivalent(), visibleEnd.deepEquivalent())) : 0;
+ }
+ }
VisiblePosition beforeParagraph = startOfParagraphToMove.previous();
// cause 'baz' to collapse onto the line with 'foobar' unless we insert a br.
if (beforeParagraph.isNotNull() && !isEndOfParagraph(beforeParagraph))
insertNodeAt(createBreakElement(document()).get(), beforeParagraph.deepEquivalent().node(), beforeParagraph.deepEquivalent().offset());
+
+ destinationIndex = TextIterator::rangeLength(new Range(document(), Position(document(), 0), destination.deepEquivalent()));
setEndingSelection(destination);
EditCommandPtr cmd(new ReplaceSelectionCommand(document(), fragment.get(), true, false, false, true));
applyCommandToComposite(cmd);
+
+ if (preserveSelection && startIndex != -1) {
+ setEndingSelection(Selection(TextIterator::rangeFromLocationAndLength(document(), destinationIndex + startIndex, 0)->startPosition(),
+ TextIterator::rangeFromLocationAndLength(document(), destinationIndex + endIndex, 0)->startPosition(),
+ DOWNSTREAM));
+ }
}
PassRefPtr<Element> createBlockPlaceholderElement(Document* document)
void pushAnchorElementDown(WebCore::Node*);
void pushPartiallySelectedAnchorElementsDown();
- void moveParagraph(const VisiblePosition&, const VisiblePosition&, const VisiblePosition&);
+ void moveParagraph(const VisiblePosition&, const VisiblePosition&, const VisiblePosition&, bool preserveSelection = false);
+ void moveParagraphs(const VisiblePosition&, const VisiblePosition&, const VisiblePosition&, bool preserveSelection = false);
DeprecatedValueList<EditCommandPtr> m_cmds;
};
using namespace HTMLNames;
-static Position positionBeforePossibleContainingSpecialElement(const Position &pos, Node **containingSpecialElement)
-{
- if (isFirstVisiblePositionInSpecialElement(pos))
- return positionBeforeContainingSpecialElement(pos, containingSpecialElement);
- return pos;
-}
-
-static Position positionAfterPossibleContainingSpecialElement(const Position &pos, Node **containingSpecialElement)
-{
- if (isLastVisiblePositionInSpecialElement(pos))
- return positionAfterContainingSpecialElement(pos, containingSpecialElement);
- return pos;
-}
-
DeleteSelectionCommand::DeleteSelectionCommand(Document *document, bool smartDelete, bool mergeBlocksAfterDelete)
: CompositeEditCommand(document),
m_hasSelectionToDelete(false),
{
Node* startSpecialContainer = 0;
Node* endSpecialContainer = 0;
-
- Position start = positionOutsideContainingSpecialElement(m_selectionToDelete.start(), &startSpecialContainer);
- Position end = positionOutsideContainingSpecialElement(m_selectionToDelete.end(), &endSpecialContainer);
-
- m_upstreamStart = positionBeforePossibleContainingSpecialElement(start.upstream(), &startSpecialContainer);
- m_downstreamStart = positionBeforePossibleContainingSpecialElement(start.downstream(), 0);
- m_upstreamEnd = positionAfterPossibleContainingSpecialElement(end.upstream(), 0);
- m_downstreamEnd = positionAfterPossibleContainingSpecialElement(end.downstream(), &endSpecialContainer);
- if (!startSpecialContainer || !endSpecialContainer) {
- start = m_selectionToDelete.start();
- end = m_selectionToDelete.end();
- m_upstreamStart = start.upstream();
- m_downstreamStart = start.downstream();
- m_upstreamEnd = end.upstream();
- m_downstreamEnd = end.downstream();
+ Position start = m_selectionToDelete.start();
+ Position end = m_selectionToDelete.end();
+
+ while (1) {
+ startSpecialContainer = 0;
+ endSpecialContainer = 0;
+
+ Position s = positionOutsideContainingSpecialElement(start, &startSpecialContainer);
+ Position e = positionOutsideContainingSpecialElement(end, &endSpecialContainer);
+
+ if (!startSpecialContainer || !endSpecialContainer)
+ break;
+
+ start = s;
+ end = e;
}
+
+ m_upstreamStart = start.upstream();
+ m_downstreamStart = start.downstream();
+ m_upstreamEnd = end.upstream();
+ m_downstreamEnd = end.downstream();
}
void DeleteSelectionCommand::initializePositionData()
{
int startOffset = m_upstreamStart.offset();
Node* startNode = m_upstreamStart.node();
- // Don't remove the block containing the start of the selection being deleted even if the selection
- // starts at the start of that block.
- if (startNode->enclosingBlockFlowElement() && startNode->firstChild()) {
- startOffset = 0;
- startNode = startNode->firstChild();
- }
- VisiblePosition visibleEnd = VisiblePosition(m_downstreamEnd, m_selectionToDelete.affinity());
- bool endAtEndOfBlock = isEndOfBlock(visibleEnd);
-
- // Handle some special cases where the selection begins and ends on specific visible units.
- // Sometimes a node that is actually selected needs to be retained in order to maintain
- // user expectations for the delete operation. Here is an example:
- // 1. Open a new Blot or Mail document
- // 2. hit Return ten times or so
- // 3. Type a letter (do not hit Return after it)
- // 4. Type shift-up-arrow to select the line containing the letter and the previous blank line
- // 5. Hit Delete
- // You expect the insertion point to wind up at the start of the line where your selection began.
- // Because of the nature of HTML, the editing code needs to perform a special check to get
- // this behavior. So:
- // If the entire start block is selected, and the selection does not extend to the end of the
- // end of a block other than the block containing the selection start, then do not delete the
- // start block, otherwise delete the start block.
- if (startOffset == 1 && startNode && startNode->hasTagName(brTag)) {
- startNode = startNode->traverseNextNode();
+ // Never remove the start block.
+ if (startNode == m_startBlock && startOffset == 0) {
startOffset = 0;
- }
- if (m_startBlock != m_endBlock && isStartOfBlock(VisiblePosition(m_upstreamStart, m_selectionToDelete.affinity()))) {
- if (!m_startBlock->isAncestor(m_endBlock.get()) && !isStartOfBlock(visibleEnd) && endAtEndOfBlock) {
- // Delete all the children of the block, but not the block itself.
- // Use traverseNextNode in case the block has no children (e.g. is an empty table cell)
- startNode = m_startBlock->traverseNextNode();
- startOffset = 0;
- }
- } else if (startOffset >= startNode->caretMaxOffset() && (isAtomicNode(startNode) || startOffset == 0)) {
- // Move the start node to the next node in the tree since the startOffset is equal to
- // or beyond the start node's caretMaxOffset This means there is nothing visible to delete.
- // But don't do this if the node is not atomic - we don't want to move into the first child.
-
- // Also, before moving on, delete any insignificant text that may be present in a text node.
- if (startNode->isTextNode()) {
- // Delete any insignificant text from this node.
- Text *text = static_cast<Text *>(startNode);
- if (text->length() > (unsigned)startNode->caretMaxOffset())
- deleteTextFromNode(text, startNode->caretMaxOffset(), text->length() - startNode->caretMaxOffset());
- }
-
- // shift the start node to the next
startNode = startNode->traverseNextNode();
+ }
+
+ if (startOffset >= startNode->caretMaxOffset() && startNode->isTextNode()) {
+ Text *text = static_cast<Text *>(startNode);
+ if (text->length() > (unsigned)startNode->caretMaxOffset())
+ deleteTextFromNode(text, startNode->caretMaxOffset(), text->length() - startNode->caretMaxOffset());
+ }
+
+ if (startOffset >= maxDeepOffset(startNode)) {
+ startNode = startNode->traverseNextSibling();
startOffset = 0;
}
--- /dev/null
+/*
+ * 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 "Element.h"
+#include "InsertListCommand.h"
+#include "DocumentFragment.h"
+#include "htmlediting.h"
+#include "HTMLElement.h"
+#include "HTMLNames.h"
+#include "visible_units.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+Node* InsertListCommand::fixOrphanedListChild(Node* node)
+{
+ RefPtr<Element> listElement = createUnorderedListElement(document());
+ insertNodeBefore(listElement.get(), node);
+ removeNode(node);
+ appendNode(node, listElement.get());
+ return listElement.get();
+}
+
+InsertListCommand::InsertListCommand(Document* document, EListType type, const String& id)
+ : CompositeEditCommand(document), m_type(type), m_id(id), m_forceCreateList(false)
+{}
+
+bool InsertListCommand::modifyRange()
+{
+ ASSERT(endingSelection().isRange());
+ VisiblePosition visibleStart = endingSelection().visibleStart();
+ VisiblePosition visibleEnd = endingSelection().visibleEnd();
+ VisiblePosition startOfLastParagraph = startOfParagraph(visibleEnd);
+
+ if (startOfParagraph(visibleStart) == startOfLastParagraph)
+ return false;
+
+ Node* startList = enclosingList(visibleStart.deepEquivalent().node());
+ Node* endList = enclosingList(visibleEnd.deepEquivalent().node());
+ if (!startList || startList != endList)
+ m_forceCreateList = true;
+
+ setEndingSelection(visibleStart);
+ doApply();
+ visibleStart = endingSelection().visibleStart();
+ VisiblePosition nextParagraph = endOfParagraph(visibleStart).next();
+ while (nextParagraph.isNotNull() && nextParagraph != startOfLastParagraph) {
+ setEndingSelection(nextParagraph);
+ doApply();
+ nextParagraph = endOfParagraph(endingSelection().visibleStart()).next();
+ }
+ setEndingSelection(visibleEnd);
+ doApply();
+ visibleEnd = endingSelection().visibleEnd();
+ setEndingSelection(Selection(visibleStart.deepEquivalent(), visibleEnd.deepEquivalent(), DOWNSTREAM));
+ m_forceCreateList = false;
+
+ return true;
+}
+
+void InsertListCommand::doApply()
+{
+ if (endingSelection().isNone())
+ return;
+
+ if (endingSelection().isRange() && modifyRange())
+ return;
+
+ if (!endingSelection().rootEditableElement())
+ return;
+
+ Node* selectionNode = endingSelection().start().node();
+ const QualifiedName listTag = (m_type == OrderedListType) ? olTag : ulTag;
+ Node* listChildNode = enclosingListChild(selectionNode);
+ bool switchListType = false;
+ if (listChildNode) {
+ // Remove the list chlild.
+ Node* listNode = enclosingList(listChildNode);
+ if (!listNode)
+ listNode = fixOrphanedListChild(listChildNode);
+ if (!listNode->hasTagName(listTag))
+ // listChildNode will be removed from the list and a list of type m_type will be created.
+ switchListType = true;
+ Node* nextListChild;
+ Node* previousListChild;
+ VisiblePosition start;
+ VisiblePosition end;
+ if (listChildNode->hasTagName(liTag)) {
+ start = VisiblePosition(Position(listChildNode, 0));
+ end = VisiblePosition(Position(listChildNode, maxDeepOffset(listChildNode)));
+ nextListChild = listChildNode->nextSibling();
+ previousListChild = listChildNode->previousSibling();
+ } else {
+ // A paragraph is visually a list item minus a list marker. The paragraph will be moved.
+ start = startOfParagraph(endingSelection().visibleStart());
+ end = endOfParagraph(endingSelection().visibleEnd());
+ nextListChild = enclosingListChild(end.next().deepEquivalent().node());
+ ASSERT(nextListChild != listChildNode);
+ if (enclosingList(nextListChild) != listNode)
+ nextListChild = 0;
+ previousListChild = enclosingListChild(start.previous().deepEquivalent().node());
+ ASSERT(previousListChild != listChildNode);
+ if (enclosingList(previousListChild) != listNode)
+ previousListChild = 0;
+ }
+ // When removing a list, we must always create a placeholder to act as a point of insertion
+ // for the list content being removed.
+ RefPtr<Element> placeholder = createBreakElement(document());
+ if (nextListChild && previousListChild) {
+ splitElement(static_cast<Element *>(listNode), nextListChild);
+ insertNodeBefore(placeholder.get(), listNode);
+ } else if (nextListChild)
+ insertNodeBefore(placeholder.get(), listNode);
+ else
+ insertNodeAfter(placeholder.get(), listNode);
+ VisiblePosition insertionPoint = VisiblePosition(Position(placeholder.get(), 0));
+ moveParagraphs(start, end, insertionPoint, true);
+ }
+ if (!listChildNode || switchListType || m_forceCreateList) {
+ // Create list.
+ VisiblePosition start = startOfParagraph(endingSelection().visibleStart());
+ VisiblePosition end = endOfParagraph(endingSelection().visibleEnd());
+
+ // Check for adjoining lists.
+ VisiblePosition previousPosition = start.previous(true);
+ VisiblePosition nextPosition = end.next(true);
+ RefPtr<Element> listItemElement = createListItemElement(document());
+ Node* previousList = outermostEnclosingList(previousPosition.deepEquivalent().node());
+ Node* nextList = outermostEnclosingList(nextPosition.deepEquivalent().node());
+ if (previousList && !previousList->hasTagName(listTag))
+ previousList = 0;
+ if (nextList && !nextList->hasTagName(listTag))
+ nextList = 0;
+ // Stitch matching adjoining lists together.
+ if (previousList)
+ appendNode(listItemElement.get(), previousList);
+ else if (nextList)
+ appendNode(listItemElement.get(), nextList);
+ else {
+ // Create the list.
+ RefPtr<Element> listElement = m_type == OrderedListType ? createOrderedListElement(document()) : createUnorderedListElement(document());
+ static_cast<HTMLElement*>(listElement.get())->setId(m_id);
+ appendNode(listItemElement.get(), listElement.get());
+ insertNodeAt(listElement.get(), start.deepEquivalent().node(), start.deepEquivalent().offset());
+ }
+ moveParagraph(start, end, VisiblePosition(Position(listItemElement.get(), 0)), true);
+ if (nextList && previousList)
+ mergeIdenticalElements(static_cast<Element*>(previousList), static_cast<Element*>(nextList));
+ }
+}
+
+}
--- /dev/null
+/*
+ * 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 InsertListCommand_h
+#define InsertListCommand_h
+
+#include "CompositeEditCommand.h"
+
+namespace WebCore {
+
+class InsertListCommand : public CompositeEditCommand
+{
+public:
+ enum EListType { OrderedListType, UnorderedListType };
+ InsertListCommand(WebCore::Document*, EListType, const String&);
+ virtual void doApply();
+private:
+ Node* fixOrphanedListChild(Node*);
+ bool modifyRange();
+ EListType m_type;
+ String m_id;
+ bool m_forceCreateList;
+};
+
+} // namespace WebCore
+
+#endif // InsertListCommand_h
// 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());
+ ASSERT(m_refChild->parentNode()->isContentEditable() || !m_refChild->parentNode()->attached());
ExceptionCode ec = 0;
m_refChild->parentNode()->insertBefore(m_insertChild.get(), m_refChild.get(), ec);
applyStyle(m_style.get());
}
-
-PassRefPtr<Element> createListItemElement(Document *document)
-{
- ExceptionCode ec = 0;
- RefPtr<Element> breakNode = document->createElementNS(xhtmlNamespaceURI, "li", ec);
- ASSERT(ec == 0);
- return breakNode.release();
-}
-
static Node* embeddedSublist(Node* listItem)
{
// check for sublist embedded in the list item
#include "Frame.h"
#include "HTMLNames.h"
#include "HTMLImageElement.h"
+#include "InsertListCommand.h"
#include "ReplaceSelectionCommand.h"
#include "SelectionController.h"
#include "TypingCommand.h"
return true;
}
+bool execInsertUnorderedList(Frame *frame, bool userInterface, const String &value)
+{
+ EditCommandPtr(new InsertListCommand(frame->document(), InsertListCommand::UnorderedListType, value)).apply();
+ return true;
+}
+
+bool execInsertOrderedList(Frame *frame, bool userInterface, const String &value)
+{
+ EditCommandPtr(new InsertListCommand(frame->document(), InsertListCommand::OrderedListType, value)).apply();
+ return true;
+}
+
bool execItalic(Frame *frame, bool userInterface, const String &value)
{
bool isItalic = selectionStartHasStyle(frame, CSS_PROP_FONT_STYLE, "italic");
return stateStyle(frame, CSS_PROP_FONT_STYLE, "italic");
}
+Frame::TriState stateList(Frame *frame)
+{
+ return frame->selectionListState();
+}
+
Frame::TriState stateStrikethrough(Frame *frame)
{
return stateStyle(frame, CSS_PROP_TEXT_DECORATION, "line-through");
{ "InsertHTML", { execInsertHTML, enabledAnyEditableSelection, stateNone, valueNull } },
{ "InsertImage", { execInsertImage, enabledAnyRichlyEditableSelection, stateNone, valueNull } },
{ "InsertLineBreak", { execInsertLineBreak, enabledAnyEditableSelection, stateNone, valueNull } },
+ { "InsertOrderedList", { execInsertOrderedList, enabledAnyRichlyEditableSelection, stateList, valueNull } },
{ "InsertParagraph", { execInsertParagraph, enabledAnyEditableSelection, stateNone, valueNull } },
{ "InsertNewlineInQuotedContent", { execInsertNewlineInQuotedContent, enabledAnyRichlyEditableSelection, stateNone, valueNull } },
{ "InsertText", { execInsertText, enabledAnyEditableSelection, stateNone, valueNull } },
+ { "InsertUnorderedList", { execInsertUnorderedList, enabledAnyRichlyEditableSelection, stateList, valueNull } },
{ "Italic", { execItalic, enabledAnyRichlyEditableSelection, stateItalic, valueNull } },
{ "JustifyCenter", { execJustifyCenter, enabledAnyRichlyEditableSelection, stateNone, valueNull } },
{ "JustifyFull", { execJustifyFull, enabledAnyRichlyEditableSelection, stateNone, valueNull } },
// InsertInputSubmit (not supported)
// InsertInputText (not supported)
// InsertMarquee (not supported)
- // InsertOrderedList (not supported)
// InsertSelectDropDown (not supported)
// InsertSelectListBox (not supported)
// InsertTextArea (not supported)
- // InsertUnorderedList (not supported)
// LiveResize (not supported)
// MultipleSelection (not supported)
// Open (not supported)
return;
}
- while (m_node && m_node != m_pastEndNode) {
+ while (m_node && m_node != m_pastEndNode && !(m_node == m_endContainer && m_endOffset == 0)) {
// handle current node according to its type
if (!m_handledNode) {
RenderObject *renderer = m_node->renderer();
m_affinity = DOWNSTREAM;
}
-VisiblePosition VisiblePosition::next() const
+VisiblePosition VisiblePosition::next(bool stayInCurrentEditableRegion) const
{
- return VisiblePosition(nextVisiblePosition(m_deepPosition), m_affinity);
+ VisiblePosition next(nextVisiblePosition(m_deepPosition), m_affinity);
+ Element* currentRoot = rootEditableElement();
+ return !stayInCurrentEditableRegion || next.rootEditableElement() == currentRoot ? next : VisiblePosition();
}
-VisiblePosition VisiblePosition::previous() const
+VisiblePosition VisiblePosition::previous(bool stayInCurrentEditableRegion) const
{
// find first previous DOM position that is visible
Position pos = previousVisiblePosition(m_deepPosition);
ASSERT(inSameLine(temp, result));
}
#endif
- return result;
+ Element* currentRoot = rootEditableElement();
+ return !stayInCurrentEditableRegion || result.rootEditableElement() == currentRoot ? result : VisiblePosition();
}
Position VisiblePosition::previousVisiblePosition(const Position& pos)
void setAffinity(EAffinity affinity) { m_affinity = affinity; }
// next() and previous() will increment/decrement by a character cluster.
- VisiblePosition next() const;
- VisiblePosition previous() const;
+ VisiblePosition next(bool stayInCurrentEditableRegion = false) const;
+ VisiblePosition previous(bool stayInCurrentEditableRegion = false) const;
bool isLastInBlock() const;
using namespace HTMLNames;
+static Node* highestAncestor(Node* node)
+{
+ ASSERT(node);
+ Node* parent = node;
+ while ((node = node->parentNode()))
+ parent = node;
+ return parent;
+}
+
// Atomic means that the node has no children, or has children which are ignored for the
// purposes of editing.
bool isAtomicNode(const Node *node)
{
if (!node)
return 0;
-
- for (Node* n = node->parentNode(); n; n = n->parentNode())
+ Node* root = (node->inDocument()) ? node->rootEditableElement() : highestAncestor(node);
+ ASSERT(root);
+ for (Node* n = node->parentNode(); n && (n == root || n->isAncestor(root)); n = n->parentNode())
if (n->hasTagName(ulTag) || n->hasTagName(olTag))
return n;
Node *enclosingListChild (Node *node)
{
- // check not just for li elements per se, but also
- // for any node whose parent is a list element
+ // Check for a list item element, or for a node whose parent is a list element. Such a node
+ // will appear visually as a list item (but without a list marker)
for (Node *n = node; n && n->parentNode(); n = n->parentNode()) {
- if (isListElement(n->parentNode()))
+ if (n->hasTagName(liTag) || isListElement(n->parentNode()))
return n;
}
return 0;
}
+Node* outermostEnclosingList(Node* node)
+{
+ Node* listNode = 0;
+ Node* nextNode = node;
+ while ((nextNode = enclosingList(nextNode)))
+ listNode = nextNode;
+ return listNode;
+}
+
// FIXME: do not require renderer, so that this can be used within fragments, or rename to isRenderedTable()
bool isTableElement(Node *n)
{
return element.release();
}
+PassRefPtr<Element> createListItemElement(Document *document)
+{
+ ExceptionCode ec = 0;
+ RefPtr<Element> breakNode = document->createElementNS(xhtmlNamespaceURI, "li", ec);
+ ASSERT(ec == 0);
+ return breakNode.release();
+}
+
bool isTabSpanNode(const Node *node)
{
return (node && node->isElementNode() && static_cast<const Element *>(node)->getAttribute("class") == AppleTabSpanClass);
PassRefPtr<Element> createBreakElement(Document*);
PassRefPtr<Element> createOrderedListElement(Document*);
PassRefPtr<Element> createUnorderedListElement(Document*);
+PassRefPtr<Element> createListItemElement(Document*);
bool isTabSpanNode(const Node*);
bool isTabSpanTextNode(const Node*);
Node* enclosingTableCell(Node*);
bool isListElement(Node*);
Node* enclosingList(Node*);
+Node* outermostEnclosingList(Node*);
Node* enclosingListChild(Node*);
bool isTableElement(Node*);
bool isFirstVisiblePositionAfterTableElement(const Position&);
}
}
+Frame::TriState Frame::selectionListState() const
+{
+ TriState state = falseTriState;
+
+ if (!d->m_selection.isRange()) {
+ Node* selectionNode = d->m_selection.selection().start().node();
+ if (enclosingList(selectionNode))
+ return trueTriState;
+ } else {
+ //FIXME: Support ranges
+ }
+
+ return state;
+}
+
Frame::TriState Frame::selectionHasStyle(CSSStyleDeclaration *style) const
{
bool atStart = true;
void applyParagraphStyle(CSSStyleDeclaration* , EditAction editingAction=EditActionUnspecified);
TriState selectionHasStyle(CSSStyleDeclaration*) const;
bool selectionStartHasStyle(CSSStyleDeclaration*) const;
+ TriState selectionListState() const;
String selectionStartStylePropertyValue(int stylePropertyID) const;
void applyEditingStyleToBodyElement() const;
void removeEditingStyleFromBodyElement() const;
+2006-06-08 Justin Garcia <justin.garcia@apple.com>
+
+ Reviewed by levi
+
+ <http://bugzilla.opendarwin.org/show_bug.cgi?id=4468>
+ Implement execCommand(Insert{Un}OrderedList)
+
+ * WebView/WebFrame.m:
+ (-[WebFrame _findFrameWithSelection]): Removed an assertion
+ that we only have one frame with a selection.
+ * WebView/WebView.m:
+ (-[WebView selectedFrame]): Ditto.
+
2006-06-08 Timothy Hatcher <timothy@apple.com>
Reviewed by Darin and John.
- (WebFrame *)_findFrameWithSelection
{
- ASSERT([self _atMostOneFrameHasSelection]);
-
for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
if ([frame _hasSelection])
return frame;
// This is faster than searching the frame hierarchy, and will give us a result even in the case
// where the focused frame doesn't actually contain a selection.
WebFrame *focusedFrame = [self _focusedFrame];
- if (focusedFrame) {
-#ifndef NDEBUG
- WebFrame *frameWithSelection = [[self mainFrame] _findFrameWithSelection];
-#endif
- ASSERT(frameWithSelection == nil || frameWithSelection == focusedFrame);
+ if (focusedFrame)
return focusedFrame;
- }
// If the first responder is outside of our view tree, we search for a frame containing a selection.
// There should be at most only one of these.