--- a/autoimplementation.html	Wed Jul 13 13:55:04 2011 -0600
+++ b/autoimplementation.html	Thu Jul 14 12:24:49 2011 -0600
@@ -156,11 +156,6 @@
 		test = test[1];
 	}
 
-	if (command == "hilitecolor" && navigator.userAgent.indexOf("MSIE") != -1) {
-		// IE behaves differently, and I want to see how it works.
-		command = "backcolor";
-	}
-
 	if (command == "hilitecolor") {
 		// Firefox refuses to do anything unless styleWithCSS is true.
 		styleWithCss = true;
@@ -187,8 +182,23 @@
 		try {
 			document.execCommand("styleWithCSS", false, styleWithCss);
 		} catch (e) {}
+
+		try { var beforeIndeterm = document.queryCommandIndeterm(command) }
+		catch(e) { beforeIndeterm = "Exception" }
+		try { var beforeState = document.queryCommandState(command) }
+		catch(e) { beforeState = "Exception" }
+		try { var beforeValue = document.queryCommandValue(command) }
+		catch(e) { beforeValue = "Exception" }
+
 		document.execCommand(command, false, value);
 
+		try { var afterIndeterm = document.queryCommandIndeterm(command) }
+		catch(e) { afterIndeterm = "Exception" }
+		try { var afterState = document.queryCommandState(command) }
+		catch(e) { afterState = "Exception" }
+		try { var afterValue = document.queryCommandValue(command) }
+		catch(e) { afterValue = "Exception" }
+
 		testDiv.contentEditable = "inherit";
 		testDiv.removeAttribute("spellcheck");
 		var compareDiv1 = testDiv.cloneNode(true);
@@ -230,7 +240,17 @@
 				browserCell.innerHTML.replace(/<div><\/div>$/, "");
 		}
 
+		if (document.body.hasAttribute("bgcolor")) {
+			var bgColor = document.body.getAttribute("bgcolor");
+			document.body.removeAttribute("bgcolor");
+			throw 'bgcolor="' + bgColor +'" added to body!';
+		}
+
 		browserCell.lastChild.textContent = browserCell.firstChild.innerHTML;
+		browserCell.lastChild.appendChild(queryOutputHelper(
+			beforeIndeterm, beforeState, beforeValue,
+			afterIndeterm, afterState, afterValue,
+			command, value));
 	} catch (e) {
 		browserCellException(e, testDiv, browserCell);
 	}
--- a/editcommands.html	Wed Jul 13 13:55:04 2011 -0600
+++ b/editcommands.html	Thu Jul 14 12:24:49 2011 -0600
@@ -60,7 +60,7 @@
 <body class=draft>
 <div class=head id=head>
 <h1>HTML Editing Commands</h1>
-<h2 class="no-num no-toc" id=work-in-progress-—-last-update-13-july-2011>Work in Progress — Last Update 13 July 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-—-last-update-14-july-2011>Work in Progress — Last Update 14 July 2011</h2>
 <dl>
  <dt>Editor
  <dd>Aryeh Gregor <<a href=mailto:ayg@aryeh.name>ayg@aryeh.name</a>>
@@ -658,6 +658,9 @@
 
   <li>If <var title="">command</var> is not <a href=#enabled>enabled</a>, return false.
 
+  <li>If the <a href=#state-override>state override</a> for <var title="">command</var> is set, return
+  it.
+
   <li>Return true if <var title="">command</var>'s <a href=#state>state</a> is true, otherwise
   false.
 </ol>
@@ -694,12 +697,36 @@
   seems to return the string "false", and IE9 seems to return boolean false.
   -->
 
+  <li>If the <a href=#value-override>value override</a> for <var title="">command</var> is set, return
+  it.
+
   <li>Return <var title="">command</var>'s <a href=#value>value</a>.
 </ol>
 
 <p>All of these methods must treat their <var title="">command</var> argument <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#ascii-case-insensitive title="ASCII case-insensitive">ASCII
 case-insensitively</a>.
 
+<p>The methods in this section have been designed so that the following
+invariants hold after <code><a href=#execcommand()>execCommand()</a></code> is called, assuming it didn't
+throw an exception:
+
+<ul>
+  <li><code><a href=#querycommandindeterm()>queryCommandIndeterm()</a></code> will return false (or throw an
+  exception).
+
+  <li><code><a href=#querycommandstate()>queryCommandState()</a></code> will return the opposite of what it did
+  before <code><a href=#execcommand()>execCommand()</a></code> was called (or throw an exception).
+
+  <li><code><a href=#querycommandvalue()>queryCommandValue()</a></code> will return something equivalent to the
+  value passed to <code><a href=#execcommand()>execCommand()</a></code> (or throw an exception).
+  "Equivalent" here needs to be construed broadly in some cases, such as
+  <a href=#the-fontsize-command>the <code title="">fontSize</code> command</a>.
+</ul>
+
+<p>The first two points do not always hold for <a href=#the-strikethrough-command>the <code title="">strikethrough</code> command</a> or <a href=#the-underline-command>the <code title="">underline</code> command</a>, because it can be impossible to unset
+text-decoration in CSS, but all three points otherwise hold in all cases
+barring bugs.
+
 
 <h2 id=common-definitions><span class=secno>5 </span>Common definitions</h2>
 
@@ -824,6 +851,17 @@
 means of the <code><a href=#execcommand()>execCommand()</a></code> and <code><a href=#querycommandstate()>queryCommandState()</a></code>
 methods.)
 
+<p>For some <a href=#command title=command>commands</a>, each <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/html/#htmldocument>HTMLDocument</a></code> must
+have a boolean <dfn id=state-override>state override</dfn> and/or a string <dfn id=value-override>value
+override</dfn>.  These do not change the <a href=#command>command</a>'s
+<a href=#state>state</a> or <a href=#value>value</a>, but change the way some algorithms
+behave, as specified in those algorithms' definitions.  Initially, both must be
+unset for every <a href=#command>command</a>.  Whenever the number of <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>ranges</a> in the
+<code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code> changes to something different, and whenever a <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point title=concept-boundary-point>boundary point</a>
+of the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> at a given index in the <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code> changes to something
+different, the <a href=#state-override>state override</a> and <a href=#value-override>value override</a> must
+be unset for every <a href=#command>command</a>.
+
 <p>When the user agent is instructed to run a particular method, it must follow
 the steps defined for that method in the appropriate specification, not act as
 though the method had actually been called from JavaScript.  In particular,
@@ -1961,14 +1999,18 @@
 
     <li>If <var title="">command</var> is "foreColor", and <var title="">new value</var> is fully
     opaque with red, green, and blue components in the range 0 to 255:
+    <!-- See comment for foreColor for discussion. -->
+
+    <p class=XXX>Check this more carefully for what happens if the components
+    are not integers or are out-of-range.
 
     <ol>
       <li>Let <var title="">new parent</var> be the result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement("font")</a></code> on the
       <code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">node</var>.
 
-      <li>If <var title="">new value</var> is one of the colors listed in the SVG color
-      keywords section of CSS3 Color, set the <code class=external data-anolis-spec=html title=dom-font-color><a href=http://www.whatwg.org/html/#dom-font-color>color</a></code> attribute of
-      <var title="">new parent</var> to <var title="">new value</var>.
+      <li>If <var title="">new value</var> is an <a href=http://www.w3.org/TR/css3-color/#svg-color>extended color
+      keyword</a>, set the <code class=external data-anolis-spec=html title=dom-font-color><a href=http://www.whatwg.org/html/#dom-font-color>color</a></code> attribute of <var title="">new parent</var> to
+      <var title="">new value</var>.
 
       <li>Otherwise, set the <code class=external data-anolis-spec=html title=dom-font-color><a href=http://www.whatwg.org/html/#dom-font-color>color</a></code> attribute of <var title="">new parent</var>
       to the result of applying the <a class=external data-anolis-spec=html href=http://www.whatwg.org/html/#rules-for-serializing-simple-color-values>rules for
@@ -2197,6 +2239,39 @@
 <ol>
   <li>Let <var title="">command</var> be the current <a href=#command>command</a>.
 
+  <li>If there is no <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node <a href=#effectively-contained>effectively
+  contained</a> in the <a href=#active-range>active range</a>:
+
+  <ol>
+    <li>If <var title="">command</var> is in the following list, set the <a href=#state-override>state
+    override</a> appropriately:
+
+    <dl class=compact>
+      <dt>bold<dd>True if <var title="">new value</var> is not null and is greater than or equal
+      to 600, false otherwise.
+
+      <dt>italic<dd>True if <var title="">new value</var> is "italic" or "oblique", false
+      otherwise.
+
+      <dt>strikethrough<dd>True if <var title="">new value</var> is "line-through", false otherwise.
+
+      <dt>subscript<dd>True if <var title="">new value</var> is "sub", false otherwise.
+
+      <dt>superscript<dd>True if <var title="">new value</var> is "super", false otherwise.
+
+      <dt>underline<dd>True if <var title="">new value</var> is "underline", false otherwise.
+    </dl>
+
+    <li>If <var title="">command</var> has a <a href=#value>value</a> specified, unset the
+    <a href=#value-override>value override</a> if <var title="">new value</var> is null, and set the
+    <a href=#value-override>value override</a> to <var title="">new value</var> if it is not null.
+
+    <p class=XXX>This doesn't work as-is for fontSize, because that uses a
+    different format for the value.
+
+    <li>Abort these steps.
+  </ol>
+
   <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is an
   <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node, and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is neither zero
   nor its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>, call <code class=external data-anolis-spec=domcore title=dom-Text-splitText><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-text-splittext>splitText()</a></code> on the <a href=#active-range>active
@@ -2324,11 +2399,15 @@
 range</a>, there are two that have distinct <a href=#effective-command-value title="effective command
 value">effective command values</a>.  Otherwise false.
 
-<p><a href=#value>Value</a>: The <a href=#effective-command-value>effective command value</a> of the
-<a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>.
-
-<p class=note>This cannot be null, since the boundary point node of a selection
-must always be either an element or a text node that's the child of an element.
+<p><a href=#value>Value</a>: The <a href=#effective-command-value>effective command value</a> of the first
+<a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node that is <a href=#effectively-contained>effectively contained</a>
+in the <a href=#active-range>active range</a>, or if there is no such node, the
+<a href=#effective-command-value>effective command value</a> of the <a href=#active-range>active range</a>'s
+<a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>.
+
+<p class=note>The effective command value of the active range's start node
+cannot be null, since the boundary point node of a selection must always be
+either an element or a text node that's the child of an element.
 
 <p><a href=#relevant-css-property>Relevant CSS property</a>: "background-color"
 
@@ -2341,9 +2420,9 @@
 (fontName, italic, etc.).  Except not for strikethrough, where it just does
 nothing if the selection is empty.  Why strikethrough?  I don't know. -->
 
-<p><a href=#action>Action</a>: If the <a href=#state>state</a> is false, <a href="#set-the-selection's-value">set the
-selection's value</a> to "bold", otherwise <a href="#set-the-selection's-value">set the selection's
-value</a> to "normal".
+<p><a href=#action>Action</a>: If <code title=queryCommandState()><a href=#querycommandstate()>queryCommandState("bold")</a></code> returns true,
+<a href="#set-the-selection's-value">set the selection's value</a> to "normal".  Otherwise <a href="#set-the-selection's-value">set the
+selection's value</a> to "bold".
 
 <p><a href=#indeterminate>Indeterminate</a>: True if among <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code>
 nodes that are <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
@@ -2440,15 +2519,7 @@
   <li><a href="#set-the-selection's-value">Set the selection's value</a> to <var title="">value</var>.
 </ol>
 
-<!--
-The state is always false in Chrome 14 dev and Opera 11.11.  Firefox 6.0a2
-throws an exception, and IE9 seems to always either return false or throw an
-exception.  Therefore we make the state always false, although this doesn't
-seem very useful.
--->
-
-<!-- I'd have expected the value to be the URL, but guess not: it's always
-false. -->
+<p class=XXX>Define state and value, although browsers don't.
 
 
 <h3 id=the-fontname-command><span class=secno>7.10 </span><dfn>The <code title="">fontName</code> command</dfn></h3>
@@ -2482,12 +2553,17 @@
 value">effective command values</a>.  Otherwise false.
 <!-- This follows Firefox 6.0a2.  Chrome 14 dev always returns false. -->
 
-<p><a href=#value>Value</a>: The <a href=#effective-command-value>effective command value</a> of the
-<a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>.
-
-<p class=note>This cannot be null, since the boundary point node of a selection
-must always be either an element or a text node that's the child of an element.
-<!-- Complicated.
+<p><a href=#value>Value</a>: The <a href=#effective-command-value>effective command value</a> of the first
+<a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node that is <a href=#effectively-contained>effectively contained</a>
+in the <a href=#active-range>active range</a>, or if there is no such node, the
+<a href=#effective-command-value>effective command value</a> of the <a href=#active-range>active range</a>'s
+<a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>.
+
+<p class=note>The effective command value of the active range's start node
+cannot be null, since the boundary point node of a selection must always be
+either an element or a text node that's the child of an element.
+<!--
+Complicated.
 
 IE 9 RC: Always the empty string.  Not very useful.
 Firefox 4b11: Confusing.  Sometimes it returns generic family names, like
@@ -2502,7 +2578,10 @@
 
 I'm just going to punt on this and say it should be the resolved value of
 font-family.  I'll leave CSSOM to decide what that means if there are no
-applicable style rules. -->
+applicable style rules.
+
+For deciding which node should be checked, see comment for hiliteColor.
+-->
 
 <p><a href=#relevant-css-property>Relevant CSS property</a>: "font-family"
 
@@ -2644,11 +2723,16 @@
 -->
 <ol>
   <li>Let <var title="">pixel size</var> be the <a href=#effective-command-value>effective command value</a> of
-  the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, as a number of pixels.
-
-  <p class=note>The active range's start node cannot be null, since the
-  boundary point node of a selection must always be either an element or a text
-  node that's the child of an element.
+  the first <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node that is <a href=#effectively-contained>effectively
+  contained</a> in the <a href=#active-range>active range</a>, or if there is no such
+  node, the <a href=#effective-command-value>effective command value</a> of the <a href=#active-range>active
+  range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, in either case interpreted as a number of
+  pixels.
+  <!-- See comment for hiliteColor on how I decided on this choice of node. -->
+
+  <p class=note>The effective command value of the active range's start node
+  cannot be null, since the boundary point node of a selection must always be
+  either an element or a text node that's the child of an element.
 
   <li>Let <var title="">returned size</var> be 1.
 
@@ -2684,29 +2768,29 @@
 
 <!-- Color interpretations (wide screen recommended):
 
-                        IE9           Firefox 4.0              Chrome 12 dev            Opera 11.00
-red                     red           red                      #ff0000                  #ff0000
+                        IE10PP2       Firefox 7.0a2            Chrome 14 dev            Opera 11.50
+blue                    blue          blue                     #0000ff                  #0000ff
 f                       #f            -                        -                        #f00000
 #f                      #f            -                        -                        #f00000
-f00                     #f00          -                        #ff0000                  #0f0000
-#f00                    #f00          rgb(255, 0, 0)           #ff0000                  #0f0000
-ff0000                  #ff0000       -                        #ff0000                  #ff0000
-#ff0000                 #ff0000       rgb(255, 0, 0)           #ff0000                  #ff0000
-fff000000               #ff0000       -                        -                        #fff000
-#fff000000              #ff0000       -                        -                        #fff000
-rgb(255, 0, 0)          rgb(255,0,0)  rgb(255, 0, 0)           #ff0000                  #00b025
-rgb(100%, 0, 0)         rgb(255,0,0)  -                        -                        #00b010
-rgb( 255 ,0 ,0)         rgb(255,0,0)  rgb(255, 0, 0)           #ff0000                  #00b025
-rgba(255, 0, 0, 0.0)    #005000       rgba(255, 0, 0, 0)       rgba(255, 0, 0, 0.0)     #00ba02
-rgb(375, -10, 15)       rgb(255,0,15) rgb(255, 0, 15)          #ff000f                  #00b037
+00f                     #00f          -                        #0000ff                  #00000f
+#00f                    #00f          rgb(0, 0, 255)           #0000ff                  #00000f
+0000ff                  #0000ff       -                        #0000ff                  #0000ff
+#0000ff                 #0000ff       rgb(0, 0, 255)           #0000ff                  #0000ff
+000000fff               #0000ff       -                        -                        -
+#000000fff              #0000ff       -                        -                        -
+rgb(0, 0, 255)          rgb(0,0,255)  rgb(0, 0, 255)           #0000ff                  #00b000
+rgb(0%, 0%, 100%)       rgb(0,0,255)  rgb(0, 0, 255)           #0000ff                  #00b000
+rgb( 0 ,0 ,255)         rgb(0,0,255)  rgb(0, 0, 255)           #0000ff                  #00b000
+rgba(0, 0, 255, 0.0)    #ba0000       rgba(0, 0, 255, 0)       rgba(0, 0, 255, 0)       #00ba00
+rgb(15, -10, 375)       rgb(15,0,255) rgb(15, 0, 255)          #0f00ff                  #00b015
 rgba(0, 0, 0, 1)        #ba0010       rgb(0, 0, 0)             -                        #00ba00
 rgba(255, 255, 255, 1)  #000055       rgb(255, 255, 255)       #ffffff                  #00ba02
-rgba(255, 0, 0, 0.5)    #005000       rgba(255, 255, 255, 0.5) rgba(255, 0, 0, 0.49804) #00ba02
-hsl(0%, 100%, 50%)      #001050       -                        -                        -
+rgba(0, 0, 255, 0.5)    #ba0000       rgba(0, 0, 255, 0.5)     rgba(0, 0, 255, 0.5)     #00ba00
+hsl(240, 100%, 50%)     #000150       rgb(0, 0, 255)           #0000ff                  #000024
 cornsilk                cornsilk      cornsilk                 #fff8dc                  #fff8dc
 potato quiche           #0000c0       -                        -                        #000a00
-transparent             transparent   -                        rgba(0, 0, 0.0)          #00a000
-currentColor            #c0e000       currentcolor             rgba(0, 0, 0.0)          #c000e0
+transparent             transparent   -                        rgba(0, 0, 0, 0)         #00a000
+currentColor            #c0e000       currentcolor             rgba(0, 0, 0, 0)         #c000e0
 
 The interpretations given for Firefox are only in styleWithCSS mode.  In
 non-styleWithCSS mode, it just outputs the string literally as the <font color>
@@ -2721,8 +2805,8 @@
 * Opera mangles #xxx, but everyone else handles it fine.
 * The leading # is optional in all browsers but Gecko.
 * rgb() is accepted by everyone but Opera.
-* rgba() is accepted by Gecko and WebKit, but rejected by IE and Opera.
-* hsl() isn't accepted by anyone.
+* rgba() and hsl() are accepted by Gecko and WebKit, but rejected by IE and
+  Opera.
 * IE and Opera mangle unrecognized stuff, Gecko and WebKit ignore.
 * Browsers will happily output stuff like "transparent" and "rgba()" into <font
   color> even though it won't be uniformly accepted there.
@@ -2759,18 +2843,25 @@
 value">effective command values</a>.  Otherwise false.
 <!-- This follows Firefox 6.0a2.  Chrome 14 dev always returns false. -->
 
-<p><a href=#value>Value</a>: The <a href=#effective-command-value>effective command value</a> of the
-<a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>.
-
-<p class=note>This cannot be null, since the boundary point node of a selection
-must always be either an element or a text node that's the child of an element.
+<p><a href=#value>Value</a>: The <a href=#effective-command-value>effective command value</a> of the first
+<a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node that is <a href=#effectively-contained>effectively contained</a>
+in the <a href=#active-range>active range</a>, or if there is no such node, the
+<a href=#effective-command-value>effective command value</a> of the <a href=#active-range>active range</a>'s
+<a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>.
+
+<p class=note>The effective command value of the active range's start node
+cannot be null, since the boundary point node of a selection must always be
+either an element or a text node that's the child of an element.
 <!--
-The spec essentially matches Firefox 6.0a2 and Chrome 14 dev.  IE9 seems to
-always return the number 0 for some bizarre reason.  There are some cases where
-Firefox returns the empty string for some reason, and it seems to select the
-active node a little differently.  Opera uses #xxxxxx format for
-getComputedStyle() but rgb() here, and also drops the transparent part of the
-color if there is any.
+The spec essentially matches Firefox 6.0a2 and Chrome 14 dev, as far as how to
+decide what color the node has.  IE9 seems to always return the number 0 for
+some bizarre reason.  There are some cases where Firefox returns the empty
+string for some reason, and it seems to select the active node a little
+differently.  Opera uses #xxxxxx format for getComputedStyle() but rgb() here,
+and also drops the transparent part of the color if there is any.
+
+For why I chose this node to key the color off of, see the comment for
+hiliteColor.
 -->
 
 <p><a href=#relevant-css-property>Relevant CSS property</a>: "color"
@@ -2817,19 +2908,28 @@
 <!-- This follows no one.  Firefox 6.0a2 and Chrome 14 dev both always return
 false.  However, it makes sense. -->
 
-<p><a href=#value>Value</a>: The <a href=#effective-command-value>effective command value</a> of the
-<a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>.
-
-<p class=note>This cannot be null, since the boundary point node of a selection
-must always be either an element or a text node that's the child of an element.
+<p><a href=#value>Value</a>: The <a href=#effective-command-value>effective command value</a> of the first
+<a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node that is <a href=#effectively-contained>effectively contained</a>
+in the <a href=#active-range>active range</a>, or if there is no such node, the
+<a href=#effective-command-value>effective command value</a> of the <a href=#active-range>active range</a>'s
+<a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>.
+
+<p class=note>The effective command value of the active range's start node
+cannot be null, since the boundary point node of a selection must always be
+either an element or a text node that's the child of an element.
 <!--
-This seems to match Opera 11.11 exactly.  Chrome 14 dev returns boolean false
-consistently, bizarrely enough.  Firefox 6.0a2 seems to follow the same idea as
-the spec, but it likes to return "transparent", including sometimes when the
-answer really clearly should not be "transparent".  IE9 throws exceptions most
-of the time for backColor, so I can't say for sure, but in the few cases where
-it doesn't throw it returns a random-looking number, so I'll assume it's crazy
-like for foreColor.
+Opera 11.11 seems to always return the effective command value of the active
+range's start node.  Chrome 14 dev returns boolean false consistently,
+bizarrely enough.  Firefox 6.0a2 seems to follow the same idea as the spec, but
+it likes to return "transparent", including sometimes when the answer really
+clearly should not be "transparent".  IE9 throws exceptions most of the time
+for backColor, so I can't say for sure, but in the few cases where it doesn't
+throw it returns a random-looking number, so I'll assume it's crazy like for
+foreColor.
+
+I decided on something that would guarantee the following invariant: whenever
+you execute a command with a value provided (assuming value is relevant),
+queryCommandValue() will always return something equivalent to what you set.
 -->
 
 <p><a href=#relevant-css-property>Relevant CSS property</a>: "background-color"
@@ -2837,9 +2937,9 @@
 
 <h3 id=the-italic-command><span class=secno>7.14 </span><dfn>The <code title="">italic</code> command</dfn></h3>
 
-<p><a href=#action>Action</a>: If the <a href=#state>state</a> is false, <a href="#set-the-selection's-value">set the
-selection's value</a> to "italic", otherwise <a href="#set-the-selection's-value">set the selection's
-value</a> to "normal".
+<p><a href=#action>Action</a>: If <code title=queryCommandState()><a href=#querycommandstate()>queryCommandState("italic")</a></code> returns true,
+<a href="#set-the-selection's-value">set the selection's value</a> to "normal".  Otherwise <a href="#set-the-selection's-value">set the
+selection's value</a> to "italic".
 
 <p><a href=#indeterminate>Indeterminate</a>: True if among <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code>
 nodes that are <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
@@ -2983,9 +3083,9 @@
 
 <h3 id=the-strikethrough-command><span class=secno>7.16 </span><dfn>The <code title="">strikethrough</code> command</dfn></h3>
 
-<p><a href=#action>Action</a>: If the <a href=#state>state</a> is false, <a href="#set-the-selection's-value">set the
-selection's value</a> to "line-through", otherwise <a href="#set-the-selection's-value">set the selection's
-value</a> to null.
+<p><a href=#action>Action</a>: If <code title=queryCommandState()><a href=#querycommandstate()>queryCommandState("strikethrough")</a></code> returns
+true, <a href="#set-the-selection's-value">set the selection's value</a> to null.  Otherwise <a href="#set-the-selection's-value">set the
+selection's value</a> to "line-through".
 
 <!-- TODO: See underline TODO. -->
 
@@ -3006,7 +3106,8 @@
 <p><a href=#action>Action</a>:
 
 <ol>
-  <li>Let <var title="">state</var> be the <a href=#state>state</a>.
+  <li>Call <code title=queryCommandState()><a href=#querycommandstate()>queryCommandState("subscript")</a></code>, and let
+  <var title="">state</var> be the result.
 
   <li><a href="#set-the-selection's-value">Set the selection's value</a> to "baseline".
 
@@ -3046,7 +3147,8 @@
 <p><a href=#action>Action</a>:
 
 <ol>
-  <li>Let <var title="">state</var> be the <a href=#state>state</a>.
+  <li>Call <code title=queryCommandState()><a href=#querycommandstate()>queryCommandState("superscript")</a></code>, and let
+  <var title="">state</var> be the result.
 
   <li><a href="#set-the-selection's-value">Set the selection's value</a> to "baseline".
 
@@ -3072,9 +3174,9 @@
 
 <h3 id=the-underline-command><span class=secno>7.19 </span><dfn>The <code title="">underline</code> command</dfn></h3>
 
-<p><a href=#action>Action</a>: If the <a href=#state>state</a> is false, <a href="#set-the-selection's-value">set the
-selection's value</a> to "underline", otherwise <a href="#set-the-selection's-value">set the selection's
-value</a> to null.
+<p><a href=#action>Action</a>: If <code title=queryCommandState()><a href=#querycommandstate()>queryCommandState("underline")</a></code> returns true,
+<a href="#set-the-selection's-value">set the selection's value</a> to null.  Otherwise <a href="#set-the-selection's-value">set the
+selection's value</a> to "underline".
 
 <!--
 TODO: There are a lot of problems with underline color and thickness, because
@@ -6671,6 +6773,8 @@
 theory, but normalize the selection first, so they don't match it in practice.
 -->
 
+<p class=XXX>Needs to handle overridden state/value.
+
 <p><a href=#action>Action</a>:
 
 <!--
--- a/implementation.js	Wed Jul 13 13:55:04 2011 -0600
+++ b/implementation.js	Thu Jul 14 12:24:49 2011 -0600
@@ -149,6 +149,16 @@
 			|| (val1.toLowerCase() == "normal" && val2 == "400")
 			|| (val2.toLowerCase() == "normal" && val1 == "400");
 	}
+
+	// This code path should probably only be hit by queryOutputHelper() in
+	// tests.js.  Anything else is most likely a bug.
+	if (command == "fontname" && /^[1-7]$/.test(val1)) {
+		val1 = [, "xx-small", "small", "medium", "large", "x-large", "xx-large", "xxx-large"][val1];
+	}
+	if (command == "fontname" && /^[1-7]$/.test(val2)) {
+		val2 = [, "xx-small", "small", "medium", "large", "x-large", "xx-large", "xxx-large"][val2];
+	}
+
 	var property = commands[command].relevantCssProperty;
 	var test1 = document.createElement("span");
 	test1.style[property] = val1;
@@ -479,38 +489,81 @@
 	return nodeList;
 }
 
