Reviewed by Chris
Fix for this bug:
<rdar://problem/3820349> REGRESSION (Mail): select all, delete does not always delete everything
* khtml/editing/htmlediting.cpp:
(khtml::DeleteSelectionCommand::startPositionForDelete): New helper that determines when to
expand the selection outwards when the selection is on the visible boundary of a root
editable element. This fixes the bug. Note that this function also contains a little code
I factored out of doApply: it also takes care of adjusting the selection in the smart delete case.
(khtml::DeleteSelectionCommand::endPositionForDelete): Ditto.
(khtml::DeleteSelectionCommand::doApply): Call new helpers. Refactored out the code as described.
* khtml/editing/htmlediting.h: Declare new helpers.
* layout-tests/editing/deleting/delete-select-all-001-expected.txt: Added.
* layout-tests/editing/deleting/delete-select-all-001.html: Added.
* layout-tests/editing/deleting/delete-select-all-002-expected.txt: Added.
* layout-tests/editing/deleting/delete-select-all-002.html: Added.
* layout-tests/editing/deleting/delete-select-all-003-expected.txt: Added.
* layout-tests/editing/deleting/delete-select-all-003.html: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@7890 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/editing/deleting/delete-select-all-001-expected.txt b/LayoutTests/editing/deleting/delete-select-all-001-expected.txt
new file mode 100644
index 0000000..ae0614d
--- /dev/null
+++ b/LayoutTests/editing/deleting/delete-select-all-001-expected.txt
@@ -0,0 +1,10 @@
+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 784x28 [border: (2px solid #FF0000)]
+selection is CARET:
+start: position 0 of of root {DIV}
+upstream: position 0 of of root {DIV}
+downstream: position 1 of of root {DIV}
diff --git a/LayoutTests/editing/deleting/delete-select-all-001.html b/LayoutTests/editing/deleting/delete-select-all-001.html
new file mode 100644
index 0000000..2264839
--- /dev/null
+++ b/LayoutTests/editing/deleting/delete-select-all-001.html
@@ -0,0 +1,51 @@
+<html>
+<head>
+
+<style>
+.editing {
+ border: 2px solid red;
+ padding: 12px;
+ font-size: 24px;
+ word-wrap: break-word;
+ -khtml-nbsp-mode: space;
+ -khtml-line-break: after-white-space;
+}
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+ selectAllCommand();
+ deleteCommand();
+}
+
+</script>
+
+<title>Editing Test</title>
+
+<!--
+
+Expected results:
+
+All the content in the contenteditable div should be deleted,
+including the table structure.
+
+-->
+
+</head>
+<body>
+<div contenteditable id="root" class="editing">
+<table border="1">
+<tr><td id="test">One</td><td>Two</td><td>Three</td></tr>
+<tr><td>One</td><td>Two</td><td>Three</td></tr>
+<tr><td>One</td><td>Two</td><td>Three</td></tr>
+</table>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
diff --git a/LayoutTests/editing/deleting/delete-select-all-002-expected.txt b/LayoutTests/editing/deleting/delete-select-all-002-expected.txt
new file mode 100644
index 0000000..214cc89
--- /dev/null
+++ b/LayoutTests/editing/deleting/delete-select-all-002-expected.txt
@@ -0,0 +1,10 @@
+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 784x56 [border: (2px solid #FF0000)]
+selection is CARET:
+start: position 0 of of root {DIV}
+upstream: position 0 of of root {DIV}
+downstream: position 1 of of root {DIV}
diff --git a/LayoutTests/editing/deleting/delete-select-all-002.html b/LayoutTests/editing/deleting/delete-select-all-002.html
new file mode 100644
index 0000000..3e6f711
--- /dev/null
+++ b/LayoutTests/editing/deleting/delete-select-all-002.html
@@ -0,0 +1,48 @@
+<html>
+<head>
+
+<style>
+.editing {
+ border: 2px solid red;
+ padding: 12px;
+ font-size: 24px;
+ word-wrap: break-word;
+ -khtml-nbsp-mode: space;
+ -khtml-line-break: after-white-space;
+}
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+ selectAllCommand();
+ deleteCommand();
+}
+
+</script>
+
+<title>Editing Test</title>
+
+<!--
+
+Expected results:
+
+All the content in the contenteditable div should be deleted,
+including the "you can't see this." span.
+
+-->
+
+</head>
+<body>
+<div contenteditable id="root" class="editing">
+<span style="display: hidden">you can't see this.</span>
+<span id="test">you can see this.</span>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
diff --git a/LayoutTests/editing/deleting/delete-select-all-003-expected.txt b/LayoutTests/editing/deleting/delete-select-all-003-expected.txt
new file mode 100644
index 0000000..ae0614d
--- /dev/null
+++ b/LayoutTests/editing/deleting/delete-select-all-003-expected.txt
@@ -0,0 +1,10 @@
+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 784x28 [border: (2px solid #FF0000)]
+selection is CARET:
+start: position 0 of of root {DIV}
+upstream: position 0 of of root {DIV}
+downstream: position 1 of of root {DIV}
diff --git a/LayoutTests/editing/deleting/delete-select-all-003.html b/LayoutTests/editing/deleting/delete-select-all-003.html
new file mode 100644
index 0000000..b1b2ab9
--- /dev/null
+++ b/LayoutTests/editing/deleting/delete-select-all-003.html
@@ -0,0 +1,47 @@
+<html>
+<head>
+
+<style>
+.editing {
+ border: 2px solid red;
+ padding: 12px;
+ font-size: 24px;
+ word-wrap: break-word;
+ -khtml-nbsp-mode: space;
+ -khtml-line-break: after-white-space;
+}
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+ selectAllCommand();
+ deleteCommand();
+}
+
+</script>
+
+<title>Editing Test</title>
+
+<!--
+
+Expected results:
+
+All the content in the contenteditable div should be deleted,
+including the unordered list element.
+
+-->
+
+</head>
+<body>
+<div contenteditable id="root" class="editing">
+<ul id="test"><li>one</li><li>two</li><li>three</li></ul>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
diff --git a/WebCore/ChangeLog-2005-08-23 b/WebCore/ChangeLog-2005-08-23
index 7079498..b00055e 100644
--- a/WebCore/ChangeLog-2005-08-23
+++ b/WebCore/ChangeLog-2005-08-23
@@ -1,5 +1,28 @@
2004-10-25 Ken Kocienda <kocienda@apple.com>
+ Reviewed by Chris
+
+ Fix for this bug:
+
+ <rdar://problem/3820349> REGRESSION (Mail): select all, delete does not always delete everything
+
+ * khtml/editing/htmlediting.cpp:
+ (khtml::DeleteSelectionCommand::startPositionForDelete): New helper that determines when to
+ expand the selection outwards when the selection is on the visible boundary of a root
+ editable element. This fixes the bug. Note that this function also contains a little code
+ I factored out of doApply: it also takes care of adjusting the selection in the smart delete case.
+ (khtml::DeleteSelectionCommand::endPositionForDelete): Ditto.
+ (khtml::DeleteSelectionCommand::doApply): Call new helpers. Refactored out the code as described.
+ * khtml/editing/htmlediting.h: Declare new helpers.
+ * layout-tests/editing/deleting/delete-select-all-001-expected.txt: Added.
+ * layout-tests/editing/deleting/delete-select-all-001.html: Added.
+ * layout-tests/editing/deleting/delete-select-all-002-expected.txt: Added.
+ * layout-tests/editing/deleting/delete-select-all-002.html: Added.
+ * layout-tests/editing/deleting/delete-select-all-003-expected.txt: Added.
+ * layout-tests/editing/deleting/delete-select-all-003.html: Added.
+
+2004-10-25 Ken Kocienda <kocienda@apple.com>
+
Reviewed by me
Added some more editing layout tests.
diff --git a/WebCore/khtml/editing/htmlediting.cpp b/WebCore/khtml/editing/htmlediting.cpp
index bf2b51f..37b8852 100644
--- a/WebCore/khtml/editing/htmlediting.cpp
+++ b/WebCore/khtml/editing/htmlediting.cpp
@@ -1296,6 +1296,34 @@
}
}
+Position DeleteSelectionCommand::startPositionForDelete() const
+{
+ Position pos = m_selectionToDelete.start();
+ ASSERT(pos.node()->inDocument());
+
+ ElementImpl *rootElement = pos.node()->rootEditableElement();
+ Position rootStart = Position(rootElement, 0);
+ if (pos == VisiblePosition(rootStart).deepEquivalent())
+ pos = rootStart;
+ else if (m_smartDelete && pos.leadingWhitespacePosition().isNotNull())
+ pos = VisiblePosition(pos).previous().deepEquivalent();
+ return pos;
+}
+
+Position DeleteSelectionCommand::endPositionForDelete() const
+{
+ Position pos = m_selectionToDelete.end();
+ ASSERT(pos.node()->inDocument());
+
+ ElementImpl *rootElement = pos.node()->rootEditableElement();
+ Position rootEnd = Position(rootElement, rootElement ? rootElement->childNodeCount() : 0).equivalentDeepPosition();
+ if (pos == VisiblePosition(rootEnd).deepEquivalent())
+ pos = rootEnd;
+ else if (m_smartDelete && pos.leadingWhitespacePosition().isNotNull())
+ pos = VisiblePosition(pos).next().deepEquivalent();
+ return pos;
+}
+
void DeleteSelectionCommand::doApply()
{
// If selection has not been set to a custom selection when the command was created,
@@ -1306,21 +1334,12 @@
if (!m_selectionToDelete.isRange())
return;
- ASSERT(m_selectionToDelete.start().node()->inDocument());
- ASSERT(m_selectionToDelete.end().node()->inDocument());
-
- if (m_smartDelete) {
- if (!m_selectionToDelete.start().leadingWhitespacePosition().isNull()) {
- m_selectionToDelete.modify(Selection::EXTEND, Selection::LEFT, CHARACTER);
- } else if (!m_selectionToDelete.end().trailingWhitespacePosition().isNull()) {
- m_selectionToDelete.modify(Selection::EXTEND, Selection::RIGHT, CHARACTER);
- }
- }
-
- Position upstreamStart(m_selectionToDelete.start().upstream(StayInBlock));
- Position downstreamStart(m_selectionToDelete.start().downstream(StayInBlock));
- Position upstreamEnd(m_selectionToDelete.end().upstream(StayInBlock));
- Position downstreamEnd(m_selectionToDelete.end().downstream(StayInBlock));
+ Position start = startPositionForDelete();
+ Position end = endPositionForDelete();
+ Position upstreamStart(start.upstream(StayInBlock));
+ Position downstreamStart(start.downstream(StayInBlock));
+ Position upstreamEnd(end.upstream(StayInBlock));
+ Position downstreamEnd(end.downstream(StayInBlock));
Position endingPosition;
// Save away whitespace situation before doing any deletions
diff --git a/WebCore/khtml/editing/htmlediting.h b/WebCore/khtml/editing/htmlediting.h
index 6fadb20..5239e79 100644
--- a/WebCore/khtml/editing/htmlediting.h
+++ b/WebCore/khtml/editing/htmlediting.h
@@ -273,9 +273,9 @@
private:
virtual bool preservesTypingStyle() const;
- void deleteDownstreamWS(const DOM::Position &start);
- bool containsOnlyWhitespace(const DOM::Position &start, const DOM::Position &end);
void moveNodesAfterNode(DOM::NodeImpl *startNode, DOM::NodeImpl *dstNode);
+ DOM::Position startPositionForDelete() const;
+ DOM::Position endPositionForDelete() const;
khtml::Selection m_selectionToDelete;
bool m_hasSelectionToDelete;