--- /dev/null
+layer at (0,0) size 800x600
+ RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderBlock {DIV} at (0,0) size 784x240 [border: (2px solid #0000FF)]
+ RenderBlock {DIV} at (14,14) size 756x84
+ RenderText {TEXT} at (0,0) size 67x28
+ text run at (0,0) width 67: "Tests: "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText {TEXT} at (0,28) size 742x56
+ text run at (0,28) width 742: "Deleting when a selection starts in a blank line created by a block with a BR"
+ text run at (0,56) width 491: "placeholder in it and extends to the end of a block."
+ RenderBlock {DIV} at (14,114) size 756x112
+ RenderText {TEXT} at (0,0) size 189x28
+ text run at (0,0) width 189: "Expected Results: "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText {TEXT} at (0,28) size 734x84
+ text run at (0,28) width 730: "Should see the three lines in the red box. First line should be \"A\". Next two"
+ text run at (0,56) width 734: "lines should be empty. Insertion point should be blinking on the second line"
+ text run at (0,84) width 198: "(the first blank one)."
+ RenderBlock {DIV} at (0,264) size 784x88
+ RenderBlock {DIV} at (0,0) size 784x88 [border: (2px solid #FF0000)]
+ RenderBlock {P} at (2,2) size 780x28
+ RenderText {TEXT} at (0,0) size 17x28
+ text run at (0,0) width 17: "A"
+ RenderBlock {P} at (2,30) size 780x28
+ RenderBR {BR} at (0,0) size 0x28
+ RenderBlock {P} at (2,58) size 780x28
+ RenderBR {BR} at (0,0) size 0x28
+selection is CARET:
+start: position 0 of child 1 {BR} of child 4 {P} of child 1 {DIV} of root {DIV}
+upstream: position 0 of child 4 {P} of child 1 {DIV} of root {DIV}
+downstream: position 0 of child 1 {BR} of child 4 {P} of child 1 {DIV} of root {DIV}
--- /dev/null
+<html>
+<head>
+
+<style>
+.editing {
+ border: 2px solid red;
+ font-size: 24px;
+}
+.explanation {
+ border: 2px solid blue;
+ padding: 12px;
+ font-size: 24px;
+ margin-bottom: 24px;
+}
+.scenario { margin-bottom: 16px;}
+.scenario:first-line { font-weight: bold; margin-bottom: 16px;}
+.expected-results:first-line { font-weight: bold }
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+ moveSelectionForwardByLineCommand();
+ extendSelectionForwardByLineCommand();
+ extendSelectionForwardByCharacterCommand();
+ deleteCommand();
+}
+
+</script>
+
+<title>Editing Test</title>
+</head>
+<body>
+
+<div class="explanation">
+<div class="scenario">
+Tests:
+<br>
+Deleting when a selection starts in a blank line created by a block with a BR placeholder in it and extends to the end of a block.
+</div>
+<div class="expected-results">
+Expected Results:
+<br>
+Should see the three lines in the red box. First line should be "A". Next two lines should be empty. Insertion point should
+be blinking on the second line (the first blank one).
+</div>
+</div>
+
+<div contenteditable id="root" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;">
+<div id="test" class="editing">
+<p style="margin-top: 0; margin-bottom: 0">A</p>
+<p style="margin-top: 0; margin-bottom: 0"><BR class="khtml-block-placeholder"></p>
+<p style="margin-top: 0; margin-bottom: 0">A</p>
+<p style="margin-top: 0; margin-bottom: 0"><BR class="khtml-block-placeholder"></p>
+</div>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
--- /dev/null
+layer at (0,0) size 800x600
+ RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderBlock {DIV} at (0,0) size 784x240 [border: (2px solid #0000FF)]
+ RenderBlock {DIV} at (14,14) size 756x84
+ RenderText {TEXT} at (0,0) size 67x28
+ text run at (0,0) width 67: "Tests: "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText {TEXT} at (0,28) size 741x56
+ text run at (0,28) width 741: "Deleting when a selection starts in a blank line created by a BR element and"
+ text run at (0,56) width 285: "extends to the end of a block."
+ RenderBlock {DIV} at (14,114) size 756x112
+ RenderText {TEXT} at (0,0) size 189x28
+ text run at (0,0) width 189: "Expected Results: "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText {TEXT} at (0,28) size 734x84
+ text run at (0,28) width 730: "Should see the three lines in the red box. First line should be \"A\". Next two"
+ text run at (0,56) width 734: "lines should be empty. Insertion point should be blinking on the second line"
+ text run at (0,84) width 198: "(the first blank one)."
+ RenderBlock {DIV} at (0,264) size 784x88
+ RenderBlock {DIV} at (0,0) size 784x88 [border: (2px solid #FF0000)]
+ RenderBlock {P} at (2,2) size 780x28
+ RenderText {TEXT} at (0,0) size 17x28
+ text run at (0,0) width 17: "A"
+ RenderBlock {P} at (2,30) size 780x28
+ RenderBR {BR} at (0,0) size 0x28
+ RenderBlock (anonymous) at (2,58) size 780x0
+ RenderBlock {P} at (2,58) size 780x28
+ RenderBR {BR} at (0,0) size 0x28
+selection is CARET:
+start: position 0 of child 1 {BR} of child 3 {P} of child 1 {DIV} of root {DIV}
+upstream: position 0 of child 3 {P} of child 1 {DIV} of root {DIV}
+downstream: position 0 of child 1 {BR} of child 3 {P} of child 1 {DIV} of root {DIV}
--- /dev/null
+<html>
+<head>
+
+<style>
+.editing {
+ border: 2px solid red;
+ font-size: 24px;
+}
+.explanation {
+ border: 2px solid blue;
+ padding: 12px;
+ font-size: 24px;
+ margin-bottom: 24px;
+}
+.scenario { margin-bottom: 16px;}
+.scenario:first-line { font-weight: bold; margin-bottom: 16px;}
+.expected-results:first-line { font-weight: bold }
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+ moveSelectionForwardByLineCommand();
+ extendSelectionForwardByLineCommand();
+ extendSelectionForwardByCharacterCommand();
+ deleteCommand();
+}
+
+</script>
+
+<title>Editing Test</title>
+</head>
+<body>
+
+<div class="explanation">
+<div class="scenario">
+Tests:
+<br>
+Deleting when a selection starts in a blank line created by a BR element and extends to the end of a block.
+</div>
+<div class="expected-results">
+Expected Results:
+<br>
+Should see the three lines in the red box. First line should be "A". Next two lines should be empty. Insertion point should
+be blinking on the second line (the first blank one).
+</div>
+</div>
+
+<div contenteditable id="root" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;">
+<div id="test" class="editing">
+<p style="margin-top: 0; margin-bottom: 0">A</p>
+<BR>
+<p style="margin-top: 0; margin-bottom: 0">A</p>
+<p style="margin-top: 0; margin-bottom: 0"><BR class="khtml-block-placeholder"></p>
+</div>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
--- /dev/null
+layer at (0,0) size 800x600
+ RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderBlock {DIV} at (0,0) size 784x240 [border: (2px solid #0000FF)]
+ RenderBlock {DIV} at (14,14) size 756x112
+ RenderText {TEXT} at (0,0) size 67x28
+ text run at (0,0) width 67: "Tests: "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText {TEXT} at (0,28) size 742x84
+ text run at (0,28) width 742: "Deleting when a selection starts in a blank line created by a block with a BR"
+ text run at (0,56) width 730: "placeholder in it and extends to a character that is not at the end of a block."
+ text run at (0,84) width 735: "This ensures that some of our \"special-case\" code does not run for this case."
+ RenderBlock {DIV} at (14,142) size 756x84
+ RenderText {TEXT} at (0,0) size 189x28
+ text run at (0,0) width 189: "Expected Results: "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText {TEXT} at (0,28) size 682x56
+ text run at (0,28) width 682: "Should see the two lines in the red box. Each should contain \"A\" only."
+ text run at (0,56) width 620: "Insertion point should be blinking at the start of the second line."
+ RenderBlock {DIV} at (0,264) size 784x60
+ RenderBlock {DIV} at (0,0) size 784x60 [border: (2px solid #FF0000)]
+ RenderBlock {P} at (2,2) size 780x28
+ RenderText {TEXT} at (0,0) size 17x28
+ text run at (0,0) width 17: "A"
+ RenderBlock {P} at (2,30) size 780x28
+ RenderText {TEXT} at (0,0) size 17x28
+ text run at (0,0) width 17: "A"
+selection is CARET:
+start: position 0 of child 1 {TEXT} of child 4 {P} of child 1 {DIV} of root {DIV}
+upstream: position 0 of child 4 {P} of child 1 {DIV} of root {DIV}
+downstream: position 0 of child 1 {TEXT} of child 4 {P} of child 1 {DIV} of root {DIV}
--- /dev/null
+<html>
+<head>
+
+<style>
+.editing {
+ border: 2px solid red;
+ font-size: 24px;
+}
+.explanation {
+ border: 2px solid blue;
+ padding: 12px;
+ font-size: 24px;
+ margin-bottom: 24px;
+}
+.scenario { margin-bottom: 16px;}
+.scenario:first-line { font-weight: bold; margin-bottom: 16px;}
+.expected-results:first-line { font-weight: bold }
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+ moveSelectionForwardByLineCommand();
+ extendSelectionForwardByLineCommand();
+ extendSelectionForwardByCharacterCommand();
+ deleteCommand();
+}
+
+</script>
+
+<title>Editing Test</title>
+</head>
+<body>
+
+<div class="explanation">
+<div class="scenario">
+Tests:
+<br>
+Deleting when a selection starts in a blank line created by a block with a BR placeholder in it and extends to a character
+that is not at the end of a block. This ensures that some of our "special-case" code does not run for this case.
+</div>
+<div class="expected-results">
+Expected Results:
+<br>
+Should see the two lines in the red box. Each should contain "A" only. Insertion point should
+be blinking at the start of the second line.
+</div>
+</div>
+
+<div contenteditable id="root" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;">
+<div id="test" class="editing">
+<p style="margin-top: 0; margin-bottom: 0">A</p>
+<p style="margin-top: 0; margin-bottom: 0"><BR class="khtml-block-placeholder"></p>
+<p style="margin-top: 0; margin-bottom: 0">AA</p>
+</div>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
--- /dev/null
+layer at (0,0) size 800x600
+ RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderBlock {DIV} at (0,0) size 784x240 [border: (2px solid #0000FF)]
+ RenderBlock {DIV} at (14,14) size 756x112
+ RenderText {TEXT} at (0,0) size 67x28
+ text run at (0,0) width 67: "Tests: "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText {TEXT} at (0,28) size 751x84
+ text run at (0,28) width 741: "Deleting when a selection starts in a blank line created by a BR element and"
+ text run at (0,56) width 751: "extends to a character that is not at the end of a block. This ensures that some"
+ text run at (0,84) width 508: "of our \"special-case\" code does not run for this case."
+ RenderBlock {DIV} at (14,142) size 756x84
+ RenderText {TEXT} at (0,0) size 189x28
+ text run at (0,0) width 189: "Expected Results: "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText {TEXT} at (0,28) size 682x56
+ text run at (0,28) width 682: "Should see the two lines in the red box. Each should contain \"A\" only."
+ text run at (0,56) width 620: "Insertion point should be blinking at the start of the second line."
+ RenderBlock {DIV} at (0,264) size 784x60
+ RenderBlock {DIV} at (0,0) size 784x60 [border: (2px solid #FF0000)]
+ RenderBlock {P} at (2,2) size 780x28
+ RenderText {TEXT} at (0,0) size 17x28
+ text run at (0,0) width 17: "A"
+ RenderBlock (anonymous) at (2,30) size 780x0
+ RenderBlock {P} at (2,30) size 780x28
+ RenderText {TEXT} at (0,0) size 17x28
+ text run at (0,0) width 17: "A"
+selection is CARET:
+start: position 0 of child 1 {TEXT} of child 3 {P} of child 1 {DIV} of root {DIV}
+upstream: position 0 of child 3 {P} of child 1 {DIV} of root {DIV}
+downstream: position 0 of child 1 {TEXT} of child 3 {P} of child 1 {DIV} of root {DIV}
--- /dev/null
+<html>
+<head>
+
+<style>
+.editing {
+ border: 2px solid red;
+ font-size: 24px;
+}
+.explanation {
+ border: 2px solid blue;
+ padding: 12px;
+ font-size: 24px;
+ margin-bottom: 24px;
+}
+.scenario { margin-bottom: 16px;}
+.scenario:first-line { font-weight: bold; margin-bottom: 16px;}
+.expected-results:first-line { font-weight: bold }
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+ moveSelectionForwardByLineCommand();
+ extendSelectionForwardByLineCommand();
+ extendSelectionForwardByCharacterCommand();
+ deleteCommand();
+}
+
+</script>
+
+<title>Editing Test</title>
+</head>
+<body>
+
+<div class="explanation">
+<div class="scenario">
+Tests:
+<br>
+Deleting when a selection starts in a blank line created by a BR element and extends to a character
+that is not at the end of a block. This ensures that some of our "special-case" code does not run for this case.
+</div>
+<div class="expected-results">
+Expected Results:
+<br>
+Should see the two lines in the red box. Each should contain "A" only. Insertion point should
+be blinking at the start of the second line.
+</div>
+</div>
+
+<div contenteditable id="root" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;">
+<div id="test" class="editing">
+<p style="margin-top: 0; margin-bottom: 0">A</p>
+<BR>
+<p style="margin-top: 0; margin-bottom: 0">AA</p>
+</div>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
--- /dev/null
+layer at (0,0) size 800x600
+ RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderBlock {DIV} at (0,0) size 784x240 [border: (2px solid #0000FF)]
+ RenderBlock {DIV} at (14,14) size 756x84
+ RenderText {TEXT} at (0,0) size 67x28
+ text run at (0,0) width 67: "Tests: "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText {TEXT} at (0,28) size 741x56
+ text run at (0,28) width 741: "Deleting when a selection starts in a blank line created by a BR element and"
+ text run at (0,56) width 346: "extends to the end of the document."
+ RenderBlock {DIV} at (14,114) size 756x112
+ RenderText {TEXT} at (0,0) size 189x28
+ text run at (0,0) width 189: "Expected Results: "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText {TEXT} at (0,28) size 743x84
+ text run at (0,28) width 716: "Should see the two lines in the red box. First line should be \"A\". Next one"
+ text run at (0,56) width 743: "should be empty. Insertion point should be blinking at the start of the second"
+ text run at (0,84) width 43: "line."
+ RenderBlock {DIV} at (0,264) size 784x60
+ RenderBlock {DIV} at (0,0) size 784x60 [border: (2px solid #FF0000)]
+ RenderBlock {P} at (2,2) size 780x28
+ RenderText {TEXT} at (0,0) size 17x28
+ text run at (0,0) width 17: "A"
+ RenderBlock (anonymous) at (2,30) size 780x28
+ RenderBR {BR} at (0,0) size 0x28
+selection is CARET:
+start: position 0 of child 3 {BR} of child 1 {DIV} of root {DIV}
+upstream: position 0 of child 3 {BR} of child 1 {DIV} of root {DIV}
+downstream: position 0 of child 3 {BR} of child 1 {DIV} of root {DIV}
--- /dev/null
+<html>
+<head>
+
+<style>
+.editing {
+ border: 2px solid red;
+ font-size: 24px;
+}
+.explanation {
+ border: 2px solid blue;
+ padding: 12px;
+ font-size: 24px;
+ margin-bottom: 24px;
+}
+.scenario { margin-bottom: 16px;}
+.scenario:first-line { font-weight: bold; margin-bottom: 16px;}
+.expected-results:first-line { font-weight: bold }
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+ moveSelectionForwardByLineCommand();
+ extendSelectionForwardByLineCommand();
+ extendSelectionForwardByLineCommand();
+ deleteCommand();
+}
+
+</script>
+
+<title>Editing Test</title>
+</head>
+<body>
+
+<div class="explanation">
+<div class="scenario">
+Tests:
+<br>
+Deleting when a selection starts in a blank line created by a BR element and extends to the end of the document.
+</div>
+<div class="expected-results">
+Expected Results:
+<br>
+Should see the two lines in the red box. First line should be "A". Next one should be empty. Insertion point should
+be blinking at the start of the second line.
+</div>
+</div>
+
+<div contenteditable id="root" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;">
+<div id="test" class="editing">
+<p style="margin-top: 0; margin-bottom: 0">A</p>
+<BR>
+<p style="margin-top: 0; margin-bottom: 0">A</p>
+<BR>
+</div>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
--- /dev/null
+layer at (0,0) size 800x600
+ RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderBlock {DIV} at (0,0) size 784x240 [border: (2px solid #0000FF)]
+ RenderBlock {DIV} at (14,14) size 756x84
+ RenderText {TEXT} at (0,0) size 67x28
+ text run at (0,0) width 67: "Tests: "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText {TEXT} at (0,28) size 742x56
+ text run at (0,28) width 742: "Deleting when a selection starts in a blank line created by a block with a BR"
+ text run at (0,56) width 552: "placeholder in it and extends to the end of the document."
+ RenderBlock {DIV} at (14,114) size 756x112
+ RenderText {TEXT} at (0,0) size 189x28
+ text run at (0,0) width 189: "Expected Results: "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText {TEXT} at (0,28) size 743x84
+ text run at (0,28) width 716: "Should see the two lines in the red box. First line should be \"A\". Next one"
+ text run at (0,56) width 743: "should be empty. Insertion point should be blinking at the start of the second"
+ text run at (0,84) width 43: "line."
+ RenderBlock {DIV} at (0,264) size 784x60
+ RenderBlock {DIV} at (0,0) size 784x60 [border: (2px solid #FF0000)]
+ RenderBlock {P} at (2,2) size 780x28
+ RenderText {TEXT} at (0,0) size 17x28
+ text run at (0,0) width 17: "A"
+ RenderBlock {P} at (2,30) size 780x28
+ RenderBR {BR} at (0,0) size 0x28
+selection is CARET:
+start: position 0 of child 1 {BR} of child 4 {P} of child 1 {DIV} of root {DIV}
+upstream: position 0 of child 4 {P} of child 1 {DIV} of root {DIV}
+downstream: position 0 of child 1 {BR} of child 4 {P} of child 1 {DIV} of root {DIV}
--- /dev/null
+<html>
+<head>
+
+<style>
+.editing {
+ border: 2px solid red;
+ font-size: 24px;
+}
+.explanation {
+ border: 2px solid blue;
+ padding: 12px;
+ font-size: 24px;
+ margin-bottom: 24px;
+}
+.scenario { margin-bottom: 16px;}
+.scenario:first-line { font-weight: bold; margin-bottom: 16px;}
+.expected-results:first-line { font-weight: bold }
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+ moveSelectionForwardByLineCommand();
+ extendSelectionForwardByLineCommand();
+ extendSelectionForwardByLineCommand();
+ deleteCommand();
+}
+
+</script>
+
+<title>Editing Test</title>
+</head>
+<body>
+
+<div class="explanation">
+<div class="scenario">
+Tests:
+<br>
+Deleting when a selection starts in a blank line created by a block with a BR placeholder in it and extends to the end of the document.
+</div>
+<div class="expected-results">
+Expected Results:
+<br>
+Should see the two lines in the red box. First line should be "A". Next one should be empty. Insertion point should
+be blinking at the start of the second line.
+</div>
+</div>
+
+<div contenteditable id="root" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;">
+<div id="test" class="editing">
+<p style="margin-top: 0; margin-bottom: 0">A</p>
+<p style="margin-top: 0; margin-bottom: 0"><BR class="khtml-block-placeholder"></p>
+<p style="margin-top: 0; margin-bottom: 0">A</p>
+<p style="margin-top: 0; margin-bottom: 0"><BR class="khtml-block-placeholder"></p>
+</div>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
+2005-02-03 Ken Kocienda <kocienda@apple.com>
+
+ Reviewed by Chris
+
+ Fix for this bug:
+
+ <rdar://problem/3986155> Insertion point goes to beginning of doc after deleting
+
+ * khtml/editing/htmlediting.cpp:
+ (khtml::DeleteSelectionCommand::setStartNode): New convenience to handle reference counting when setting.
+ (khtml::DeleteSelectionCommand::handleGeneralDelete): This contains the crux of the bug fix. Improve tests
+ that detect when a selected node needs to be retained, rather than deleted, to preserve the intent of the user.
+ This has the side effect of causing the insertion point placement code to succeed rather than fail. Before
+ this fix, the failure of the insertion point placement code caused the insertion point to jump to the start
+ of the document, which is the symptom that can be perceived by users when editing.
+ * khtml/editing/htmlediting.h: Add setStartNode declaration.
+ * khtml/editing/visible_units.cpp:
+ (khtml::startOfBlock): This function had a stubbed-in non-tested implementation. Implement and
+ * layout-tests/editing/deleting/delete-at-paragraph-boundaries-001-expected.txt: Added.
+ * layout-tests/editing/deleting/delete-at-paragraph-boundaries-001.html: Added.
+ * layout-tests/editing/deleting/delete-at-paragraph-boundaries-002-expected.txt: Added.
+ * layout-tests/editing/deleting/delete-at-paragraph-boundaries-002.html: Added.
+ * layout-tests/editing/deleting/delete-at-paragraph-boundaries-003-expected.txt: Added.
+ * layout-tests/editing/deleting/delete-at-paragraph-boundaries-003.html: Added.
+ * layout-tests/editing/deleting/delete-at-paragraph-boundaries-004-expected.txt: Added.
+ * layout-tests/editing/deleting/delete-at-paragraph-boundaries-004.html: Added.
+ * layout-tests/editing/deleting/delete-at-paragraph-boundaries-005-expected.txt: Added.
+ * layout-tests/editing/deleting/delete-at-paragraph-boundaries-005.html: Added.
+ * layout-tests/editing/deleting/delete-at-paragraph-boundaries-006-expected.txt: Added.
+ * layout-tests/editing/deleting/delete-at-paragraph-boundaries-006.html: Added.
+
=== Safari-183 ===
2005-02-03 Richard Williamson <rjw@apple.com>
// However, the end of the document is an exception and always selects the previous word even though it could be
// both the start of a line and after a hard line break.
VisiblePosition pos(m_base);
- EWordSide side = LeftWordIfOnBoundary;
- if ((isEndOfParagraph(pos) || isStartOfLine(pos, m_affinity)) && !isEndOfDocument(pos))
- side = RightWordIfOnBoundary;
- m_start = startOfWord(pos, side).deepEquivalent();
- m_end = endOfWord(pos, side).deepEquivalent();
+ if (isStartOfBlock(pos) && isEndOfBlock(pos)) {
+ m_start = m_end = m_base;
+ }
+ else {
+ EWordSide side = LeftWordIfOnBoundary;
+ //if ((isEndOfParagraph(pos) || isStartOfLine(pos, m_affinity)) && !isEndOfDocument(pos))
+ // side = RightWordIfOnBoundary;
+ m_start = startOfWord(pos, side).deepEquivalent();
+ m_end = endOfWord(pos, side).deepEquivalent();
+ }
} else if (m_baseIsStart) {
m_start = startOfWord(VisiblePosition(m_base)).deepEquivalent();
m_end = endOfWord(VisiblePosition(m_extent)).deepEquivalent();
return false;
}
+void DeleteSelectionCommand::setStartNode(NodeImpl *node)
+{
+ NodeImpl *old = m_startNode;
+ m_startNode = node;
+ if (m_startNode)
+ m_startNode->ref();
+ if (old)
+ old->deref();
+}
+
void DeleteSelectionCommand::handleGeneralDelete()
{
int startOffset = m_upstreamStart.offset();
-
- if (startOffset == 0 && m_startNode->isBlockFlow() && m_startBlock != m_endBlock && !m_endBlock->isAncestor(m_startBlock)) {
- // The block containing the start of the selection is completely selected.
- // See if it can be deleted in one step right here.
- ASSERT(!m_downstreamEnd.node()->isAncestor(m_startNode));
-
- // The next few lines help us deal with a bit of a quirk.
- // 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
- // a) the selection does not extend to the end of the document, then delete the start block, otherwise
- // b) the selection extends to the end of the document, then do not delete the start block.
- //
- NodeImpl *old = m_startNode;
- VisiblePosition visibleEnd = VisiblePosition(m_downstreamEnd);
- if (isEndOfDocument(visibleEnd) && !isFirstVisiblePositionOnLine(visibleEnd)) {
- m_startNode = m_startBlock->firstChild();
+ VisiblePosition visibleEnd = VisiblePosition(m_downstreamEnd);
+ 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.
+ // A similar case is provided to cover selections starting in BR elements.
+ if (startOffset == 1 && m_startNode->id() == ID_BR) {
+ setStartNode(m_startNode->traverseNextNode());
+ startOffset = 0;
+ }
+ if (m_startBlock != m_endBlock && startOffset == 0 && m_startNode->id() == ID_BR && endAtEndOfBlock) {
+ // Don't delete the BR element
+ setStartNode(m_startNode->traverseNextNode());
+ }
+ else if (m_startBlock != m_endBlock && isStartOfBlock(VisiblePosition(m_upstreamStart))) {
+ if (!isStartOfBlock(visibleEnd) && endAtEndOfBlock) {
+ // Delete all the children of the block, but not the block itself.
+ setStartNode(m_startBlock->firstChild());
}
else {
- // shift the start node to the start of the next block.
- m_startNode = m_startBlock->traverseNextSibling();
+ // The whole block can be deleted.
+ setStartNode(m_startBlock->traverseNextSibling());
removeFullySelectedNode(m_startBlock);
}
-
- if (m_startNode)
- m_startNode->ref();
- old->deref();
startOffset = 0;
}
else if (startOffset >= m_startNode->caretMaxOffset()) {
}
// shift the start node to the next
- NodeImpl *old = m_startNode;
- m_startNode = old->traverseNextNode();
- m_startNode->ref();
- old->deref();
+ setStartNode(m_startNode->traverseNextNode());
startOffset = 0;
}
void calculateTypingStyleAfterDelete(bool insertedPlaceholder);
void clearTransientState();
+ void setStartNode(DOM::NodeImpl *);
+
bool m_hasSelectionToDelete;
bool m_smartDelete;
bool m_mergeBlocksAfterDelete;
// However, the end of the document is an exception and always selects the previous word even though it could be
// both the start of a line and after a hard line break.
VisiblePosition pos(m_base);
- EWordSide side = LeftWordIfOnBoundary;
- if ((isEndOfParagraph(pos) || isStartOfLine(pos, m_affinity)) && !isEndOfDocument(pos))
- side = RightWordIfOnBoundary;
- m_start = startOfWord(pos, side).deepEquivalent();
- m_end = endOfWord(pos, side).deepEquivalent();
+ if (isStartOfBlock(pos) && isEndOfBlock(pos)) {
+ m_start = m_end = m_base;
+ }
+ else {
+ EWordSide side = LeftWordIfOnBoundary;
+ //if ((isEndOfParagraph(pos) || isStartOfLine(pos, m_affinity)) && !isEndOfDocument(pos))
+ // side = RightWordIfOnBoundary;
+ m_start = startOfWord(pos, side).deepEquivalent();
+ m_end = endOfWord(pos, side).deepEquivalent();
+ }
} else if (m_baseIsStart) {
m_start = startOfWord(VisiblePosition(m_base)).deepEquivalent();
m_end = endOfWord(VisiblePosition(m_extent)).deepEquivalent();
NodeImpl *de = d->documentElement();
if (!de)
return VisiblePosition();
+ NodeImpl *boundary = n->enclosingBlockFlowElement();
+ if (!boundary)
+ return VisiblePosition();
+ bool isContentEditable = boundary->isContentEditable();
+ while (boundary && boundary != de && boundary->parentNode() && isContentEditable == boundary->parentNode()->isContentEditable()) {
+ boundary = boundary->parentNode();
+ }
Range searchRange(d);
- searchRange.setStartBefore(de);
+ searchRange.setStartBefore(boundary);
Position end(pos.equivalentRangeCompliantPosition());
searchRange.setEnd(end.node(), end.offset());
SimplifiedBackwardsTextIterator it(searchRange);
NodeImpl *de = d->documentElement();
if (!de)
return VisiblePosition();
+ NodeImpl *boundary = n->enclosingBlockFlowElement();
+ if (!boundary)
+ return VisiblePosition();
+ bool isContentEditable = boundary->isContentEditable();
+ while (boundary && boundary != de && boundary->parentNode() && isContentEditable == boundary->parentNode()->isContentEditable()) {
+ boundary = boundary->parentNode();
+ }
Range searchRange(d);
Position start(pos.equivalentRangeCompliantPosition());
searchRange.setStart(start.node(), start.offset());
- searchRange.setEndAfter(de);
+ searchRange.setEndAfter(boundary);
TextIterator it(searchRange, RUNFINDER);
QString string;
unsigned next = 0;
long offset = p.offset();
for (NodeImpl *n = startNode; n; n = n->traverseNextNode(stayInsideBlock)) {
+ if (n->isContentEditable() != startNode->isContentEditable())
+ break;
RenderObject *r = n->renderer();
if (!r)
continue;
// ---------
-// written, but not yet tested
VisiblePosition startOfBlock(const VisiblePosition &c)
{
Position p = c.deepEquivalent();
NodeImpl *startNode = p.node();
if (!startNode)
return VisiblePosition();
-
- NodeImpl *startBlock = startNode->enclosingBlockFlowElement();
-
- NodeImpl *node = startNode;
- long offset = p.offset();
-
- for (NodeImpl *n = startNode; n; n = n->traversePreviousNodePostOrder(startBlock)) {
- RenderObject *r = n->renderer();
- if (!r)
- continue;
- RenderStyle *style = r->style();
- if (style->visibility() != VISIBLE)
- continue;
- if (r->isBlockFlow())
- break;
- if (r->isText()) {
- node = n;
- offset = 0;
- } else if (r->isReplaced()) {
- node = n;
- offset = 0;
- }
- }
-
- return VisiblePosition(node, offset);
+ return VisiblePosition(Position(startNode->enclosingBlockFlowElement(), 0));
}
// written, but not yet tested