-
+// Returns either null, or something of the form #xxxxxx, or the color itself
+// if it's a valid keyword.
 function parseSimpleColor(color) {
-	// This is stupid, but otherwise my automated tests will have places where
-	// they're known to contradict the spec, which is annoying, so . . . I
-	// don't aim for correctness, beyond my own provisional tests.  Real tests
-	// will have to be more exhaustive.
-
-	if (color.length == 7 && color[0] == "#") {
+	color = color.toLowerCase();
+	// Yay for Gecko allowing you to select a column of a table without
+	// selecting anything from other columns.
+	if (["aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
+	"bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
+	"burlywood", "cadetblue", "chartreuse", "chocolate", "coral",
+	"cornflowerblue", "cornsilk", "crimson", "cyan", "darkblue", "darkcyan",
+	"darkgoldenrod", "darkgray", "darkgreen", "darkgrey", "darkkhaki",
+	"darkmagenta", "darkolivegreen", "darkorange", "darkorchid", "darkred",
+	"darksalmon", "darkseagreen", "darkslateblue", "darkslategray",
+	"darkslategrey", "darkturquoise", "darkviolet", "deeppink", "deepskyblue",
+	"dimgray", "dimgrey", "dodgerblue", "firebrick", "floralwhite",
+	"forestgreen", "fuchsia", "gainsboro", "ghostwhite", "gold", "goldenrod",
+	"gray", "green", "greenyellow", "grey", "honeydew", "hotpink", "indianred",
+	"indigo", "ivory", "khaki", "lavender", "lavenderblush", "lawngreen",
+	"lemonchiffon", "lightblue", "lightcoral", "lightcyan",
+	"lightgoldenrodyellow", "lightgray", "lightgreen", "lightgrey",
+	"lightpink", "lightsalmon", "lightseagreen", "lightskyblue",
+	"lightslategray", "lightslategrey", "lightsteelblue", "lightyellow",
+	"lime", "limegreen", "linen", "magenta", "maroon", "mediumaquamarine",
+	"mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen",
+	"mediumslateblue", "mediumspringgreen", "mediumturquoise",
+	"mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
+	"navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange",
+	"orangered", "orchid", "palegoldenrod", "palegreen", "paleturquoise",
+	"palevioletred", "papayawhip", "peachpuff", "peru", "pink", "plum",
+	"powderblue", "purple", "red", "rosybrown", "royalblue", "saddlebrown",
+	"salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver",
+	"skyblue", "slateblue", "slategray", "slategrey", "snow", "springgreen",
+	"steelblue", "tan", "teal", "thistle", "tomato", "turquoise", "violet",
+	"wheat", "white", "whitesmoke", "yellow", "yellowgreen"].indexOf(color) != -1) {
 		return color;
 	}
 
-	if (color.length == 4 && color[0] == "#") {
-		return "#" + color[1] + color[1] + color[2] + color[2] + color[3] + color[3];
-	}
-
-	// Otherwise, don't even try.
-	return {
-		"red": "red",
-		"blue": "blue",
-		"rgb(255, 0, 0)": "#ff0000",
-		"rgb(100%, 0, 0)": "#ff0000",
-		"rgb( 255 ,0 ,0)": "#ff0000",
-		"rgba(255, 0, 0, 0.0)": false,
-		"rgb(375, -10, 15)": false,
-		"rgba(0, 0, 0, 1)": "#000000",
-		"rgba(255, 255, 255, 1)": "#ffffff",
-		"rgba(255, 0, 0, 0.5)": false,
-		"hsl(0%, 100%, 50%)": "#ff0000",
-		"cornsilk": "cornsilk",
-		"transparent": false,
-		"currentColor": false,
-	}[color];
+	var outerSpan = document.createElement("span");
+	document.body.appendChild(outerSpan);
+	outerSpan.style.color = "black";
+
+	var innerSpan = document.createElement("span");
+	outerSpan.appendChild(innerSpan);
+	innerSpan.style.color = color;
+	color = getComputedStyle(innerSpan).color;
+
+	if (color == "rgb(0, 0, 0)") {
+		// Maybe it's really black, maybe it's invalid.
+		outerSpan.color = "white";
+		color = getComputedStyle(innerSpan).color;
+		if (color == "rgb(0, 0, 0)") {
+			return null;
+		}
+	}
+
+	document.body.removeChild(outerSpan);
+
+	if (/^rgba\([0-9]+, [0-9]+, [0-9]+, 1\)$/.test(color)) {
+		// IE10PP2 seems to do this sometimes.
+		color = color.replace("rgba", "rgb").replace(", 1)", ")");
+	}
+	// I rely on the fact that browsers generally provide consistent syntax for
+	// getComputedStyle(), although it's not standardized.  In particular, they
+	// seem to clamp the components to integers between 0 and 255, and use
+	// consistent spacing, and always return rgb() syntax.  (Firefox 7.0a2
+	// sometimes returns "transparent", but we need to return null then
+	// anyway.)
+	var matches = /^rgb\(([0-9]+), ([0-9]+), ([0-9]+)\)$/.exec(color);
+	if (matches) {
+		return "#"
+			+ parseInt(matches[1]).toString(16).replace(/^.$/, "0$&")
+			+ parseInt(matches[2]).toString(16).replace(/^.$/, "0$&")
+			+ parseInt(matches[3]).toString(16).replace(/^.$/, "0$&");
+	}
+	return null;
 }
 
 //@}
@@ -642,6 +695,11 @@
 		return false;
 	}
 
+	// "If the state override for command is set, return it."
+	if (typeof getStateOverride(command) != "undefined") {
+		return getStateOverride(command);
+	}
+
 	// "Return true if command's state is true, otherwise false."
 	return commands[command].state();
 }
@@ -672,6 +730,11 @@
 		return "";
 	}
 
+	// "If the value override for command is set, return it."
+	if (typeof getValueOverride(command) != "undefined") {
+		return getValueOverride(command);
+	}
+
 	// "Return command's value."
 	return commands[command].value();
 }
@@ -938,6 +1001,72 @@
 	}
 	return ret;
 }
+
+// "For some commands, each HTMLDocument must have a boolean state override
+// and/or a string value override. These do not change the command's state or
+// value, but change the way some algorithms behave, as specified in those
+// algorithms' definitions. Initially, both must be unset for every command.
+// Whenever the number of ranges in the Selection changes to something
+// different, and whenever a boundary point of the range at a given index in
+// the Selection changes to something different, the state override and value
+// override must be unset for every command."
+//
+// We implement this crudely by using setters and getters.  To verify that the
+// selection hasn't changed, we copy the active range and just check the
+// endpoints match.  This isn't really correct, but it's good enough for us.
+// Unset state/value overrides are undefined.  We put everything in a function
+// so no one can access anything except via the provided functions, since
+// otherwise callers might mistakenly use outdated overrides (if the selection
+// has changed).
+var getStateOverride, setStateOverride, unsetStateOverride,
+	getValueOverride, setValueOverride, unsetValueOverride;
+(function() {
+	var stateOverrides = {};
+	var valueOverrides = {};
+	var storedRange = null;
+
+	function resetOverrides() {
+		if (!storedRange
+		|| storedRange.startContainer != getActiveRange().startContainer
+		|| storedRange.endContainer != getActiveRange().endContainer
+		|| storedRange.startOffset != getActiveRange().startOffset
+		|| storedRange.endOffset != getActiveRange().endOffset) {
+			stateOverrides = {};
+			valueOverrides = {};
+			storedRange = getActiveRange().cloneRange();
+		}
+	}
+
+	getStateOverride = function(command) {
+		resetOverrides();
+		return stateOverrides[command];
+	};
+
+	setStateOverride = function(command, newState) {
+		resetOverrides();
+		stateOverrides[command] = newState;
+	};
+
+	unsetStateOverride = function(command) {
+		resetOverrides();
+		delete stateOverrides[command];
+	}
+
+	getValueOverride = function(command) {
+		resetOverrides();
+		return valueOverrides[command];
+	}
+
+	setValueOverride = function(command, newValue) {
+		resetOverrides();
+		valueOverrides[command] = newValue;
+	}
+
+	unsetValueOverride = function(command) {
+		resetOverrides();
+		delete valueOverrides[command];
+	}
+})();
 //@}
 
 /////////////////////////////
@@ -2482,16 +2611,13 @@
 
 		// "If command is "foreColor", and new value is fully opaque with red,
 		// green, and blue components in the range 0 to 255:"
-		//
-		// Not going to do this properly, only well enough to pass tests.
 		if (command == "forecolor" && parseSimpleColor(newValue)) {
 			// "Let new parent be the result of calling createElement("font")
 			// on the ownerDocument of node."
 			newParent = node.ownerDocument.createElement("font");
 
-			// "If new value is one of the colors listed in the SVG color
-			// keywords section of CSS3 Color, set the color attribute of new
-			// parent to new value."
+			// "If new value is an extended color keyword, set the color
+			// attribute of new parent to new value."
 			//
 			// "Otherwise, set the color attribute of new parent to the result
 			// of applying the rules for serializing simple color values to new
@@ -2697,6 +2823,51 @@
 //@{
 
 function setSelectionValue(command, newValue) {
+	// "If there is no editable text node effectively contained in the active
+	// range:"
+	if (!getAllEffectivelyContainedNodes(getActiveRange())
+	.filter(function(node) { return node.nodeType == Node.TEXT_NODE})
+	.some(isEditable)) {
+		// "If command is in the following list, set the state override
+		// appropriately:"
+		switch (command) {
+			// "bold: True if new value is not null and is greater than or
+			// equal to 600, false otherwise."
+			case "bold": setStateOverride(command, newValue === "bold"); break;
+
+			// "italic: True if new value is "italic" or "oblique", false
+			// otherwise."
+			case "italic": setStateOverride(command, newValue === "italic"); break;
+
+			// "strikethrough: True if new value is "line-through", false
+			// otherwise."
+			case "strikethrough": setStateOverride(command, newValue === "line-through"); break;
+
+			// "subscript: True if new value is "sub", false otherwise."
+			case "subscript": setStateOverride(command, newValue === "sub"); break;
+
+			// "superscript: True if new value is "super", false otherwise."
+			case "superscript": setStateOverride(command, newValue === "super"); break;
+
+			// "underline: True if new value is "underline", false otherwise."
+			case "underline": setStateOverride(command, newValue === "underline");
+		}
+
+		// "If command has a value specified, unset the value override if new
+		// value is null, and set the value override to new value if it is not
+		// null."
+		if ("value" in commands[command]) {
+			if (newValue === null) {
+				unsetValueOverride(command);
+			} else {
+				setValueOverride(command, newValue);
+			}
+		}
+
+		// "Abort these steps."
+		return;
+	}
+
 	// "If the active range's start node is an editable Text node, and its
 	// start offset is neither zero nor its start node's length, call
 	// splitText() on the active range's start node, with argument equal to the
@@ -2764,6 +2935,8 @@
 commands.backcolor = {
 	// Copy-pasted, same as hiliteColor
 	action: function(value) {
+		// Action is further copy-pasted, same as foreColor
+
 		// "If value is not a valid CSS color, prepend "#" to it."
 		//
 		// "If value is still not a valid CSS color, or if it is currentColor,
@@ -2773,12 +2946,9 @@
 		if (/^([0-9a-fA-F]{3}){1,2}$/.test(value)) {
 			value = "#" + value;
 		}
-		if (!/^#([0-9a-fA-F]{3}){1,2}$/.test(value)
-		&& !/^(rgba?|hsla?)\(.*\)$/.test(value)
-		// Not gonna list all the keywords, only the ones I use.
-		&& value != "red"
-		&& value != "cornsilk"
-		&& value != "transparent") {
+		if (!/^(rgba?|hsla?)\(.*\)$/.test(value)
+		&& !parseSimpleColor(value)
+		&& value.toLowerCase() != "transparent") {
 			throw "SYNTAX_ERR";
 		}
 
@@ -2796,12 +2966,20 @@
 			return arr.slice(0, i).indexOf(value) == -1;
 		}).length >= 2;
 	}, value: function() {
-		// "The effective command value of the active range's start node."
+		// "The effective command value of the first editable Text node that is
+		// effectively contained in the active range, or if there is no such
+		// node, the effective command value of the active range's start node."
 		//
 		// Opera uses a different format, so let's be nice and support that for
 		// the time being (since all this resolved value stuff is underdefined
 		// anyway).
-		var value = getEffectiveCommandValue(getActiveRange().startContainer, "backcolor");
+		var node = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
+			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
+		})[0];
+		if (node === undefined) {
+			node = getActiveRange().startContainer;
+		}
+		var value = getEffectiveCommandValue(node, "backcolor");
 		if (/^#[0-9a-f]{6}$/.test(value)) {
 			value = "rgb(" + parseInt(value.slice(1, 3), 16)
 				+ "," + parseInt(value.slice(3, 5), 16)
@@ -2816,12 +2994,12 @@
 //@{
 commands.bold = {
 	action: function() {
-		// "If the state is false, set the selection's value to "bold",
-		// otherwise set the selection's value to "normal"."
-		if (!commands.bold.state()) {
+		// "If queryCommandState("bold") returns true, set the selection's
+		// value to "normal". Otherwise set the selection's value to "bold"."
+		if (myQueryCommandState("bold", getActiveRange())) {
+			setSelectionValue("bold", "normal");
+		} else {
 			setSelectionValue("bold", "bold");
-		} else {
-			setSelectionValue("bold", "normal");
 		}
 	}, indeterm: function() { return indetermHelper(function(node) {
 		// "True if among editable Text nodes that are effectively contained in
@@ -2897,8 +3075,16 @@
 			return arr.slice(0, i).indexOf(value) == -1;
 		}).length >= 2;
 	}, value: function() {
-		// "The effective command value of the active range's start node."
-		return getEffectiveCommandValue(getActiveRange().startContainer, "fontname");
+		// "The effective command value of the first editable Text node that is
+		// effectively contained in the active range, or if there is no such
+		// node, the effective command value of the active range's start node."
+		var node = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
+			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
+		})[0];
+		if (node === undefined) {
+			node = getActiveRange().startContainer;
+		}
+		return getEffectiveCommandValue(node, "fontname");
 	}, relevantCssProperty: "fontFamily"
 };
 
@@ -3002,9 +3188,18 @@
 			return arr.slice(0, i).indexOf(value) == -1;
 		}).length >= 2;
 	}, value: function() {
-		// "Let pixel size be the effective command value of the active range's
-		// start node, as a number of pixels."
-		var pixelSize = parseInt(getEffectiveCommandValue(getActiveRange().startContainer, "fontsize"));
+		// "Let pixel size be the effective command value of the first editable
+		// Text node that is effectively contained in the active range, or if
+		// there is no such node, the effective command value of the active
+		// range's start node, in either case interpreted as a number of
+		// pixels."
+		var node = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
+			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
+		})[0];
+		if (node === undefined) {
+			node = getActiveRange().startContainer;
+		}
+		var pixelSize = parseInt(getEffectiveCommandValue(node, "fontsize"));
 
 		// "Let returned size be 1."
 		var returnedSize = 1;
@@ -3048,7 +3243,7 @@
 //@{
 commands.forecolor = {
 	action: function(value) {
-		// Copy-pasted, same as hiliteColor
+		// Copy-pasted, same as backColor and hiliteColor
 
 		// "If value is not a valid CSS color, prepend "#" to it."
 		//
@@ -3059,12 +3254,9 @@
 		if (/^([0-9a-fA-F]{3}){1,2}$/.test(value)) {
 			value = "#" + value;
 		}
-		if (!/^#([0-9a-fA-F]{3}){1,2}$/.test(value)
-		&& !/^(rgba?|hsla?)\(.*\)$/.test(value)
-		// Not gonna list all the keywords, only the ones I use.
-		&& value != "red"
-		&& value != "cornsilk"
-		&& value != "transparent") {
+		if (!/^(rgba?|hsla?)\(.*\)$/.test(value)
+		&& !parseSimpleColor(value)
+		&& value.toLowerCase() != "transparent") {
 			throw "SYNTAX_ERR";
 		}
 
@@ -3082,12 +3274,20 @@
 			return arr.slice(0, i).indexOf(value) == -1;
 		}).length >= 2;
 	}, value: function() {
-		// "The effective command value of the active range's start node."
+		// "The effective command value of the first editable Text node that is
+		// effectively contained in the active range, or if there is no such
+		// node, the effective command value of the active range's start node."
 		//
 		// Opera uses a different format, so let's be nice and support that for
 		// the time being (since all this resolved value stuff is underdefined
 		// anyway).
-		var value = getEffectiveCommandValue(getActiveRange().startContainer, "forecolor");
+		var node = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
+			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
+		})[0];
+		if (node === undefined) {
+			node = getActiveRange().startContainer;
+		}
+		var value = getEffectiveCommandValue(node, "forecolor");
 		if (/^#[0-9a-f]{6}$/.test(value)) {
 			value = "rgb(" + parseInt(value.slice(1, 3), 16)
 				+ "," + parseInt(value.slice(3, 5), 16)
@@ -3101,8 +3301,9 @@
 ///// The hiliteColor command /////
 //@{
 commands.hilitecolor = {
+	// Copy-pasted, same as backColor
 	action: function(value) {
-		// Copy-pasted, same as foreColor
+		// Action is further copy-pasted, same as foreColor
 
 		// "If value is not a valid CSS color, prepend "#" to it."
 		//
@@ -3113,12 +3314,9 @@
 		if (/^([0-9a-fA-F]{3}){1,2}$/.test(value)) {
 			value = "#" + value;
 		}
-		if (!/^#([0-9a-fA-F]{3}){1,2}$/.test(value)
-		&& !/^(rgba?|hsla?)\(.*\)$/.test(value)
-		// Not gonna list all the keywords, only the ones I use.
-		&& value != "red"
-		&& value != "cornsilk"
-		&& value != "transparent") {
+		if (!/^(rgba?|hsla?)\(.*\)$/.test(value)
+		&& !parseSimpleColor(value)
+		&& value.toLowerCase() != "transparent") {
 			throw "SYNTAX_ERR";
 		}
 
@@ -3136,12 +3334,20 @@
 			return arr.slice(0, i).indexOf(value) == -1;
 		}).length >= 2;
 	}, value: function() {
-		// "The effective command value of the active range's start node."
+		// "The effective command value of the first editable Text node that is
+		// effectively contained in the active range, or if there is no such
+		// node, the effective command value of the active range's start node."
 		//
 		// Opera uses a different format, so let's be nice and support that for
 		// the time being (since all this resolved value stuff is underdefined
 		// anyway).
-		var value = getEffectiveCommandValue(getActiveRange().startContainer, "hilitecolor");
+		var node = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
+			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
+		})[0];
+		if (node === undefined) {
+			node = getActiveRange().startContainer;
+		}
+		var value = getEffectiveCommandValue(node, "hilitecolor");
 		if (/^#[0-9a-f]{6}$/.test(value)) {
 			value = "rgb(" + parseInt(value.slice(1, 3), 16)
 				+ "," + parseInt(value.slice(3, 5), 16)
@@ -3156,12 +3362,12 @@
 //@{
 commands.italic = {
 	action: function() {
-		// "If the state is false, set the selection's value to "italic",
-		// otherwise set the selection's value to "normal"."
-		if (!commands.italic.state()) {
+		// "If queryCommandState("italic") returns true, set the selection's
+		// value to "normal". Otherwise set the selection's value to "italic"."
+		if (myQueryCommandState("italic", getActiveRange())) {
+			setSelectionValue("italic", "normal");
+		} else {
 			setSelectionValue("italic", "italic");
-		} else {
-			setSelectionValue("italic", "normal");
 		}
 	}, indeterm: function() { return indetermHelper(function(node) {
 		// "True if among editable Text nodes that are effectively contained in
@@ -3286,12 +3492,13 @@
 //@{
 commands.strikethrough = {
 	action: function() {
-		// "If the state is false, set the selection's value to "line-through",
-		// otherwise set the selection's value to null."
-		if (!commands.strikethrough.state()) {
+		// "If queryCommandState("strikethrough") returns true, set the
+		// selection's value to null. Otherwise set the selection's value to
+		// "line-through"."
+		if (myQueryCommandState("strikethrough", getActiveRange())) {
+			setSelectionValue("strikethrough", null);
+		} else {
 			setSelectionValue("strikethrough", "line-through");
-		} else {
-			setSelectionValue("strikethrough", null);
 		}
 	}, indeterm: function() { return indetermHelper(function(node) {
 		// "True if among editable Text nodes that are effectively contained in
@@ -3312,8 +3519,8 @@
 //@{
 commands.subscript = {
 	action: function() {
-		// "Let state be the state."
-		var state = commands.subscript.state();
+		// "Call queryCommandState("subscript"), and let state be the result."
+		var state = myQueryCommandState("subscript", getActiveRange());
 
 		// "Set the selection's value to "baseline"."
 		setSelectionValue("subscript", "baseline");
@@ -3348,8 +3555,9 @@
 //@{
 commands.superscript = {
 	action: function() {
-		// "Let state be the state."
-		var state = commands.superscript.state();
+		// "Call queryCommandState("superscript"), and let state be the
+		// result."
+		var state = myQueryCommandState("superscript", getActiveRange());
 
 		// "Set the selection's value to "baseline"."
 		setSelectionValue("superscript", "baseline");
@@ -3385,12 +3593,12 @@
 //@{
 commands.underline = {
 	action: function() {
-		// "If the state is false, set the selection's value to "underline",
-		// otherwise set the selection's value to null."
-		if (!commands.underline.state()) {
+		// "If queryCommandState("underline") returns true, set the selection's
+		// value to null. Otherwise set the selection's value to "underline"."
+		if (myQueryCommandState("underline", getActiveRange())) {
+			setSelectionValue("underline", null);
+		} else {
 			setSelectionValue("underline", "underline");
-		} else {
-			setSelectionValue("underline", null);
 		}
 	}, indeterm: function() { return indetermHelper(function(node) {
 		// "True if among editable Text nodes that are effectively contained in
--- a/source.html	Wed Jul 13 13:55:04 2011 -0600
+++ b/source.html	Thu Jul 14 12:24:49 2011 -0600
@@ -604,6 +604,9 @@
 
   <li>If <var>command</var> is not <span>enabled</span>, return false.
 
+  <li>If the <span>state override</span> for <var>command</var> is set, return
+  it.
+
   <li>Return true if <var>command</var>'s <span>state</span> is true, otherwise
   false.
 </ol>
@@ -642,12 +645,38 @@
   seems to return the string "false", and IE9 seems to return boolean false.
   -->
 
+  <li>If the <span>value override</span> for <var>command</var> is set, return
+  it.
+
   <li>Return <var>command</var>'s <span>value</span>.
 </ol>
 
 <p>All of these methods must treat their <var>command</var> argument <span
 data-anolis-spec=domcore title="ASCII case-insensitive">ASCII
 case-insensitively</span>.
+
+<p>The methods in this section have been designed so that the following
+invariants hold after <code>execCommand()</code> is called, assuming it didn't
+throw an exception:
+
+<ul>
+  <li><code>queryCommandIndeterm()</code> will return false (or throw an
+  exception).
+
+  <li><code>queryCommandState()</code> will return the opposite of what it did
+  before <code>execCommand()</code> was called (or throw an exception).
+
+  <li><code>queryCommandValue()</code> will return something equivalent to the
+  value passed to <code>execCommand()</code> (or throw an exception).
+  "Equivalent" here needs to be construed broadly in some cases, such as
+  <span>the <code title>fontSize</code> command</span>.
+</ul>
+
+<p>The first two points do not always hold for <span>the <code
+title>strikethrough</code> command</span> or <span>the <code
+title>underline</code> command</span>, because it can be impossible to unset
+text-decoration in CSS, but all three points otherwise hold in all cases
+barring bugs.
 <!-- @} -->
 
 <h2>Common definitions</h2>
@@ -775,6 +804,17 @@
 means of the <code>execCommand()</code> and <code>queryCommandState()</code>
 methods.)
 
+<p>For some <span title=command>commands</span>, each [[htmldocument]] must
+have a boolean <dfn>state override</dfn> and/or a string <dfn>value
+override</dfn>.  These do not change the <span>command</span>'s
+<span>state</span> or <span>value</span>, but change the way some algorithms
+behave, as specified in those algorithms' definitions.  Initially, both must be
+unset for every <span>command</span>.  Whenever the number of [[ranges]] in the
+[[selection]] changes to something different, and whenever a [[boundarypoint]]
+of the [[range]] at a given index in the [[selection]] changes to something
+different, the <span>state override</span> and <span>value override</span> must
+be unset for every <span>command</span>.
+
 <p>When the user agent is instructed to run a particular method, it must follow
 the steps defined for that method in the appropriate specification, not act as
 though the method had actually been called from JavaScript.  In particular,
@@ -1928,6 +1968,10 @@
 
     <li>If <var>command</var> is "foreColor", and <var>new value</var> is fully
     opaque with red, green, and blue components in the range 0 to 255:
+    <!-- See comment for foreColor for discussion. -->
+
+    <p class=XXX>Check this more carefully for what happens if the components
+    are not integers or are out-of-range.
 
     <ol>
       <li>Let <var>new parent</var> be the result of calling <code
@@ -1935,9 +1979,10 @@
       title=dom-Document-createElement>createElement("font")</code> on the
       [[ownerdocument]] of <var>node</var>.
 
-      <li>If <var>new value</var> is one of the colors listed in the SVG color
-      keywords section of CSS3 Color, set the [[fontcolor]] attribute of
-      <var>new parent</var> to <var>new value</var>.
+      <li>If <var>new value</var> is an <a
+      href=http://www.w3.org/TR/css3-color/#svg-color>extended color
+      keyword</a>, set the [[fontcolor]] attribute of <var>new parent</var> to
+      <var>new value</var>.
 
       <li>Otherwise, set the [[fontcolor]] attribute of <var>new parent</var>
       to the result of applying the <span data-anolis-spec=html>rules for
@@ -2174,6 +2219,39 @@
 <ol>
   <li>Let <var>command</var> be the current <span>command</span>.
 
+  <li>If there is no <span>editable</span> [[text]] node <span>effectively
+  contained</span> in the <span>active range</span>:
+
+  <ol>
+    <li>If <var>command</var> is in the following list, set the <span>state
+    override</span> appropriately:
+
+    <dl class=compact>
+      <dt>bold<dd>True if <var>new value</var> is not null and is greater than or equal
+      to 600, false otherwise.
+
+      <dt>italic<dd>True if <var>new value</var> is "italic" or "oblique", false
+      otherwise.
+
+      <dt>strikethrough<dd>True if <var>new value</var> is "line-through", false otherwise.
+
+      <dt>subscript<dd>True if <var>new value</var> is "sub", false otherwise.
+
+      <dt>superscript<dd>True if <var>new value</var> is "super", false otherwise.
+
+      <dt>underline<dd>True if <var>new value</var> is "underline", false otherwise.
+    </dl>
+
+    <li>If <var>command</var> has a <span>value</span> specified, unset the
+    <span>value override</span> if <var>new value</var> is null, and set the
+    <span>value override</span> to <var>new value</var> if it is not null.
+
+    <p class=XXX>This doesn't work as-is for fontSize, because that uses a
+    different format for the value.
+
+    <li>Abort these steps.
+  </ol>
+
   <li>If the <span>active range</span>'s [[startnode]] is an
   <span>editable</span> [[text]] node, and its [[startoffset]] is neither zero
   nor its [[startnode]]'s [[length]], call [[splittext|]] on the <span>active
@@ -2301,11 +2379,15 @@
 range</span>, there are two that have distinct <span title="effective command
 value">effective command values</span>.  Otherwise false.
 
-<p><span>Value</span>: The <span>effective command value</span> of the
-<span>active range</span>'s [[startnode]].
-
-<p class=note>This cannot be null, since the boundary point node of a selection
-must always be either an element or a text node that's the child of an element.
+<p><span>Value</span>: The <span>effective command value</span> of the first
+<span>editable</span> [[text]] node that is <span>effectively contained</span>
+in the <span>active range</span>, or if there is no such node, the
+<span>effective command value</span> of the <span>active range</span>'s
+[[startnode]].
+
+<p class=note>The effective command value of the active range's start node
+cannot be null, since the boundary point node of a selection must always be
+either an element or a text node that's the child of an element.
 
 <p><span>Relevant CSS property</span>: "background-color"
 
@@ -2318,9 +2400,10 @@
 (fontName, italic, etc.).  Except not for strikethrough, where it just does
 nothing if the selection is empty.  Why strikethrough?  I don't know. -->
 
-<p><span>Action</span>: If the <span>state</span> is false, <span>set the
-selection's value</span> to "bold", otherwise <span>set the selection's
-value</span> to "normal".
+<p><span>Action</span>: If <code
+title=queryCommandState()>queryCommandState("bold")</code> returns true,
+<span>set the selection's value</span> to "normal".  Otherwise <span>set the
+selection's value</span> to "bold".
 
 <p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
 nodes that are <span>effectively contained</span> in the <span>active
@@ -2417,15 +2500,7 @@
   <li><span>Set the selection's value</span> to <var>value</var>.
 </ol>
 
-<!--
-The state is always false in Chrome 14 dev and Opera 11.11.  Firefox 6.0a2
-throws an exception, and IE9 seems to always either return false or throw an
-exception.  Therefore we make the state always false, although this doesn't
-seem very useful.
--->
-
-<!-- I'd have expected the value to be the URL, but guess not: it's always
-false. -->
+<p class=XXX>Define state and value, although browsers don't.
 
 <!-- @} -->
 <h3><dfn>The <code title>fontName</code> command</dfn></h3>
@@ -2459,12 +2534,17 @@
 value">effective command values</span>.  Otherwise false.
 <!-- This follows Firefox 6.0a2.  Chrome 14 dev always returns false. -->
 
-<p><span>Value</span>: The <span>effective command value</span> of the
-<span>active range</span>'s [[startnode]].
-
-<p class=note>This cannot be null, since the boundary point node of a selection
-must always be either an element or a text node that's the child of an element.
-<!-- Complicated.
+<p><span>Value</span>: The <span>effective command value</span> of the first
+<span>editable</span> [[text]] node that is <span>effectively contained</span>
+in the <span>active range</span>, or if there is no such node, the
+<span>effective command value</span> of the <span>active range</span>'s
+[[startnode]].
+
+<p class=note>The effective command value of the active range's start node
+cannot be null, since the boundary point node of a selection must always be
+either an element or a text node that's the child of an element.
+<!--
+Complicated.
 
 IE 9 RC: Always the empty string.  Not very useful.
 Firefox 4b11: Confusing.  Sometimes it returns generic family names, like
@@ -2479,7 +2559,10 @@
 
 I'm just going to punt on this and say it should be the resolved value of
 font-family.  I'll leave CSSOM to decide what that means if there are no
-applicable style rules. -->
+applicable style rules.
+
+For deciding which node should be checked, see comment for hiliteColor.
+-->
 
 <p><span>Relevant CSS property</span>: "font-family"
 
@@ -2621,11 +2704,16 @@
 -->
 <ol>
   <li>Let <var>pixel size</var> be the <span>effective command value</span> of
-  the <span>active range</span>'s [[startnode]], as a number of pixels.
-
-  <p class=note>The active range's start node cannot be null, since the
-  boundary point node of a selection must always be either an element or a text
-  node that's the child of an element.
+  the first <span>editable</span> [[text]] node that is <span>effectively
+  contained</span> in the <span>active range</span>, or if there is no such
+  node, the <span>effective command value</span> of the <span>active
+  range</span>'s [[startnode]], in either case interpreted as a number of
+  pixels.
+  <!-- See comment for hiliteColor on how I decided on this choice of node. -->
+
+  <p class=note>The effective command value of the active range's start node
+  cannot be null, since the boundary point node of a selection must always be
+  either an element or a text node that's the child of an element.
 
   <li>Let <var>returned size</var> be 1.
 
@@ -2661,29 +2749,29 @@
 
 <!-- Color interpretations (wide screen recommended):
 
-                        IE9           Firefox 4.0              Chrome 12 dev            Opera 11.00
-red                     red           red                      #ff0000                  #ff0000
+                        IE10PP2       Firefox 7.0a2            Chrome 14 dev            Opera 11.50
+blue                    blue          blue                     #0000ff                  #0000ff
 f                       #f            -                        -                        #f00000
 #f                      #f            -                        -                        #f00000
-f00                     #f00          -                        #ff0000                  #0f0000
-#f00                    #f00          rgb(255, 0, 0)           #ff0000                  #0f0000
-ff0000                  #ff0000       -                        #ff0000                  #ff0000
-#ff0000                 #ff0000       rgb(255, 0, 0)           #ff0000                  #ff0000
-fff000000               #ff0000       -                        -                        #fff000
-#fff000000              #ff0000       -                        -                        #fff000
-rgb(255, 0, 0)          rgb(255,0,0)  rgb(255, 0, 0)           #ff0000                  #00b025
-rgb(100%, 0, 0)         rgb(255,0,0)  -                        -                        #00b010
-rgb( 255 ,0 ,0)         rgb(255,0,0)  rgb(255, 0, 0)           #ff0000                  #00b025
-rgba(255, 0, 0, 0.0)    #005000       rgba(255, 0, 0, 0)       rgba(255, 0, 0, 0.0)     #00ba02
-rgb(375, -10, 15)       rgb(255,0,15) rgb(255, 0, 15)          #ff000f                  #00b037
+00f                     #00f          -                        #0000ff                  #00000f
+#00f                    #00f          rgb(0, 0, 255)           #0000ff                  #00000f
+0000ff                  #0000ff       -                        #0000ff                  #0000ff
+#0000ff                 #0000ff       rgb(0, 0, 255)           #0000ff                  #0000ff
+000000fff               #0000ff       -                        -                        -
+#000000fff              #0000ff       -                        -                        -
+rgb(0, 0, 255)          rgb(0,0,255)  rgb(0, 0, 255)           #0000ff                  #00b000
+rgb(0%, 0%, 100%)       rgb(0,0,255)  rgb(0, 0, 255)           #0000ff                  #00b000
+rgb( 0 ,0 ,255)         rgb(0,0,255)  rgb(0, 0, 255)           #0000ff                  #00b000
+rgba(0, 0, 255, 0.0)    #ba0000       rgba(0, 0, 255, 0)       rgba(0, 0, 255, 0)       #00ba00
+rgb(15, -10, 375)       rgb(15,0,255) rgb(15, 0, 255)          #0f00ff                  #00b015
 rgba(0, 0, 0, 1)        #ba0010       rgb(0, 0, 0)             -                        #00ba00
 rgba(255, 255, 255, 1)  #000055       rgb(255, 255, 255)       #ffffff                  #00ba02
-rgba(255, 0, 0, 0.5)    #005000       rgba(255, 255, 255, 0.5) rgba(255, 0, 0, 0.49804) #00ba02
-hsl(0%, 100%, 50%)      #001050       -                        -                        -
+rgba(0, 0, 255, 0.5)    #ba0000       rgba(0, 0, 255, 0.5)     rgba(0, 0, 255, 0.5)     #00ba00
+hsl(240, 100%, 50%)     #000150       rgb(0, 0, 255)           #0000ff                  #000024
 cornsilk                cornsilk      cornsilk                 #fff8dc                  #fff8dc
 potato quiche           #0000c0       -                        -                        #000a00
-transparent             transparent   -                        rgba(0, 0, 0.0)          #00a000
-currentColor            #c0e000       currentcolor             rgba(0, 0, 0.0)          #c000e0
+transparent             transparent   -                        rgba(0, 0, 0, 0)         #00a000
+currentColor            #c0e000       currentcolor             rgba(0, 0, 0, 0)         #c000e0
 
 The interpretations given for Firefox are only in styleWithCSS mode.  In
 non-styleWithCSS mode, it just outputs the string literally as the <font color>
@@ -2698,8 +2786,8 @@
 * Opera mangles #xxx, but everyone else handles it fine.
 * The leading # is optional in all browsers but Gecko.
 * rgb() is accepted by everyone but Opera.
-* rgba() is accepted by Gecko and WebKit, but rejected by IE and Opera.
-* hsl() isn't accepted by anyone.
+* rgba() and hsl() are accepted by Gecko and WebKit, but rejected by IE and
+  Opera.
 * IE and Opera mangle unrecognized stuff, Gecko and WebKit ignore.
 * Browsers will happily output stuff like "transparent" and "rgba()" into <font
   color> even though it won't be uniformly accepted there.
@@ -2736,18 +2824,25 @@
 value">effective command values</span>.  Otherwise false.
 <!-- This follows Firefox 6.0a2.  Chrome 14 dev always returns false. -->
 
-<p><span>Value</span>: The <span>effective command value</span> of the
-<span>active range</span>'s [[startnode]].
-
-<p class=note>This cannot be null, since the boundary point node of a selection
-must always be either an element or a text node that's the child of an element.
+<p><span>Value</span>: The <span>effective command value</span> of the first
+<span>editable</span> [[text]] node that is <span>effectively contained</span>
+in the <span>active range</span>, or if there is no such node, the
+<span>effective command value</span> of the <span>active range</span>'s
+[[startnode]].
+
+<p class=note>The effective command value of the active range's start node
+cannot be null, since the boundary point node of a selection must always be
+either an element or a text node that's the child of an element.
 <!--
-The spec essentially matches Firefox 6.0a2 and Chrome 14 dev.  IE9 seems to
-always return the number 0 for some bizarre reason.  There are some cases where
-Firefox returns the empty string for some reason, and it seems to select the
-active node a little differently.  Opera uses #xxxxxx format for
-getComputedStyle() but rgb() here, and also drops the transparent part of the
-color if there is any.
+The spec essentially matches Firefox 6.0a2 and Chrome 14 dev, as far as how to
+decide what color the node has.  IE9 seems to always return the number 0 for
+some bizarre reason.  There are some cases where Firefox returns the empty
+string for some reason, and it seems to select the active node a little
+differently.  Opera uses #xxxxxx format for getComputedStyle() but rgb() here,
+and also drops the transparent part of the color if there is any.
+
+For why I chose this node to key the color off of, see the comment for
+hiliteColor.
 -->
 
 <p><span>Relevant CSS property</span>: "color"
@@ -2794,19 +2889,28 @@
 <!-- This follows no one.  Firefox 6.0a2 and Chrome 14 dev both always return
 false.  However, it makes sense. -->
 
-<p><span>Value</span>: The <span>effective command value</span> of the
-<span>active range</span>'s [[startnode]].
-
-<p class=note>This cannot be null, since the boundary point node of a selection
-must always be either an element or a text node that's the child of an element.
+<p><span>Value</span>: The <span>effective command value</span> of the first
+<span>editable</span> [[text]] node that is <span>effectively contained</span>
+in the <span>active range</span>, or if there is no such node, the
+<span>effective command value</span> of the <span>active range</span>'s
+[[startnode]].
+
+<p class=note>The effective command value of the active range's start node
+cannot be null, since the boundary point node of a selection must always be
+either an element or a text node that's the child of an element.
 <!--
-This seems to match Opera 11.11 exactly.  Chrome 14 dev returns boolean false
-consistently, bizarrely enough.  Firefox 6.0a2 seems to follow the same idea as
-the spec, but it likes to return "transparent", including sometimes when the
-answer really clearly should not be "transparent".  IE9 throws exceptions most
-of the time for backColor, so I can't say for sure, but in the few cases where
-it doesn't throw it returns a random-looking number, so I'll assume it's crazy
-like for foreColor.
+Opera 11.11 seems to always return the effective command value of the active
+range's start node.  Chrome 14 dev returns boolean false consistently,
+bizarrely enough.  Firefox 6.0a2 seems to follow the same idea as the spec, but
+it likes to return "transparent", including sometimes when the answer really
+clearly should not be "transparent".  IE9 throws exceptions most of the time
+for backColor, so I can't say for sure, but in the few cases where it doesn't
+throw it returns a random-looking number, so I'll assume it's crazy like for
+foreColor.
+
+I decided on something that would guarantee the following invariant: whenever
+you execute a command with a value provided (assuming value is relevant),
+queryCommandValue() will always return something equivalent to what you set.
 -->
 
 <p><span>Relevant CSS property</span>: "background-color"
@@ -2814,9 +2918,10 @@
 <!-- @} -->
 <h3><dfn>The <code title>italic</code> command</dfn></h3>
 <!-- @{ -->
-<p><span>Action</span>: If the <span>state</span> is false, <span>set the
-selection's value</span> to "italic", otherwise <span>set the selection's
-value</span> to "normal".
+<p><span>Action</span>: If <code
+title=queryCommandState()>queryCommandState("italic")</code> returns true,
+<span>set the selection's value</span> to "normal".  Otherwise <span>set the
+selection's value</span> to "italic".
 
 <p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
 nodes that are <span>effectively contained</span> in the <span>active
@@ -2960,9 +3065,10 @@
 <!-- @} -->
 <h3><dfn>The <code title>strikethrough</code> command</dfn></h3>
 <!-- @{ -->
-<p><span>Action</span>: If the <span>state</span> is false, <span>set the
-selection's value</span> to "line-through", otherwise <span>set the selection's
-value</span> to null.
+<p><span>Action</span>: If <code
+title=queryCommandState()>queryCommandState("strikethrough")</code> returns
+true, <span>set the selection's value</span> to null.  Otherwise <span>set the
+selection's value</span> to "line-through".
 
 <!-- TODO: See underline TODO. -->
 
@@ -2983,7 +3089,9 @@
 <p><span>Action</span>:
 
 <ol>
-  <li>Let <var>state</var> be the <span>state</span>.
+  <li>Call <code
+  title=queryCommandState()>queryCommandState("subscript")</code>, and let
+  <var>state</var> be the result.
 
   <li><span>Set the selection's value</span> to "baseline".
 
@@ -3023,7 +3131,9 @@
 <p><span>Action</span>:
 
 <ol>
-  <li>Let <var>state</var> be the <span>state</span>.
+  <li>Call <code
+  title=queryCommandState()>queryCommandState("superscript")</code>, and let
+  <var>state</var> be the result.
 
   <li><span>Set the selection's value</span> to "baseline".
 
@@ -3049,9 +3159,10 @@
 <!-- @} -->
 <h3><dfn>The <code title>underline</code> command</dfn></h3>
 <!-- @{ -->
-<p><span>Action</span>: If the <span>state</span> is false, <span>set the
-selection's value</span> to "underline", otherwise <span>set the selection's
-value</span> to null.
+<p><span>Action</span>: If <code
+title=queryCommandState()>queryCommandState("underline")</code> returns true,
+<span>set the selection's value</span> to null.  Otherwise <span>set the
+selection's value</span> to "underline".
 
 <!--
 TODO: There are a lot of problems with underline color and thickness, because
@@ -6666,6 +6777,8 @@
 theory, but normalize the selection first, so they don't match it in practice.
 -->
 
+<p class=XXX>Needs to handle overridden state/value.
+
 <p><span>Action</span>:
 
 <!--
--- a/tests.css	Wed Jul 13 13:55:04 2011 -0600
+++ b/tests.css	Thu Jul 14 12:24:49 2011 -0600
@@ -15,6 +15,9 @@
 	color: red;
 	font-weight: bold;
 }
+.extra-results { font-size: small }
+.good-result { color: green }
+.bad-result { color: red }
 /* http://www.w3.org/Bugs/Public/show_bug.cgi?id=12154
  * https://bugzilla.mozilla.org/show_bug.cgi?id=589124
  * https://bugs.webkit.org/show_bug.cgi?id=56400 */
--- a/tests.js	Wed Jul 13 13:55:04 2011 -0600
+++ b/tests.js	Thu Jul 14 12:24:49 2011 -0600
@@ -187,7 +187,7 @@
 		'<i><b>foo</b></i>[bar]<i><b>baz</b></i>',
 		'<i><b>foo</b></i>[bar]<b>baz</b>',
 		'<b>foo</b>[bar]<i><b>baz</b></i>',
-		'<font color=red face=monospace><b>foo</b></font>[bar]',
+		'<font color=blue face=monospace><b>foo</b></font>[bar]',
 
 		'foo<span style="font-weight: normal"><b>{bar}</b></span>baz',
 		'[foo<span class=notbold>bar</span>baz]',
@@ -393,11 +393,11 @@
 		'foo<blockquote>[]bar</blockquote>',
 		'foo<blockquote><blockquote>[]bar</blockquote></blockquote>',
 		'foo<blockquote><div>[]bar</div></blockquote>',
-		'foo<blockquote style="color: red">[]bar</blockquote>',
+		'foo<blockquote style="color: blue">[]bar</blockquote>',
 
 		'foo<blockquote><blockquote><p>[]bar<p>baz</blockquote></blockquote>',
 		'foo<blockquote><div><p>[]bar<p>baz</div></blockquote>',
-		'foo<blockquote style="color: red"><p>[]bar<p>baz</blockquote>',
+		'foo<blockquote style="color: blue"><p>[]bar<p>baz</blockquote>',
 
 		'foo<blockquote><p><b>[]bar</b><p>baz</blockquote>',
 		'foo<blockquote><p><strong>[]bar</strong><p>baz</blockquote>',
@@ -434,22 +434,22 @@
 		'<div><div><p>foo</p></div></div><div><div><div><!--abc-->[]bar</div></div></div>',
 
 		// Styled stuff with collapsed selection
-		'<p style=color:red>foo<p>[]bar',
-		'<p style=color:red>foo<p style=color:blue>[]bar',
-		'<p>foo<p style=color:blue>[]bar',
-		'<p><font color=red>foo</font><p>[]bar',
-		'<p><font color=red>foo</font><p><font color=blue>[]bar</font>',
-		'<p>foo<p><font color=blue>[]bar</font>',
-		'<p><span style=color:red>foo</font><p>[]bar',
-		'<p><span style=color:red>foo</font><p><span style=color:blue>[]bar</font>',
-		'<p>foo<p><span style=color:blue>[]bar</font>',
-
-		'<p style=background-color:salmon>foo<p>[]bar',
-		'<p style=background-color:salmon>foo<p style=background-color:aqua>[]bar',
-		'<p>foo<p style=background-color:aqua>[]bar',
-		'<p><span style=background-color:salmon>foo</font><p>[]bar',
-		'<p><span style=background-color:salmon>foo</font><p><span style=background-color:aqua>[]bar</font>',
-		'<p>foo<p><span style=background-color:aqua>[]bar</font>',
+		'<p style=color:blue>foo<p>[]bar',
+		'<p style=color:blue>foo<p style=color:brown>[]bar',
+		'<p>foo<p style=color:brown>[]bar',
+		'<p><font color=blue>foo</font><p>[]bar',
+		'<p><font color=blue>foo</font><p><font color=brown>[]bar</font>',
+		'<p>foo<p><font color=brown>[]bar</font>',
+		'<p><span style=color:blue>foo</font><p>[]bar',
+		'<p><span style=color:blue>foo</font><p><span style=color:brown>[]bar</font>',
+		'<p>foo<p><span style=color:brown>[]bar</font>',
+
+		'<p style=background-color:aqua>foo<p>[]bar',
+		'<p style=background-color:aqua>foo<p style=background-color:tan>[]bar',
+		'<p>foo<p style=background-color:tan>[]bar',
+		'<p><span style=background-color:aqua>foo</font><p>[]bar',
+		'<p><span style=background-color:aqua>foo</font><p><span style=background-color:tan>[]bar</font>',
+		'<p>foo<p><span style=background-color:tan>[]bar</font>',
 
 		'<p style=text-decoration:underline>foo<p>[]bar',
 		'<p style=text-decoration:underline>foo<p style=text-decoration:line-through>[]bar',
@@ -458,11 +458,11 @@
 		'<p><u>foo</u><p><s>[]bar</s>',
 		'<p>foo<p><s>[]bar</s>',
 
-		'<p style=color:red>foo</p>[]bar',
-		'foo<p style=color:blue>[]bar',
-		'<div style=color:red><p style=color:green>foo</div>[]bar',
-		'<div style=color:red><p style=color:green>foo</div><p style=color:blue>[]bar',
-		'<p style=color:red>foo<div style=color:blue><p style=color:green>[]bar',
+		'<p style=color:blue>foo</p>[]bar',
+		'foo<p style=color:brown>[]bar',
+		'<div style=color:blue><p style=color:green>foo</div>[]bar',
+		'<div style=color:blue><p style=color:green>foo</div><p style=color:brown>[]bar',
+		'<p style=color:blue>foo<div style=color:brown><p style=color:green>[]bar',
 
 		// Uncollapsed selection
 		'foo[bar]baz',
@@ -489,7 +489,7 @@
 		'<p><b>foo[bar</b><p>baz]quz',
 		'<div><p>foo[bar</div><p>baz]quz',
 		'<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote',
-		'<p>foo[bar<p style=color:red>baz]quz',
+		'<p>foo[bar<p style=color:blue>baz]quz',
 		'<p>foo[bar<p><b>baz]quz</b>',
 
 		'<div><p>foo<p>[bar<p>baz]</div>',
@@ -751,24 +751,24 @@
 		'{<p><p> <p>foo</p>}',
 		'foo[bar<i>baz]qoz</i>quz',
 
-		['red', 'foo[bar]baz'],
+		['blue', 'foo[bar]baz'],
 		['f', 'foo[bar]baz'],
 		['#f', 'foo[bar]baz'],
-		['f00', 'foo[bar]baz'],
-		['#f00', 'foo[bar]baz'],
-		['ff0000', 'foo[bar]baz'],
-		['#ff0000', 'foo[bar]baz'],
-		['fff000000', 'foo[bar]baz'],
-		['#fff000000', 'foo[bar]baz'],
-		['rgb(255, 0, 0)', 'foo[bar]baz'],
-		['rgb(100%, 0, 0)', 'foo[bar]baz'],
-		['rgb( 255 ,0 ,0)', 'foo[bar]baz'],
-		['rgba(255, 0, 0, 0.0)', 'foo[bar]baz'],
-		['rgb(375, -10, 15)', 'foo[bar]baz'],
+		['00f', 'foo[bar]baz'],
+		['#00f', 'foo[bar]baz'],
+		['0000ff', 'foo[bar]baz'],
+		['#0000ff', 'foo[bar]baz'],
+		['000000fff', 'foo[bar]baz'],
+		['#000000fff', 'foo[bar]baz'],
+		['rgb(0, 0, 255)', 'foo[bar]baz'],
+		['rgb(0%, 0%, 100%)', 'foo[bar]baz'],
+		['rgb( 0 ,0 ,255)', 'foo[bar]baz'],
+		['rgba(0, 0, 255, 0.0)', 'foo[bar]baz'],
+		['rgb(15, -10, 375)', 'foo[bar]baz'],
 		['rgba(0, 0, 0, 1)', 'foo[bar]baz'],
 		['rgba(255, 255, 255, 1)', 'foo[bar]baz'],
-		['rgba(255, 0, 0, 0.5)', 'foo[bar]baz'],
-		['hsl(0%, 100%, 50%)', 'foo[bar]baz'],
+		['rgba(0, 0, 255, 0.5)', 'foo[bar]baz'],
+		['hsl(240, 100%, 50%)', 'foo[bar]baz'],
 		['cornsilk', 'foo[bar]baz'],
 		['potato quiche', 'foo[bar]baz'],
 		['transparent', 'foo[bar]baz'],
@@ -781,47 +781,47 @@
 		'<table data-start=0 data-end=1><tbody><tr><td>foo<td>bar<td>baz</table>',
 		'{<table><tr><td>foo<td>bar<td>baz</table>}',
 
-		'foo<font color=red>[bar]</font>baz',
-		'foo{<font color=red>bar</font>}baz',
-		'<span style="color: red">foo<span style="color: blue">[bar]</span>baz</span>',
-		'<span style="color: #f00">foo<span style="color: blue">[bar]</span>baz</span>',
-		'<span style="color: #ff0000">foo<span style="color: blue">[bar]</span>baz</span>',
-		'<span style="color: rgb(255, 0, 0)">foo<span style="color: blue">[bar]</span>baz</span>',
-		'<font color=red>foo<font color=blue>[bar]</font>baz</font>',
-		'<span style="color: rgb(255, 0, 0)">foo<span style="color: blue">b[ar]</span>baz</span>',
+		'foo<font color=blue>[bar]</font>baz',
+		'foo{<font color=blue>bar</font>}baz',
+		'<span style="color: blue">foo<span style="color: brown">[bar]</span>baz</span>',
+		'<span style="color: #00f">foo<span style="color: brown">[bar]</span>baz</span>',
+		'<span style="color: #0000ff">foo<span style="color: brown">[bar]</span>baz</span>',
+		'<span style="color: rgb(0, 0, 255)">foo<span style="color: brown">[bar]</span>baz</span>',
+		'<font color=blue>foo<font color=brown>[bar]</font>baz</font>',
+		'<span style="color: rgb(0, 0, 255)">foo<span style="color: brown">b[ar]</span>baz</span>',
 		'foo<span id=purple>ba[r</span>ba]z',
-		'<span style="color: rgb(255, 0, 0)">foo<span id=purple>b[a]r</span>baz</span>',
+		'<span style="color: rgb(0, 0, 255)">foo<span id=purple>b[a]r</span>baz</span>',
 
 		// Tests for queryCommandValue()
-		'<font color="red">[foo]</font>',
-		'<font color="ff0000">[foo]</font>',
-		'<font color="#ff0000">[foo]</font>',
-		'<span style="color: red">[foo]</span>',
-		'<span style="color: #ff0000">[foo]</span>',
-		'<span style="color: rgb(255, 0, 0)">[foo]</span>',
-		'<span style="color: rgb(100%, 0, 0)">[foo]</span>',
-		'<span style="color: rgb( 255 ,0 ,0)">[foo]</span>',
-		'<span style="color: rgba(255, 0, 0, 0.0)">[foo]</span>',
-		'<span style="color: rgb(375, -10, 15)">[foo]</span>',
+		'<font color="blue">[foo]</font>',
+		'<font color="0000ff">[foo]</font>',
+		'<font color="#0000ff">[foo]</font>',
+		'<span style="color: blue">[foo]</span>',
+		'<span style="color: #0000ff">[foo]</span>',
+		'<span style="color: rgb(0, 0, 255)">[foo]</span>',
+		'<span style="color: rgb(0%, 0%, 100%)">[foo]</span>',
+		'<span style="color: rgb( 0 ,0 ,255)">[foo]</span>',
+		'<span style="color: rgba(0, 0, 255, 0.0)">[foo]</span>',
+		'<span style="color: rgb(15, -10, 375)">[foo]</span>',
 		'<span style="color: rgba(0, 0, 0, 1)">[foo]</span>',
 		'<span style="color: rgba(255, 255, 255, 1)">[foo]</span>',
-		'<span style="color: rgba(255, 0, 0, 0.5)">[foo]</span>',
-		'<span style="color: hsl(0%, 100%, 50%)">[foo]</span>',
+		'<span style="color: rgba(0, 0, 255, 0.5)">[foo]</span>',
+		'<span style="color: hsl(240, 100%, 50%)">[foo]</span>',
 		'<span style="color: cornsilk">[foo]</span>',
 		'<span style="color: transparent">[foo]</span>',
 		'<span style="color: currentColor">[foo]</span>',
 
 		// Tests for queryCommandIndeterm() and queryCommandState()
-		'fo[o<font color=blue>b]ar</font>baz',
-		'foo<font color=blue>ba[r</font>b]az',
-		'fo[o<font color=blue>bar</font>b]az',
-		'foo[<font color=blue>b]ar</font>baz',
-		'foo<font color=blue>ba[r</font>]baz',
-		'foo[<font color=blue>bar</font>]baz',
-		'foo<font color=blue>[bar]</font>baz',
-		'foo{<font color=blue>bar</font>}baz',
-		'<font color=blue>fo[o</font><span style=color:blue>b]ar</span>',
-		'<span style=color:blue>fo[o</span><span style=color:#0000ff>b]ar</span>',
+		'fo[o<font color=brown>b]ar</font>baz',
+		'foo<font color=brown>ba[r</font>b]az',
+		'fo[o<font color=brown>bar</font>b]az',
+		'foo[<font color=brown>b]ar</font>baz',
+		'foo<font color=brown>ba[r</font>]baz',
+		'foo[<font color=brown>bar</font>]baz',
+		'foo<font color=brown>[bar]</font>baz',
+		'foo{<font color=brown>bar</font>}baz',
+		'<font color=brown>fo[o</font><span style=color:brown>b]ar</span>',
+		'<span style=color:brown>fo[o</span><span style=color:#0000ff>b]ar</span>',
 	],
 	//@}
 	formatblock: [
@@ -1075,7 +1075,7 @@
 		'<h1>[foo</h1><h2>bar]</h2>',
 		'<div>[foo</div>bar]',
 
-		['<p>', '<div style=color:red>[foo]</div>'],
+		['<p>', '<div style=color:blue>[foo]</div>'],
 	],
 	//@}
 	forwarddelete: [
@@ -1192,11 +1192,11 @@
 		'foo[]<blockquote>bar</blockquote>',
 		'foo[]<blockquote><blockquote>bar</blockquote></blockquote>',
 		'foo[]<blockquote><div>bar</div></blockquote>',
-		'foo[]<blockquote style="color: red">bar</blockquote>',
+		'foo[]<blockquote style="color: blue">bar</blockquote>',
 
 		'foo[]<blockquote><blockquote><p>bar<p>baz</blockquote></blockquote>',
 		'foo[]<blockquote><div><p>bar<p>baz</div></blockquote>',
-		'foo[]<blockquote style="color: red"><p>bar<p>baz</blockquote>',
+		'foo[]<blockquote style="color: blue"><p>bar<p>baz</blockquote>',
 
 		'foo[]<blockquote><p><b>bar</b><p>baz</blockquote>',
 		'foo[]<blockquote><p><strong>bar</strong><p>baz</blockquote>',
@@ -1233,22 +1233,22 @@
 		'<div><div><p>foo[]</p></div></div><div><div><div><!--abc-->bar</div></div></div>',
 
 		// Styled stuff with collapsed selection
-		'<p style=color:red>foo[]<p>bar',
-		'<p style=color:red>foo[]<p style=color:blue>bar',
-		'<p>foo[]<p style=color:blue>bar',
-		'<p><font color=red>foo[]</font><p>bar',
-		'<p><font color=red>foo[]</font><p><font color=blue>bar</font>',
-		'<p>foo[]<p><font color=blue>bar</font>',
-		'<p><span style=color:red>foo[]</font><p>bar',
-		'<p><span style=color:red>foo[]</font><p><span style=color:blue>bar</font>',
-		'<p>foo[]<p><span style=color:blue>bar</font>',
-
-		'<p style=background-color:salmon>foo[]<p>bar',
-		'<p style=background-color:salmon>foo[]<p style=background-color:aqua>bar',
-		'<p>foo[]<p style=background-color:aqua>bar',
-		'<p><span style=background-color:salmon>foo[]</font><p>bar',
-		'<p><span style=background-color:salmon>foo[]</font><p><span style=background-color:aqua>bar</font>',
-		'<p>foo[]<p><span style=background-color:aqua>bar</font>',
+		'<p style=color:blue>foo[]<p>bar',
+		'<p style=color:blue>foo[]<p style=color:brown>bar',
+		'<p>foo[]<p style=color:brown>bar',
+		'<p><font color=blue>foo[]</font><p>bar',
+		'<p><font color=blue>foo[]</font><p><font color=brown>bar</font>',
+		'<p>foo[]<p><font color=brown>bar</font>',
+		'<p><span style=color:blue>foo[]</font><p>bar',
+		'<p><span style=color:blue>foo[]</font><p><span style=color:brown>bar</font>',
+		'<p>foo[]<p><span style=color:brown>bar</font>',
+
+		'<p style=background-color:aqua>foo[]<p>bar',
+		'<p style=background-color:aqua>foo[]<p style=background-color:tan>bar',
+		'<p>foo[]<p style=background-color:tan>bar',
+		'<p><span style=background-color:aqua>foo[]</font><p>bar',
+		'<p><span style=background-color:aqua>foo[]</font><p><span style=background-color:tan>bar</font>',
+		'<p>foo[]<p><span style=background-color:tan>bar</font>',
 
 		'<p style=text-decoration:underline>foo[]<p>bar',
 		'<p style=text-decoration:underline>foo[]<p style=text-decoration:line-through>bar',
@@ -1257,11 +1257,11 @@
 		'<p><u>foo[]</u><p><s>bar</s>',
 		'<p>foo[]<p><s>bar</s>',
 
-		'<p style=color:red>foo[]</p>bar',
-		'foo[]<p style=color:blue>bar',
-		'<div style=color:red><p style=color:green>foo[]</div>bar',
-		'<div style=color:red><p style=color:green>foo[]</div><p style=color:blue>bar',
-		'<p style=color:red>foo[]<div style=color:blue><p style=color:green>bar',
+		'<p style=color:blue>foo[]</p>bar',
+		'foo[]<p style=color:brown>bar',
+		'<div style=color:blue><p style=color:green>foo[]</div>bar',
+		'<div style=color:blue><p style=color:green>foo[]</div><p style=color:brown>bar',
+		'<p style=color:blue>foo[]<div style=color:brown><p style=color:green>bar',
 
 		// Uncollapsed selection (should be same as delete command)
 		'foo[bar]baz',
@@ -1288,7 +1288,7 @@
 		'<p><b>foo[bar</b><p>baz]quz',
 		'<div><p>foo[bar</div><p>baz]quz',
 		'<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote',
-		'<p>foo[bar<p style=color:red>baz]quz',
+		'<p>foo[bar<p style=color:blue>baz]quz',
 		'<p>foo[bar<p><b>baz]quz</b>',
 
 		'<div><p>foo<p>[bar<p>baz]</div>',
@@ -1369,30 +1369,31 @@
 		'<table data-start=0 data-end=1><tbody><tr><td>foo<td>bar<td>baz</table>',
 		'{<table><tr><td>foo<td>bar<td>baz</table>}',
 
-		'<p style="background-color: rgb(255, 136, 136)">foo[bar]baz</p>',
-		'<p style="background-color: #ff8888">foo[bar]baz</p>',
+		'<p style="background-color: rgb(0, 255, 255)">foo[bar]baz</p>',
+		'<p style="background-color: #00ffff">foo[bar]baz</p>',
 		'<p style="background-color: aqua">foo[bar]baz</p>',
 		'{<p style="background-color: aqua">foo</p><p>bar</p>}',
-		'<span style="background-color: #ff8888">foo<span style="background-color: aqua">[bar]</span>baz</span>',
-		'<span style="background-color: #f88">foo<span style="background-color: aqua">[bar]</span>baz</span>',
-		'<span style="background-color: rgb(255, 136, 136)">foo<span style="background-color: aqua">[bar]</span>baz</span>',
-		'<span style="background-color: #ff8888">foo<span style="background-color: aqua">b[ar]</span>baz</span>',
-		'<p style="background-color: #ff8888">foo<span style="background-color: aqua">b[ar]</span>baz</p>',
-		'<div style="background-color: #ff8888"><p style="background-color: aqua">b[ar]</p></div>',
-		'<span style="display: block; background-color: #ff8888"><span style="display: block; background-color: aqua">b[ar]</span></span>',
+		'<span style="background-color: aqua">foo<span style="background-color: tan">[bar]</span>baz</span>',
+		'<span style="background-color: #00ffff">foo<span style="background-color: tan">[bar]</span>baz</span>',
+		'<span style="background-color: #0ff">foo<span style="background-color: tan">[bar]</span>baz</span>',
+		'<span style="background-color: rgb(0, 255, 255)">foo<span style="background-color: tan">[bar]</span>baz</span>',
+		'<span style="background-color: aqua">foo<span style="background-color: tan">b[ar]</span>baz</span>',
+		'<p style="background-color: aqua">foo<span style="background-color: tan">b[ar]</span>baz</p>',
+		'<div style="background-color: aqua"><p style="background-color: tan">b[ar]</p></div>',
+		'<span style="display: block; background-color: aqua"><span style="display: block; background-color: tan">b[ar]</span></span>',
 
 		// Tests for queryCommandIndeterm() and queryCommandState()
-		'fo[o<span style=background-color:aqua>b]ar</span>baz',
-		'foo<span style=background-color:aqua>ba[r</span>b]az',
-		'fo[o<span style=background-color:aqua>bar</span>b]az',
-		'foo[<span style=background-color:aqua>b]ar</span>baz',
-		'foo<span style=background-color:aqua>ba[r</span>]baz',
-		'foo[<span style=background-color:aqua>bar</span>]baz',
-		'foo<span style=background-color:aqua>[bar]</span>baz',
-		'foo{<span style=background-color:aqua>bar</span>}baz',
-		'<span style=background-color:aqua>fo[o</span><span style=background-color:lime>b]ar</span>',
-		'<span style=background-color:aqua>fo[o</span><span style=background-color:aqua>b]ar</span>',
-		'<span style=background-color:aqua>fo[o<span style=background-color:transparent>b]ar</span></span>',
+		'fo[o<span style=background-color:tan>b]ar</span>baz',
+		'foo<span style=background-color:tan>ba[r</span>b]az',
+		'fo[o<span style=background-color:tan>bar</span>b]az',
+		'foo[<span style=background-color:tan>b]ar</span>baz',
+		'foo<span style=background-color:tan>ba[r</span>]baz',
+		'foo[<span style=background-color:tan>bar</span>]baz',
+		'foo<span style=background-color:tan>[bar]</span>baz',
+		'foo{<span style=background-color:tan>bar</span>}baz',
+		'<span style=background-color:tan>fo[o</span><span style=background-color:yellow>b]ar</span>',
+		'<span style=background-color:tan>fo[o</span><span style=background-color:tan>b]ar</span>',
+		'<span style=background-color:tan>fo[o<span style=background-color:transparent>b]ar</span></span>',
 	],
 	//@}
 	indent: [
@@ -1710,8 +1711,8 @@
 		['<nobr>abc</nobr>', '<nobr>f[o]o</nobr>'],
 		['<nobr>abc</nobr>', 'f[o]o'],
 
-		['<p>abc', '<font color=red>foo[]bar</font>'],
-		['<p>abc', '<span style=color:red>foo[]bar</span>'],
+		['<p>abc', '<font color=blue>foo[]bar</font>'],
+		['<p>abc', '<span style=color:blue>foo[]bar</span>'],
 		['<p>abc', '<span style=font-variant:small-caps>foo[]bar</span>'],
 		[' ', '<p>[foo]</p>'],
 		['<span style=display:none></span>', '<p>[foo]</p>'],
@@ -1746,7 +1747,7 @@
 		'<p><b>foo[bar</b><p>baz]quz',
 		'<div><p>foo[bar</div><p>baz]quz',
 		'<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote',
-		'<p>foo[bar<p style=color:red>baz]quz',
+		'<p>foo[bar<p style=color:blue>baz]quz',
 		'<p>foo[bar<p><b>baz]quz</b>',
 
 		'<div><p>foo<p>[bar<p>baz]</div>',
@@ -1951,13 +1952,13 @@
 
 		// Attributes
 		'<ul id=abc><li>foo<li>[bar]<li>baz</ul>',
-		'<ul style=color:red><li>foo<li>[bar]<li>baz</ul>',
+		'<ul style=color:blue><li>foo<li>[bar]<li>baz</ul>',
 		'<ul style=text-indent:1em><li>foo<li>[bar]<li>baz</ul>',
 		'<ul id=abc><li>[foo]<li>bar<li>baz</ul>',
-		'<ul style=color:red><li>[foo]<li>bar<li>baz</ul>',
+		'<ul style=color:blue><li>[foo]<li>bar<li>baz</ul>',
 		'<ul style=text-indent:1em><li>[foo]<li>bar<li>baz</ul>',
 		'<ul id=abc><li>foo<li>bar<li>[baz]</ul>',
-		'<ul style=color:red><li>foo<li>bar<li>[baz]</ul>',
+		'<ul style=color:blue><li>foo<li>bar<li>[baz]</ul>',
 		'<ul style=text-indent:1em><li>foo<li>bar<li>[baz]</ul>',
 	],
 	//@}
@@ -2346,13 +2347,13 @@
 
 		// Attributes
 		'<ul id=abc><li>foo<li>[bar]<li>baz</ul>',
-		'<ul style=color:red><li>foo<li>[bar]<li>baz</ul>',
+		'<ul style=color:blue><li>foo<li>[bar]<li>baz</ul>',
 		'<ul style=text-indent:1em><li>foo<li>[bar]<li>baz</ul>',
 		'<ul id=abc><li>[foo]<li>bar<li>baz</ul>',
-		'<ul style=color:red><li>[foo]<li>bar<li>baz</ul>',
+		'<ul style=color:blue><li>[foo]<li>bar<li>baz</ul>',
 		'<ul style=text-indent:1em><li>[foo]<li>bar<li>baz</ul>',
 		'<ul id=abc><li>foo<li>bar<li>[baz]</ul>',
-		'<ul style=color:red><li>foo<li>bar<li>[baz]</ul>',
+		'<ul style=color:blue><li>foo<li>bar<li>[baz]</ul>',
 		'<ul style=text-indent:1em><li>foo<li>bar<li>[baz]</ul>',
 	],
 	//@}
@@ -2884,7 +2885,7 @@
 		'<blockquote><div>foo[bar]baz</div></blockquote>',
 		'<blockquote><div id=abc>foo[bar]baz</div></blockquote>',
 		'<blockquote id=abc>foo[bar]baz</blockquote>',
-		'<blockquote style="color: red">foo[bar]baz</blockquote>',
+		'<blockquote style="color: blue">foo[bar]baz</blockquote>',
 
 		'<blockquote><blockquote><p>foo[bar]<p>baz</blockquote></blockquote>',
 		'<blockquote><blockquote data-abc=def><p>foo[bar]<p>baz</blockquote></blockquote>',
@@ -2892,13 +2893,13 @@
 		'<blockquote><div><p>foo[bar]<p>baz</div></blockquote>',
 		'<blockquote><div id=abc><p>foo[bar]<p>baz</div></blockquote>',
 		'<blockquote id=abc><p>foo[bar]<p>baz</blockquote>',
-		'<blockquote style="color: red"><p>foo[bar]<p>baz</blockquote>',
+		'<blockquote style="color: blue"><p>foo[bar]<p>baz</blockquote>',
 
 		'<blockquote><p><b>foo[bar]</b><p>baz</blockquote>',
 		'<blockquote><p><strong>foo[bar]</strong><p>baz</blockquote>',
 		'<blockquote><p><span>foo[bar]</span><p>baz</blockquote>',
-		'<blockquote><blockquote style="color: red"><p>foo[bar]</blockquote><p>baz</blockquote>',
-		'<blockquote style="color: red"><blockquote><p>foo[bar]</blockquote><p>baz</blockquote>',
+		'<blockquote><blockquote style="color: blue"><p>foo[bar]</blockquote><p>baz</blockquote>',
+		'<blockquote style="color: blue"><blockquote><p>foo[bar]</blockquote><p>baz</blockquote>',
 
 		// Lists!
 		'<ol><li>foo<li>[bar]<li>baz</ol>',
@@ -2942,19 +2943,19 @@
 		// Attribute handling on lists
 		'foo<ol start=5><li>[bar]</ol>baz',
 		'foo<ol id=abc><li>[bar]</ol>baz',
-		'foo<ol style=color:red><li>[bar]</ol>baz',
+		'foo<ol style=color:blue><li>[bar]</ol>baz',
 		'foo<ol><li value=5>[bar]</ol>baz',
 		'foo<ol><li id=abc>[bar]</ol>baz',
-		'foo<ol><li style=color:red>[bar]</ol>baz',
+		'foo<ol><li style=color:blue>[bar]</ol>baz',
 		'<ol><li>foo</li><ol><li value=5>[bar]</ol></ol>',
 		'<ul><li>foo</li><ol><li value=5>[bar]</ol></ul>',
 		'<ol><li>foo</li><ol start=5><li>[bar]</ol><li>baz</ol>',
 		'<ol><li>foo</li><ol id=abc><li>[bar]</ol><li>baz</ol>',
-		'<ol><li>foo</li><ol style=color:red><li>[bar]</ol><li>baz</ol>',
+		'<ol><li>foo</li><ol style=color:blue><li>[bar]</ol><li>baz</ol>',
 		'<ol><li>foo</li><ol style=text-indent:1em><li>[bar]</ol><li>baz</ol>',
 		'<ol><li>foo</li><ol start=5><li>[bar<li>baz]</ol><li>quz</ol>',
 		'<ol><li>foo</li><ol id=abc><li>[bar<li>baz]</ol><li>quz</ol>',
-		'<ol><li>foo</li><ol style=color:red><li>[bar<li>baz]</ol><li>quz</ol>',
+		'<ol><li>foo</li><ol style=color:blue><li>[bar<li>baz]</ol><li>quz</ol>',
 		'<ol><li>foo</li><ol style=text-indent:1em><li>[bar<li>baz]</ol><li>quz</ol>',
 
 		// List inside indentation element
@@ -3014,8 +3015,8 @@
 		'foo<em>b[a]r</em>baz',
 		'[foo<font>bar</font>baz]',
 		'foo<font>b[a]r</font>baz',
-		'[foo<font color=red>bar</font>baz]',
-		'foo<font color=red>b[a]r</font>baz',
+		'[foo<font color=blue>bar</font>baz]',
+		'foo<font color=blue>b[a]r</font>baz',
 		'[foo<i>bar</i>baz]',
 		'foo<i>b[a]r</i>baz',
 		'[foo<ins>bar</ins>baz]',
@@ -3059,7 +3060,7 @@
 		'[foo<img src=abc>bar]',
 		'[foo<video></video>bar]',
 		'[foo<video src=abc></video>bar]',
-		'[foo<svg><circle fill=red r=20 cx=20 cy=20 /></svg>bar]',
+		'[foo<svg><circle fill=blue r=20 cx=20 cy=20 /></svg>bar]',
 
 		// Unrecognized elements
 		'[foo<nonexistentelement>bar</nonexistentelement>baz]',
@@ -3074,8 +3075,8 @@
 		'foo<span class=foo>b[a]r</span>baz',
 		'[foo<b style="font-weight: normal">bar</b>baz]',
 		'foo<b style="font-weight: normal">b[a]r</b>baz',
-		'<p style="background-color: red">foo[bar]baz</p>',
-		'<p><span style="background-color: red">foo[bar]baz</span></p>',
+		'<p style="background-color: blue">foo[bar]baz</p>',
+		'<p><span style="background-color: blue">foo[bar]baz</span></p>',
 		'<p style="font-weight: bold">foo[bar]baz</p>',
 		'<b><p style="font-weight: bold">foo[bar]baz</p></b>',
 		'<p style="font-variant: small-caps">foo[bar]baz</p>',
@@ -3104,8 +3105,8 @@
 		'foo<u>[bar]</u>baz',
 		'foo<span style="text-decoration: underline">[bar]</span>baz',
 		'<u>foo[bar]baz</u>',
-		'<u>foo[b<span style="color:red">ar]ba</span>z</u>',
-		'<u>foo[b<span style="color:red" id=foo>ar]ba</span>z</u>',
+		'<u>foo[b<span style="color:blue">ar]ba</span>z</u>',
+		'<u>foo[b<span style="color:blue" id=foo>ar]ba</span>z</u>',
 		'<u>foo[b<span style="font-size:3em">ar]ba</span>z</u>',
 		'<u>foo[b<i>ar]ba</i>z</u>',
 		'<p style="text-decoration: underline">foo[bar]baz</p>',
@@ -3113,30 +3114,30 @@
 		'foo<s>[bar]</s>baz',
 		'foo<span style="text-decoration: line-through">[bar]</span>baz',
 		'<s>foo[bar]baz</s>',
-		'<s>foo[b<span style="color:red">ar]ba</span>z</s>',
-		'<s>foo[b<span style="color:red" id=foo>ar]ba</span>z</s>',
+		'<s>foo[b<span style="color:blue">ar]ba</span>z</s>',
+		'<s>foo[b<span style="color:blue" id=foo>ar]ba</span>z</s>',
 		'<s>foo[b<span style="font-size:3em">ar]ba</span>z</s>',
 		'<s>foo[b<i>ar]ba</i>z</s>',
 		'<p style="text-decoration: line-through">foo[bar]baz</p>',
 
 		'foo<strike>[bar]</strike>baz',
 		'<strike>foo[bar]baz</strike>',
-		'<strike>foo[b<span style="color:red">ar]ba</span>z</strike>',
-		'<strike>foo[b<span style="color:red" id=foo>ar]ba</span>z</strike>',
+		'<strike>foo[b<span style="color:blue">ar]ba</span>z</strike>',
+		'<strike>foo[b<span style="color:blue" id=foo>ar]ba</span>z</strike>',
 		'<strike>foo[b<span style="font-size:3em">ar]ba</span>z</strike>',
 		'<strike>foo[b<i>ar]ba</i>z</strike>',
 
 		'foo<ins>[bar]</ins>baz',
 		'<ins>foo[bar]baz</ins>',
-		'<ins>foo[b<span style="color:red">ar]ba</span>z</ins>',
-		'<ins>foo[b<span style="color:red" id=foo>ar]ba</span>z</ins>',
+		'<ins>foo[b<span style="color:blue">ar]ba</span>z</ins>',
+		'<ins>foo[b<span style="color:blue" id=foo>ar]ba</span>z</ins>',
 		'<ins>foo[b<span style="font-size:3em">ar]ba</span>z</ins>',
 		'<ins>foo[b<i>ar]ba</i>z</ins>',
 
 		'foo<del>[bar]</del>baz',
 		'<del>foo[bar]baz</del>',
-		'<del>foo[b<span style="color:red">ar]ba</span>z</del>',
-		'<del>foo[b<span style="color:red" id=foo>ar]ba</span>z</del>',
+		'<del>foo[b<span style="color:blue">ar]ba</span>z</del>',
+		'<del>foo[b<span style="color:blue" id=foo>ar]ba</span>z</del>',
 		'<del>foo[b<span style="font-size:3em">ar]ba</span>z</del>',
 		'<del>foo[b<i>ar]ba</i>z</del>',
 
@@ -3297,8 +3298,8 @@
 		'foo<u>[bar]</u>baz',
 		'foo<span style="text-decoration: underline">[bar]</span>baz',
 		'<u>foo[bar]baz</u>',
-		'<u>foo[b<span style="color:red">ar]ba</span>z</u>',
-		'<u>foo[b<span style="color:red" id=foo>ar]ba</span>z</u>',
+		'<u>foo[b<span style="color:blue">ar]ba</span>z</u>',
+		'<u>foo[b<span style="color:blue" id=foo>ar]ba</span>z</u>',
 		'<u>foo[b<span style="font-size:3em">ar]ba</span>z</u>',
 		'<u>foo[b<i>ar]ba</i>z</u>',
 		'<p style="text-decoration: underline">foo[bar]baz</p>',
@@ -3306,30 +3307,30 @@
 		'foo<s>[bar]</s>baz',
 		'foo<span style="text-decoration: line-through">[bar]</span>baz',
 		'<s>foo[bar]baz</s>',
-		'<s>foo[b<span style="color:red">ar]ba</span>z</s>',
-		'<s>foo[b<span style="color:red" id=foo>ar]ba</span>z</s>',
+		'<s>foo[b<span style="color:blue">ar]ba</span>z</s>',
+		'<s>foo[b<span style="color:blue" id=foo>ar]ba</span>z</s>',
 		'<s>foo[b<span style="font-size:3em">ar]ba</span>z</s>',
 		'<s>foo[b<i>ar]ba</i>z</s>',
 		'<p style="text-decoration: line-through">foo[bar]baz</p>',
 
 		'foo<strike>[bar]</strike>baz',
 		'<strike>foo[bar]baz</strike>',
-		'<strike>foo[b<span style="color:red">ar]ba</span>z</strike>',
-		'<strike>foo[b<span style="color:red" id=foo>ar]ba</span>z</strike>',
+		'<strike>foo[b<span style="color:blue">ar]ba</span>z</strike>',
+		'<strike>foo[b<span style="color:blue" id=foo>ar]ba</span>z</strike>',
 		'<strike>foo[b<span style="font-size:3em">ar]ba</span>z</strike>',
 		'<strike>foo[b<i>ar]ba</i>z</strike>',
 
 		'foo<ins>[bar]</ins>baz',
 		'<ins>foo[bar]baz</ins>',
-		'<ins>foo[b<span style="color:red">ar]ba</span>z</ins>',
-		'<ins>foo[b<span style="color:red" id=foo>ar]ba</span>z</ins>',
+		'<ins>foo[b<span style="color:blue">ar]ba</span>z</ins>',
+		'<ins>foo[b<span style="color:blue" id=foo>ar]ba</span>z</ins>',
 		'<ins>foo[b<span style="font-size:3em">ar]ba</span>z</ins>',
 		'<ins>foo[b<i>ar]ba</i>z</ins>',
 
 		'foo<del>[bar]</del>baz',
 		'<del>foo[bar]baz</del>',
-		'<del>foo[b<span style="color:red">ar]ba</span>z</del>',
-		'<del>foo[b<span style="color:red" id=foo>ar]ba</span>z</del>',
+		'<del>foo[b<span style="color:blue">ar]ba</span>z</del>',
+		'<del>foo[b<span style="color:blue" id=foo>ar]ba</span>z</del>',
 		'<del>foo[b<span style="font-size:3em">ar]ba</span>z</del>',
 		'<del>foo[b<i>ar]ba</i>z</del>',
 
@@ -3414,13 +3415,13 @@
 
 var defaultValues = {
 //@{
-	backcolor: "#FF8888",
+	backcolor: "#00FFFF",
 	createlink: "http://www.google.com/",
 	fontname: "sans-serif",
 	fontsize: "4",
-	forecolor: "#FF0000",
+	forecolor: "#0000FF",
 	formatblock: "<div>",
-	hilitecolor: "#FF8888",
+	hilitecolor: "#00FFFF",
 	inserthorizontalrule: "",
 	inserthtml: "ab<b>c</b>d",
 	insertimage: "/img/lion.svg",
@@ -3430,9 +3431,7 @@
 
 var notes = {
 //@{
-	backcolor: '<strong>Note:</strong> No spec has yet been written, so the spec column does nothing.',
 	fontname: 'Note that the body\'s font-family is "serif".',
-	hilitecolor: 'In IE we run backColor instead of hiliteColor.',
 };
 //@}
 
@@ -3512,6 +3511,69 @@
 }
 //@}
 
+function queryOutputHelper(beforeIndeterm, beforeState, beforeValue, afterIndeterm, afterState, afterValue, command, value) {
+//@{
+	var frag = document.createDocumentFragment();
+	var beforeDiv = document.createElement("div");
+	var afterDiv = document.createElement("div");
+	frag.appendChild(beforeDiv);
+	frag.appendChild(afterDiv);
+	beforeDiv.className = afterDiv.className = "extra-results";
+	beforeDiv.textContent = "Before: ";
+	afterDiv.textContent = "After: ";
+
+	beforeDiv.appendChild(document.createElement("span"));
+	afterDiv.appendChild(document.createElement("span"));
+	if (afterIndeterm !== "Exception") {
+		afterDiv.lastChild.className =
+			!afterIndeterm
+				? "good-result"
+				: "bad-result";
+	}
+	beforeDiv.lastChild.textContent = "indeterm " + beforeIndeterm;
+	afterDiv.lastChild.textContent = "indeterm " + afterIndeterm;
+
+	beforeDiv.appendChild(document.createTextNode(", "));
+	afterDiv.appendChild(document.createTextNode(", "));
+
+	beforeDiv.appendChild(document.createElement("span"));
+	afterDiv.appendChild(document.createElement("span"));
+	if (beforeState !== "Exception" || afterState !== "Exception") {
+		beforeDiv.lastChild.className =
+		afterDiv.lastChild.className =
+			beforeState !== "Exception" && afterState !== "Exception" && beforeState === !afterState
+				? "good-result"
+				: "bad-result";
+	}
+	beforeDiv.lastChild.textContent = "state " + beforeState;
+	afterDiv.lastChild.textContent = "state " + afterState;
+
+	beforeDiv.appendChild(document.createTextNode(", "));
+	afterDiv.appendChild(document.createTextNode(", "));
+
+	// Hack to get highlighting working right for colors
+	if (command == "backcolor" || command == "forecolor" || command == "hilitecolor") {
+		if (/^([0-9a-fA-F]{3}){1,2}$/.test(value)) {
+			value = "#" + value;
+		}
+	}
+
+	beforeDiv.appendChild(document.createElement("span"));
+	afterDiv.appendChild(document.createElement("span"));
+	if (afterValue !== "Exception"
+	&& typeof value != "undefined") {
+		afterDiv.lastChild.className =
+			valuesEqual(command, afterValue, value)
+				? "good-result"
+				: "bad-result";
+	}
+	beforeDiv.lastChild.textContent = "value " + beforeValue;
+	afterDiv.lastChild.textContent = "value " + afterValue;
+
+	return frag;
+}
+//@}
+
 function doInputCell(tr, test) {
 //@{
 	var value = null;
@@ -3553,8 +3615,24 @@
 		}
 		specCell.firstChild.contentEditable = "true";
 		specCell.firstChild.spellcheck = false;
-		myExecCommand("styleWithCSS", false, styleWithCss);
+		myExecCommand("styleWithCSS", false, styleWithCss, range);
+
+		try { var beforeIndeterm = myQueryCommandIndeterm(command, range) }
+		catch(e) { beforeIndeterm = "Exception" }
+		try { var beforeState = myQueryCommandState(command, range) }
+		catch(e) { beforeState = "Exception" }
+		try { var beforeValue = myQueryCommandValue(command, range) }
+		catch(e) { beforeValue = "Exception" }
+
 		myExecCommand(command, false, value, range);
+
+		try { var afterIndeterm = myQueryCommandIndeterm(command, range) }
+		catch(e) { afterIndeterm = "Exception" }
+		try { var afterState = myQueryCommandState(command, range) }
+		catch(e) { afterState = "Exception" }
+		try { var afterValue = myQueryCommandValue(command, range) }
+		catch(e) { afterValue = "Exception" }
+
 		specCell.firstChild.contentEditable = "inherit";
 		specCell.firstChild.removeAttribute("spellcheck");
 		var compareDiv1 = specCell.firstChild.cloneNode(true);
@@ -3586,6 +3664,10 @@
 		}
 
 		specCell.lastChild.textContent = specCell.firstChild.innerHTML;
+		specCell.lastChild.appendChild(queryOutputHelper(
+			beforeIndeterm, beforeState, beforeValue,
+			afterIndeterm, afterState, afterValue,
+			command, value));
 	} catch (e) {
 		specCell.firstChild.contentEditable = "inherit";
 		specCell.firstChild.removeAttribute("spellcheck");