2010-09-14 Ryosuke Niwa <rniwa@webkit.org>
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Sep 2010 20:29:00 +0000 (20:29 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Sep 2010 20:29:00 +0000 (20:29 +0000)
        Reviewed by Tony Chang.

        applyInlineStyleToNodeRange does not extend run properly
        https://bugs.webkit.org/show_bug.cgi?id=45616

        The bug was caused by applyInlineStyleToNodeRange's skipping a node whenever it has children.
        Fixed the bug by only skipping a node that contains the past end node, contains non-editable region,
        or has a non-editable parent node. Also fixed a bug that applyInlineStyleToNodeRange does not remove
        styled elements in a run that are identical to the one added. addInlineStyleIfNeeded now removes
        all styled elements in a run using removeStyleFromRunBeforeApplyingStyle before calling addInlineStyleIfNeeded.

        Test: editing/style/inline-style-extend-run.html

        * editing/ApplyStyleCommand.cpp:
        (WebCore::containsNonEditableRegion): Added.
        (WebCore::ApplyStyleCommand::applyInlineStyleToNodeRange): See above.
        (WebCore::ApplyStyleCommand::removeStyleFromRunBeforeApplyingStyle): Added, see above.
        (WebCore::ApplyStyleCommand::removeInlineStyleFromElement): Added support for RemoveAlways.
        (WebCore::ApplyStyleCommand::removeImplicitlyStyledElement): Replaced RemoveAttributesAndElements by RemoveIfNeeded.
        (WebCore::ApplyStyleCommand::extractInlineStyleToPushDown): Replaced RemoveAttributesAndElements by RemoveIfNeeded.
        * editing/ApplyStyleCommand.h:
2010-09-14  Ryosuke Niwa  <rniwa@webkit.org>

        Reviewed by Tony Chang.

        applyInlineStyleToNodeRange does not extend a run properly
        https://bugs.webkit.org/show_bug.cgi?id=45616

        Added a test to ensure WebKit adds just one element when applying inline style and removes redundant styled elements.
        Rebaseline of other tests are required because WebKit now generates less elements.

        * editing/execCommand/script-tests/toggle-style-3.js: Merged two b elements.
        * editing/execCommand/toggle-style-3-expected.txt: Ditto.
        * editing/execCommand/unlink-expected.txt: Changed the order in which span and anchor appear.
        * editing/style/inline-style-extend-run-expected.txt: Added.
        * editing/style/inline-style-extend-run.html: Added.
        * editing/style/script-tests/inline-style-extend-run.js: Added.
        (testSingleToggle):
        * editing/style/script-tests/make-text-writing-direction-inline.js: Merged two spans.
        * fast/events/event-input-contentEditable-expected.txt: Merged two anchor elements.
        * fast/events/event-input-contentEditable.html: Ditto.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@67490 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/execCommand/script-tests/toggle-style-3.js
LayoutTests/editing/execCommand/toggle-style-3-expected.txt
LayoutTests/editing/execCommand/unlink-expected.txt
LayoutTests/editing/style/inline-style-extend-run-expected.txt [new file with mode: 0644]
LayoutTests/editing/style/inline-style-extend-run.html [new file with mode: 0644]
LayoutTests/editing/style/script-tests/inline-style-extend-run.js [new file with mode: 0644]
LayoutTests/editing/style/script-tests/make-text-writing-direction-inline.js
LayoutTests/fast/events/event-input-contentEditable-expected.txt
LayoutTests/fast/events/script-tests/event-input-contentEditable.js
WebCore/ChangeLog
WebCore/editing/ApplyStyleCommand.cpp
WebCore/editing/ApplyStyleCommand.h

index 1c10b97..cd21ddc 100644 (file)
@@ -1,3 +1,24 @@
+2010-09-14  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Reviewed by Tony Chang.
+
+        applyInlineStyleToNodeRange does not extend a run properly
+        https://bugs.webkit.org/show_bug.cgi?id=45616
+
+        Added a test to ensure WebKit adds just one element when applying inline style and removes redundant styled elements.
+        Rebaseline of other tests are required because WebKit now generates less elements.
+
+        * editing/execCommand/script-tests/toggle-style-3.js: Merged two b elements.
+        * editing/execCommand/toggle-style-3-expected.txt: Ditto.
+        * editing/execCommand/unlink-expected.txt: Changed the order in which span and anchor appear.
+        * editing/style/inline-style-extend-run-expected.txt: Added.
+        * editing/style/inline-style-extend-run.html: Added.
+        * editing/style/script-tests/inline-style-extend-run.js: Added.
+        (testSingleToggle):
+        * editing/style/script-tests/make-text-writing-direction-inline.js: Merged two spans.
+        * fast/events/event-input-contentEditable-expected.txt: Merged two anchor elements.
+        * fast/events/event-input-contentEditable.html: Ditto.
+
 2010-09-14  Adam Barth  <abarth@webkit.org>
 
         Reviewed by Eric Seidel.
index 6d4ffb9..39849e6 100644 (file)
@@ -16,7 +16,7 @@ function testSingleToggle(toggleCommand, initialContents, expectedContents)
     }
 }
 
