diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.cpp b/mozilla/content/base/src/nsGenericDOMDataNode.cpp index 7c2006818d0..001c259f4c2 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.cpp +++ b/mozilla/content/base/src/nsGenericDOMDataNode.cpp @@ -655,6 +655,11 @@ nsGenericDOMDataNode::SetDocument(nsIDocument* aDocument, PRBool aDeep, PRBool a // XXX: Root! } } +#ifdef IBMBIDI + if (mText.IsBidi()) { + mDocument->SetBidiEnabled(PR_TRUE); + } +#endif } return NS_OK; @@ -961,16 +966,10 @@ nsGenericDOMDataNode::SetText(nsIContent *aOuterContent, if (aNotify && (nsnull != mDocument)) { mDocument->BeginUpdate(); } -#ifdef IBMBIDI - if (mDocument != nsnull) { - PRBool bidiEnabled = mText.SetTo(aBuffer, aLength); - if (bidiEnabled) { - mDocument->SetBidiEnabled(PR_TRUE); - } - } - else -#endif // IBMBIDI mText.SetTo(aBuffer, aLength); +#ifdef IBMBIDI + SetBidiStatus(); +#endif // IBMBIDI if (mDocument && nsGenericElement::HasMutationListeners(aOuterContent, NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED)) { nsCOMPtr node(do_QueryInterface(aOuterContent)); @@ -1045,6 +1044,9 @@ nsGenericDOMDataNode::SetText(nsIContent *aOuterContent, mDocument->BeginUpdate(); } mText = aStr; +#ifdef IBMBIDI + SetBidiStatus(); +#endif // IBMBIDI if (mDocument && nsGenericElement::HasMutationListeners(aOuterContent, NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED)) { nsCOMPtr node(do_QueryInterface(aOuterContent)); @@ -1101,3 +1103,21 @@ nsGenericDOMDataNode::IsOnlyWhitespace(PRBool* aResult) *aResult = PR_TRUE; return NS_OK; } + +#ifdef IBMBIDI +void nsGenericDOMDataNode::SetBidiStatus() +{ + PRBool isBidiDocument = PR_FALSE; + if (mDocument) { + mDocument->GetBidiEnabled(&isBidiDocument); + if (isBidiDocument) { + // OK, we already know it's Bidi, so we won't test again + return; + } + } + mText.SetBidiFlag(); + if (mDocument && mText.IsBidi()) { + mDocument->SetBidiEnabled(PR_TRUE); + } +} +#endif // IBMBIDI diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.h b/mozilla/content/base/src/nsGenericDOMDataNode.h index 5f64c3d3c2e..141bdc4c14b 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.h +++ b/mozilla/content/base/src/nsGenericDOMDataNode.h @@ -287,6 +287,9 @@ struct nsGenericDOMDataNode { //---------------------------------------- void ToCString(nsAWritableString& aBuf, PRInt32 aOffset, PRInt32 aLen) const; +#ifdef IBMBIDI + void SetBidiStatus(); +#endif nsIDocument* mDocument; nsIContent* mParent; diff --git a/mozilla/content/base/src/nsTextFragment.h b/mozilla/content/base/src/nsTextFragment.h index 8a857c90aed..34d6c8dc364 100644 --- a/mozilla/content/base/src/nsTextFragment.h +++ b/mozilla/content/base/src/nsTextFragment.h @@ -138,6 +138,19 @@ public: return mState.mIs2b; } +#ifdef IBMBIDI + /** + * Return PR_TRUE if this fragment contains Bidi text + * For performance reasons this flag is not set automatically, but + * requires an explicit call to SetBidiFlag() + */ + PRBool IsBidi() const + { + return mState.mIsBidi; + } +#endif + + /** * Get a pointer to constant PRUnichar data. */ @@ -178,7 +191,7 @@ public: * buffer. Like operator= except a length is specified instead of * assuming 0 termination. */ - PRBool SetTo(const PRUnichar *aBuffer, PRInt32 aLength); + void SetTo(const PRUnichar* aBuffer, PRInt32 aLength); /** * Change the contents of this fragment to be a copy of the given @@ -218,10 +231,19 @@ public: return mState.mIs2b ? m2b[aIndex] : PRUnichar(m1b[aIndex]); } +#ifdef IBMBIDI + /** + * Scan the contents of the fragment and turn on mState.mIsBidi if it + * includes any Bidi characters. + */ + void SetBidiFlag(); +#endif + struct FragmentBits { PRBool mInHeap : 1; PRBool mIs2b : 1; - PRUint32 mLength : 30; + PRBool mIsBidi : 1; + PRUint32 mLength : 29; }; protected: diff --git a/mozilla/content/shared/public/nsTextFragment.h b/mozilla/content/shared/public/nsTextFragment.h index 8a857c90aed..34d6c8dc364 100644 --- a/mozilla/content/shared/public/nsTextFragment.h +++ b/mozilla/content/shared/public/nsTextFragment.h @@ -138,6 +138,19 @@ public: return mState.mIs2b; } +#ifdef IBMBIDI + /** + * Return PR_TRUE if this fragment contains Bidi text + * For performance reasons this flag is not set automatically, but + * requires an explicit call to SetBidiFlag() + */ + PRBool IsBidi() const + { + return mState.mIsBidi; + } +#endif + + /** * Get a pointer to constant PRUnichar data. */ @@ -178,7 +191,7 @@ public: * buffer. Like operator= except a length is specified instead of * assuming 0 termination. */ - PRBool SetTo(const PRUnichar *aBuffer, PRInt32 aLength); + void SetTo(const PRUnichar* aBuffer, PRInt32 aLength); /** * Change the contents of this fragment to be a copy of the given @@ -218,10 +231,19 @@ public: return mState.mIs2b ? m2b[aIndex] : PRUnichar(m1b[aIndex]); } +#ifdef IBMBIDI + /** + * Scan the contents of the fragment and turn on mState.mIsBidi if it + * includes any Bidi characters. + */ + void SetBidiFlag(); +#endif + struct FragmentBits { PRBool mInHeap : 1; PRBool mIs2b : 1; - PRUint32 mLength : 30; + PRBool mIsBidi : 1; + PRUint32 mLength : 29; }; protected: diff --git a/mozilla/content/shared/src/nsTextFragment.cpp b/mozilla/content/shared/src/nsTextFragment.cpp index fe49641d0ab..6e932478221 100644 --- a/mozilla/content/shared/src/nsTextFragment.cpp +++ b/mozilla/content/shared/src/nsTextFragment.cpp @@ -167,11 +167,9 @@ nsTextFragment::SetTo(PRUnichar *aBuffer, PRInt32 aLength, PRBool aRelease) mState.mLength = aLength; } -PRBool -nsTextFragment::SetTo(const PRUnichar *aBuffer, PRInt32 aLength) +void +nsTextFragment::SetTo(const PRUnichar* aBuffer, PRInt32 aLength) { - PRBool bidiEnabled = PR_FALSE; - ReleaseText(); if (aLength != 0) { @@ -183,14 +181,7 @@ nsTextFragment::SetTo(const PRUnichar *aBuffer, PRInt32 aLength) PRUnichar ch = *ucp++; if (ch >> 8) { need2 = PR_TRUE; -#ifdef IBMBIDI - if (CHAR_IS_BIDI(ch) ) { - bidiEnabled = PR_TRUE; -#endif // IBMBIDI break; -#ifdef IBMBIDI - } -#endif // IBMBIDI } } @@ -202,7 +193,7 @@ nsTextFragment::SetTo(const PRUnichar *aBuffer, PRInt32 aLength) if (!m2b) { NS_ERROR("Failed to clone string buffer!"); - return PR_FALSE; + return; } // Setup our fields @@ -225,7 +216,7 @@ nsTextFragment::SetTo(const PRUnichar *aBuffer, PRInt32 aLength) if (!nt) { NS_ERROR("Failed to allocate string buffer!"); - return bidiEnabled; + return; } // Copy data @@ -242,8 +233,6 @@ nsTextFragment::SetTo(const PRUnichar *aBuffer, PRInt32 aLength) mState.mLength = aLength; } } - - return bidiEnabled; } void @@ -337,3 +326,23 @@ nsTextFragment::CopyTo(char *aDest, PRInt32 aOffset, PRInt32 aCount) } } } + +#ifdef IBMBIDI +// To save time we only do this when we really want to know, not during +// every allocation +void +nsTextFragment::SetBidiFlag() +{ + if (mState.mIs2b && !mState.mIsBidi) { + const PRUnichar* cp = m2b; + const PRUnichar* end = cp + mState.mLength; + while (cp < end) { + PRUnichar ch = *cp++; + if (CHAR_IS_BIDI(ch) ) { + mState.mIsBidi = PR_TRUE; + break; + } + } + } +} +#endif