Commit 5614540c authored by rniwa@webkit.org's avatar rniwa@webkit.org

2011-04-07 Ryosuke Niwa <rniwa@webkit.org>

        Reviewed by Darin Adler.

        REGRESSION (r46914, r48764): When typing in Mail, line wrapping frequently occurs in the middle of words
        https://bugs.webkit.org/show_bug.cgi?id=57872

        Added tests to ensure WebKit inserts a paragraph separator properly around tab span.

        * editing/inserting/insert-div-021-expected.txt: No longer duplicates span[id="test"] incorrectly.
        * editing/inserting/insert-paragraph-after-tab-span-and-text-expected.txt: Added.
        * editing/inserting/insert-paragraph-after-tab-span-and-text.html: Added.
        * editing/inserting/insert-paragraph-separator-tab-span-expected.txt: Added.
        * editing/inserting/insert-paragraph-separator-tab-span.html: Added.
        * editing/inserting/insert-paragraph-at-end-of-line-expected.txt: No longer duplicates a[id="anchor"] incorrectly.
2011-04-07  Ryosuke Niwa  <rniwa@webkit.org>

        Reviewed by Eric Seidel.

        REGRESSION (r46914, r48764): When typing in Mail, line wrapping frequently occurs in the middle of words
        https://bugs.webkit.org/show_bug.cgi?id=57872

        r46914 initially introduced a regression by replacing calls to styleAtPosition by editingStyleAtPosition
        because editingStyleAtPosition did not avoid tab span to obtain the computed style unlike styleAtPosition.

        r46914 also introduced a regression by cloning hierarchy under new block at the insertion position without
        avoiding the tab span.

        Fixed the both regressions by avoiding tab spans when computing the editing style and when cloning hierarchy.
        Also reverted r46914 for the general code path because re-creating node hierarchy duplicates nodes when
        we're moving nodes after the paragraph separator. Instead, we now split the tree up until the start block
        before moving the nodes.

        Tests: editing/inserting/insert-paragraph-after-tab-span-and-text.html
               editing/inserting/insert-paragraph-separator-tab-span.html

        * editing/DeleteSelectionCommand.cpp:
        (WebCore::DeleteSelectionCommand::saveTypingStyleState): Since EditingStyle's constructor avoids a tab span,
        no longer calls positionBeforeTabSpan on the position passed to EditingStyle's constructor.
        * editing/EditingStyle.cpp:
        (WebCore::EditingStyle::init): Always avoid a tab span when computing the editing style.
        * editing/InsertParagraphSeparatorCommand.cpp:
        (WebCore::InsertParagraphSeparatorCommand::doApply): Avoid cloning tab spans and inserting a paragraph
        separator into a paragraph separator.
        * editing/htmlediting.cpp:
        (WebCore::positionOutsideTabSpan): Renamed from positionBeforeTabSpan. Also returns the position in the parent
        node after the tab span if the position was at the end of the tab span.
        * editing/htmlediting.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@83247 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 6683441a
