[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

rniwa at webkit.org rniwa at webkit.org
Wed Dec 22 14:39:47 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit aeeef96044d41cc7b99bb23f127fd813e8906c98
Author: rniwa at webkit.org <rniwa at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Oct 15 04:09:48 2010 +0000

    2010-10-14  Ryosuke Niwa  <rniwa at webkit.org>
    
            Reviewed by Tony Chang and Darin Adler.
    
            execCommand FormatBlock creates lots of blockquotes
            https://bugs.webkit.org/show_bug.cgi?id=19795
    
            The bug was caused by WebKit's not reusing the block node added by previous iteration
            and its inserting block node at wrong places.
    
            Fixed the bug by rewriting FormatBlockCommand::formatRange.  New code resembles that of
            IndentOutdentCommand::indentIntoBlockquote.  The difference between two is that formatRange
            avoids the existing block elements when replacing blocks and it also adds a placeholder
            when removing the existing block caused paragraphs to collapse.
    
            Also fixed a bug in moveParagraphWithClones where erroneous br is added to the start of
            the block element to which the paragraph is moved if the block element is the start of a paragraph
            and not the end of a paragraph.
    
            Tests: editing/execCommand/format-block-multiple-paragraphs.html
                   editing/execCommand/format-block-table.html
    
            * editing/CompositeEditCommand.cpp:
            (WebCore::CompositeEditCommand::moveParagraphWithClones): No longer adds erroneous br.
            * editing/EditorCommand.cpp:
            (WebCore::executeFormatBlock):
            * editing/FormatBlockCommand.cpp:
            (WebCore::FormatBlockCommand::formatRange): Rewritten; see above.
            (WebCore::FormatBlockCommand::isElementToApplyInFormatBlockCommand): Renamed from validBlockElement
            and moved from htmlediting.cpp.
            (WebCore::enclosingBlockToSplitTreeTo): Added.
            * editing/FormatBlockCommand.h:
            * editing/VisiblePosition.cpp:
            (WebCore::enclosingBlockFlowElement): Changed the return type to Element*
            * editing/VisiblePosition.h:
    2010-10-14  Ryosuke Niwa  <rniwa at webkit.org>
    
            Reviewed by Tony Chang and Darin Adler.
    
            execCommand FormatBlock creates lots of blockquotes
            https://bugs.webkit.org/show_bug.cgi?id=19795
    
            Added tests to ensure WebKit does not add multiple block elements when applying block element to
            multiple paragraphs.  Also added a test to ensure formatBlock works with tables.
    
            * fast/html/nav-element-expected.txt: Preserved new lines and removed redundant br.
            * editing/execCommand/format-block-expected.txt: Preserved span and removed erroneous br.
            * editing/execCommand/format-block-from-range-selection-expected.txt: Merged dl's and removed erroneous br.
            * editing/execCommand/format-block-multiple-paragraphs-expected.txt: Added.
            * editing/execCommand/format-block-multiple-paragraphs.html: Added.
            * editing/execCommand/format-block-table-expected.txt: Added.
            * editing/execCommand/format-block-table.html: Added.
            * editing/execCommand/format-block-with-braces-expected.txt: Removed erroneous br.
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@69836 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index d6bd84a..7781c98 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,22 @@
+2010-10-14  Ryosuke Niwa  <rniwa at webkit.org>
+
+        Reviewed by Tony Chang and Darin Adler.
+
+        execCommand FormatBlock creates lots of blockquotes
+        https://bugs.webkit.org/show_bug.cgi?id=19795
+
+        Added tests to ensure WebKit does not add multiple block elements when applying block element to
+        multiple paragraphs.  Also added a test to ensure formatBlock works with tables.
+
+        * fast/html/nav-element-expected.txt: Preserved new lines and removed redundant br.
+        * editing/execCommand/format-block-expected.txt: Preserved span and removed erroneous br.
+        * editing/execCommand/format-block-from-range-selection-expected.txt: Merged dl's and removed erroneous br.
+        * editing/execCommand/format-block-multiple-paragraphs-expected.txt: Added.
+        * editing/execCommand/format-block-multiple-paragraphs.html: Added.
+        * editing/execCommand/format-block-table-expected.txt: Added.
+        * editing/execCommand/format-block-table.html: Added.
+        * editing/execCommand/format-block-with-braces-expected.txt: Removed erroneous br.
+
 2010-10-14  Kinuko Yasuda  <kinuko at chromium.org>
 
         Unreviewed, asssigned a bug number to failing filesystem tests.
diff --git a/LayoutTests/editing/execCommand/format-block-expected.txt b/LayoutTests/editing/execCommand/format-block-expected.txt
index 9b21c11..03f0262 100644
--- a/LayoutTests/editing/execCommand/format-block-expected.txt
+++ b/LayoutTests/editing/execCommand/format-block-expected.txt
@@ -52,7 +52,6 @@ After FormatBlock:
 "
 | <pre>
 |   "Make Pre"
-|   <br>
 | "
 "
 | <br>
@@ -62,8 +61,9 @@ After FormatBlock:
 |   "Foo"
 |   <br>
 |   <h1>
-|     "Make h1"
-|     <br>
+|     <span>
+|       id="item2"
+|       "Make h1"
 |   "baz"
 | "
 "
diff --git a/LayoutTests/editing/execCommand/format-block-from-range-selection-expected.txt b/LayoutTests/editing/execCommand/format-block-from-range-selection-expected.txt
index f8d91ac..aa68510 100644
--- a/LayoutTests/editing/execCommand/format-block-from-range-selection-expected.txt
+++ b/LayoutTests/editing/execCommand/format-block-from-range-selection-expected.txt
@@ -32,22 +32,23 @@ after FormatBlock:
 "
 | <dl>
 |   "Fo<#selection-anchor>o"
+|   <br>
+|   "bar"
+|   <br>
+|   <span>
+|     "baz"
+|     <br>
+|   "raz"
+|   <br>
+|   "
+dar"
+|   <br>
+|   "
+"
+|   "yar<#selection-focus>"
 | "
 "
-| <div>
-|   <dl>
-|     "bar"
-|   <span>
-|     <dl>
-|       "baz"
-|   <dl>
-|     "raz"
-| <dl>
-|   "dar"
-|   " "
 | "
 "
-| <dl>
-|   "ya<#selection-focus>r"
 | "
 "
diff --git a/LayoutTests/editing/execCommand/format-block-multiple-paragraphs-expected.txt b/LayoutTests/editing/execCommand/format-block-multiple-paragraphs-expected.txt
new file mode 100644
index 0000000..a524cc8
--- /dev/null
+++ b/LayoutTests/editing/execCommand/format-block-multiple-paragraphs-expected.txt
@@ -0,0 +1,233 @@
+This tests ensures formatBlock do not make multiple elements when formatting multiple paragraphs.
+
+Formatting:
+| "
+"
+| <div>
+|   "<#selection-anchor>hello"
+| <div>
+|   "world"
+| <div>
+|   "WebKit<#selection-focus>"
+| "
+"
+
+by p yields:
+| "
+"
+| <p>
+|   "<#selection-anchor>hello"
+|   <br>
+|   "world"
+|   <br>
+|   "WebKit<#selection-focus>"
+| "
+"
+
+Formatting:
+| "
+"
+| <p>
+|   "<#selection-anchor>hello"
+| <p>
+|   "world<#selection-focus>"
+| "
+"
+
+by blockquote yields:
+| "
+"
+| <blockquote>
+|   "<#selection-anchor>hello"
+|   <br>
+|   "world<#selection-focus>"
+| "
+"
+
+Formatting:
+| "
+"
+| <div>
+|   "<#selection-anchor>hello"
+|   <pre>
+|     "world<#selection-focus>"
+| "
+"
+
+by p yields:
+| "
+"
+| <div>
+|   <p>
+|     "<#selection-anchor>hello"
+|     <br>
+|     "world<#selection-focus>"
+| "
+"
+
+Formatting:
+| "
+"
+| <h1>
+|   "<#selection-anchor>hello"
+| <div>
+|   <h2>
+|     "world"
+|   <h3>
+|     "WebKit<#selection-focus>"
+| "
+"
+
+by pre yields:
+| "
+"
+| <pre>
+|   "<#selection-anchor>hello"
+|   <br>
+|   "world"
+|   <br>
+|   "WebKit<#selection-focus>"
+| "
+"
+
+Formatting:
+| "
+"
+| <div>
+|   "hello"
+|   <p>
+|     "<#selection-anchor>world"
+|   "webki<#selection-focus>t"
+| "
+"
+
+by h1 yields:
+| "
+"
+| <div>
+|   "hello"
+|   <h1>
+|     "<#selection-anchor>world"
+|     <br>
+|     "webkit<#selection-focus>"
+| "
+"
+
+Formatting:
+| "
+"
+| <pre>
+|   "<#selection-anchor>hello
+world<#selection-focus>
+webkit
+"
+| "
+"
+
+by blockquote yields:
+| "
+"
+| <pre>
+|   <blockquote>
+|     "<#selection-anchor>hello"
+|     <br>
+|     "world<#selection-focus>"
+|     <br>
+|     "webkit"
+| "
+"
+
+Formatting:
+| "
+"
+| <pre>
+|   "hello
+<#selection-anchor>world
+webki<#selection-focus>t
+"
+| "
+"
+
+by blockquote yields:
+| "
+"
+| <pre>
+|   "hello
+"
+|   <blockquote>
+|     "<#selection-anchor>world"
+|     <br>
+|     "webki<#selection-focus>t"
+| "
+"
+
+Formatting:
+| "
+<#selection-anchor>hello"
+| <p>
+|   "world<#selection-focus>"
+| <p>
+|   "webkit"
+| "
+
+"
+
+by pre yields:
+| <pre>
+|   "<#selection-anchor>
+hello"
+|   <br>
+|   "worl<#selection-focus>d"
+| <p>
+|   "webkit"
+| "
+
+"
+
+Formatting:
+| "
+"
+| <div>
+|   "hello"
+| <div>
+|   "<#selection-anchor>world"
+| <div>
+|   "webki<#selection-focus>t"
+| "
+"
+
+by pre yields:
+| "
+"
+| <div>
+|   "hello"
+| <pre>
+|   "<#selection-anchor>world"
+|   <br>
+|   "webki<#selection-focus>t"
+| "
+"
+
+Formatting:
+| "
+"
+| <ul>
+|   <li>
+|     "<#selection-anchor>hello"
+|   <li>
+|     "world<#selection-focus>"
+| "
+"
+
+by blockquote yields:
+| "
+"
+| <blockquote>
+|   <ul>
+|     <li>
+|       "<#selection-anchor>hello"
+|   <ul>
+|     <li>
+|       "world<#selection-focus>"
+| "
+"
diff --git a/LayoutTests/editing/execCommand/format-block-multiple-paragraphs.html b/LayoutTests/editing/execCommand/format-block-multiple-paragraphs.html
new file mode 100644
index 0000000..dc41425
--- /dev/null
+++ b/LayoutTests/editing/execCommand/format-block-multiple-paragraphs.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src="../../resources/dump-as-markup.js"></script>
+<div id="test0" contenteditable>
+<div>hello</div><div>world</div><div>WebKit</div>
+</div>
+<div id="test1" contenteditable>
+<p>hello</p><p>world</p>
+</div>
+<div id="test2" contenteditable>
+<div>hello<pre>world</pre></div>
+</div>
+<div id="test3" contenteditable>
+<h1>hello</h1><div><h2>world</h2><h3>WebKit</h3></div>
+</div>
+<div id="test4" contenteditable>
+<div>hello<p>world</p>webkit</div>
+</div>
+<div id="test5" contenteditable>
+<pre>hello
+world
+webkit
+</pre>
+</div>
+<div id="test6" contenteditable>
+<pre>hello
+world
+webkit
+</pre>
+</div>
+<div id="test7" contenteditable>
+hello<p>world</p><p>webkit</p>
+</pre>
+</div>
+<div id="test8" contenteditable>
+<div>hello</div><div>world</div><div>webkit</div>
+</div>
+<div id="test9" contenteditable>
+<ul><li>hello</li><li>world</li></ul>
+</div>
+<script>
+
+Markup.description('This tests ensures formatBlock do not make multiple elements when formatting multiple paragraphs.')
+
+function testIndentation(containerId, selector, value) {
+    var container = document.getElementById(containerId);
+    selector(container);
+    Markup.dump(container, 'Formatting');
+    document.execCommand('FormatBlock', false, value);
+    Markup.dump(container, 'by ' + value + ' yields');
+}
+
+function selectAll(container) {
+    window.getSelection().selectAllChildren(container);
+}
+
+function selectorForLines(first, last) {
+    return function (container) {
+        window.getSelection().setPosition(container, 0);
+        for (var i = 0; i < first - 1; i++)
+            window.getSelection().modify('move', 'forward', 'line');
+        for (var i = 0; i < Math.abs(last - first, 0) + 1; i++)
+            window.getSelection().modify('extend', 'forward', 'line');
+        window.getSelection().modify('extend', 'backward', 'character');
+    }
+}
+
+testIndentation('test0', selectAll, 'p');
+testIndentation('test1', selectAll, 'blockquote');
+testIndentation('test2', selectAll, 'p');
+testIndentation('test3', selectAll, 'pre');
+testIndentation('test4', selectorForLines(2, 3), 'h1');
+testIndentation('test5', selectorForLines(1, 2), 'blockquote');
+testIndentation('test6', selectorForLines(2, 3), 'blockquote');
+testIndentation('test7', selectorForLines(1, 2), 'pre');
+testIndentation('test8', selectorForLines(2, 3), 'pre');
+testIndentation('test9', selectAll, 'blockquote');
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/editing/execCommand/format-block-table-expected.txt b/LayoutTests/editing/execCommand/format-block-table-expected.txt
new file mode 100644
index 0000000..7f6ddde
--- /dev/null
+++ b/LayoutTests/editing/execCommand/format-block-table-expected.txt
@@ -0,0 +1,124 @@
+
+Formatting:
+| "
+"
+| <table>
+|   <tbody>
+|     <tr>
+|       <td>
+|         "hello"
+|       <td>
+|         "world"
+| "
+"
+
+by p yields:
+| "
+"
+| <p>
+|   <#selection-anchor>
+|   <table>
+|     <tbody>
+|       <tr>
+|         <td>
+|           "hello"
+|         <td>
+|           "world"
+|   <#selection-focus>
+| "
+"
+
+Formatting:
+| "
+"
+| <table>
+|   <tbody>
+|     <tr>
+|       <td>
+|         "<#selection-anchor>hello<#selection-focus>"
+|       <td>
+|         "world"
+| "
+"
+
+by blockquote yields:
+| "
+"
+| <table>
+|   <tbody>
+|     <tr>
+|       <td>
+|         <blockquote>
+|           "<#selection-anchor>hello<#selection-focus>"
+|       <td>
+|         "world"
+| "
+"
+
+Formatting:
+| "
+"
+| <table>
+|   <tbody>
+|     <tr>
+|       <td>
+|         <p>
+|           "<#selection-anchor>hello"
+|         <div>
+|           "world<#selection-focus>"
+|       <td>
+|         "WebKit"
+| "
+"
+
+by h3 yields:
+| "
+"
+| <table>
+|   <tbody>
+|     <tr>
+|       <td>
+|         <h3>
+|           "<#selection-anchor>hello"
+|           <br>
+|           "world<#selection-focus>"
+|       <td>
+|         "WebKit"
+| "
+"
+
+Formatting:
+| "
+"
+| <table>
+|   <tbody>
+|     <tr>
+|       <td>
+|         <ul>
+|           <li>
+|             "<#selection-anchor>hello"
+|           <li>
+|             "world<#selection-focus>"
+|       <td>
+|         "WebKit"
+| "
+"
+
+by address yields:
+| "
+"
+| <table>
+|   <tbody>
+|     <tr>
+|       <td>
+|         <address>
+|           <ul>
+|             <li>
+|               "<#selection-anchor>hello"
+|           <ul>
+|             <li>
+|               "world<#selection-focus>"
+|       <td>
+|         "WebKit"
+| "
+"
diff --git a/LayoutTests/editing/execCommand/format-block-table.html b/LayoutTests/editing/execCommand/format-block-table.html
new file mode 100644
index 0000000..28ba100
--- /dev/null
+++ b/LayoutTests/editing/execCommand/format-block-table.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src="../../resources/dump-as-markup.js"></script>
+<div id="test0" contenteditable>
+<table><tr><td>hello</td><td>world</td></tr></table>
+</div>
+<div id="test1" contenteditable>
+<table><tr><td>hello</td><td>world</td></tr></table>
+</div>
+<div id="test2" contenteditable>
+<table><tr><td><p>hello</p><div>world</div></td><td>WebKit</td></tr></table>
+</div>
+<div id="test3" contenteditable>
+<table><tr><td><ul><li>hello</li><li>world</li></ul></td><td>WebKit</td></tr></table>
+</div>
+<script>
+
+function testIndentation(containerId, selector, value) {
+    var container = document.getElementById(containerId);
+    selector(container);
+    Markup.dump(container, 'Formatting');
+    document.execCommand('FormatBlock', false, value);
+    Markup.dump(container, 'by ' + value + ' yields');
+}
+
+function selectAll(container) {
+    window.getSelection().selectAllChildren(container);
+}
+
+function selectFirstCell(container) {
+    window.getSelection().selectAllChildren(container.getElementsByTagName('td')[0]);
+}
+
+testIndentation('test0', selectAll, 'p');
+testIndentation('test1', selectFirstCell, 'blockquote');
+testIndentation('test2', selectFirstCell, 'h3');
+testIndentation('test3', selectFirstCell, 'address');
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/editing/execCommand/format-block-with-braces-expected.txt b/LayoutTests/editing/execCommand/format-block-with-braces-expected.txt
index 89b4435..2b5b4dc 100644
--- a/LayoutTests/editing/execCommand/format-block-with-braces-expected.txt
+++ b/LayoutTests/editing/execCommand/format-block-with-braces-expected.txt
@@ -16,5 +16,6 @@ Format Me
 
 After FormatBlock with <h1>:
 | <h1>
-|   "<#selection-caret>Format Me"
-|   <br>
+|   "
+<#selection-caret>Format Me
+"
diff --git a/LayoutTests/fast/html/nav-element-expected.txt b/LayoutTests/fast/html/nav-element-expected.txt
index 742d349..4cab53a 100644
--- a/LayoutTests/fast/html/nav-element-expected.txt
+++ b/LayoutTests/fast/html/nav-element-expected.txt
@@ -24,5 +24,7 @@ DOM for the above (so this test can dump as text)
 
 <p><br></p>
 
-<div contenteditable="true" id="editable"><nav>Test of FormatBlock behavior. This text should have a green border.<br></nav></div>
+<div contenteditable="true" id="editable"><nav>
+Test of FormatBlock behavior. This text should have a green border.
+</nav></div>
 
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 77e2ea5..953f1f0 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,39 @@
+2010-10-14  Ryosuke Niwa  <rniwa at webkit.org>
+
+        Reviewed by Tony Chang and Darin Adler.
+
+        execCommand FormatBlock creates lots of blockquotes
+        https://bugs.webkit.org/show_bug.cgi?id=19795
+
+        The bug was caused by WebKit's not reusing the block node added by previous iteration
+        and its inserting block node at wrong places.
+
+        Fixed the bug by rewriting FormatBlockCommand::formatRange.  New code resembles that of
+        IndentOutdentCommand::indentIntoBlockquote.  The difference between two is that formatRange
+        avoids the existing block elements when replacing blocks and it also adds a placeholder
+        when removing the existing block caused paragraphs to collapse.
+
+        Also fixed a bug in moveParagraphWithClones where erroneous br is added to the start of
+        the block element to which the paragraph is moved if the block element is the start of a paragraph
+        and not the end of a paragraph.
+
+        Tests: editing/execCommand/format-block-multiple-paragraphs.html
+               editing/execCommand/format-block-table.html
+
+        * editing/CompositeEditCommand.cpp:
+        (WebCore::CompositeEditCommand::moveParagraphWithClones): No longer adds erroneous br.
+        * editing/EditorCommand.cpp:
+        (WebCore::executeFormatBlock):
+        * editing/FormatBlockCommand.cpp:
+        (WebCore::FormatBlockCommand::formatRange): Rewritten; see above.
+        (WebCore::FormatBlockCommand::isElementToApplyInFormatBlockCommand): Renamed from validBlockElement
+        and moved from htmlediting.cpp.
+        (WebCore::enclosingBlockToSplitTreeTo): Added.
+        * editing/FormatBlockCommand.h:
+        * editing/VisiblePosition.cpp:
+        (WebCore::enclosingBlockFlowElement): Changed the return type to Element*
+        * editing/VisiblePosition.h:
+
 2010-10-14  Justin Schuh  <jschuh at chromium.org>
 
         Reviewed by James Robinson.
diff --git a/WebCore/editing/ApplyBlockElementCommand.cpp b/WebCore/editing/ApplyBlockElementCommand.cpp
index d810555..ecd3d9b 100644
--- a/WebCore/editing/ApplyBlockElementCommand.cpp
+++ b/WebCore/editing/ApplyBlockElementCommand.cpp
@@ -112,10 +112,8 @@ void ApplyBlockElementCommand::formatSelection(const VisiblePosition& startOfSel
     VisiblePosition endOfLastParagraph = endOfParagraph(endOfSelection);
 
     bool atEnd = false;
+    Position end;
     while (endOfCurrentParagraph != endAfterSelection && !atEnd) {
-        Position start;
-        Position end;
-
         if (endOfCurrentParagraph == endOfLastParagraph)
             atEnd = true;
 
diff --git a/WebCore/editing/CompositeEditCommand.cpp b/WebCore/editing/CompositeEditCommand.cpp
index f27a2e5..4cb3005 100644
--- a/WebCore/editing/CompositeEditCommand.cpp
+++ b/WebCore/editing/CompositeEditCommand.cpp
@@ -863,7 +863,8 @@ void CompositeEditCommand::moveParagraphWithClones(const VisiblePosition& startO
     beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent());
     afterParagraph = VisiblePosition(afterParagraph.deepEquivalent());
 
-    if (beforeParagraph.isNotNull() && !isTableElement(beforeParagraph.deepEquivalent().node()) && (!isEndOfParagraph(beforeParagraph) || beforeParagraph == afterParagraph)) {
+    if (beforeParagraph.isNotNull() && !isTableElement(beforeParagraph.deepEquivalent().node())
+        && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforeParagraph)) || beforeParagraph == afterParagraph)) {
         // FIXME: Trim text between beforeParagraph and afterParagraph if they aren't equal.
         insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquivalent());
     }
diff --git a/WebCore/editing/EditorCommand.cpp b/WebCore/editing/EditorCommand.cpp
index a7a5af5..a8a23fb 100644
--- a/WebCore/editing/EditorCommand.cpp
+++ b/WebCore/editing/EditorCommand.cpp
@@ -432,8 +432,6 @@ static bool executeFormatBlock(Frame* frame, Event*, EditorCommandSource, const
     String tagName = value.lower();
     if (tagName[0] == '<' && tagName[tagName.length() - 1] == '>')
         tagName = tagName.substring(1, tagName.length() - 2);
-    if (!validBlockTag(tagName))
-        return false;
 
     ExceptionCode ec;
     String localName, prefix;
@@ -441,6 +439,9 @@ static bool executeFormatBlock(Frame* frame, Event*, EditorCommandSource, const
         return false;
     QualifiedName qualifiedTagName(prefix, localName, xhtmlNamespaceURI);
 
+    if (!FormatBlockCommand::isElementToApplyInFormatBlockCommand(qualifiedTagName))
+        return false;
+
     applyCommand(FormatBlockCommand::create(frame->document(), qualifiedTagName));
     return true;
 }
diff --git a/WebCore/editing/FormatBlockCommand.cpp b/WebCore/editing/FormatBlockCommand.cpp
index c4e81e2..1673235 100644
--- a/WebCore/editing/FormatBlockCommand.cpp
+++ b/WebCore/editing/FormatBlockCommand.cpp
@@ -36,46 +36,91 @@ namespace WebCore {
 
 using namespace HTMLNames;
 
+static Node* enclosingBlockToSplitTreeTo(Node* startNode);
+
 FormatBlockCommand::FormatBlockCommand(Document* document, const QualifiedName& tagName) 
     : ApplyBlockElementCommand(document, tagName)
 {
 }
 
-void FormatBlockCommand::formatRange(const Position&, const Position& end, RefPtr<Element>&)
+void FormatBlockCommand::formatRange(const Position& start, const Position& end, RefPtr<Element>& blockNode)
 {
-    setEndingSelection(VisiblePosition(end));
+    Node* nodeToSplitTo = enclosingBlockToSplitTreeTo(start.node());
+    RefPtr<Node> outerBlock = (start.node() == nodeToSplitTo) ? start.node() : splitTreeToNode(start.node(), nodeToSplitTo);
+    RefPtr<Node> nodeAfterInsertionPosition = outerBlock;
+
+    Element* refNode = enclosingBlockFlowElement(end);
+    Element* root = editableRootForPosition(start);
+    if (isElementToApplyInFormatBlockCommand(refNode->tagQName()) && start == startOfBlock(start) && end == endOfBlock(end)
+        && refNode != root && !root->isDescendantOf(refNode)) {
+        // Already in a block element that only contains the current paragraph
+        if (refNode->hasTagName(tagName()))
+            return;
+        nodeAfterInsertionPosition = refNode;
+    }
+
+    if (!blockNode) {
+        // Create a new blockquote and insert it as a child of the root editable element. We accomplish
+        // this by splitting all parents of the current paragraph up to that point.
+        blockNode = createBlockElement();
+        insertNodeBefore(blockNode, nodeAfterInsertionPosition);
+    }
 
-    Node* refNode = enclosingBlockFlowElement(endingSelection().visibleStart());
-    if (refNode->hasTagName(tagName()))
-        // We're already in a block with the format we want, so we don't have to do anything
-        return;
+    Position lastParagraphInBlockNode = lastPositionInNode(blockNode.get());
+    bool wasEndOfParagraph = isEndOfParagraph(lastParagraphInBlockNode);
 
-    VisiblePosition paragraphStart = startOfParagraph(end);
-    VisiblePosition paragraphEnd = endOfParagraph(end);
-    VisiblePosition blockStart = startOfBlock(endingSelection().visibleStart());
-    VisiblePosition blockEnd = endOfBlock(endingSelection().visibleStart());
-    RefPtr<Element> blockNode = createBlockElement();
-    RefPtr<Element> placeholder = createBreakElement(document());
+    moveParagraphWithClones(start, end, blockNode.get(), outerBlock.get());
 
-    Node* root = endingSelection().start().node()->rootEditableElement();
-    if (validBlockTag(refNode->nodeName().lower()) && 
-        paragraphStart == blockStart && paragraphEnd == blockEnd && 
-        refNode != root && !root->isDescendantOf(refNode))
-        // Already in a valid block tag that only contains the current paragraph, so we can swap with the new tag
-        insertNodeBefore(blockNode, refNode);
-    else {
-        // Avoid inserting inside inline elements that surround paragraphStart with upstream().
-        // This is only to avoid creating bloated markup.
-        insertNodeAt(blockNode, paragraphStart.deepEquivalent().upstream());
+    if (wasEndOfParagraph && !isEndOfParagraph(lastParagraphInBlockNode) && !isStartOfParagraph(lastParagraphInBlockNode))
+        insertBlockPlaceholder(lastParagraphInBlockNode);
+}
+
+// FIXME: We should consider merging this function with isElementForFormatBlockCommand in Editor.cpp
+// Checks if a tag name is valid for execCommand('FormatBlock').
+bool FormatBlockCommand::isElementToApplyInFormatBlockCommand(const QualifiedName& tagName)
+{
+    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, blockTags, ());
+    if (blockTags.isEmpty()) {
+        blockTags.add(addressTag);
+        blockTags.add(articleTag);
+        blockTags.add(asideTag);
+        blockTags.add(blockquoteTag);
+        blockTags.add(ddTag);
+        blockTags.add(divTag);
+        blockTags.add(dlTag);
+        blockTags.add(dtTag);
+        blockTags.add(footerTag);
+        blockTags.add(h1Tag);
+        blockTags.add(h2Tag);
+        blockTags.add(h3Tag);
+        blockTags.add(h4Tag);
+        blockTags.add(h5Tag);
+        blockTags.add(h6Tag);
+        blockTags.add(headerTag);
+        blockTags.add(hgroupTag);
+        blockTags.add(navTag);
+        blockTags.add(pTag);
+        blockTags.add(preTag);
+        blockTags.add(sectionTag);
     }
-    appendNode(placeholder, blockNode);
+    return blockTags.contains(tagName);
+}
 
-    VisiblePosition destination(Position(placeholder.get(), 0));
-    if (paragraphStart == paragraphEnd && !lineBreakExistsAtVisiblePosition(paragraphStart)) {
-        setEndingSelection(destination);
-        return;
+Node* enclosingBlockToSplitTreeTo(Node* startNode)
+{
+    Node* lastBlock = startNode;
+    for (Node* n = startNode; n; n = n->parentNode()) {
+        if (!n->isContentEditable())
+            return lastBlock;
+        if (isTableCell(n) || n->hasTagName(bodyTag) || !n->parentNode() || !n->parentNode()->isContentEditable()
+            || (n->isElementNode() && FormatBlockCommand::isElementToApplyInFormatBlockCommand(static_cast<Element*>(n)->tagQName())))
+            return n;
+        if (isBlock(n))
+            lastBlock = n;
+        if (isListElement(n))
+            return n->parentNode()->isContentEditable() ? n->parentNode() : n;
     }
-    moveParagraph(paragraphStart, paragraphEnd, destination, true, false);
+    return lastBlock;
 }
 
 }
diff --git a/WebCore/editing/FormatBlockCommand.h b/WebCore/editing/FormatBlockCommand.h
index 5e9cb96..68a1f47 100644
--- a/WebCore/editing/FormatBlockCommand.h
+++ b/WebCore/editing/FormatBlockCommand.h
@@ -38,11 +38,13 @@ public:
         return adoptRef(new FormatBlockCommand(document, tagName));
     }
 
+    static bool isElementToApplyInFormatBlockCommand(const QualifiedName& tagName);
+
 private:
     FormatBlockCommand(Document*, const QualifiedName& tagName);
 
-    virtual void formatRange(const Position&, const Position&, RefPtr<Element>&);
-    virtual EditAction editingAction() const { return EditActionFormatBlock; }
+    void formatRange(const Position&, const Position&, RefPtr<Element>&);
+    EditAction editingAction() const { return EditActionFormatBlock; }
 };
 
 } // namespace WebCore
diff --git a/WebCore/editing/VisiblePosition.cpp b/WebCore/editing/VisiblePosition.cpp
index 1e68538..760c68c 100644
--- a/WebCore/editing/VisiblePosition.cpp
+++ b/WebCore/editing/VisiblePosition.cpp
@@ -634,7 +634,7 @@ bool setEnd(Range *r, const VisiblePosition &visiblePosition)
     return code == 0;
 }
 
-Node *enclosingBlockFlowElement(const VisiblePosition &visiblePosition)
+Element* enclosingBlockFlowElement(const VisiblePosition &visiblePosition)
 {
     if (visiblePosition.isNull())
         return NULL;
diff --git a/WebCore/editing/VisiblePosition.h b/WebCore/editing/VisiblePosition.h
index fe795a1..e649b68 100644
--- a/WebCore/editing/VisiblePosition.h
+++ b/WebCore/editing/VisiblePosition.h
@@ -136,7 +136,7 @@ bool setEnd(Range*, const VisiblePosition&);
 VisiblePosition startVisiblePosition(const Range*, EAffinity);
 VisiblePosition endVisiblePosition(const Range*, EAffinity);
 
-Node *enclosingBlockFlowElement(const VisiblePosition&);
+Element* enclosingBlockFlowElement(const VisiblePosition&);
 
 bool isFirstVisiblePositionInNode(const VisiblePosition&, const Node*);
 bool isLastVisiblePositionInNode(const VisiblePosition&, const Node*);
diff --git a/WebCore/editing/htmlediting.cpp b/WebCore/editing/htmlediting.cpp
index 9ec71e7..7927900 100644
--- a/WebCore/editing/htmlediting.cpp
+++ b/WebCore/editing/htmlediting.cpp
@@ -465,39 +465,6 @@ bool isSpecialElement(const Node *n)
     return false;
 }
 
-// Checks if a string is a valid tag for the FormatBlockCommand function of execCommand. Expects lower case strings.
-bool validBlockTag(const AtomicString& blockTag)
-{
-    if (blockTag.isEmpty())
-        return false;
-
-    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, blockTags, ());
-    if (blockTags.isEmpty()) {
-        blockTags.add(addressTag.localName());
-        blockTags.add(articleTag.localName());
-        blockTags.add(asideTag.localName());
-        blockTags.add(blockquoteTag.localName());
-        blockTags.add(ddTag.localName());
-        blockTags.add(divTag.localName());
-        blockTags.add(dlTag.localName());
-        blockTags.add(dtTag.localName());
-        blockTags.add(footerTag.localName());
-        blockTags.add(h1Tag.localName());
-        blockTags.add(h2Tag.localName());
-        blockTags.add(h3Tag.localName());
-        blockTags.add(h4Tag.localName());
-        blockTags.add(h5Tag.localName());
-        blockTags.add(h6Tag.localName());
-        blockTags.add(headerTag.localName());
-        blockTags.add(hgroupTag.localName());
-        blockTags.add(navTag.localName());
-        blockTags.add(pTag.localName());
-        blockTags.add(preTag.localName());
-        blockTags.add(sectionTag.localName());
-    }
-    return blockTags.contains(blockTag);
-}
-
 static Node* firstInSpecialElement(const Position& pos)
 {
     // FIXME: This begins at pos.node(), which doesn't necessarily contain pos (suppose pos was [img, 0]).  See <rdar://problem/5027702>.
diff --git a/WebCore/editing/htmlediting.h b/WebCore/editing/htmlediting.h
index aaf6ef2..1892357 100644
--- a/WebCore/editing/htmlediting.h
+++ b/WebCore/editing/htmlediting.h
@@ -228,8 +228,6 @@ VisibleSelection selectionForParagraphIteration(const VisibleSelection&);
     
 String stringWithRebalancedWhitespace(const String&, bool, bool);
 const String& nonBreakingSpaceString();
-bool validBlockTag(const AtomicString&);
-    
 
 }
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list