Fix for this bug:
<rdar://problem/
3928305> selecting an entire line and typing over causes new inserted text at top of document
* khtml/editing/htmlediting.cpp:
(khtml::DeleteSelectionCommand::insertPlaceholderForAncestorBlockContent): New function to detect case
formerly undetected and unhandled. This is the crux of the bug fix.
(khtml::DeleteSelectionCommand::doApply): Call insertPlaceholderForAncestorBlockContent() during
execution of command.
* khtml/editing/htmlediting.h: Declare new function.
* layout-tests/editing/deleting/delete-
3928305-fix-expected.txt: Added.
* layout-tests/editing/deleting/delete-
3928305-fix.html: Added.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8271
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
--- /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 (anonymous) at (0,0) size 784x18
+ RenderText {TEXT} at (0,0) size 309x18
+ text run at (0,0) width 309: "Should see a blank line between \"foo\" and \"baz\""
+ RenderBlock {DIV} at (0,18) size 784x24
+ RenderBlock {DIV} at (0,42) size 784x112 [border: (2px solid #FF0000)]
+ RenderBlock {DIV} at (14,14) size 756x28
+ RenderText {TEXT} at (0,0) size 32x28
+ text run at (0,0) width 32: "foo"
+ RenderBlock {P} at (14,42) size 756x28
+ RenderBR {BR} at (0,0) size 0x28
+ RenderBlock (anonymous) at (14,70) size 756x0
+ RenderBlock {DIV} at (14,70) size 756x28
+ RenderText {TEXT} at (0,0) size 34x28
+ text run at (0,0) width 34: "baz"
+selection is CARET:
+start: position 0 of child 1 {BR} of child 2 {P} of root {DIV}
+upstream: position 0 of child 2 {P} of root {DIV}
+downstream: position 0 of child 1 {BR} of child 2 {P} of root {DIV}
--- /dev/null
+<html>
+<head>
+
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<style>
+.editing {
+ border: 2px solid red;
+ padding: 12px;
+ font-size: 24px;
+}
+</style>
+
+<script>
+
+function editingTest() {
+ for (i = 0; i < 4; i++)
+ moveSelectionForwardByCharacterCommand();
+ for (i = 0; i < 3; i++)
+ extendSelectionForwardByCharacterCommand();
+ deleteCommand();
+}
+
+</script>
+
+<title>Editing Test</title>
+</head>
+<body contenteditable="true">
+
+Should see a blank line between "foo" and "baz"
+<div style="height: 24px"></div>
+
+<div id="root" class="editing">
+<div id="test">foo</div>bar<div>baz</div>
+
+<!--
+
+Fix for this bug:
+
+<rdar://problem/3928305> selecting an entire line and typing over causes new inserted text at top of document
+
+-->
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
+2004-12-21 Ken Kocienda <kocienda@apple.com>
+
+ Reviewed by John
+
+ Fix for this bug:
+
+ <rdar://problem/3928305> selecting an entire line and typing over causes new inserted text at top of document
+
+ * khtml/editing/htmlediting.cpp:
+ (khtml::DeleteSelectionCommand::insertPlaceholderForAncestorBlockContent): New function to detect case
+ formerly undetected and unhandled. This is the crux of the bug fix.
+ (khtml::DeleteSelectionCommand::doApply): Call insertPlaceholderForAncestorBlockContent() during
+ execution of command.
+ * khtml/editing/htmlediting.h: Declare new function.
+ * layout-tests/editing/deleting/delete-3928305-fix-expected.txt: Added.
+ * layout-tests/editing/deleting/delete-3928305-fix.html: Added.
+
2004-12-21 Ken Kocienda <kocienda@apple.com>
Reviewed by me
debugNode( "m_startNode ", m_startNode);
}
+void DeleteSelectionCommand::insertPlaceholderForAncestorBlockContent()
+{
+ // This code makes sure a line does not disappear when deleting in this case:
+ // <p>foo</p>bar<p>baz</p>
+ // Select "bar" and hit delete. If nothing is done, the line containing bar will disappear.
+ // It needs to be held open by inserting a placeholder.
+ // Also see:
+ // <rdar://problem/3928305> selecting an entire line and typing over causes new inserted text at top of document
+ //
+ // The checks below detect the case where the selection contains content in an ancestor block
+ // surrounded by child blocks.
+ //
+ NodeImpl *upstreamBlock = m_upstreamStart.node()->enclosingBlockFlowElement();
+ NodeImpl *beforeUpstreamBlock = m_upstreamStart.upstream().node()->enclosingBlockFlowElement();
+
+ if (upstreamBlock != beforeUpstreamBlock && beforeUpstreamBlock->isAncestor(upstreamBlock)) {
+ NodeImpl *downstreamBlock = m_downstreamEnd.node()->enclosingBlockFlowElement();
+ NodeImpl *afterDownstreamBlock = m_downstreamEnd.downstream().node()->enclosingBlockFlowElement();
+
+ if (afterDownstreamBlock != downstreamBlock && afterDownstreamBlock != upstreamBlock) {
+ NodeImpl *block = createDefaultParagraphElement(document());
+ insertNodeBefore(block, m_upstreamStart.node());
+ insertBlockPlaceholderIfNeeded(block);
+ m_endingPosition = Position(block, 0);
+ }
+ }
+}
+
void DeleteSelectionCommand::saveTypingStyleState()
{
// Figure out the typing style in effect before the delete is done.
deleteInsignificantTextDownstream(m_trailingWhitespace);
saveTypingStyleState();
+ insertPlaceholderForAncestorBlockContent();
if (!handleSpecialCaseAllContentDelete())
if (!handleSpecialCaseBRDelete())
void initializePositionData();
void saveTypingStyleState();
+ void insertPlaceholderForAncestorBlockContent();
bool handleSpecialCaseAllContentDelete();
bool handleSpecialCaseBRDelete();
void handleGeneralDelete();