-testSingleToggle("bold", 'hello<b id="test">world</b>', '<b>hello</b><b id="test">world</b>');
+testSingleToggle("bold", 'hello<b id="test">world</b>', '<b>hello<span id="test">world</span></b>');
 testSingleToggle("bold", 'hello<b><i>world</i></b>', '<b>hello<i>world</i></b>');
 testSingleToggle("italic", 'hello <i>world</i> <b>webkit</b>', '<i>hello world <b>webkit</b></i>');
 testSingleToggle("italic", 'hello <i>world</i> webkit', '<i>hello world webkit</i>');
index f20af7b..9062a80 100644 (file)
@@ -3,7 +3,7 @@ Test to make sure we remove span tags with no attributes if we removed the last
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS one bold command converted hello<b id="test">world</b> to <b>hello</b><b id="test">world</b>
+PASS one bold command converted hello<b id="test">world</b> to <b>hello<span id="test">world</span></b>
 PASS one bold command converted hello<b><i>world</i></b> to <b>hello<i>world</i></b>
 PASS one italic command converted hello <i>world</i> <b>webkit</b> to <i>hello world <b>webkit</b></i>
 PASS one italic command converted hello <i>world</i> webkit to <i>hello world webkit</i>
index 5e04322..b9b114e 100644 (file)
@@ -65,4 +65,4 @@ The innerHTML of editable regions after the test:
 This paragraph should should end up unlinked.
 <a href="http://www.apple.com/">The</a> second<a href="http://www.apple.com/"> word in this paragraph should end up being unlinked, everything else should be a link.</a>
 This paragraph starts with <i><a href="http://www.google.com">a</a></i><span id="test3start"> link</span> in the middle. Only the 'a' in the previous sentence should be linked after the test.
-<p>This <i>editable region</i> contains lists, tables, styled text, and images. Everything in this region that is not selected should be a link, nothing that is selected should be a link.</p> <ul> <li>Item 1</li> <li>Item 2</li> </ul> <table border="1"><tbody><tr><td>1</td><td>2</td><td><span id="test4end"><a href="http://www.google.com/">3</a></span></td></tr></tbody></table> <a href="http://www.google.com/"><br> This <b>line</b> contains <img src="../resources/abe.png"> an image. </a>
+<p>This <i>editable region</i> contains lists, tables, styled text, and images. Everything in this region that is not selected should be a link, nothing that is selected should be a link.</p> <ul> <li>Item 1</li> <li>Item 2</li> </ul> <table border="1"><tbody><tr><td>1</td><td>2</td><td><a href="http://www.google.com/"><span id="test4end">3</span></a></td></tr></tbody></table> <a href="http://www.google.com/"><br> This <b>line</b> contains <img src="../resources/abe.png"> an image. </a>
diff --git a/LayoutTests/editing/style/inline-style-extend-run-expected.txt b/LayoutTests/editing/style/inline-style-extend-run-expected.txt
new file mode 100644 (file)
index 0000000..885a6a1
--- /dev/null
@@ -0,0 +1,21 @@
+Test to make sure WebKit adds just one element when applying inline style and removes redundant styled elements.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS fontSize(4) on all of "hello <font size="4">world</font> WebKit" yields "<font class="Apple-style-span" size="4">hello world WebKit</font>"
+PASS fontName(Arial) on all of "hello <b><font face="Arial">world</font></b> WebKit" yields "<font class="Apple-style-span" face="Arial">hello <b>world</b> WebKit</font>"
+PASS italic(null) on all of "hello <u><i title="message">world </i><i>WebKit</i></u>" yields "<i>hello <u><span title="message">world </span>WebKit</u></i>"
+PASS bold(null) on all of "hello <i><b>world</b> WebKit</i>" yields "<b>hello <i>world WebKit</i></b>"
+PASS bold(null) on all of "hello <i><b class="test">world</b> WebKit</i>" yields "<b>hello <i><span class="test">world</span> WebKit</i></b>"
+PASS bold(null) on all of "hello <b contenteditable="false">world</b> <b>WebKit </b><u><b>rocks</b></u>" yields "<b>hello </b><b contenteditable="false">world</b><b> WebKit <u>rocks</u></b>"
+PASS strikeThrough(null) on all of "hello <b>world <s>WebKit</s></b>" yields "<s>hello <b>world WebKit</b></s>"
+PASS strikeThrough(null) on all of "hello <i><s>world</s></i><b><s>WebKit</s></b> rocks" yields "<s>hello <i>world</i><b>WebKit</b> rocks</s>"
+PASS strikeThrough(null) on all of "hello <i><s>world</s></i> WebKit <b><s>rocks</s></b>" yields "<s>hello <i>world</i> WebKit <b>rocks</b></s>"
+PASS bold(null) on all of "hello<div><i>world</i> <b>WebKit</b></div><div>rocks</div>" yields "<b>hello</b><div><b><i>world</i> WebKit</b></div><div><b>rocks</b></div>"
+PASS bold(null) on all of "hello<br style="display: block;"><i><b>world</b></i><br><b>WebKit</b>" yields "<b>hello<br style="display: block;"><i>world</i><br>WebKit</b>"
+PASS bold(null) on all of "hello<p><b>world</b> <i><b>W</b>ebKit</i></p><b>rocks</b>" yields "<b>hello</b><p><b>world <i>WebKit</i></b></p><b>rocks</b>"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/editing/style/inline-style-extend-run.html b/LayoutTests/editing/style/inline-style-extend-run.html
new file mode 100644 (file)
index 0000000..f705633
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/inline-style-extend-run.js"></script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/editing/style/script-tests/inline-style-extend-run.js b/LayoutTests/editing/style/script-tests/inline-style-extend-run.js
new file mode 100644 (file)
index 0000000..4ef0fad
--- /dev/null
@@ -0,0 +1,36 @@
+description('Test to make sure WebKit adds just one element when applying inline style and removes redundant styled elements.');
+
+var testContainer = document.createElement("div");
+testContainer.contentEditable = true;
+document.body.appendChild(testContainer);
+
+function testSingleToggle(toggleCommand, value, initialContents, expectedContents)
+{
+    testContainer.innerHTML = initialContents;
+    window.getSelection().selectAllChildren(testContainer);
+    document.execCommand('styleWithCSS', false, 'false');
+    document.execCommand(toggleCommand, false, value);
+    var action = toggleCommand + '(' + value + ') on all of "' + initialContents + '" yields "' + testContainer.innerHTML + '"';
+    if (testContainer.innerHTML == expectedContents)
+        testPassed(action);
+    else
+        testFailed(action + ', expected "' + expectedContents + '"');
+}
+
+testSingleToggle("fontSize", 4, 'hello <font size="4">world</font> WebKit', '<font class="Apple-style-span" size="4">hello world WebKit</font>');
+testSingleToggle("fontName", "Arial", 'hello <b><font face="Arial">world</font></b> WebKit', '<font class="Apple-style-span" face="Arial">hello <b>world</b> WebKit</font>');
+testSingleToggle("italic", null, 'hello <u><i title="message">world </i><i>WebKit</i></u>', '<i>hello <u><span title="message">world </span>WebKit</u></i>');
+testSingleToggle("bold", null, 'hello <i><b>world</b> WebKit</i>', '<b>hello <i>world WebKit</i></b>');
+testSingleToggle("bold", null, 'hello <i><b class="test">world</b> WebKit</i>', '<b>hello <i><span class="test">world</span> WebKit</i></b>');
+testSingleToggle("bold", null, 'hello <b contenteditable="false">world</b> <b>WebKit </b><u><b>rocks</b></u>', '<b>hello </b><b contenteditable="false">world</b><b> WebKit <u>rocks</u></b>');
+testSingleToggle("strikeThrough", null, 'hello <b>world <s>WebKit</s></b>', '<s>hello <b>world WebKit</b></s>');
+testSingleToggle("strikeThrough", null, 'hello <i><s>world</s></i><b><s>WebKit</s></b> rocks', '<s>hello <i>world</i><b>WebKit</b> rocks</s>');
+testSingleToggle("strikeThrough", null, 'hello <i><s>world</s></i> WebKit <b><s>rocks</s></b>', '<s>hello <i>world</i> WebKit <b>rocks</b></s>');
+
+// block nodes and br tests
+testSingleToggle("bold", null, 'hello<div><i>world</i> <b>WebKit</b></div><div>rocks</div>', '<b>hello</b><div><b><i>world</i> WebKit</b></div><div><b>rocks</b></div>');
+testSingleToggle("bold", null, 'hello<br style="display: block;"><i><b>world</b></i><br><b>WebKit</b>', '<b>hello<br style="display: block;"><i>world</i><br>WebKit</b>');
+testSingleToggle("bold", null, 'hello<p><b>world</b> <i><b>W</b>ebKit</i></p><b>rocks</b>', '<b>hello</b><p><b>world <i>WebKit</i></b></p><b>rocks</b>');
+
+document.body.removeChild(testContainer);
+var successfullyParsed = true;
index bb8dd48..e3c5c56 100644 (file)
@@ -97,7 +97,7 @@ modifyWritingDirection('<div dir="rtl"><b>هنا يكتب</b> النص العر
 modifyWritingDirection('<div dir="rtl">هنا <span dir="ltr">يكتب النص العربي</span></div>', selectThirdWord, 'Natural',
                        '<div dir="rtl">هنا <span dir="ltr">يكتب</span> النص<span dir="ltr"> العربي</span></div>');
 modifyWritingDirection('<div dir="rtl">هنا <span dir="ltr">يكتب النص العربي</span></div>', selectThirdWord, 'LeftToRight',
-                       '<div dir="rtl"><span style="direction: ltr;">هنا </span><span dir="ltr">يكتب النص العربي</span></div>');
+                       '<div dir="rtl"><span style="direction: ltr;">هنا يكتب النص العربي</span></div>');
 modifyWritingDirection('<div dir="rtl">هنا <span dir="ltr">يكتب النص العربي</span></div>', selectThirdWord, 'RightToLeft',
                        '<div dir="rtl">هنا <span dir="ltr">يكتب</span><span style="unicode-bidi: embed;"> النص</span><span dir="ltr"> العربي</span></div>');
 
index 934ff0b..eb2f6d0 100644 (file)
@@ -12,7 +12,7 @@ PASS event.target.innerHTML is '<br>'
 PASS event.target.id is 'target4'
 PASS event.target.innerHTML is '<a href="http://www.example.com/">This text should be a link.</a>'
 PASS event.target.id is 'target6parent'
-PASS event.target.innerHTML is '<span id="target6start"><a href="http://www.example.com/">Start,</a></span><span id="target6middle"><a href="http://www.example.com/">Middle,</a></span><span id="target6end"><a href="http://www.example.com/">End.</a></span>'
+PASS event.target.innerHTML is '<span id="target6start"><a href="http://www.example.com/">Start,</a></span><a href="http://www.example.com/"><span id="target6middle">Middle,</span><span id="target6end">End.</span></a>'
 PASS event.target.id is 'target7'
 PASS event.target.innerHTML is 'X'
 PASS event.target.id is 'target8'
index a7053ab..8580841 100644 (file)
@@ -74,7 +74,7 @@ var target6start = document.getElementById("target6start");
 var target6middle = document.getElementById("target6middle");
 var target6end = document.getElementById("target6end");
 
-var expectedText6 = "<span id=\"target6start\"><a href=\"http://www.example.com/\">Start,</a></span><span id=\"target6middle\"><a href=\"http://www.example.com/\">Middle,</a></span><span id=\"target6end\"><a href=\"http://www.example.com/\">End.</a></span>";
+var expectedText6 = "<span id=\"target6start\"><a href=\"http://www.example.com/\">Start,</a></span><a href=\"http://www.example.com/\"><span id=\"target6middle\">Middle,</span><span id=\"target6end\">End.</span></a>";
 target6parent.addEventListener("input", function(evt) { fired(evt, "target6parent", expectedText6); });
 expectedInputEventCount++;
 target6start.addEventListener("input", function(evt) { testFailed("should not be reached"); });
index aa0695d..b05e980 100644 (file)
@@ -1,3 +1,27 @@
+2010-09-14  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Reviewed by Tony Chang.
+
+        applyInlineStyleToNodeRange does not extend run properly
+        https://bugs.webkit.org/show_bug.cgi?id=45616
+
+        The bug was caused by applyInlineStyleToNodeRange's skipping a node whenever it has children.
+        Fixed the bug by only skipping a node that contains the past end node, contains non-editable region,
+        or has a non-editable parent node. Also fixed a bug that applyInlineStyleToNodeRange does not remove
+        styled elements in a run that are identical to the one added. addInlineStyleIfNeeded now removes
+        all styled elements in a run using removeStyleFromRunBeforeApplyingStyle before calling addInlineStyleIfNeeded.
+
+        Test: editing/style/inline-style-extend-run.html
+
+        * editing/ApplyStyleCommand.cpp:
+        (WebCore::containsNonEditableRegion): Added.
+        (WebCore::ApplyStyleCommand::applyInlineStyleToNodeRange): See above.
+        (WebCore::ApplyStyleCommand::removeStyleFromRunBeforeApplyingStyle): Added, see above.
+        (WebCore::ApplyStyleCommand::removeInlineStyleFromElement): Added support for RemoveAlways.
+        (WebCore::ApplyStyleCommand::removeImplicitlyStyledElement): Replaced RemoveAttributesAndElements by RemoveIfNeeded.
+        (WebCore::ApplyStyleCommand::extractInlineStyleToPushDown): Replaced RemoveAttributesAndElements by RemoveIfNeeded.
+        * editing/ApplyStyleCommand.h:
+
 2010-09-14  Andreas Kling  <andreas.kling@nokia.com>
 
         Reviewed by Kenneth Rohde Christiansen.
index 69dc619..b2e93ec 100644 (file)
@@ -1071,6 +1071,20 @@ void ApplyStyleCommand::fixRangeAndApplyInlineStyle(CSSMutableStyleDeclaration*
     applyInlineStyleToNodeRange(style, startNode, pastEndNode);
 }
 
+static bool containsNonEditableRegion(Node* node)
+{
+    if (!node->isContentEditable())
+        return true;
+
+    Node* sibling = node->traverseNextSibling();
+    for (Node* descendent = node->firstChild(); descendent && descendent != sibling; descendent = descendent->traverseNextNode()) {
+        if (!descendent->isContentEditable())
+            return true;
+    }
+
+    return false;
+}
+
 void ApplyStyleCommand::applyInlineStyleToNodeRange(CSSMutableStyleDeclaration* style, Node* node, Node* pastEndNode)
 {
     for (Node* next; node && node != pastEndNode; node = next) {
@@ -1098,32 +1112,62 @@ void ApplyStyleCommand::applyInlineStyleToNodeRange(CSSMutableStyleDeclaration*
             continue;
         
         if (node->childNodeCount()) {
-            if (editingIgnoresContent(node))
+            if (node->contains(pastEndNode) || containsNonEditableRegion(node) || !node->parentNode()->isContentEditable())
+                continue;
+            if (editingIgnoresContent(node)) {
                 next = node->traverseNextSibling();
-            continue;
+                continue;
+            }
         }
 
         Node* runEnd = node;
         Node* sibling = node->nextSibling();
-        StyleChange startChange(style, Position(node, 0));
         while (sibling && sibling != pastEndNode && !sibling->contains(pastEndNode)
                && (!isBlock(sibling) || sibling->hasTagName(brTag))
-               && StyleChange(style, Position(sibling, 0)) == startChange) {
+               && !containsNonEditableRegion(sibling)) {
             runEnd = sibling;
             sibling = runEnd->nextSibling();
         }
         next = runEnd->traverseNextSibling();
+
+        if (!removeStyleFromRunBeforeApplyingStyle(style, node, runEnd))
+            continue;
         addInlineStyleIfNeeded(style, node, runEnd, m_removeOnly ? DoNotAddStyledElement : AddStyledElement);
     }
 }
 
+bool ApplyStyleCommand::removeStyleFromRunBeforeApplyingStyle(CSSMutableStyleDeclaration* style, Node*& runStart, Node*& runEnd)
+{
+    Node* pastEndNode = runEnd->traverseNextSibling();
+    Node* next;
+    for (Node* node = runStart; node && node != pastEndNode; node = next) {
+        next = node->traverseNextNode();
+        if (!node->isHTMLElement())
+            continue;
+        
+        Node* previousSibling = node->previousSibling();
+        Node* nextSibling = node->nextSibling();
+        Node* parent = node->parentNode();
+        removeInlineStyleFromElement(style, static_cast<HTMLElement*>(node), RemoveAlways);
+        if (!node->inDocument()) {
+            // FIXME: We might need to update the start and the end of current selection here but need a test.
+            if (runStart == node)
+                runStart = previousSibling ? previousSibling->nextSibling() : parent->firstChild();
+            if (runEnd == node)
+                runEnd = nextSibling ? nextSibling->previousSibling() : parent->lastChild();
+        }
+    }
+
+    return true;
+}
+
 bool ApplyStyleCommand::removeInlineStyleFromElement(CSSMutableStyleDeclaration* style, HTMLElement* element, InlineStyleRemovalMode mode)
 {
     ASSERT(style);
     ASSERT(element);
 
     if (m_styledInlineElement && element->hasTagName(m_styledInlineElement->tagQName())) {
-        if (mode == RemoveAttributesAndElements)
+        if (mode != RemoveNone)
             removeNodePreservingChildren(element);
         return true;
     }
@@ -1220,10 +1264,12 @@ bool ApplyStyleCommand::removeImplicitlyStyledElement(CSSMutableStyleDeclaration
         else
             mapValue = CSSPrimitiveValue::createIdentifier(equivalent.primitiveId).get();
 
-        if (equivalent.isValueList && styleValue->isValueList() && static_cast<CSSValueList*>(styleValue.get())->hasValue(mapValue.get()))
-            continue; // If CSS value assumes CSSValueList, then only skip if the value was present in style to apply.
-        else if (mapValue && styleValue->cssText() == mapValue->cssText())
-            continue; // If CSS value is primitive, then skip if they are equal.
+        if (mode != RemoveAlways) {
+            if (equivalent.isValueList && styleValue->isValueList() && static_cast<CSSValueList*>(styleValue.get())->hasValue(mapValue.get()))
+                continue; // If CSS value assumes CSSValueList, then only skip if the value was present in style to apply.
+            else if (mapValue && styleValue->cssText() == mapValue->cssText())
+                continue; // If CSS value is primitive, then skip if they are equal.
+        }
 
         if (extractedStyle)
             extractedStyle->setProperty(equivalent.propertyID, mapValue->cssText());
@@ -1342,7 +1388,7 @@ PassRefPtr<CSSMutableStyleDeclaration> ApplyStyleCommand::extractInlineStyleToPu
 
     if (!style) {
         style = CSSMutableStyleDeclaration::create();
-        removeImplicitlyStyledElement(styleToApply, element, RemoveAttributesAndElements, style.get());
+        removeImplicitlyStyledElement(styleToApply, element, RemoveIfNeeded, style.get());
         return style.release();
     }
 
@@ -1364,7 +1410,7 @@ PassRefPtr<CSSMutableStyleDeclaration> ApplyStyleCommand::extractInlineStyleToPu
     if (isSpanWithoutAttributesOrUnstyleStyleSpan(element))
         removeNodePreservingChildren(element);
 
-    removeImplicitlyStyledElement(styleToApply, element, RemoveAttributesAndElements, style.get());
+    removeImplicitlyStyledElement(styleToApply, element, RemoveIfNeeded, style.get());
 
     return style.release();
 }
index 9f297e2..78f592e 100644 (file)
@@ -42,7 +42,7 @@ enum ShouldIncludeTypingStyle {
 class ApplyStyleCommand : public CompositeEditCommand {
 public:
     enum EPropertyLevel { PropertyDefault, ForceBlockProperties };
-    enum InlineStyleRemovalMode { RemoveAttributesAndElements, RemoveNone };
+    enum InlineStyleRemovalMode { RemoveIfNeeded, RemoveAlways, RemoveNone };
     enum EAddStyledElement { AddStyledElement, DoNotAddStyledElement };
 
     static PassRefPtr<ApplyStyleCommand> create(Document* document, CSSStyleDeclaration* style, EditAction action = EditActionChangeAttributes, EPropertyLevel level = PropertyDefault)
@@ -71,11 +71,12 @@ private:
     CSSMutableStyleDeclaration* style() const { return m_style.get(); }
 
     // style-removal helpers
-    bool removeInlineStyleFromElement(CSSMutableStyleDeclaration*, HTMLElement*, InlineStyleRemovalMode = RemoveAttributesAndElements);
+    bool removeStyleFromRunBeforeApplyingStyle(CSSMutableStyleDeclaration* style, Node*& runStart, Node*& runEnd);
+    bool removeInlineStyleFromElement(CSSMutableStyleDeclaration*, HTMLElement*, InlineStyleRemovalMode = RemoveIfNeeded);
     inline bool shouldRemoveInlineStyleFromElement(CSSMutableStyleDeclaration* style, HTMLElement* element) {return removeInlineStyleFromElement(style, element, RemoveNone);}
     bool removeImplicitlyStyledElement(CSSMutableStyleDeclaration*, HTMLElement*, InlineStyleRemovalMode, CSSMutableStyleDeclaration* extractedStyle = 0);
     void replaceWithSpanOrRemoveIfWithoutAttributes(HTMLElement*&);
-    bool removeCSSStyle(CSSMutableStyleDeclaration*, HTMLElement*, InlineStyleRemovalMode = RemoveAttributesAndElements);
+    bool removeCSSStyle(CSSMutableStyleDeclaration*, HTMLElement*, InlineStyleRemovalMode = RemoveIfNeeded);
     HTMLElement* highestAncestorWithConflictingInlineStyle(CSSMutableStyleDeclaration*, Node*);
     PassRefPtr<CSSMutableStyleDeclaration> extractInlineStyleToPushDown(CSSMutableStyleDeclaration*, Node*, bool isStyledElement);
     void applyInlineStyleToPushDown(Node*, CSSMutableStyleDeclaration *style);