2010-10-15 Ryosuke Niwa <rniwa@webkit.org>
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Oct 2010 20:53:46 +0000 (20:53 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Oct 2010 20:53:46 +0000 (20:53 +0000)
        Reviewed by Darin Adler.

        Match the elements supported by execCommand('formatBlock') and queryCommandValue('formatBlock')
        https://bugs.webkit.org/show_bug.cgi?id=47712

        Extended queryCommandValue('formatBlock', false, null) to support article, aside, blockquote, dd, dl,
        div, dl, dt, dl, footer, header, hgroup, nav, and section. Because this makes isElementForFormatBlockCommand
        in Editor.cpp and FormatBlockCommand::isElementToApplyInFormatBlockCommand identical, they are merged and moved
        to FormatBlockCommand.cpp

        Tests are added to editing/execCommand/query-format-block.html

        * editing/Editor.cpp: Removed isElementForFormatBlockCommand and Editor::elementForFormatBlockCommand.
        * editing/Editor.h:
        * editing/EditorCommand.cpp:
        (WebCore::executeFormatBlock): Removed the check of tag name; the check is moved into FormatBlockCommand.
        (WebCore::valueFormatBlock): Calls FormatBlockCommand::elementForFormatBlockCommand.
        * editing/FormatBlockCommand.cpp:
        (WebCore::isElementForFormatBlock):
        (WebCore::FormatBlockCommand::FormatBlockCommand):
        (WebCore::FormatBlockCommand::formatSelection): Added to check the tag name. Exit early if the specified tag name
        is not what FormatBlock should apply. Set m_didApply true if m_didApply did apply the element.
        (WebCore::FormatBlockCommand::formatRange): Moved from Editor.cpp.  Takes Range* instead of accessing selection directly.
        (WebCore::FormatBlockCommand::elementForFormatBlockCommand): Moved from Editor.cpp
        (WebCore::enclosingBlockToSplitTreeTo): Calls isElementForFormatBlock.
        * editing/FormatBlockCommand.h:
        (WebCore::FormatBlockCommand::didApply): Added.
2010-10-15  Ryosuke Niwa  <rniwa@webkit.org>

        Reviewed by Darin Adler.

        Match the elements supported by execCommand('formatBlock') and queryCommandValue('formatBlock')
        https://bugs.webkit.org/show_bug.cgi?id=47712

        Added queryCommandValue('formatBlock') tests for support article, aside, blockquote, dd, dl, div,
        dl, dt, dl, footer, header, hgroup, nav, and section.

        Also added tests to ensure we don't return tag name for a subset of unsupported elements.

        * editing/execCommand/query-format-block-expected.txt:
        * editing/execCommand/script-tests/query-format-block.js:
        (queryFormatBlock):
        (selectFirstPosition):
        (selectMiddleOfHelloWorld):

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

LayoutTests/ChangeLog
LayoutTests/editing/execCommand/query-format-block-expected.txt
LayoutTests/editing/execCommand/script-tests/query-format-block.js
WebCore/ChangeLog
WebCore/editing/Editor.cpp
WebCore/editing/Editor.h
WebCore/editing/EditorCommand.cpp
WebCore/editing/FormatBlockCommand.cpp
WebCore/editing/FormatBlockCommand.h

index 6492125..15b954b 100644 (file)
@@ -1,3 +1,21 @@
+2010-10-15  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Reviewed by Darin Adler.
+
+        Match the elements supported by execCommand('formatBlock') and queryCommandValue('formatBlock')
+        https://bugs.webkit.org/show_bug.cgi?id=47712
+
+        Added queryCommandValue('formatBlock') tests for support article, aside, blockquote, dd, dl, div,
+        dl, dt, dl, footer, header, hgroup, nav, and section.
+
+        Also added tests to ensure we don't return tag name for a subset of unsupported elements.
+
+        * editing/execCommand/query-format-block-expected.txt:
+        * editing/execCommand/script-tests/query-format-block.js:
+        (queryFormatBlock):
+        (selectFirstPosition):
+        (selectMiddleOfHelloWorld):
+
 2010-10-15  Martin Robinson  <mrobinson@igalia.com>
 
         Rebaseline two GTK+ tests.
 2010-10-15  Martin Robinson  <mrobinson@igalia.com>
 
         Rebaseline two GTK+ tests.
index ffc96d8..dab9fd5 100644 (file)
@@ -4,25 +4,79 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 Basic cases
 
 
 Basic cases
-PASS queryCommand('format') returned ""
-PASS queryCommand('format') returned ""
-PASS queryCommand('format') returned "address"
-PASS queryCommand('format') returned "h1"
-PASS queryCommand('format') returned "h2"
-PASS queryCommand('format') returned "h3"
-PASS queryCommand('format') returned "h4"
-PASS queryCommand('format') returned "h5"
-PASS queryCommand('format') returned "h6"
-PASS queryCommand('format') returned "p"
-PASS queryCommand('format') returned "pre"
+PASS queryCommand('formatBlock') returned "" selecting none of "hello"
+PASS queryCommand('formatBlock') returned "" selecting first position of "hello"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<a>hello</a>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<abbr>hello</abbr>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<acronym>hello</acronym>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<b>hello</b>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<bdo>hello</bdo>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<big>hello</big>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<button>hello</button>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<caption>hello</caption>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<center>hello</center>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<cite>hello</cite>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<code>hello</code>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<del>hello</del>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<dfn>hello</dfn>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<dir>hello</dir>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<em>hello</em>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<form><fieldset>hello</fieldset></form>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<font>hello</font>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<form>hello</form>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<i>hello</i>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<kbd>hello</kbd>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<label>hello</label>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<legend>hello</legend>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<ul><li>hello<li></ul>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<menu>hello</menu>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<ol>hello</ol>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<q>hello</q>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<s>hello</s>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<samp>hello</samp>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<small>hello</small>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<span>hello</span>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<strike>hello</strike>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<strong>hello</strong>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<sub>hello</sub>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<sup>hello</sup>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<table><td>hello</td></table>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<table><th>hello</th></table>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<tt>hello</tt>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<u>hello</u>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<ul>hello</ul>"
+PASS queryCommand('formatBlock') returned "" selecting first position of "<var>hello</var>"
+PASS queryCommand('formatBlock') returned "address" selecting first position of "<address>hello</address>"
+PASS queryCommand('formatBlock') returned "article" selecting first position of "<article>hello</article>"
+PASS queryCommand('formatBlock') returned "aside" selecting first position of "<aside>hello</aside>"
+PASS queryCommand('formatBlock') returned "blockquote" selecting first position of "<blockquote>hello</blockquote>"
+PASS queryCommand('formatBlock') returned "dd" selecting first position of "<dd>hello</dd>"
+PASS queryCommand('formatBlock') returned "dd" selecting first position of "<dl><dd>hello</dd></dl>"
+PASS queryCommand('formatBlock') returned "div" selecting first position of "<div>hello</div>"
+PASS queryCommand('formatBlock') returned "dl" selecting first position of "<dl>hello</dl>"
+PASS queryCommand('formatBlock') returned "dt" selecting first position of "<dt>hello</dt>"
+PASS queryCommand('formatBlock') returned "dt" selecting first position of "<dl><dt>hello</dt></dl>"
+PASS queryCommand('formatBlock') returned "footer" selecting first position of "<footer>hello</footer>"
+PASS queryCommand('formatBlock') returned "h1" selecting first position of "<h1>hello</h1>"
+PASS queryCommand('formatBlock') returned "h2" selecting first position of "<h2>hello</h2>"
+PASS queryCommand('formatBlock') returned "h3" selecting first position of "<h3>hello</h3>"
+PASS queryCommand('formatBlock') returned "h4" selecting first position of "<h4>hello</h4>"
+PASS queryCommand('formatBlock') returned "h5" selecting first position of "<h5>hello</h5>"
+PASS queryCommand('formatBlock') returned "h6" selecting first position of "<h6>hello</h6>"
+PASS queryCommand('formatBlock') returned "header" selecting first position of "<header>hello</header>"
+PASS queryCommand('formatBlock') returned "hgroup" selecting first position of "<hgroup>hello</hgroup>"
+PASS queryCommand('formatBlock') returned "nav" selecting first position of "<nav>hello</nav>"
+PASS queryCommand('formatBlock') returned "p" selecting first position of "<p>hello</p>"
+PASS queryCommand('formatBlock') returned "pre" selecting first position of "<pre>hello</pre>"
+PASS queryCommand('formatBlock') returned "section" selecting first position of "<section>hello</section>"
 
 Nested cases
 
 Nested cases
-PASS queryCommand('format') returned "h2"
-PASS queryCommand('format') returned "address"
-PASS queryCommand('format') returned "pre"
-PASS queryCommand('format') returned "pre"
-PASS queryCommand('format') returned "address"
-PASS queryCommand('format') returned ""
+PASS queryCommand('formatBlock') returned "h2" selecting first position of "<h1><h2>hello</h2></h1>"
+PASS queryCommand('formatBlock') returned "address" selecting first position of "<h1><address>hello</address></h1>"
+PASS queryCommand('formatBlock') returned "pre" selecting first position of "<pre>hello<p>world</p></pre>"
+PASS queryCommand('formatBlock') returned "pre" selecting "llo wo" of "<pre>hello<p>world</p></pre>"
+PASS queryCommand('formatBlock') returned "address" selecting "llo wo" of "<address><h1>hello</h1>world</address>"
+PASS queryCommand('formatBlock') returned "" selecting "llo wo" of "<h1>hello</h1>world"
 PASS successfullyParsed is true
 
 TEST COMPLETE
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 4e84caf..e9123a1 100644 (file)
@@ -1,15 +1,15 @@
 description("Tests queryCommandValue('formatBlock')")
 
 description("Tests queryCommandValue('formatBlock')")
 
-var testContainer = document.createElement("div");
+var testContainer = document.createElement("span");
 testContainer.contentEditable = true;
 document.body.appendChild(testContainer);
 
 function queryFormatBlock(selector, content, expected)
 {
     testContainer.innerHTML = content;
 testContainer.contentEditable = true;
 document.body.appendChild(testContainer);
 
 function queryFormatBlock(selector, content, expected)
 {
     testContainer.innerHTML = content;
-    selector(testContainer);
+    var selected = selector(testContainer);
     var actual = document.queryCommandValue('formatBlock');
     var actual = document.queryCommandValue('formatBlock');
-    var action = "queryCommand('format') returned \"" + actual + '"';
+    var action = "queryCommand('formatBlock') returned \"" + actual + '" selecting ' + selected + ' of "' + content + '"';
     if (actual == expected)
         testPassed(action);
     else
     if (actual == expected)
         testPassed(action);
     else
@@ -20,6 +20,7 @@ function selectFirstPosition(container) {
     while (container.firstChild)
         container = container.firstChild;
     window.getSelection().setPosition(container, 0);
     while (container.firstChild)
         container = container.firstChild;
     window.getSelection().setPosition(container, 0);
+    return 'first position'
 }
 
 function selectMiddleOfHelloWorld(container) {
 }
 
 function selectMiddleOfHelloWorld(container) {
@@ -30,20 +31,76 @@ function selectMiddleOfHelloWorld(container) {
     window.getSelection().modify('extend', 'forward', 'character');
     window.getSelection().modify('extend', 'forward', 'character');
     window.getSelection().modify('extend', 'forward', 'character');
     window.getSelection().modify('extend', 'forward', 'character');
     window.getSelection().modify('extend', 'forward', 'character');
     window.getSelection().modify('extend', 'forward', 'character');
+    return '"llo wo"'
 }
 
 debug('Basic cases');
 }
 
 debug('Basic cases');
-queryFormatBlock(function () {}, 'hello', '');
+queryFormatBlock(function () {return 'none' }, 'hello', '');
 queryFormatBlock(selectFirstPosition, 'hello', '');
 queryFormatBlock(selectFirstPosition, 'hello', '');
+queryFormatBlock(selectFirstPosition, '<a>hello</a>', '');
+queryFormatBlock(selectFirstPosition, '<abbr>hello</abbr>', '');
+queryFormatBlock(selectFirstPosition, '<acronym>hello</acronym>', '');
+queryFormatBlock(selectFirstPosition, '<b>hello</b>', '');
+queryFormatBlock(selectFirstPosition, '<bdo>hello</bdo>', '');
+queryFormatBlock(selectFirstPosition, '<big>hello</big>', '');
+queryFormatBlock(selectFirstPosition, '<button>hello</button>', '');
+queryFormatBlock(selectFirstPosition, '<caption>hello</caption>', '');
+queryFormatBlock(selectFirstPosition, '<center>hello</center>', '');
+queryFormatBlock(selectFirstPosition, '<cite>hello</cite>', '');
+queryFormatBlock(selectFirstPosition, '<code>hello</code>', '');
+queryFormatBlock(selectFirstPosition, '<del>hello</del>', '');
+queryFormatBlock(selectFirstPosition, '<dfn>hello</dfn>', '');
+queryFormatBlock(selectFirstPosition, '<dir>hello</dir>', '');
+queryFormatBlock(selectFirstPosition, '<em>hello</em>', '');
+queryFormatBlock(selectFirstPosition, '<form><fieldset>hello</fieldset></form>', '');
+queryFormatBlock(selectFirstPosition, '<font>hello</font>', '');
+queryFormatBlock(selectFirstPosition, '<form>hello</form>', '');
+queryFormatBlock(selectFirstPosition, '<i>hello</i>', '');
+queryFormatBlock(selectFirstPosition, '<kbd>hello</kbd>', '');
+queryFormatBlock(selectFirstPosition, '<label>hello</label>', '');
+queryFormatBlock(selectFirstPosition, '<legend>hello</legend>', '');
+queryFormatBlock(selectFirstPosition, '<ul><li>hello<li></ul>', '');
+queryFormatBlock(selectFirstPosition, '<menu>hello</menu>', '');
+queryFormatBlock(selectFirstPosition, '<ol>hello</ol>', '');
+queryFormatBlock(selectFirstPosition, '<q>hello</q>', '');
+queryFormatBlock(selectFirstPosition, '<s>hello</s>', '');
+queryFormatBlock(selectFirstPosition, '<samp>hello</samp>', '');
+queryFormatBlock(selectFirstPosition, '<small>hello</small>', '');
+queryFormatBlock(selectFirstPosition, '<span>hello</span>', '');
+queryFormatBlock(selectFirstPosition, '<strike>hello</strike>', '');
+queryFormatBlock(selectFirstPosition, '<strong>hello</strong>', '');
+queryFormatBlock(selectFirstPosition, '<sub>hello</sub>', '');
+queryFormatBlock(selectFirstPosition, '<sup>hello</sup>', '');
+queryFormatBlock(selectFirstPosition, '<table><td>hello</td></table>', '');
+queryFormatBlock(selectFirstPosition, '<table><th>hello</th></table>', '');
+queryFormatBlock(selectFirstPosition, '<tt>hello</tt>', '');
+queryFormatBlock(selectFirstPosition, '<u>hello</u>', '');
+queryFormatBlock(selectFirstPosition, '<ul>hello</ul>', '');
+queryFormatBlock(selectFirstPosition, '<var>hello</var>', '');
+
 queryFormatBlock(selectFirstPosition, '<address>hello</address>', 'address');
 queryFormatBlock(selectFirstPosition, '<address>hello</address>', 'address');
+queryFormatBlock(selectFirstPosition, '<article>hello</article>', 'article');
+queryFormatBlock(selectFirstPosition, '<aside>hello</aside>', 'aside');
+queryFormatBlock(selectFirstPosition, '<blockquote>hello</blockquote>', 'blockquote');
+queryFormatBlock(selectFirstPosition, '<dd>hello</dd>', 'dd');
+queryFormatBlock(selectFirstPosition, '<dl><dd>hello</dd></dl>', 'dd');
+queryFormatBlock(selectFirstPosition, '<div>hello</div>', 'div');
+queryFormatBlock(selectFirstPosition, '<dl>hello</dl>', 'dl');
+queryFormatBlock(selectFirstPosition, '<dt>hello</dt>', 'dt');
+queryFormatBlock(selectFirstPosition, '<dl><dt>hello</dt></dl>', 'dt');
+queryFormatBlock(selectFirstPosition, '<footer>hello</footer>', 'footer');
 queryFormatBlock(selectFirstPosition, '<h1>hello</h1>', 'h1');
 queryFormatBlock(selectFirstPosition, '<h2>hello</h2>', 'h2');
 queryFormatBlock(selectFirstPosition, '<h3>hello</h3>', 'h3');
 queryFormatBlock(selectFirstPosition, '<h4>hello</h4>', 'h4');
 queryFormatBlock(selectFirstPosition, '<h5>hello</h5>', 'h5');
 queryFormatBlock(selectFirstPosition, '<h6>hello</h6>', 'h6');
 queryFormatBlock(selectFirstPosition, '<h1>hello</h1>', 'h1');
 queryFormatBlock(selectFirstPosition, '<h2>hello</h2>', 'h2');
 queryFormatBlock(selectFirstPosition, '<h3>hello</h3>', 'h3');
 queryFormatBlock(selectFirstPosition, '<h4>hello</h4>', 'h4');
 queryFormatBlock(selectFirstPosition, '<h5>hello</h5>', 'h5');
 queryFormatBlock(selectFirstPosition, '<h6>hello</h6>', 'h6');
+queryFormatBlock(selectFirstPosition, '<header>hello</header>', 'header');
+queryFormatBlock(selectFirstPosition, '<hgroup>hello</hgroup>', 'hgroup');
+queryFormatBlock(selectFirstPosition, '<nav>hello</nav>', 'nav');
 queryFormatBlock(selectFirstPosition, '<p>hello</p>', 'p');
 queryFormatBlock(selectFirstPosition, '<pre>hello</pre>', 'pre');
 queryFormatBlock(selectFirstPosition, '<p>hello</p>', 'p');
 queryFormatBlock(selectFirstPosition, '<pre>hello</pre>', 'pre');
+queryFormatBlock(selectFirstPosition, '<section>hello</section>', 'section');
 
 debug('');
 debug('Nested cases');
 
 debug('');
 debug('Nested cases');
index 14cefd8..c306598 100644 (file)
@@ -1,3 +1,33 @@
+2010-10-15  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Reviewed by Darin Adler.
+
+        Match the elements supported by execCommand('formatBlock') and queryCommandValue('formatBlock')
+        https://bugs.webkit.org/show_bug.cgi?id=47712
+
+        Extended queryCommandValue('formatBlock', false, null) to support article, aside, blockquote, dd, dl,
+        div, dl, dt, dl, footer, header, hgroup, nav, and section. Because this makes isElementForFormatBlockCommand
+        in Editor.cpp and FormatBlockCommand::isElementToApplyInFormatBlockCommand identical, they are merged and moved
+        to FormatBlockCommand.cpp
+
+        Tests are added to editing/execCommand/query-format-block.html
+
+        * editing/Editor.cpp: Removed isElementForFormatBlockCommand and Editor::elementForFormatBlockCommand.
+        * editing/Editor.h:
+        * editing/EditorCommand.cpp:
+        (WebCore::executeFormatBlock): Removed the check of tag name; the check is moved into FormatBlockCommand.
+        (WebCore::valueFormatBlock): Calls FormatBlockCommand::elementForFormatBlockCommand.
+        * editing/FormatBlockCommand.cpp:
+        (WebCore::isElementForFormatBlock):
+        (WebCore::FormatBlockCommand::FormatBlockCommand):
+        (WebCore::FormatBlockCommand::formatSelection): Added to check the tag name. Exit early if the specified tag name
+        is not what FormatBlock should apply. Set m_didApply true if m_didApply did apply the element.
+        (WebCore::FormatBlockCommand::formatRange): Moved from Editor.cpp.  Takes Range* instead of accessing selection directly.
+        (WebCore::FormatBlockCommand::elementForFormatBlockCommand): Moved from Editor.cpp
+        (WebCore::enclosingBlockToSplitTreeTo): Calls isElementForFormatBlock.
+        * editing/FormatBlockCommand.h:
+        (WebCore::FormatBlockCommand::didApply): Added.
+
 2010-10-15  Dirk Schulze  <krit@webkit.org>
 
         Reviewed by Nikolas Zimmermann.
 2010-10-15  Dirk Schulze  <krit@webkit.org>
 
         Reviewed by Nikolas Zimmermann.
index 0b9b9ea..9980d67 100644 (file)
@@ -970,37 +970,6 @@ String Editor::selectionStartCSSPropertyValue(int propertyID)
     return value;
 }
 
     return value;
 }
 
-static bool isElementForFormatBlockCommand(const Node* node)
-{
-    return node->hasTagName(addressTag)
-        || node->hasTagName(h1Tag)
-        || node->hasTagName(h2Tag)
-        || node->hasTagName(h3Tag)
-        || node->hasTagName(h4Tag)
-        || node->hasTagName(h5Tag)
-        || node->hasTagName(h6Tag)
-        || node->hasTagName(pTag)
-        || node->hasTagName(preTag);
-}
-
-Element* Editor::elementForFormatBlockCommand() const
-{
-    const VisibleSelection& selection = m_frame->selection()->selection();
-    if (!selection.isNonOrphanedCaretOrRange() || !selection.isContentEditable())
-        return 0;
-
-    ExceptionCode ec;
-    Node* commonAncestor = selection.firstRange()->commonAncestorContainer(ec);
-    while (commonAncestor && !isElementForFormatBlockCommand(commonAncestor))
-        commonAncestor = commonAncestor->parentNode();
-
-    if (!commonAncestor)
-        return 0;
-
-    ASSERT(commonAncestor->isElementNode());
-    return static_cast<Element*>(commonAncestor);
-}
-
 void Editor::indent()
 {
     applyCommand(IndentOutdentCommand::create(m_frame->document(), IndentOutdentCommand::Indent));
 void Editor::indent()
 {
     applyCommand(IndentOutdentCommand::create(m_frame->document(), IndentOutdentCommand::Indent));
index 928662c..df2e947 100644 (file)
@@ -125,7 +125,6 @@ public:
 
     TriState selectionHasStyle(CSSStyleDeclaration*) const;
     String selectionStartCSSPropertyValue(int propertyID);
 
     TriState selectionHasStyle(CSSStyleDeclaration*) const;
     String selectionStartCSSPropertyValue(int propertyID);
-    Element* elementForFormatBlockCommand() const;
     const SimpleFontData* fontForSelection(bool&) const;
     WritingDirection textDirectionForSelection(bool&) const;
     
     const SimpleFontData* fontForSelection(bool&) const;
     WritingDirection textDirectionForSelection(bool&) const;
     
index a8a23fb..23fba39 100644 (file)
@@ -439,11 +439,9 @@ static bool executeFormatBlock(Frame* frame, Event*, EditorCommandSource, const
         return false;
     QualifiedName qualifiedTagName(prefix, localName, xhtmlNamespaceURI);
 
         return false;
     QualifiedName qualifiedTagName(prefix, localName, xhtmlNamespaceURI);
 
-    if (!FormatBlockCommand::isElementToApplyInFormatBlockCommand(qualifiedTagName))
-        return false;
-
-    applyCommand(FormatBlockCommand::create(frame->document(), qualifiedTagName));
-    return true;
+    RefPtr<FormatBlockCommand> command = FormatBlockCommand::create(frame->document(), qualifiedTagName);
+    applyCommand(command);
+    return command->didApply();
 }
 
 static bool executeForwardDelete(Frame* frame, Event*, EditorCommandSource source, const String&)
 }
 
 static bool executeForwardDelete(Frame* frame, Event*, EditorCommandSource source, const String&)
@@ -1361,7 +1359,10 @@ static String valueForeColor(Frame* frame, Event*)
 
 static String valueFormatBlock(Frame* frame, Event*)
 {
 
 static String valueFormatBlock(Frame* frame, Event*)
 {
-    Element* formatBlockElement = frame->editor()->elementForFormatBlockCommand();
+    const VisibleSelection& selection = frame->selection()->selection();
+    if (!selection.isNonOrphanedCaretOrRange() || !selection.isContentEditable())
+        return "";
+    Element* formatBlockElement = FormatBlockCommand::elementForFormatBlockCommand(selection.firstRange().get());
     if (!formatBlockElement)
         return "";
     return formatBlockElement->localName();
     if (!formatBlockElement)
         return "";
     return formatBlockElement->localName();
index 1673235..2e42fb3 100644 (file)
@@ -30,6 +30,7 @@
 #include "htmlediting.h"
 #include "HTMLElement.h"
 #include "HTMLNames.h"
 #include "htmlediting.h"
 #include "HTMLElement.h"
 #include "HTMLNames.h"
+#include "Range.h"
 #include "visible_units.h"
 
 namespace WebCore {
 #include "visible_units.h"
 
 namespace WebCore {
@@ -37,10 +38,24 @@ namespace WebCore {
 using namespace HTMLNames;
 
 static Node* enclosingBlockToSplitTreeTo(Node* startNode);
 using namespace HTMLNames;
 
 static Node* enclosingBlockToSplitTreeTo(Node* startNode);
+static bool isElementForFormatBlock(const QualifiedName& tagName);
+static inline bool isElementForFormatBlock(Node* node)
+{
+    return node->isElementNode() && isElementForFormatBlock(static_cast<Element*>(node)->tagQName());
+}
 
 FormatBlockCommand::FormatBlockCommand(Document* document, const QualifiedName& tagName) 
     : ApplyBlockElementCommand(document, tagName)
 
 FormatBlockCommand::FormatBlockCommand(Document* document, const QualifiedName& tagName) 
     : ApplyBlockElementCommand(document, tagName)
+    , m_didApply(false)
+{
+}
+
+void FormatBlockCommand::formatSelection(const VisiblePosition& startOfSelection, const VisiblePosition& endOfSelection)
 {
 {
+    if (!isElementForFormatBlock(tagName()))
+        return;
+    ApplyBlockElementCommand::formatSelection(startOfSelection, endOfSelection);
+    m_didApply = true;
 }
 
 void FormatBlockCommand::formatRange(const Position& start, const Position& end, RefPtr<Element>& blockNode)
 }
 
 void FormatBlockCommand::formatRange(const Position& start, const Position& end, RefPtr<Element>& blockNode)
@@ -51,7 +66,7 @@ void FormatBlockCommand::formatRange(const Position& start, const Position& end,
 
     Element* refNode = enclosingBlockFlowElement(end);
     Element* root = editableRootForPosition(start);
 
     Element* refNode = enclosingBlockFlowElement(end);
     Element* root = editableRootForPosition(start);
-    if (isElementToApplyInFormatBlockCommand(refNode->tagQName()) && start == startOfBlock(start) && end == endOfBlock(end)
+    if (isElementForFormatBlock(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()))
         && refNode != root && !root->isDescendantOf(refNode)) {
         // Already in a block element that only contains the current paragraph
         if (refNode->hasTagName(tagName()))
@@ -74,10 +89,25 @@ void FormatBlockCommand::formatRange(const Position& start, const Position& end,
     if (wasEndOfParagraph && !isEndOfParagraph(lastParagraphInBlockNode) && !isStartOfParagraph(lastParagraphInBlockNode))
         insertBlockPlaceholder(lastParagraphInBlockNode);
 }
     if (wasEndOfParagraph && !isEndOfParagraph(lastParagraphInBlockNode) && !isStartOfParagraph(lastParagraphInBlockNode))
         insertBlockPlaceholder(lastParagraphInBlockNode);
 }
+    
+Element* FormatBlockCommand::elementForFormatBlockCommand(Range* range)
+{
+    if (!range)
+        return 0;
+
+    ExceptionCode ec;
+    Node* commonAncestor = range->commonAncestorContainer(ec);
+    while (commonAncestor && !isElementForFormatBlock(commonAncestor))
+        commonAncestor = commonAncestor->parentNode();
+
+    if (!commonAncestor)
+        return 0;
+
+    ASSERT(commonAncestor->isElementNode());
+    return static_cast<Element*>(commonAncestor);
+}
 
 
-// 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)
+bool isElementForFormatBlock(const QualifiedName& tagName)
 {
     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, blockTags, ());
     if (blockTags.isEmpty()) {
 {
     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, blockTags, ());
     if (blockTags.isEmpty()) {
@@ -112,8 +142,7 @@ Node* enclosingBlockToSplitTreeTo(Node* startNode)
     for (Node* n = startNode; n; n = n->parentNode()) {
         if (!n->isContentEditable())
             return lastBlock;
     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())))
+        if (isTableCell(n) || n->hasTagName(bodyTag) || !n->parentNode() || !n->parentNode()->isContentEditable() || isElementForFormatBlock(n))
             return n;
         if (isBlock(n))
             lastBlock = n;
             return n;
         if (isBlock(n))
             lastBlock = n;
index 68a1f47..134a422 100644 (file)
@@ -38,13 +38,17 @@ public:
         return adoptRef(new FormatBlockCommand(document, tagName));
     }
 
         return adoptRef(new FormatBlockCommand(document, tagName));
     }
 
-    static bool isElementToApplyInFormatBlockCommand(const QualifiedName& tagName);
+    static Element* elementForFormatBlockCommand(Range*);
+    bool didApply() const { return m_didApply; }
 
 private:
     FormatBlockCommand(Document*, const QualifiedName& tagName);
 
 
 private:
     FormatBlockCommand(Document*, const QualifiedName& tagName);
 
+    void formatSelection(const VisiblePosition& startOfSelection, const VisiblePosition& endOfSelection);
     void formatRange(const Position&, const Position&, RefPtr<Element>&);
     EditAction editingAction() const { return EditActionFormatBlock; }
     void formatRange(const Position&, const Position&, RefPtr<Element>&);
     EditAction editingAction() const { return EditActionFormatBlock; }
+
+    bool m_didApply;
 };
 
 } // namespace WebCore
 };
 
 } // namespace WebCore