2011-04-07 Ryosuke Niwa <rniwa@webkit.org>
Reviewed by Darin Adler.
REGRESSION (r46914, r48764): When typing in Mail, line wrapping frequently occurs in the middle of words
https://bugs.webkit.org/show_bug.cgi?id=57872
Added tests to ensure WebKit inserts a paragraph separator properly around tab span.
* editing/inserting/insert-div-021-expected.txt: No longer duplicates span[id="test"] incorrectly.
* editing/inserting/insert-paragraph-after-tab-span-and-text-expected.txt: Added.
* editing/inserting/insert-paragraph-after-tab-span-and-text.html: Added.
* editing/inserting/insert-paragraph-separator-tab-span-expected.txt: Added.
* editing/inserting/insert-paragraph-separator-tab-span.html: Added.
* editing/inserting/insert-paragraph-at-end-of-line-expected.txt: No longer duplicates a[id="anchor"] incorrectly.
2011-04-07 Ryosuke Niwa <rniwa@webkit.org>
Reviewed by Eric Seidel.
......@@ -408,6 +424,19 @@
* platform/chromium-mac-leopard/fast/speech/input-appearance-searchandspeech-expected.png: Added.
* platform/chromium-mac/fast/speech/input-appearance-numberandspeech-expected.txt:
2011-04-07 Ryosuke Niwa <rniwa@webkit.org>
Reviewed by Eric Seidel.
REGRESSION (r46914, r48764): When typing in Mail, line wrapping frequently occurs in the middle of words
https://bugs.webkit.org/show_bug.cgi?id=57872
Added a test insert a paragraph separator and text around tab spans. WebKit should not apply the tab span's
style to the paragraph separator or the text.
* editing/inserting/insert-paragraph-separator-tab-span-expected.txt: Added.
* editing/inserting/insert-paragraph-separator-tab-span.html: Added.
2011-04-07 Ryosuke Niwa <rniwa@webkit.org>
Reviewed by Eric Seidel.
......@@ -32,7 +32,5 @@ Fix for this bug: <rdar://problem/3924579> REGRESSION (Mail): After deleting, hi
| <div>
| <br>
| <div>
| <span>
| id="test"
| "<#selection-caret>bar
"
This test ensures WebKit inserts a paragraph separator properly at the end of a tab span.
| "
"
| <span>
| class="Apple-tab-span"
| style="white-space:pre"
| " hello"
| <div>
| <#selection-caret>
| <br>
| "
"
| <span>
| class="Apple-style-span"
| <span>
| class="Apple-tab-span"
| style="white-space: pre; "
| " "
| "world"
<!DOCTYPE html>
<html>
<body>
<div id="test" contenteditable>
<span class="Apple-tab-span" style="white-space:pre"> hello</span><br>
<span class="Apple-style-span"><span class="Apple-tab-span" style="white-space: pre; "> </span>world</span></div>
<script src="../../resources/dump-as-markup.js"></script>
<script>
document.body.focus();
var span = document.getElementsByClassName('Apple-tab-span')[0];
window.getSelection().setPosition(span, 1);
document.execCommand('InsertParagraph', false, null);
Markup.description('This test ensures WebKit inserts a paragraph separator properly at the end of a tab span.')
Markup.dump('test');
</script>
</body>
</html>
......@@ -18,9 +18,6 @@ If the test has passed, the numbers should be in order, and only "1" should be a
| id="anchor"
| "1"
| <div>
| <a>
| href="#"
| id="anchor"
| "2<#selection-caret>"
| <br>
| <div>
......
This test ensures WebKit avoids cloning Apple tab span when inserting a paragraph separator.
Only tab should be inside a Apple tab span in the following tests.
last visible position:
| <span>
| class="Apple-tab-span"
| style="white-space:pre"
| " "
| <div>
| "hello world WebKit <#selection-caret>"
first visible position:
| <div>
| <br>
| "hello world WebKit <#selection-caret>"
| <span>
| class="Apple-tab-span"
| style="white-space:pre"
| " "
before tab span:
| "hi, "
| <div>
| "hello world WebKit <#selection-caret>"
| <span>
| class="Apple-tab-span"
| style="white-space:pre"
| " "
| " rocks"
after tab span:
| "hi, "
| <span>
| class="Apple-tab-span"
| style="white-space:pre"
| " "
| <div>
| "hello world WebKit <#selection-caret>rocks"
<!DOCTYPE html>
<html>
<body>
<div contenteditable title="1: last visible position" style="word-wrap: break-word; width: 10ex; border: solid thin black;"><span class="Apple-tab-span" style="white-space:pre"> </span></div>
<div contenteditable title="0: first visible position" style="word-wrap: break-word; width: 10ex; border: solid thin black;"><span class="Apple-tab-span" style="white-space:pre"> </span></div>
<div contenteditable title="1: before tab span" style="word-wrap: break-word; width: 10ex; border: solid thin black;">hi, <span class="Apple-tab-span" style="white-space:pre"> </span> rocks</div>
<div contenteditable title="2: after tab span" style="word-wrap: break-word; width: 10ex; border: solid thin black;">hi, <span class="Apple-tab-span" style="white-space:pre"> </span> rocks</div>
<script src="../../resources/dump-as-markup.js"></script>
<script>
Markup.description('This test ensures WebKit avoids cloning Apple tab span when inserting a paragraph separator.\n'+
'Only tab should be inside a Apple tab span in the following tests.');
function runTest(div) {
var offset = div.title.substr(0, div.title.indexOf(':'));
window.getSelection().setPosition(div, offset);
document.execCommand("InsertParagraph");
document.execCommand("InsertText", false, "hello world WebKit ");
Markup.dump(div, div.title.substr(div.title.indexOf(': ') + 2));
}
var divs = document.getElementsByTagName('div');
var tests = new Array();
for (var i = 0; i < divs.length; i++)
tests.push(divs[i]);
for (i in tests)
runTest(tests[i]);
</script>
</body>
</html>
2011-04-07 Ryosuke Niwa <rniwa@webkit.org>
Reviewed by Eric Seidel.
REGRESSION (r46914, r48764): When typing in Mail, line wrapping frequently occurs in the middle of words
https://bugs.webkit.org/show_bug.cgi?id=57872
r46914 initially introduced a regression by replacing calls to styleAtPosition by editingStyleAtPosition
because editingStyleAtPosition did not avoid tab span to obtain the computed style unlike styleAtPosition.
r46914 also introduced a regression by cloning hierarchy under new block at the insertion position without
avoiding the tab span.
Fixed the both regressions by avoiding tab spans when computing the editing style and when cloning hierarchy.
Also reverted r46914 for the general code path because re-creating node hierarchy duplicates nodes when
we're moving nodes after the paragraph separator. Instead, we now split the tree up until the start block
before moving the nodes.
Tests: editing/inserting/insert-paragraph-after-tab-span-and-text.html
editing/inserting/insert-paragraph-separator-tab-span.html
* editing/DeleteSelectionCommand.cpp:
(WebCore::DeleteSelectionCommand::saveTypingStyleState): Since EditingStyle's constructor avoids a tab span,
no longer calls positionBeforeTabSpan on the position passed to EditingStyle's constructor.
* editing/EditingStyle.cpp:
(WebCore::EditingStyle::init): Always avoid a tab span when computing the editing style.
* editing/InsertParagraphSeparatorCommand.cpp:
(WebCore::InsertParagraphSeparatorCommand::doApply): Avoid cloning tab spans and inserting a paragraph
separator into a paragraph separator.
* editing/htmlediting.cpp:
(WebCore::positionOutsideTabSpan): Renamed from positionBeforeTabSpan. Also returns the position in the parent
node after the tab span if the position was at the end of the tab span.
* editing/htmlediting.h:
2011-04-07 Jia Pu <jpu@apple.com>
Reviewed by Darin Adler.
......@@ -281,7 +281,7 @@ void DeleteSelectionCommand::saveTypingStyleState()
return;
// Figure out the typing style in effect before the delete is done.
m_typingStyle = EditingStyle::create(positionBeforeTabSpan(m_selectionToDelete.start()));
m_typingStyle = EditingStyle::create(m_selectionToDelete.start());
m_typingStyle->removeStyleAddedByNode(enclosingAnchorElement(m_selectionToDelete.start()));
// If we're deleting into a Mail blockquote, save the style at end() instead of start()
......
......@@ -300,6 +300,11 @@ EditingStyle::~EditingStyle()
void EditingStyle::init(Node* node, PropertiesToInclude propertiesToInclude)
{
if (isTabSpanTextNode(node))
node = tabSpanNode(node)->parentNode();
else if (isTabSpanNode(node))
node = node->parentNode();
RefPtr<CSSComputedStyleDeclaration> computedStyleAtPosition = computedStyle(node);
m_mutableStyle = propertiesToInclude == AllProperties && computedStyleAtPosition ? computedStyleAtPosition->copy() : editingStyleFromComputedStyle(computedStyleAtPosition);
......
......@@ -239,7 +239,7 @@ void InsertParagraphSeparatorCommand::doApply()
// Recreate the same structure in the new paragraph.
Vector<Element*> ancestors;
getAncestorsInsideBlock(insertionPosition.deprecatedNode(), startBlock, ancestors);
getAncestorsInsideBlock(positionOutsideTabSpan(insertionPosition).deprecatedNode(), startBlock, ancestors);
RefPtr<Element> parent = cloneHierarchyUnderNewBlock(ancestors, blockToInsert);
appendBlockPlaceholder(parent);
......@@ -254,6 +254,9 @@ void InsertParagraphSeparatorCommand::doApply()
// similar case where previous position is in another, presumeably nested, block.
if (isFirstInBlock || !inSameBlock(visiblePos, visiblePos.previous())) {
Node *refNode;
insertionPosition = positionOutsideTabSpan(insertionPosition);
if (isFirstInBlock && !nestNewBlock)
refNode = startBlock;
else if (insertionPosition.deprecatedNode() == startBlock && nestNewBlock) {
......@@ -270,7 +273,7 @@ void InsertParagraphSeparatorCommand::doApply()
// Recreate the same structure in the new paragraph.
Vector<Element*> ancestors;
getAncestorsInsideBlock(positionAvoidingSpecialElementBoundary(insertionPosition).deprecatedNode(), startBlock, ancestors);
getAncestorsInsideBlock(positionAvoidingSpecialElementBoundary(positionOutsideTabSpan(insertionPosition)).deprecatedNode(), startBlock, ancestors);
appendBlockPlaceholder(cloneHierarchyUnderNewBlock(ancestors, blockToInsert));
......@@ -299,11 +302,7 @@ void InsertParagraphSeparatorCommand::doApply()
// At this point, the insertionPosition's node could be a container, and we want to make sure we include
// all of the correct nodes when building the ancestor list. So this needs to be the deepest representation of the position
// before we walk the DOM tree.
insertionPosition = VisiblePosition(insertionPosition).deepEquivalent();
// Build up list of ancestors in between the start node and the start block.
Vector<Element*> ancestors;
getAncestorsInsideBlock(insertionPosition.deprecatedNode(), startBlock, ancestors);
insertionPosition = positionOutsideTabSpan(VisiblePosition(insertionPosition).deepEquivalent());
// Make sure we do not cause a rendered space to become unrendered.
// FIXME: We need the affinity for pos, but pos.downstream() does not give it
......@@ -336,9 +335,6 @@ void InsertParagraphSeparatorCommand::doApply()
updateLayout();
// Make clones of ancestors in between the start node and the outer block.
RefPtr<Element> parent = cloneHierarchyUnderNewBlock(ancestors, blockToInsert);
// If the paragraph separator was inserted at the end of a paragraph, an empty line must be
// created. All of the nodes, starting at visiblePos, are about to be added to the new paragraph
// element. If the first node to be inserted won't be one that will hold an empty line open, add a br.
......@@ -346,35 +342,25 @@ void InsertParagraphSeparatorCommand::doApply()
appendNode(createBreakElement(document()).get(), blockToInsert.get());
// Move the start node and the siblings of the start node.
if (insertionPosition.deprecatedNode() != startBlock) {
Node* n = insertionPosition.deprecatedNode();
if (insertionPosition.deprecatedEditingOffset() >= caretMaxOffset(n))
n = n->nextSibling();
while (n && n != blockToInsert) {
Node *next = n->nextSibling();
removeNode(n);
appendNode(n, parent.get());
n = next;
if (VisiblePosition(insertionPosition) != VisiblePosition(positionBeforeNode(blockToInsert.get()))) {
Node* n;
if (insertionPosition.containerNode() == startBlock)
n = insertionPosition.computeNodeAfterPosition();
else {
splitTreeToNode(insertionPosition.containerNode(), startBlock);
for (n = startBlock->firstChild(); n; n = n->nextSibling()) {
if (comparePositions(VisiblePosition(insertionPosition), positionBeforeNode(n)) <= 0)
break;
}
}
// Move everything after the start node.
if (!ancestors.isEmpty()) {
Element* leftParent = ancestors.first();
while (leftParent && leftParent != startBlock) {
parent = parent->parentElement();
if (!parent)
break;
Node* n = leftParent->nextSibling();
while (n && n != blockToInsert) {
Node* next = n->nextSibling();
Node *next = n->nextSibling();
removeNode(n);
appendNode(n, parent.get());
appendNode(n, blockToInsert);
n = next;
}
leftParent = leftParent->parentElement();
}
}
// Handle whitespace that occurs after the split
......
......@@ -894,14 +894,17 @@ bool isNodeInTextFormControl(Node* node)
return ancestor->isElementNode() && static_cast<Element*>(ancestor)->isTextFormControl();
}
Position positionBeforeTabSpan(const Position& pos)
Position positionOutsideTabSpan(const Position& pos)
{
Node* node = pos.deprecatedNode();
Node* node = pos.containerNode();
if (isTabSpanTextNode(node))
node = tabSpanNode(node);
else if (!isTabSpanNode(node))
return pos;
if (node && VisiblePosition(pos) == lastPositionInNode(node))
return positionInParentAfterNode(node);
return positionInParentBeforeNode(node);
}
......
......@@ -111,7 +111,7 @@ Position previousCandidate(const Position&);
Position nextVisuallyDistinctCandidate(const Position&);
Position previousVisuallyDistinctCandidate(const Position&);
Position positionBeforeTabSpan(const Position&);
Position positionOutsideTabSpan(const Position&);
Position positionBeforeContainingSpecialElement(const Position&, Node** containingSpecialElement=0);
Position positionAfterContainingSpecialElement(const Position&, Node** containingSpecialElement=0);
Position positionOutsideContainingSpecialElement(const Position&, Node** containingSpecialElement=0);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment