Bug 1413181 - part 9: Make EditorBase::SplitNodeDeep() use EditorDOMPoint in the loop r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Mon, 13 Nov 2017 16:44:58 +0900
changeset 701129 33de454727010774d539c336154fde93b71db39a
parent 701128 f0bcbddc994e0b05203439d4adb8b76b879ed45b
child 701130 7370f20e5f8cb0070a45baebd4f78510ac361f59
push id90079
push usermasayuki@d-toybox.com
push dateTue, 21 Nov 2017 08:41:26 +0000
reviewersm_kato
bugs1413181
milestone59.0a1
Bug 1413181 - part 9: Make EditorBase::SplitNodeDeep() use EditorDOMPoint in the loop r?m_kato Make the loop in EditorBase::SplitNodeDeep() use EditorDOMPoint for making the code simpler. MozReview-Commit-ID: 3do3rWV4eIh
editor/libeditor/EditorBase.cpp
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -4062,87 +4062,109 @@ EditorBase::SplitNodeDeep(nsIContent& aN
                           int32_t aSplitPointOffset,
                           SplitAtEdges aSplitAtEdges,
                           nsIContent** aOutLeftNode,
                           nsIContent** aOutRightNode,
                           nsCOMPtr<nsIContent>* ioChildAtSplitPointOffset)
 {
   MOZ_ASSERT(&aSplitPointParent == &aNode ||
              EditorUtils::IsDescendantOf(aSplitPointParent, aNode));
-  int32_t offset = aSplitPointOffset;
+
+  int32_t offset =
+    std::min(std::max(aSplitPointOffset, 0),
+             static_cast<int32_t>(aSplitPointParent.Length()));
+  EditorDOMPoint atStartOfRightNode(&aSplitPointParent, offset);
+  if (NS_WARN_IF(!atStartOfRightNode.IsSet())) {
+    return -1;
+  }
+  MOZ_ASSERT(atStartOfRightNode.IsSetAndValid());
 
   nsCOMPtr<nsIContent> leftNode, rightNode;
-  OwningNonNull<nsIContent> nodeToSplit = aSplitPointParent;
   while (true) {
     // If we meet an orphan node before meeting aNode, we need to stop
     // splitting.  This is a bug of the caller.
-    nsCOMPtr<nsIContent> parent = nodeToSplit->GetParent();
-    if (NS_WARN_IF(nodeToSplit != &aNode && !parent)) {
+    if (NS_WARN_IF(atStartOfRightNode.Container() != &aNode &&
+                   !atStartOfRightNode.Container()->GetParent())) {
       return -1;
     }
 
     // Need to insert rules code call here to do things like not split a list
     // if you are after the last <li> or before the first, etc.  For now we
     // just have some smarts about unneccessarily splitting text nodes, which
     // should be universal enough to put straight in this EditorBase routine.
 
+    if (NS_WARN_IF(!atStartOfRightNode.Container()->IsContent())) {
+      return -1;
+    }
+    nsIContent* currentRightNode = atStartOfRightNode.Container()->AsContent();
+
     // If the split point is middle of the node or the node is not a text node
     // and we're allowed to create empty element node, split it.
     if ((aSplitAtEdges == SplitAtEdges::eAllowToCreateEmptyContainer &&
-         !nodeToSplit->GetAsText()) ||
-        (offset && offset != (int32_t)nodeToSplit->Length())) {
+         !atStartOfRightNode.Container()->GetAsText()) ||
+        (!atStartOfRightNode.IsStartOfContainer() &&
+         !atStartOfRightNode.IsEndOfContainer())) {
       ErrorResult error;
-      int32_t offsetAtStartOfRightNode =
-        std::min(std::max(offset, 0),
-                 static_cast<int32_t>(nodeToSplit->Length()));
-      nsCOMPtr<nsIContent> newLeftNode =
-        SplitNode(EditorRawDOMPoint(nodeToSplit, offsetAtStartOfRightNode),
-                  error);
+      rightNode = currentRightNode;
+      leftNode = SplitNode(atStartOfRightNode.AsRaw(), error);
       if (NS_WARN_IF(error.Failed())) {
         error.SuppressException();
         return -1;
       }
 
-      // Then, try to split its parent.
-      offset = parent->IndexOf(nodeToSplit);
-      rightNode = nodeToSplit;
-      leftNode = newLeftNode;
+      // Then, try to split its parent before current node.
+      atStartOfRightNode.Set(currentRightNode);
     }
     // If the split point is end of the node and it is a text node or we're not
     // allowed to create empty container node, try to split its parent after it.
-    else if (offset) {
-      offset = parent->IndexOf(nodeToSplit) + 1;
-      leftNode = nodeToSplit;
+    else if (!atStartOfRightNode.IsStartOfContainer()) {
+      // XXX Making current node which wasn't split treated as new left node
+      //     here.  However, rightNode still may keep referring a descendant
+      //     of the leftNode, which was split.  This must be odd behavior for
+      //     the callers.
+      //     Perhaps, we should set rightNode to currentRightNode?
+      leftNode = currentRightNode;
+
+      // Try to split its parent after current node.
+      atStartOfRightNode.Set(currentRightNode);
+      DebugOnly<bool> advanced = atStartOfRightNode.AdvanceOffset();
+      NS_WARNING_ASSERTION(advanced,
+        "Failed to advance offset after current node");
     }
     // If the split point is start of the node and it is a text node or we're
     // not allowed to create empty container node, try to split its parent.
     else {
-      offset = parent->IndexOf(nodeToSplit);
-      rightNode = nodeToSplit;
+      // XXX Making current node which wasn't split treated as exiting right
+      //     node here.  However, leftNode still may keep referring a
+      //     descendant of rightNode, which was created at splitting.  This
+      //     must be odd behavior for the callers.
+      //     Perhaps, we should set leftNode to nullptr?
+      rightNode = currentRightNode;
+
+      // Try to split its parent before current node.
+      atStartOfRightNode.Set(currentRightNode);
     }
 
-    if (nodeToSplit == &aNode) {
+    if (currentRightNode == &aNode) {
       // we split all the way up to (and including) aNode; we're done
       break;
     }
-
-    nodeToSplit = *parent;
   }
 
   if (aOutLeftNode) {
     leftNode.forget(aOutLeftNode);
   }
   if (aOutRightNode) {
     rightNode.forget(aOutRightNode);
   }
   if (ioChildAtSplitPointOffset) {
-    *ioChildAtSplitPointOffset = nodeToSplit;
-  }
-
-  return offset;
+    *ioChildAtSplitPointOffset = atStartOfRightNode.GetChildAtOffset();
+  }
+
+  return atStartOfRightNode.Offset();
 }
 
 /**
  * This joins two like nodes "deeply", joining children as appropriate.
  * Returns the point of the join, or (nullptr, -1) in case of error.
  */
 EditorDOMPoint
 EditorBase::JoinNodeDeep(nsIContent& aLeftNode,