Bug 1037641 - Split SetDirectionFromChangedTextNode into TextNodeWillChangeDirection and TextNodeChangedDirection. r=ehsan, a=1.3.x+
authorSimon Montagu <smontagu@smontagu.org>
Wed, 06 Aug 2014 12:02:59 +0300
changeset 171611 3601db2820f5f82c6ec48c0a59de270522ede6bb
parent 171610 e4471d4702173002a1d34e75049ea2cd519e88ba
child 171612 709347e7fb78d404255fc234d2068d0877e4307f
push id592
push userryanvm@gmail.com
push dateSun, 17 Aug 2014 17:51:43 +0000
reviewersehsan, 1
bugs1037641
milestone28.0
Bug 1037641 - Split SetDirectionFromChangedTextNode into TextNodeWillChangeDirection and TextNodeChangedDirection. r=ehsan, a=1.3.x+
content/base/public/DirectionalityUtils.h
content/base/src/DirectionalityUtils.cpp
content/base/src/nsGenericDOMDataNode.cpp
--- a/content/base/public/DirectionalityUtils.h
+++ b/content/base/public/DirectionalityUtils.h
@@ -74,22 +74,30 @@ void WalkDescendantsSetDirAuto(mozilla::
 /**
  * After unsetting dir=auto on an element, walk its descendants in tree order,
  * skipping any that have dir=auto themselves, and unset the
  * NODE_ANCESTOR_HAS_DIR_AUTO flag
  */
 void WalkDescendantsClearAncestorDirAuto(mozilla::dom::Element* aElement);
 
 /**
- * When the contents of a text node have changed, deal with any elements whose
- * directionality needs to change
+ * When the contents of a text node are about to change, retrieve the current
+ * directionality of the text
+ *
+ * @return whether the text node affects the directionality of any element
  */
-void SetDirectionFromChangedTextNode(nsIContent* aTextNode, uint32_t aOffset,
-                                     const PRUnichar* aBuffer, uint32_t aLength,
-                                     bool aNotify);
+bool TextNodeWillChangeDirection(nsIContent* aTextNode, Directionality* aOldDir,
+                                 uint32_t aOffset);
+
+/**
+ * After the contents of a text node have changed, change the directionality
+ * of any elements whose directionality is determined by that node
+ */
+void TextNodeChangedDirection(nsIContent* aTextNode, Directionality aOldDir,
+                              bool aNotify);
 
 /**
  * When a text node is appended to an element, find any ancestors with dir=auto
  * whose directionality will be determined by the text node
  */
 void SetDirectionFromNewTextNode(nsIContent* aTextNode);
 
 /**
--- a/content/base/src/DirectionalityUtils.cpp
+++ b/content/base/src/DirectionalityUtils.cpp
@@ -312,16 +312,17 @@ GetDirectionFromText(const PRUnichar* aT
   while (start < end) {
     uint32_t current = start - aText;
     uint32_t ch = *start++;
 
     if (NS_IS_HIGH_SURROGATE(ch) &&
         start < end &&
         NS_IS_LOW_SURROGATE(*start)) {
       ch = SURROGATE_TO_UCS4(ch, *start++);
+      current++;
     }
 
     Directionality dir = GetDirectionFromChar(ch);
     if (dir != eDir_NotSet) {
       if (aFirstStrong) {
         *aFirstStrong = current;
       }
       return dir;
@@ -818,36 +819,37 @@ void SetAncestorDirectionIfAuto(nsINode*
       // parent chain: none of its ancestors will have their direction set by
       // any of its descendants.
       return;
     }
     parent = parent->GetParentElement();
   }
 }
 
-void
-SetDirectionFromChangedTextNode(nsIContent* aTextNode, uint32_t aOffset,
-                                const PRUnichar* aBuffer, uint32_t aLength,
-                                bool aNotify)
+bool
+TextNodeWillChangeDirection(nsIContent* aTextNode, Directionality* aOldDir,
+                            uint32_t aOffset)
 {
   if (!NodeAffectsDirAutoAncestor(aTextNode)) {
     nsTextNodeDirectionalityMap::EnsureMapIsClearFor(aTextNode);
-    return;
+    return false;
   }
 
   uint32_t firstStrong;
-  Directionality oldDir = GetDirectionFromText(aTextNode->GetText(),
-                                               &firstStrong);
-  if (aOffset > firstStrong) {
-    return;
-  }
+  *aOldDir = GetDirectionFromText(aTextNode->GetText(), &firstStrong);
+  return (aOffset <= firstStrong);
+}
 
-  Directionality newDir = GetDirectionFromText(aBuffer, aLength);
+void
+TextNodeChangedDirection(nsIContent* aTextNode, Directionality aOldDir,
+                         bool aNotify)
+{
+  Directionality newDir = GetDirectionFromText(aTextNode->GetText());
   if (newDir == eDir_NotSet) {
-    if (oldDir != eDir_NotSet && aTextNode->HasTextNodeDirectionalityMap()) {
+    if (aOldDir != eDir_NotSet && aTextNode->HasTextNodeDirectionalityMap()) {
       // This node used to have a strong directional character but no
       // longer does. ResetTextNodeDirection() will re-resolve the
       // directionality of any elements whose directionality was
       // determined by this node.
       nsTextNodeDirectionalityMap::ResetTextNodeDirection(aTextNode);
     }
   } else {
     // This node has a strong directional character. If it has a
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -301,19 +301,19 @@ nsGenericDOMDataNode::SetTextInternal(ui
       aOffset,
       endOffset,
       aLength,
       aDetails
     };
     nsNodeUtils::CharacterDataWillChange(this, &info);
   }
 
-  if (NodeType() == nsIDOMNode::TEXT_NODE) {
-    SetDirectionFromChangedTextNode(this, aOffset, aBuffer, aLength, aNotify);
-  }
+  Directionality oldDir = eDir_NotSet;
+  bool dirAffectsAncestor = (NodeType() == nsIDOMNode::TEXT_NODE &&
+                             TextNodeWillChangeDirection(this, &oldDir, aOffset));
 
   if (aOffset == 0 && endOffset == textLength) {
     // Replacing whole text or old text was empty.  Don't bother to check for
     // bidi in this string if the document already has bidi enabled.
     mText.SetTo(aBuffer, aLength, !document || !document->GetBidiEnabled());
   }
   else if (aOffset == textLength) {
     // Appending to existing
@@ -347,16 +347,20 @@ nsGenericDOMDataNode::SetTextInternal(ui
   UnsetFlags(NS_CACHED_TEXT_IS_ONLY_WHITESPACE);
 
   if (document && mText.IsBidi()) {
     // If we found bidi characters in mText.SetTo() above, indicate that the
     // document contains bidi characters.
     document->SetBidiEnabled();
   }
 
+  if (dirAffectsAncestor) {
+    TextNodeChangedDirection(this, oldDir, aNotify);
+  }
+
   // Notify observers
   if (aNotify) {
     CharacterDataChangeInfo info = {
       aOffset == textLength,
       aOffset,
       endOffset,
       aLength,
       aDetails