Bug 1213589 part.6 ContentEventHandler should insert line breaks at open tag of elements except non-replaced inline elements r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 02 Dec 2015 13:20:00 +0900
changeset 275165 23e3c6bf330f3e77834c2c08f40642a9731885ad
parent 275164 afae79e8f7d2cbd4a0cdd18d8309053d4d8c8173
child 275166 be5d2f1ae122666135bbb4550bdc53f50643040d
push id29747
push usercbook@mozilla.com
push dateWed, 02 Dec 2015 14:21:19 +0000
treeherdermozilla-central@f6ac392322b3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1213589
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1213589 part.6 ContentEventHandler should insert line breaks at open tag of elements except non-replaced inline elements r=smaug
dom/events/ContentEventHandler.cpp
dom/events/ContentEventHandler.h
dom/events/IMEContentObserver.cpp
dom/events/IMEContentObserver.h
editor/libeditor/tests/test_contenteditable_text_input_handling.html
widget/tests/window_composition_text_querycontent.xul
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -42,19 +42,20 @@ using namespace widget;
 
 // NOTE
 //
 // ContentEventHandler *creates* ranges as following rules:
 // 1. Start of range:
 //   1.1. Cases: [textNode or text[Node or textNode[
 //        When text node is start of a range, start node is the text node and
 //        start offset is any number between 0 and the length of the text.
-//   1.2. Case: [<element>
-//        When before an element node is start of a range, start node is parent
-//        of the element and start offset is the element's index in the parent.
+//   1.2. Case: [<element>:
+//        When start of an element node is start of a range, start node is
+//        parent of the element and start offset is the element's index in the
+//        parent.
 //   1.3. Case: <element/>[
 //        When after an empty element node is start of a range, start node is
 //        parent of the element and start offset is the element's index in the
 //        parent + 1.
 //   1.4. Case: <element>[
 //        When start of a non-empty element is start of a range, start node is
 //        the element and start offset is 0.
 //   1.5. Case: [</root>
@@ -66,21 +67,26 @@ using namespace widget;
 //        end offset is any number between 0 and the length of the text.
 //   2.2. Case: ]<element>
 //        When before an element node (meaning before the open tag of the
 //        element) is end of a range, end node is previous node causing text.
 //        Note that this case shouldn't be handled directly.  If rule 2.1 and
 //        2.3 are handled correctly, the loop with nsContentIterator shouldn't
 //        reach the element node since the loop should've finished already at
 //        handling the last node which caused some text.
-//   2.3. Case: </element>]
-//        When after an element node is end of a range, end node is parent of
-//        the element node and end offset is the element's index in the parent
-//        + 1.
-//   2.4. Case: ]</root>
+//   2.3. Case: <element>]
+//        When a line break is caused before a non-empty element node and it's
+//        end of a range, end node is the element and end offset is 0.
+//        (i.e., including open tag of the element)
+//   2.4. Cases: <element/>]
+//        When after an empty element node is end of a range, end node is
+//        parent of the element node and end offset is the element's index in
+//        the parent + 1.  (i.e., including close tag of the element or empty
+//        element)
+//   2.5. Case: ]</root>
 //        When end of a range is out of bounds, end node is the root node and
 //        end offset is number of the children.
 //
 // ContentEventHandler *treats* ranges as following additional rules:
 // 1. When the start node is an element node which doesn't have children,
 //    it includes a line break caused before itself (i.e., includes its open
 //    tag).  For example, if start position is { <br>, 0 }, the line break
 //    caused by <br> should be included into the flatten text.
@@ -393,22 +399,24 @@ ContentEventHandler::GetNativeTextLength
 {
   if (NS_WARN_IF(!aContent->IsNodeOfType(nsINode::eTEXT))) {
     return 0;
   }
   return GetTextLength(aContent, LINE_BREAK_TYPE_NATIVE, aMaxLength);
 }
 
 /* static */ uint32_t
-ContentEventHandler::GetNativeTextLengthBefore(nsIContent* aContent)
+ContentEventHandler::GetNativeTextLengthBefore(nsIContent* aContent,
+                                               nsINode* aRootNode)
 {
   if (NS_WARN_IF(aContent->IsNodeOfType(nsINode::eTEXT))) {
     return 0;
   }
-  return IsContentBR(aContent) ? GetBRLength(LINE_BREAK_TYPE_NATIVE) : 0;
+  return ShouldBreakLineBefore(aContent, aRootNode) ?
+           GetBRLength(LINE_BREAK_TYPE_NATIVE) : 0;
 }
 
 /* static inline */ uint32_t
 ContentEventHandler::GetBRLength(LineBreakType aLineBreakType)
 {
 #if defined(XP_WIN)
   // Length of \r\n
   return (aLineBreakType == LINE_BREAK_TYPE_NATIVE) ? 2 : 1;
@@ -452,16 +460,77 @@ static uint32_t ConvertToXPOffset(nsICon
   // offset minus the number of newlines encountered in the string.
   return aNativeOffset - CountNewlinesInNativeLength(aContent, aNativeOffset);
 #else
   // On other platforms, the native and XP newlines are the same.
   return aNativeOffset;
 #endif
 }
 
+/* static */ bool
+ContentEventHandler::ShouldBreakLineBefore(nsIContent* aContent,
+                                           nsINode* aRootNode)
+{
+  // We don't need to append linebreak at the start of the root element.
+  if (aContent == aRootNode) {
+    return false;
+  }
+
+  // If it's not an HTML element (including other markup language's elements),
+  // we shouldn't insert like break before that for now.  Becoming this is a
+  // problem must be edge case.  E.g., when ContentEventHandler is used with
+  // MathML or SVG elements.
+  if (!aContent->IsHTMLElement()) {
+    return false;
+  }
+
+  // If the element is <br>, we need to check if the <br> is caused by web
+  // content.  Otherwise, i.e., it's caused by internal reason of Gecko,
+  // it shouldn't be exposed as a line break to flatten text.
+  if (aContent->IsHTMLElement(nsGkAtoms::br)) {
+    return IsContentBR(aContent);
+  }
+
+  // Note that ideally, we should refer the style of the primary frame of
+  // aContent for deciding if it's an inline.  However, it's difficult
+  // IMEContentObserver to notify IME of text change caused by style change.
+  // Therefore, currently, we should check only from the tag for now.
+  // TODO: Check if the element is an unknown HTML element.
+  return !aContent->IsAnyOfHTMLElements(nsGkAtoms::a,
+                                        nsGkAtoms::abbr,
+                                        nsGkAtoms::acronym,
+                                        nsGkAtoms::b,
+                                        nsGkAtoms::bdi,
+                                        nsGkAtoms::bdo,
+                                        nsGkAtoms::big,
+                                        nsGkAtoms::cite,
+                                        nsGkAtoms::code,
+                                        nsGkAtoms::data,
+                                        nsGkAtoms::del,
+                                        nsGkAtoms::dfn,
+                                        nsGkAtoms::em,
+                                        nsGkAtoms::font,
+                                        nsGkAtoms::i,
+                                        nsGkAtoms::ins,
+                                        nsGkAtoms::kbd,
+                                        nsGkAtoms::mark,
+                                        nsGkAtoms::s,
+                                        nsGkAtoms::samp,
+                                        nsGkAtoms::small,
+                                        nsGkAtoms::span,
+                                        nsGkAtoms::strike,
+                                        nsGkAtoms::strong,
+                                        nsGkAtoms::sub,
+                                        nsGkAtoms::sup,
+                                        nsGkAtoms::time,
+                                        nsGkAtoms::tt,
+                                        nsGkAtoms::u,
+                                        nsGkAtoms::var);
+}
+
 nsresult
 ContentEventHandler::GenerateFlatTextContent(nsRange* aRange,
                                              nsAFlatString& aString,
                                              LineBreakType aLineBreakType)
 {
   NS_ASSERTION(aString.IsEmpty(), "aString must be empty string");
 
   if (aRange->Collapsed()) {
@@ -501,17 +570,17 @@ ContentEventHandler::GenerateFlatTextCon
       if (content == startNode) {
         AppendSubString(aString, content, aRange->StartOffset(),
                         content->TextLength() - aRange->StartOffset());
       } else if (content == endNode) {
         AppendSubString(aString, content, 0, aRange->EndOffset());
       } else {
         AppendString(aString, content);
       }
-    } else if (IsContentBR(content)) {
+    } else if (ShouldBreakLineBefore(content, mRootContent)) {
       aString.Append(char16_t('\n'));
     }
   }
   if (aLineBreakType == LINE_BREAK_TYPE_NATIVE) {
     ConvertToNativeNewlines(aString);
   }
   return NS_OK;
 }
@@ -621,17 +690,17 @@ ContentEventHandler::AppendFontRanges(Fo
       baseOffset += GetTextLengthInRange(
         aContent, lastXPEndOffset, frameXPEnd, aLineBreakType);
     }
 
     curr = next;
   }
 }
 
-/* static */ nsresult
+nsresult
 ContentEventHandler::GenerateFlatFontRanges(nsRange* aRange,
                                             FontRangeArray& aFontRanges,
                                             uint32_t& aLength,
                                             LineBreakType aLineBreakType)
 {
   MOZ_ASSERT(aFontRanges.IsEmpty(), "aRanges must be empty array");
 
   if (aRange->Collapsed()) {
@@ -664,17 +733,17 @@ ContentEventHandler::GenerateFlatFontRan
     if (content->IsNodeOfType(nsINode::eTEXT)) {
       int32_t startOffset = content != startNode ? 0 : aRange->StartOffset();
       int32_t endOffset = content != endNode ?
         content->TextLength() : aRange->EndOffset();
       AppendFontRanges(aFontRanges, content, baseOffset,
                        startOffset, endOffset, aLineBreakType);
       baseOffset += GetTextLengthInRange(content, startOffset, endOffset,
                                          aLineBreakType);
-    } else if (IsContentBR(content)) {
+    } else if (ShouldBreakLineBefore(content, mRootContent)) {
       if (aFontRanges.IsEmpty()) {
         MOZ_ASSERT(baseOffset == 0);
         FontRange* fontRange = AppendFontRange(aFontRanges, baseOffset);
         nsIFrame* frame = content->GetPrimaryFrame();
         if (frame) {
           const nsFont& font = frame->GetParent()->StyleFont()->mFont;
           const FontFamilyList& fontList = font.fontlist;
           const FontFamilyName& fontName = fontList.IsEmpty() ?
@@ -784,17 +853,18 @@ ContentEventHandler::SetRangeFromFlatTex
     if (node == mRootContent || !node->IsContent()) {
       continue;
     }
     nsIContent* content = node->AsContent();
 
     uint32_t textLength =
       content->IsNodeOfType(nsINode::eTEXT) ?
         GetTextLength(content, aLineBreakType) :
-        (IsContentBR(content) ? GetBRLength(aLineBreakType) : 0);
+        (ShouldBreakLineBefore(content, mRootContent) ?
+           GetBRLength(aLineBreakType) : 0);
     if (!textLength) {
       continue;
     }
 
     // When the start offset is in between accumulated offset and the last
     // offset of the node, the node is the start node of the range.
     if (!startSet && aOffset <= offset + textLength) {
       nsINode* startNode = nullptr;
@@ -895,17 +965,27 @@ ContentEventHandler::SetRangeFromFlatTex
         // NOTE: Please don't crash on release builds because it must be
         //       overreaction but we shouldn't allow this bug when some
         //       automated tests find this.
         MOZ_ASSERT(false, "This case should've already been handled at "
                           "the last node which caused some text");
         return NS_ERROR_FAILURE;
       }
 
-      // Rule #2.3: </element>]
+      if (content->HasChildren() &&
+          ShouldBreakLineBefore(content, mRootContent)) {
+        // Rule #2.3: </element>]
+        rv = aRange->SetEnd(content, 0);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
+        return NS_OK;
+      }
+
+      // Rule #2.4: <element/>]
       nsINode* endNode = content->GetParent();
       if (NS_WARN_IF(!endNode)) {
         return NS_ERROR_FAILURE;
       }
       int32_t indexInParent = endNode->IndexOf(content);
       if (NS_WARN_IF(indexInParent == -1)) {
         // The content is being removed from the parent!
         return NS_ERROR_FAILURE;
@@ -927,17 +1007,17 @@ ContentEventHandler::SetRangeFromFlatTex
                           static_cast<int32_t>(mRootContent->GetChildCount()));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     if (aNewOffset) {
       *aNewOffset = offset;
     }
   }
-  // Rule #2.4: ]</root>
+  // Rule #2.5: ]</root>
   rv = aRange->SetEnd(mRootContent,
                       static_cast<int32_t>(mRootContent->GetChildCount()));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
@@ -1607,30 +1687,59 @@ ContentEventHandler::GetFlatTextLengthIn
     }
   } else {
     RefPtr<nsRange> prev = new nsRange(aRootContent);
     nsresult rv = aStartPosition.SetToRangeStart(prev);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
-    if (aEndPosition.OffsetIsValid()) {
+    // When the end position is immediately after non-root element's open tag,
+    // we need to include a line break caused by the open tag.
+    NodePosition endPosition;
+    if (aEndPosition.mNode != aRootContent &&
+        aEndPosition.IsImmediatelyAfterOpenTag()) {
+      if (aEndPosition.mNode->HasChildren()) {
+        // When the end node has some children, move the end position to the
+        // start of its first child.
+        nsINode* firstChild = aEndPosition.mNode->GetFirstChild();
+        if (NS_WARN_IF(!firstChild)) {
+          return NS_ERROR_FAILURE;
+        }
+        endPosition = NodePosition(firstChild, 0);
+      } else {
+        // When the end node is empty, move the end position after the node.
+        nsIContent* parentContent = aEndPosition.mNode->GetParent();
+        if (NS_WARN_IF(!parentContent)) {
+          return NS_ERROR_FAILURE;
+        }
+        int32_t indexInParent = parentContent->IndexOf(aEndPosition.mNode);
+        if (NS_WARN_IF(indexInParent < 0)) {
+          return NS_ERROR_FAILURE;
+        }
+        endPosition = NodePosition(parentContent, indexInParent + 1);
+      }
+    } else {
+      endPosition = aEndPosition;
+    }
+
+    if (endPosition.OffsetIsValid()) {
       // Offset is within node's length; set end of range to that offset
-      rv = aEndPosition.SetToRangeEnd(prev);
+      rv = endPosition.SetToRangeEnd(prev);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       iter = NS_NewPreContentIterator();
       rv = iter->Init(prev);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
-    } else if (aEndPosition.mNode != aRootContent) {
+    } else if (endPosition.mNode != aRootContent) {
       // Offset is past node's length; set end of range to end of node
-      rv = aEndPosition.SetToRangeEndAfter(prev);
+      rv = endPosition.SetToRangeEndAfter(prev);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       iter = NS_NewPreContentIterator();
       rv = iter->Init(prev);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
@@ -1658,32 +1767,37 @@ ContentEventHandler::GetFlatTextLengthIn
     if (node->IsNodeOfType(nsINode::eTEXT)) {
       // Note: our range always starts from offset 0
       if (node == aEndPosition.mNode) {
         *aLength += GetTextLength(content, aLineBreakType,
                                   aEndPosition.mOffset);
       } else {
         *aLength += GetTextLength(content, aLineBreakType);
       }
-    } else if (IsContentBR(content)) {
+    } else if (ShouldBreakLineBefore(content, aRootContent)) {
+      // If the start position is start of this node but doesn't include the
+      // open tag, don't append the line break length.
+      if (node == aStartPosition.mNode && !aStartPosition.IsBeforeOpenTag()) {
+        continue;
+      }
       *aLength += GetBRLength(aLineBreakType);
     }
   }
   return NS_OK;
 }
 
 nsresult
 ContentEventHandler::GetFlatTextLengthBefore(nsRange* aRange,
                                              uint32_t* aOffset,
                                              LineBreakType aLineBreakType)
 {
   MOZ_ASSERT(aRange);
   return GetFlatTextLengthInRange(
            NodePosition(mRootContent, 0),
-           NodePosition(aRange->GetStartParent(), aRange->StartOffset()),
+           NodePositionBefore(aRange->GetStartParent(), aRange->StartOffset()),
            mRootContent, aOffset, aLineBreakType);
 }
 
 nsresult
 ContentEventHandler::AdjustCollapsedRangeMaybeIntoTextNode(nsRange* aRange)
 {
   MOZ_ASSERT(aRange);
   MOZ_ASSERT(aRange->Collapsed());
--- a/dom/events/ContentEventHandler.h
+++ b/dom/events/ContentEventHandler.h
@@ -79,52 +79,79 @@ protected:
   nsresult InitBasic();
   nsresult InitCommon();
 
 public:
   // FlatText means the text that is generated from DOM tree. The BR elements
   // are replaced to native linefeeds. Other elements are ignored.
 
   // NodePosition stores a pair of node and offset in the node.
+  // When mNode is an element and mOffset is 0, the start position means after
+  // the open tag of mNode.
   // This is useful to receive one or more sets of them instead of nsRange.
-  struct NodePosition final
+  struct NodePosition
   {
     nsCOMPtr<nsINode> mNode;
     int32_t mOffset;
+    // Only when mNode is an element node and mOffset is 0, mAfterOpenTag is
+    // referred.
+    bool mAfterOpenTag;
 
     NodePosition()
       : mOffset(-1)
+      , mAfterOpenTag(true)
     {
     }
 
     NodePosition(nsINode* aNode, int32_t aOffset)
       : mNode(aNode)
       , mOffset(aOffset)
+      , mAfterOpenTag(true)
     {
     }
 
     explicit NodePosition(const nsIFrame::ContentOffsets& aContentOffsets)
       : mNode(aContentOffsets.content)
       , mOffset(aContentOffsets.offset)
+      , mAfterOpenTag(true)
     {
     }
 
+  protected:
+    NodePosition(nsINode* aNode, int32_t aOffset, bool aAfterOpenTag)
+      : mNode(aNode)
+      , mOffset(aOffset)
+      , mAfterOpenTag(aAfterOpenTag)
+    {
+    }
+
+  public:
     bool operator==(const NodePosition& aOther) const
     {
-      return mNode == aOther.mNode && mOffset == aOther.mOffset;
+      return mNode == aOther.mNode &&
+             mOffset == aOther.mOffset &&
+             mAfterOpenTag == aOther.mAfterOpenTag;
     }
 
     bool IsValid() const
     {
       return mNode && mOffset >= 0;
     }
     bool OffsetIsValid() const
     {
       return IsValid() && static_cast<uint32_t>(mOffset) <= mNode->Length();
     }
+    bool IsBeforeOpenTag() const
+    {
+      return IsValid() && mNode->IsElement() && !mOffset && !mAfterOpenTag;
+    }
+    bool IsImmediatelyAfterOpenTag() const
+    {
+      return IsValid() && mNode->IsElement() && !mOffset && mAfterOpenTag;
+    }
     nsresult SetToRangeStart(nsRange* aRange) const
     {
       nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mNode));
       return aRange->SetStart(domNode, mOffset);
     }
     nsresult SetToRangeEnd(nsRange* aRange) const
     {
       nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mNode));
@@ -132,36 +159,63 @@ public:
     }
     nsresult SetToRangeEndAfter(nsRange* aRange) const
     {
       nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mNode));
       return aRange->SetEndAfter(domNode);
     }
   };
 
+  // NodePositionBefore isn't good name if mNode isn't an element node nor
+  // mOffset is not 0, though, when mNode is an element node and mOffset is 0,
+  // this is treated as before the open tag of mNode.
+  struct NodePositionBefore final : public NodePosition
+  {
+    NodePositionBefore(nsINode* aNode, int32_t aOffset)
+      : NodePosition(aNode, aOffset, false)
+    {
+    }
+  };
+
   // Get the flatten text length in the range.
+  // @param aStartPosition      Start node and offset in the node of the range.
+  // @param aEndPosition        End node and offset in the node of the range.
+  // @param aRootContent        The root content of the editor or document.
+  //                            aRootContent won't cause any text including
+  //                            line breaks.
+  // @param aLength             The result of the flatten text length of the
+  //                            range.
+  // @param aLineBreakType      Whether this computes flatten text length with
+  //                            native line breakers on the platform or
+  //                            with XP line breaker (\n).
   // @param aIsRemovingNode     Should be true only when this is called from
   //                            nsIMutationObserver::ContentRemoved().
+  //                            When this is true, aStartPosition.mNode should
+  //                            be the root node of removing nodes and mOffset
+  //                            should be 0 and aEndPosition.mNode should be
+  //                            same as aStartPosition.mNode and mOffset should
+  //                            be number of the children of mNode.
   static nsresult GetFlatTextLengthInRange(const NodePosition& aStartPosition,
                                            const NodePosition& aEndPosition,
                                            nsIContent* aRootContent,
                                            uint32_t* aLength,
                                            LineBreakType aLineBreakType,
                                            bool aIsRemovingNode = false);
   // Computes the native text length between aStartOffset and aEndOffset of
   // aContent.  aContent must be a text node.
   static uint32_t GetNativeTextLength(nsIContent* aContent,
                                       uint32_t aStartOffset,
                                       uint32_t aEndOffset);
   // Get the native text length of aContent.  aContent must be a text node.
   static uint32_t GetNativeTextLength(nsIContent* aContent,
                                       uint32_t aMaxLength = UINT32_MAX);
   // Get the native text length which is inserted before aContent.
-  // aContent should be a <br> element for now.
-  static uint32_t GetNativeTextLengthBefore(nsIContent* aContent);
+  // aContent should be an element.
+  static uint32_t GetNativeTextLengthBefore(nsIContent* aContent,
+                                            nsINode* aRootNode);
 
 protected:
   // Get the text length of aContent.  aContent must be a text node.
   static uint32_t GetTextLength(nsIContent* aContent,
                                 LineBreakType aLineBreakType,
                                 uint32_t aMaxLength = UINT32_MAX);
   // Get the text length of a given range of a content node in
   // the given line break type.
@@ -172,16 +226,21 @@ protected:
   // Get the contents of aRange as plain text.
   nsresult GenerateFlatTextContent(nsRange* aRange,
                                    nsAFlatString& aString,
                                    LineBreakType aLineBreakType);
   // Get the text length before the start position of aRange.
   nsresult GetFlatTextLengthBefore(nsRange* aRange,
                                    uint32_t* aOffset,
                                    LineBreakType aLineBreakType);
+  // Check if we should insert a line break before aContent.
+  // This should return false only when aContent is an html element which
+  // is typically used in a paragraph like <em>.
+  static bool ShouldBreakLineBefore(nsIContent* aContent,
+                                    nsINode* aRootNode);
   // Get the line breaker length.
   static inline uint32_t GetBRLength(LineBreakType aLineBreakType);
   static LineBreakType GetLineBreakType(WidgetQueryContentEvent* aEvent);
   static LineBreakType GetLineBreakType(WidgetSelectionEvent* aEvent);
   static LineBreakType GetLineBreakType(bool aUseNativeLineBreak);
   // Returns focused content (including its descendant documents).
   nsIContent* GetFocusedContent();
   // Returns true if the content is a plugin host.
@@ -216,17 +275,17 @@ protected:
 
   typedef nsTArray<mozilla::FontRange> FontRangeArray;
   static void AppendFontRanges(FontRangeArray& aFontRanges,
                                nsIContent* aContent,
                                int32_t aBaseOffset,
                                int32_t aXPStartOffset,
                                int32_t aXPEndOffset,
                                LineBreakType aLineBreakType);
-  static nsresult GenerateFlatFontRanges(nsRange* aRange,
-                                         FontRangeArray& aFontRanges,
-                                         uint32_t& aLength,
-                                         LineBreakType aLineBreakType);
+  nsresult GenerateFlatFontRanges(nsRange* aRange,
+                                  FontRangeArray& aFontRanges,
+                                  uint32_t& aLength,
+                                  LineBreakType aLineBreakType);
 };
 
 } // namespace mozilla
 
 #endif // mozilla_ContentEventHandler_h_
--- a/dom/events/IMEContentObserver.cpp
+++ b/dom/events/IMEContentObserver.cpp
@@ -874,19 +874,17 @@ IMEContentObserver::CharacterDataChanged
              "CharacterDataWillChange()");
 
   uint32_t offset = 0;
   // get offsets of change and fire notification
   nsresult rv =
     ContentEventHandler::GetFlatTextLengthInRange(
                            NodePosition(mRootContent, 0),
                            NodePosition(aContent, aInfo->mChangeStart),
-                           mRootContent,
-                           &offset,
-                           LINE_BREAK_TYPE_NATIVE);
+                           mRootContent, &offset, LINE_BREAK_TYPE_NATIVE);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   uint32_t newLength =
     ContentEventHandler::GetNativeTextLength(aContent, aInfo->mChangeStart,
                                              aInfo->mChangeStart +
                                                aInfo->mReplaceLength);
@@ -913,30 +911,29 @@ IMEContentObserver::NotifyContentAdded(n
   }
 
   uint32_t offset = 0;
   nsresult rv = NS_OK;
   if (!mEndOfAddedTextCache.Match(aContainer, aStartIndex)) {
     mEndOfAddedTextCache.Clear();
     rv = ContentEventHandler::GetFlatTextLengthInRange(
                                 NodePosition(mRootContent, 0),
-                                NodePosition(aContainer, aStartIndex),
-                                mRootContent, &offset,
-                                LINE_BREAK_TYPE_NATIVE);
+                                NodePositionBefore(aContainer, aStartIndex),
+                                mRootContent, &offset, LINE_BREAK_TYPE_NATIVE);
     if (NS_WARN_IF(NS_FAILED((rv)))) {
       return;
     }
   } else {
     offset = mEndOfAddedTextCache.mFlatTextLength;
   }
 
   // get offset at the end of the last added node
   uint32_t addingLength = 0;
   rv = ContentEventHandler::GetFlatTextLengthInRange(
-                              NodePosition(aContainer, aStartIndex),
+                              NodePositionBefore(aContainer, aStartIndex),
                               NodePosition(aContainer, aEndIndex),
                               mRootContent, &addingLength,
                               LINE_BREAK_TYPE_NATIVE);
   if (NS_WARN_IF(NS_FAILED((rv)))) {
     mEndOfAddedTextCache.Clear();
     return;
   }
 
@@ -990,22 +987,22 @@ IMEContentObserver::ContentRemoved(nsIDo
     return;
   }
 
   nsINode* containerNode = NODE_FROM(aContainer, aDocument);
 
   uint32_t offset = 0;
   nsresult rv = NS_OK;
   if (!mStartOfRemovingTextRangeCache.Match(containerNode, aIndexInContainer)) {
+    // At removing a child node of aContainer, we need the line break caused
+    // by open tag of aContainer.  Be careful when aIndexInContainer is 0.
     rv = ContentEventHandler::GetFlatTextLengthInRange(
                                 NodePosition(mRootContent, 0),
                                 NodePosition(containerNode, aIndexInContainer),
-                                mRootContent,
-                                &offset,
-                                LINE_BREAK_TYPE_NATIVE);
+                                mRootContent, &offset, LINE_BREAK_TYPE_NATIVE);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       mStartOfRemovingTextRangeCache.Clear();
       return;
     }
     mStartOfRemovingTextRangeCache.Cache(containerNode, aIndexInContainer,
                                          offset);
   } else {
     offset = mStartOfRemovingTextRangeCache.mFlatTextLength;
@@ -1013,17 +1010,17 @@ IMEContentObserver::ContentRemoved(nsIDo
 
   // get offset at the end of the deleted node
   uint32_t textLength = 0;
   if (aChild->IsNodeOfType(nsINode::eTEXT)) {
     textLength = ContentEventHandler::GetNativeTextLength(aChild);
   } else {
     uint32_t nodeLength = static_cast<int32_t>(aChild->GetChildCount());
     rv = ContentEventHandler::GetFlatTextLengthInRange(
-                                NodePosition(aChild, 0),
+                                NodePositionBefore(aChild, 0),
                                 NodePosition(aChild, nodeLength),
                                 mRootContent, &textLength,
                                 LINE_BREAK_TYPE_NATIVE, true);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       mStartOfRemovingTextRangeCache.Clear();
       return;
     }
   }
@@ -1041,17 +1038,17 @@ void
 IMEContentObserver::AttributeWillChange(nsIDocument* aDocument,
                                         dom::Element* aElement,
                                         int32_t aNameSpaceID,
                                         nsIAtom* aAttribute,
                                         int32_t aModType,
                                         const nsAttrValue* aNewValue)
 {
   mPreAttrChangeLength =
-    ContentEventHandler::GetNativeTextLengthBefore(aElement);
+    ContentEventHandler::GetNativeTextLengthBefore(aElement, mRootContent);
 }
 
 void
 IMEContentObserver::AttributeChanged(nsIDocument* aDocument,
                                      dom::Element* aElement,
                                      int32_t aNameSpaceID,
                                      nsIAtom* aAttribute,
                                      int32_t aModType,
@@ -1062,27 +1059,26 @@ IMEContentObserver::AttributeChanged(nsI
 
   bool causedByComposition = IsEditorHandlingEventForComposition();
   if (!mTextChangeData.IsValid() && causedByComposition &&
       !mUpdatePreference.WantChangesCausedByComposition()) {
     return;
   }
 
   uint32_t postAttrChangeLength =
-    ContentEventHandler::GetNativeTextLengthBefore(aElement);
+    ContentEventHandler::GetNativeTextLengthBefore(aElement, mRootContent);
   if (postAttrChangeLength == mPreAttrChangeLength) {
     return;
   }
   uint32_t start;
   nsresult rv =
-    ContentEventHandler::GetFlatTextLengthInRange(NodePosition(mRootContent, 0),
-                                                  NodePosition(aElement, 0),
-                                                  mRootContent,
-                                                  &start,
-                                                  LINE_BREAK_TYPE_NATIVE);
+    ContentEventHandler::GetFlatTextLengthInRange(
+                           NodePosition(mRootContent, 0),
+                           NodePositionBefore(aElement, 0),
+                           mRootContent, &start, LINE_BREAK_TYPE_NATIVE);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   TextChangeData data(start, start + mPreAttrChangeLength,
                       start + postAttrChangeLength, causedByComposition,
                       IsEditorComposing());
   MaybeNotifyIMEOfTextChange(data);
--- a/dom/events/IMEContentObserver.h
+++ b/dom/events/IMEContentObserver.h
@@ -36,16 +36,17 @@ class IMEContentObserver final : public 
                                , public nsStubMutationObserver
                                , public nsIReflowObserver
                                , public nsIScrollObserver
                                , public nsSupportsWeakReference
                                , public nsIEditorObserver
 {
 public:
   typedef ContentEventHandler::NodePosition NodePosition;
+  typedef ContentEventHandler::NodePositionBefore NodePositionBefore;
   typedef widget::IMENotification::SelectionChangeData SelectionChangeData;
   typedef widget::IMENotification::TextChangeData TextChangeData;
   typedef widget::IMENotification::TextChangeDataBase TextChangeDataBase;
   typedef widget::IMEMessage IMEMessage;
 
   IMEContentObserver();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
--- a/editor/libeditor/tests/test_contenteditable_text_input_handling.html
+++ b/editor/libeditor/tests/test_contenteditable_text_input_handling.html
@@ -20,16 +20,18 @@
 <pre id="test">
 </pre>
 
 <script class="testbody" type="application/javascript">
 
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(runTests);
 
+const kLF = !navigator.platform.indexOf("Win") ? "\r\n" : "\n";
+
 function runTests()
 {
   var fm = Components.classes["@mozilla.org/focus-manager;1"].
              getService(Components.interfaces.nsIFocusManager);
 
   var listener = {
     handleEvent: function _hv(aEvent)
     {
@@ -77,18 +79,29 @@ function runTests()
   textareaInEditor._isContentEditable = false;
   textareaInEditor._description = "textarea element in contenteditable editor";
 
   function getTextValue(aElement)
   {
     if (aElement == editor) {
       var value = "";
       for (var node = aElement.firstChild; node; node = node.nextSibling) {
-        if (node.nodeType == 3) {
+        if (node.nodeType == Node.TEXT_NODE) {
           value += node.data;
+        } else if (node.nodeType == Node.ELEMENT_NODE) {
+          var tagName = node.tagName.toLowerCase();
+          switch (tagName) {
+            case "input":
+            case "textarea":
+              value += kLF;
+              break;
+            default:
+              ok(false, "Undefined tag is used in the editor: " + tagName);
+              break;
+          }
         }
       }
       return value;
     }
     return aElement.value;
   }
 
   function testTextInput(aFocus)
--- a/widget/tests/window_composition_text_querycontent.xul
+++ b/widget/tests/window_composition_text_querycontent.xul
@@ -2320,27 +2320,16 @@ function runSetSelectionEventTest()
 {
   contenteditable.focus();
 
   var selection = windowOfContenteditable.getSelection();
 
   // #1
   contenteditable.innerHTML = "abc<br>def";
 
-  synthesizeSelectionSet(0, 6 + kLFLen);
-  is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
-  is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
-  is(selection.focusNode, contenteditable.lastChild,
-     "runSetSelectionEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node of the editor");
-  is(selection.focusOffset, contenteditable.lastChild.wholeText.length,
-     "runSetSelectionEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
-  checkSelection(0, "abc" + kLF + "def", "runSetSelectionEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\"");
-
   synthesizeSelectionSet(0, 100);
   is(selection.anchorNode, contenteditable.firstChild,
      "runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
   is(selection.anchorOffset, 0,
      "runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
   is(selection.focusNode, contenteditable,
      "runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node of the editor");
   is(selection.focusOffset, contenteditable.childNodes.length,
@@ -2400,274 +2389,274 @@ function runSetSelectionEventTest()
      "runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node of the editor");
   is(selection.focusOffset, contenteditable.childNodes.length,
      "runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of children");
   checkSelection(6 + kLFLen, "", "runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\"");
 
   // #2
   contenteditable.innerHTML = "<p>a<b>b</b>c</p><p>def</p>";
 
-  synthesizeSelectionSet(0, 4);
-  is(selection.anchorNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
+  synthesizeSelectionSet(kLFLen, 4+kLFLen);
+  is(selection.anchorNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first <p> node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
+     "runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the first <p> node");
   is(selection.focusNode, contenteditable.lastChild.firstChild,
-     "runSetSelectionEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the second <p> node");
+     "runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the second <p> node");
   is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
-  checkSelection(0, "abcd", "runSetSelectionEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(0, 2);
+     "runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(kLFLen, "abc" + kLF + "d", "runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(kLFLen, 2);
+  is(selection.anchorNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first <p> node");
+  is(selection.anchorOffset, 0,
+     "runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the first <p> node");
+  is(selection.focusNode, contenteditable.firstChild.childNodes.item(1).firstChild,
+     "runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <b> node");
+  is(selection.focusOffset, contenteditable.firstChild.childNodes.item(1).firstChild.wholeText.length,
+     "runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <b> node");
+  checkSelection(kLFLen, "ab", "runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(1+kLFLen, 2);
   is(selection.anchorNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
-  is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
-  is(selection.focusNode, contenteditable.firstChild.childNodes.item(1).firstChild,
-     "runSetSelectionEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <b> node");
-  is(selection.focusOffset, contenteditable.firstChild.childNodes.item(1).firstChild.wholeText.length,
-     "runSetSelectionEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <b> node");
-  checkSelection(0, "ab", "runSetSelectionEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(1, 2);
-  is(selection.anchorNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
+     "runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+     "runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node in the first <p> node");
+     "runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node in the first <p> node");
   is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
-     "runSetSelectionEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node in the first <p> node");
-  checkSelection(1, "bc", "runSetSelectionEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(2, 2);
+     "runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node in the first <p> node");
+  checkSelection(1+kLFLen, "bc", "runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(2+kLFLen, 2+kLFLen);
   is(selection.anchorNode, contenteditable.firstChild.childNodes.item(1).firstChild,
-     "runSetSelectionEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <b> node");
+     "runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <b> node");
   is(selection.anchorOffset, contenteditable.firstChild.childNodes.item(1).firstChild.wholeText.length,
-     "runSetSelectionEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the text node in the <b> node");
+     "runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the text node in the <b> node");
   is(selection.focusNode, contenteditable.lastChild.firstChild,
-     "runSetSelectionEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the last <p> node");
+     "runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the last <p> node");
   is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
-  checkSelection(2, "cd", "runSetSelectionEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(3, 1);
-  is(selection.anchorNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node in the first <p> node");
-  is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
-     "runSetSelectionEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node in the first <p> node");
+     "runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(2+kLFLen, "c" + kLF + "d", "runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(3+kLFLen*2, 1);
+  is(selection.anchorNode, contenteditable.lastChild,
+     "runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the second <p> node");
+  is(selection.anchorOffset, 0,
+     "runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the second <p> node");
   is(selection.focusNode, contenteditable.lastChild.firstChild,
-     "runSetSelectionEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the second <p> node");
+     "runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the second <p> node");
   is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
-  checkSelection(3, "d", "runSetSelectionEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\"");
+     "runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(3+kLFLen*2, "d", "runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #3
   contenteditable.innerHTML = "<div>abc<p>def</p></div>";
 
-  synthesizeSelectionSet(1, 2);
+  synthesizeSelectionSet(1+kLFLen, 2);
   is(selection.anchorNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
+     "runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+     "runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the first text node");
+     "runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the first text node");
   is(selection.focusOffset, contenteditable.firstChild.firstChild.wholeText.length,
-     "runSetSelectionEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the first text node");
-  checkSelection(1, "bc", "runSetSelectionEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(1, 3);
+     "runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the first text node");
+  checkSelection(1+kLFLen, "bc", "runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(1+kLFLen, 3+kLFLen);
   is(selection.anchorNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
+     "runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+     "runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
-     "runSetSelectionEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
+     "runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
   is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
-  checkSelection(1, "bcd", "runSetSelectionEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(3, 0);
+     "runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(1+kLFLen, "bc" + kLF + "d", "runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(3+kLFLen, 0);
   is(selection.anchorNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #3 (3, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
+     "runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
   is(selection.anchorOffset, contenteditable.firstChild.firstChild.wholeText.length,
-     "runSetSelectionEventTest #3 (3, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the first text node");
+     "runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the first text node");
   is(selection.focusNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #3 (3, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the first text node");
+     "runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the first text node");
   is(selection.focusOffset, contenteditable.firstChild.firstChild.wholeText.length,
-     "runSetSelectionEventTest #3 (3, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the first text node");
-  checkSelection(3, "", "runSetSelectionEventTest #3 (3, 0), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(0, 6);
-  is(selection.anchorNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
+     "runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the first text node");
+  checkSelection(3+kLFLen, "", "runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(0, 6+kLFLen*2);
+  is(selection.anchorNode, contenteditable,
+     "runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
+     "runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
   is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
-     "runSetSelectionEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
+     "runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
   is(selection.focusOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
-     "runSetSelectionEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
-  checkSelection(0, "abcdef", "runSetSelectionEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\"");
+     "runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
+  checkSelection(0, kLF + "abc" + kLF + "def", "runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(0, 100);
-  is(selection.anchorNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
+  is(selection.anchorNode, contenteditable,
+     "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
   is(selection.anchorOffset, 0,
      "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
   is(selection.focusNode, contenteditable,
      "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
      "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
-  checkSelection(0, "abcdef", "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(4, 2);
+  checkSelection(0, kLF + "abc" + kLF + "def", "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(4+kLFLen*2, 2);
   is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
-     "runSetSelectionEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
+     "runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+     "runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
-     "runSetSelectionEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
+     "runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
   is(selection.focusOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
-     "runSetSelectionEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
-  checkSelection(4, "ef", "runSetSelectionEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(4, 100);
+     "runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
+  checkSelection(4+kLFLen*2, "ef", "runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(4+kLFLen*2, 100);
   is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
-     "runSetSelectionEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
+     "runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+     "runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
+     "runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
-  checkSelection(4, "ef", "runSetSelectionEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(6, 0);
+     "runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(4+kLFLen*2, "ef", "runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(6+kLFLen*2, 0);
   is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
-     "runSetSelectionEventTest #3 (6, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
+     "runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
   is(selection.anchorOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
-     "runSetSelectionEventTest #3 (6, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
+     "runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
   is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
-     "runSetSelectionEventTest #3 (6, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
+     "runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
   is(selection.focusOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
-     "runSetSelectionEventTest #3 (6, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
-  checkSelection(6, "", "runSetSelectionEventTest #3 (6, 0), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(6, 1);
+     "runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
+  checkSelection(6+kLFLen*2, "", "runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(6+kLFLen*2, 1);
   is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
-     "runSetSelectionEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
+     "runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
   is(selection.anchorOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
-     "runSetSelectionEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
+     "runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
+     "runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
-  checkSelection(6, "", "runSetSelectionEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\"");
+     "runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(6+kLFLen*2, "", "runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #4
   contenteditable.innerHTML = "<div><p>abc</p>def</div>";
 
-  synthesizeSelectionSet(1, 2);
+  synthesizeSelectionSet(1+kLFLen*2, 2);
   is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
-     "runSetSelectionEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
+     "runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+     "runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable.firstChild.firstChild.firstChild,
-     "runSetSelectionEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
+     "runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
   is(selection.focusOffset, contenteditable.firstChild.firstChild.firstChild.wholeText.length,
-     "runSetSelectionEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <p> node");
-  checkSelection(1, "bc", "runSetSelectionEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(1, 3);
+     "runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <p> node");
+  checkSelection(1+kLFLen*2, "bc", "runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(1+kLFLen*2, 3);
   is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
-     "runSetSelectionEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
+     "runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+     "runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
+     "runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
   is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
-  checkSelection(1, "bcd", "runSetSelectionEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(3, 0);
+     "runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(1+kLFLen*2, "bcd", "runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(3+kLFLen*2, 0);
   is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
-     "runSetSelectionEventTest #4 (3, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
+     "runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
   is(selection.anchorOffset, contenteditable.firstChild.firstChild.firstChild.wholeText.length,
-     "runSetSelectionEventTest #4 (3, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the text node in the <p> node");
+     "runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the text node in the <p> node");
   is(selection.focusNode, contenteditable.firstChild.firstChild.firstChild,
-     "runSetSelectionEventTest #4 (3, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
+     "runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
   is(selection.focusOffset, contenteditable.firstChild.firstChild.firstChild.wholeText.length,
-     "runSetSelectionEventTest #4 (3, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <p> node");
-  checkSelection(3, "", "runSetSelectionEventTest #4 (3, 0), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(0, 6);
-  is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
-     "runSetSelectionEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
+     "runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <p> node");
+  checkSelection(3+kLFLen*2, "", "runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(0, 6+kLFLen*2);
+  is(selection.anchorNode, contenteditable,
+     "runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
+     "runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
   is(selection.focusNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
+     "runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
   is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
-     "runSetSelectionEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
-  checkSelection(0, "abcdef", "runSetSelectionEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\"");
+     "runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
+  checkSelection(0, kLF + kLF + "abcdef", "runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(0, 100);
-  is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
-     "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
+  is(selection.anchorNode, contenteditable,
+     "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
   is(selection.anchorOffset, 0,
      "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
   is(selection.focusNode, contenteditable,
      "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
      "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
-  checkSelection(0, "abcdef", "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(4, 2);
+  checkSelection(0, kLF + kLF + "abcdef", "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(4+kLFLen*2, 2);
   is(selection.anchorNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
+     "runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+     "runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
+     "runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
   is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
-     "runSetSelectionEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
-  checkSelection(4, "ef", "runSetSelectionEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(4, 100);
+     "runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
+  checkSelection(4+kLFLen*2, "ef", "runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(4+kLFLen*2, 100);
   is(selection.anchorNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
+     "runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+     "runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
+     "runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
-  checkSelection(4, "ef", "runSetSelectionEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(6, 0);
+     "runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(4+kLFLen*2, "ef", "runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(6+kLFLen*2, 0);
   is(selection.anchorNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #4 (6, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
+     "runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
   is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
-     "runSetSelectionEventTest #4 (6, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
+     "runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
   is(selection.focusNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #4 (6, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
+     "runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
   is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
-     "runSetSelectionEventTest #4 (6, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
-  checkSelection(6, "", "runSetSelectionEventTest #4 (6, 0), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(6, 1);
+     "runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
+  checkSelection(6+kLFLen*2, "", "runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(6+kLFLen*2, 1);
   is(selection.anchorNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
+     "runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
   is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
-     "runSetSelectionEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
+     "runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
+     "runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
-  checkSelection(6, "", "runSetSelectionEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\"");
+     "runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(6+kLFLen*2, "", "runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #5
   contenteditable.innerHTML = "<br>";
 
   synthesizeSelectionSet(0, kLFLen);
   is(selection.anchorNode, contenteditable,
      "runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
   is(selection.anchorOffset, 0,
@@ -2698,48 +2687,48 @@ function runSetSelectionEventTest()
      "runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
      "runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
   checkSelection(kLFLen, "", "runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #6
   contenteditable.innerHTML = "<p><br></p>";
 
-  synthesizeSelectionSet(0, kLFLen);
+  synthesizeSelectionSet(kLFLen, kLFLen);
   is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
+     "runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+     "runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
+     "runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
   is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
-  checkSelection(0, kLF, "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(kLFLen, 0);
+     "runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
+  checkSelection(kLFLen, kLF, "runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(kLFLen*2, 0);
   is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
+     "runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
   is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the <p>'s children");
+     "runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the <p>'s children");
   is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
+     "runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
   is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
-  checkSelection(kLFLen, "", "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(kLFLen, 1);
+     "runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
+  checkSelection(kLFLen*2, "", "runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(kLFLen*2, 1);
   is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #6 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
+     "runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
   is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #6 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the root's children");
+     "runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the root's children");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #6 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
+     "runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #6 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
-  checkSelection(kLFLen, "", "runSetSelectionEventTest #6 (kLFLen, 1), \"" + contenteditable.innerHTML + "\"");
+     "runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(kLFLen*2, "", "runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #7
   contenteditable.innerHTML = "<br><br>";
 
   synthesizeSelectionSet(0, kLFLen);
   is(selection.anchorNode, contenteditable,
      "runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
   is(selection.anchorOffset, 0,
@@ -2792,70 +2781,70 @@ function runSetSelectionEventTest()
      "runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
      "runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
   checkSelection(kLFLen * 2, "", "runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
 
   // #8
   contenteditable.innerHTML = "<p><br><br></p>";
 
-  synthesizeSelectionSet(0, kLFLen);
-  is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
-  is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #8 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
-  is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
-  is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #8 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
-  checkSelection(0, kLF, "runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(0, kLFLen * 2);
-  is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
-  is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
-  is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
-  is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
-  checkSelection(0, kLF + kLF, "runSetSelectionEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(kLFLen, 0);
-  is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
-  is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #8 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
-  is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
-  is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #8 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
-  checkSelection(kLFLen, "", "runSetSelectionEventTest #8 (kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
-
   synthesizeSelectionSet(kLFLen, kLFLen);
   is(selection.anchorNode, contenteditable.firstChild,
      "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
-  is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+  is(selection.anchorOffset, 0,
+     "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
   is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (kLFLen, kLFLen) selection focus node should be the <p> node");
+     "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
+  is(selection.focusOffset, 1,
+     "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(kLFLen, kLF, "runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(kLFLen, kLFLen * 2);
+  is(selection.anchorNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
+  is(selection.anchorOffset, 0,
+     "runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
+  is(selection.focusNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
   is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
-  checkSelection(kLFLen, kLF, "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
-
-  synthesizeSelectionSet(kLFLen * 2, 0);
+     "runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
+  checkSelection(kLFLen, kLF + kLF, "runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(kLFLen*2, 0);
   is(selection.anchorNode, contenteditable.firstChild,
      "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
-  is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the <p>'s children");
+  is(selection.anchorOffset, 1,
+     "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable.firstChild,
      "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
+  is(selection.focusOffset, 1,
+     "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(kLFLen*2, "", "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(kLFLen*2, kLFLen);
+  is(selection.anchorNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
+  is(selection.anchorOffset, 1,
+     "runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+  is(selection.focusNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #8 (kLFLen*2, kLFLen) selection focus node should be the <p> node");
   is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
-  checkSelection(kLFLen * 2, "", "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
+     "runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
+  checkSelection(kLFLen*2, kLF, "runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\"");
+
+  synthesizeSelectionSet(kLFLen*3, 0);
+  is(selection.anchorNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
+  is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
+     "runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the <p>'s children");
+  is(selection.focusNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
+  is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
+     "runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
+  checkSelection(kLFLen*3, "", "runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\"");
 }
 
 function runQueryTextContentEventTest()
 {
   contenteditable.focus();
 
   var result;
 
@@ -2878,102 +2867,102 @@ function runQueryTextContentEventTest()
   is(result.text, kLF, "runQueryTextContentEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(6 + kLFLen, 1);
   is(result.text, "", "runQueryTextContentEventTest #1 (6 + kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
 
   // #2
   contenteditable.innerHTML = "<p>a<b>b</b>c</p><p>def</p>";
 
-  result = synthesizeQueryTextContent(0, 4);
-  is(result.text, "abcd", "runQueryTextContentEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(0, 2);
-  is(result.text, "ab", "runQueryTextContentEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(1, 2);
-  is(result.text, "bc", "runQueryTextContentEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(2, 2);
-  is(result.text, "cd", "runQueryTextContentEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(3, 1);
-  is(result.text, "d", "runQueryTextContentEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\"");
+  result = synthesizeQueryTextContent(kLFLen, 4+kLFLen);
+  is(result.text, "abc" + kLF + "d", "runQueryTextContentEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(kLFLen, 2);
+  is(result.text, "ab", "runQueryTextContentEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(1+kLFLen, 2);
+  is(result.text, "bc", "runQueryTextContentEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(2+kLFLen, 2+kLFLen);
+  is(result.text, "c" + kLF + "d", "runQueryTextContentEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(3+kLFLen*2, 1);
+  is(result.text, "d", "runQueryTextContentEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #3
   contenteditable.innerHTML = "<div>abc<p>def</p></div>";
 
-  result = synthesizeQueryTextContent(1, 2);
-  is(result.text, "bc", "runQueryTextContentEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(1, 3);
-  is(result.text, "bcd", "runQueryTextContentEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(3, 1);
-  is(result.text, "d", "runQueryTextContentEventTest #3 (3, 1), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(0, 6);
-  is(result.text, "abcdef", "runQueryTextContentEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\"");
+  result = synthesizeQueryTextContent(1+kLFLen, 2);
+  is(result.text, "bc", "runQueryTextContentEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(1+kLFLen, 3+kLFLen);
+  is(result.text, "bc" + kLF + "d", "runQueryTextContentEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(3+kLFLen*2, 1);
+  is(result.text, "d", "runQueryTextContentEventTest #3 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(0, 6+kLFLen*2);
+  is(result.text, kLF + "abc" + kLF + "def", "runQueryTextContentEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(0, 100);
-  is(result.text, "abcdef", "runQueryTextContentEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(4, 2);
-  is(result.text, "ef", "runQueryTextContentEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(4, 100);
-  is(result.text, "ef", "runQueryTextContentEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(6, 1);
-  is(result.text, "", "runQueryTextContentEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\"");
+  is(result.text, kLF + "abc" + kLF + "def", "runQueryTextContentEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(4+kLFLen*2, 2);
+  is(result.text, "ef", "runQueryTextContentEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(4+kLFLen*2, 100);
+  is(result.text, "ef", "runQueryTextContentEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(6+kLFLen*2, 1);
+  is(result.text, "", "runQueryTextContentEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #4
   contenteditable.innerHTML = "<div><p>abc</p>def</div>";
 
-  result = synthesizeQueryTextContent(1, 2);
-  is(result.text, "bc", "runQueryTextContentEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(1, 3);
-  is(result.text, "bcd", "runQueryTextContentEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(3, 1);
-  is(result.text, "d", "runQueryTextContentEventTest #4 (3, 1), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(0, 6);
-  is(result.text, "abcdef", "runQueryTextContentEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\"");
+  result = synthesizeQueryTextContent(1+kLFLen*2, 2);
+  is(result.text, "bc", "runQueryTextContentEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(1+kLFLen*2, 3);
+  is(result.text, "bcd", "runQueryTextContentEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(3+kLFLen*2, 1);
+  is(result.text, "d", "runQueryTextContentEventTest #4 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(0, 6+kLFLen*2);
+  is(result.text, kLF + kLF + "abcdef", "runQueryTextContentEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(0, 100);
-  is(result.text, "abcdef", "runQueryTextContentEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(4, 2);
-  is(result.text, "ef", "runQueryTextContentEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(4, 100);
-  is(result.text, "ef", "runQueryTextContentEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(6, 1);
-  is(result.text, "", "runQueryTextContentEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\"");
+  is(result.text, kLF + kLF + "abcdef", "runQueryTextContentEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(4+kLFLen*2, 2);
+  is(result.text, "ef", "runQueryTextContentEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(4+kLFLen*2, 100);
+  is(result.text, "ef", "runQueryTextContentEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(6+kLFLen*2, 1);
+  is(result.text, "", "runQueryTextContentEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #5
   contenteditable.innerHTML = "<br>";
 
   result = synthesizeQueryTextContent(0, kLFLen);
   is(result.text, kLF, "runQueryTextContentEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(kLFLen, 1);
   is(result.text, "", "runQueryTextContentEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #6
   contenteditable.innerHTML = "<p><br></p>";
 
-  result = synthesizeQueryTextContent(0, kLFLen);
-  is(result.text, kLF, "runQueryTextContentEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(kLFLen, 1);
-  is(result.text, "", "runQueryTextContentEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\"");
+  result = synthesizeQueryTextContent(kLFLen, kLFLen);
+  is(result.text, kLF, "runQueryTextContentEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(kLFLen*2, 1);
+  is(result.text, "", "runQueryTextContentEventTest #5 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #7
   contenteditable.innerHTML = "<br><br>";
 
   result = synthesizeQueryTextContent(0, kLFLen);
   is(result.text, kLF, "runQueryTextContentEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(0, kLFLen * 2);
@@ -2983,27 +2972,27 @@ function runQueryTextContentEventTest()
   is(result.text, kLF, "runQueryTextContentEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(kLFLen * 2, 1);
   is(result.text, "", "runQueryTextContentEventTest #7 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #8
   contenteditable.innerHTML = "<p><br><br></p>";
 
-  result = synthesizeQueryTextContent(0, kLFLen);
-  is(result.text, kLF, "runQueryTextContentEventTest #8 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
-
-  result = synthesizeQueryTextContent(0, kLFLen * 2);
-  is(result.text, kLF + kLF, "runQueryTextContentEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
-
   result = synthesizeQueryTextContent(kLFLen, kLFLen);
   is(result.text, kLF, "runQueryTextContentEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
-  result = synthesizeQueryTextContent(kLFLen * 2, 1);
-  is(result.text, "", "runQueryTextContentEventTest #8 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
+  result = synthesizeQueryTextContent(kLFLen, kLFLen * 2);
+  is(result.text, kLF + kLF, "runQueryTextContentEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(kLFLen*2, kLFLen);
+  is(result.text, kLF, "runQueryTextContentEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\"");
+
+  result = synthesizeQueryTextContent(kLFLen*3, 1);
+  is(result.text, "", "runQueryTextContentEventTest #8 (kLFLen*3, 1), \"" + contenteditable.innerHTML + "\"");
 }
 
 function runCSSTransformTest()
 {
   textarea.focus();
   textarea.value = "some text";
   textarea.selectionStart = textarea.selectionEnd = textarea.value.length;
   var editorRect = synthesizeQueryEditorRect();