Fix for this bug:
<rdar://problem/
3917863> REGRESSION (Mail): pasting two lines of plain text copied from an RTF document results in two styles
Code to figuire out the end node to merge was missing the font tag in the second paragraph
written out by AppKit convert-to-HTML function. I refined the algorithm to be smarter.
* khtml/editing/htmlediting.cpp:
(khtml::ReplacementFragment::mergeEndNode): Refine algorithm used to walk through the fragment being pasted
looking for the node that is the last inline in the last block of the fragment. The old algorithm was
insufficiently powerful.
(khtml::ReplacementFragment::enclosingBlock): New helper function.
* khtml/editing/htmlediting.h: Add declaration for new helper function.
* layout-tests/editing/pasteboard/paste-text-011-expected.txt: Added.
* layout-tests/editing/pasteboard/paste-text-011.html: Added.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8195
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 784x576
+ RenderBlock {P} at (0,0) size 784x18
+ RenderInline {FONT} at (0,0) size 37x18
+ RenderInline {B} at (0,0) size 37x18
+ RenderText {TEXT} at (0,0) size 37x18
+ text run at (0,0) width 37: "hello"
+ RenderBlock {P} at (0,34) size 784x18
+ RenderInline {FONT} at (0,0) size 39x18
+ RenderInline {B} at (0,0) size 39x18
+ RenderText {TEXT} at (0,0) size 39x18
+ text run at (0,0) width 39: "there"
+ RenderBlock {P} at (0,68) size 784x18
+ RenderInline {FONT} at (0,0) size 37x18
+ RenderInline {B} at (0,0) size 37x18
+ RenderText {TEXT} at (0,0) size 37x18
+ text run at (0,0) width 37: "hello"
+ RenderBlock {P} at (0,102) size 784x18
+ RenderInline {FONT} at (0,0) size 39x18
+ RenderInline {B} at (0,0) size 39x18
+ RenderText {TEXT} at (0,0) size 39x18
+ text run at (0,0) width 39: "there"
+selection is CARET:
+start: position 5 of child 1 {TEXT} of child 1 {B} of child 1 {FONT} of child 5 {P} of root {BODY}
+upstream: position 5 of child 1 {TEXT} of child 1 {B} of child 1 {FONT} of child 5 {P} of root {BODY}
+downstream: position 5 of child 1 {TEXT} of child 1 {B} of child 1 {FONT} of child 5 {P} of root {BODY}
--- /dev/null
+
+<html>
+<head>
+
+<style>
+.editing {
+ border: 2px solid red;
+ padding: 12px;
+ font-size: 24px;
+}
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+// There was a bug when pasting at the end of the block. The content was inserted at the
+// start of the block instead of the end. This tests the insert-at-end case.
+
+function editingTest() {
+ selectAllCommand();
+ copyCommand();
+ moveSelectionForwardByCharacterCommand();
+ insertParagraphCommand();
+ pasteCommand();
+}
+
+</script>
+
+<title>Editing Test</title>
+</head>
+<body contenteditable id="root" id="test">
+<p><font face="Monaco"><b>hello</b></font></p>
+<p><font face="Monaco"><b>there</b></font></p>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
+2004-12-13 Ken Kocienda <kocienda@apple.com>
+
+ Reviewed by John
+
+ Fix for this bug:
+
+ <rdar://problem/3917863> REGRESSION (Mail): pasting two lines of plain text copied from an RTF document results in two styles
+
+ Code to figuire out the end node to merge was missing the font tag in the second paragraph
+ written out by AppKit convert-to-HTML function. I refined the algorithm to be smarter.
+
+ * khtml/editing/htmlediting.cpp:
+ (khtml::ReplacementFragment::mergeEndNode): Refine algorithm used to walk through the fragment being pasted
+ looking for the node that is the last inline in the last block of the fragment. The old algorithm was
+ insufficiently powerful.
+ (khtml::ReplacementFragment::enclosingBlock): New helper function.
+ * khtml/editing/htmlediting.h: Add declaration for new helper function.
+ * layout-tests/editing/pasteboard/paste-text-011-expected.txt: Added.
+ * layout-tests/editing/pasteboard/paste-text-011.html: Added.
+
2004-12-13 Ken Kocienda <kocienda@apple.com>
Reviewed by John
NodeImpl *node = m_fragment->lastChild();
while (node && node->lastChild())
node = node->lastChild();
+
+ if (isProbablyBlock(node))
+ return 0;
+
+ NodeImpl *startingBlock = enclosingBlock(node);
+ ASSERT(startingBlock != node);
while (node) {
NodeImpl *prev = node->traversePreviousNode();
- if (!isProbablyBlock(node)) {
- NodeImpl *previousSibling = node->previousSibling();
- while (1) {
- if (!previousSibling || isProbablyBlock(previousSibling))
- return node;
- node = previousSibling;
- previousSibling = node->previousSibling();
- }
- }
+ if (prev == m_fragment || prev == startingBlock || enclosingBlock(prev) != startingBlock)
+ return node;
node = prev;
}
+
return 0;
}
return node->isHTMLElement() && static_cast<const HTMLElementImpl *>(node)->getAttribute(ATTR_CLASS) == convertedSpaceSpanClassString;
}
+NodeImpl *ReplacementFragment::enclosingBlock(NodeImpl *node) const
+{
+ while (node && !isProbablyBlock(node))
+ node = node->parentNode();
+ return node ? node : m_fragment;
+}
+
void ReplacementFragment::removeNode(NodeImpl *node)
{
if (!node)
static bool isInterchangeConvertedSpaceSpan(const DOM::NodeImpl *);
// A couple simple DOM helpers
+ DOM::NodeImpl *enclosingBlock(DOM::NodeImpl *) const;
void removeNode(DOM::NodeImpl *);
void insertNodeBefore(DOM::NodeImpl *node, DOM::NodeImpl *refNode);