From 5624d576e921735a54cd4c59f36701f4551391f6 Mon Sep 17 00:00:00 2001 From: "vidur%netscape.com" Date: Mon, 22 Jan 2001 23:11:02 +0000 Subject: [PATCH] Fix for bug 63081. We remove carriage returns passed to us by the parser in the copy from the sink buffer to the content model. r=jst git-svn-id: svn://10.0.0.236/trunk@85317 18797224-902f-48f8-a5cc-f745e15eee43 --- .../base/src/nsPlainTextSerializer.cpp | 19 ++- .../html/document/src/nsHTMLContentSink.cpp | 7 +- .../src/nsHTMLFragmentContentSink.cpp | 7 +- .../xml/document/src/nsXMLContentSink.cpp | 7 +- mozilla/layout/base/nsLayoutUtils.cpp | 152 ++++++++++++++++++ mozilla/layout/base/nsLayoutUtils.h | 8 + mozilla/layout/base/public/nsLayoutUtils.h | 8 + mozilla/layout/base/src/nsLayoutUtils.cpp | 152 ++++++++++++++++++ .../layout/base/src/nsPlainTextSerializer.cpp | 19 ++- .../html/document/src/nsHTMLContentSink.cpp | 7 +- .../src/nsHTMLFragmentContentSink.cpp | 7 +- .../xml/document/src/nsXMLContentSink.cpp | 7 +- 12 files changed, 384 insertions(+), 16 deletions(-) diff --git a/mozilla/content/base/src/nsPlainTextSerializer.cpp b/mozilla/content/base/src/nsPlainTextSerializer.cpp index 9739669a776..2e75ff27fab 100644 --- a/mozilla/content/base/src/nsPlainTextSerializer.cpp +++ b/mozilla/content/base/src/nsPlainTextSerializer.cpp @@ -35,6 +35,7 @@ #include "nsITextContent.h" #include "nsTextFragment.h" #include "nsParserCIID.h" +#include "nsLayoutUtils.h" static NS_DEFINE_CID(kLWBrkCID, NS_LWBRK_CID); static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); @@ -363,11 +364,25 @@ nsPlainTextSerializer::CloseContainer(const nsIParserNode& aNode) NS_IMETHODIMP nsPlainTextSerializer::AddLeaf(const nsIParserNode& aNode) { - PRInt32 type = aNode.GetNodeType(); + eHTMLTags type = (eHTMLTags)aNode.GetNodeType(); const nsAReadableString& text = aNode.GetText(); mParserNode = NS_CONST_CAST(nsIParserNode *, &aNode); - return DoAddLeaf(type, text); + if ((type == eHTMLTag_text) || + (type == eHTMLTag_whitespace) || + (type == eHTMLTag_newline)) { + // Copy the text out, stripping out CRs + nsAutoString str; + PRUint32 length; + str.SetCapacity(text.Length()); + nsReadingIterator srcStart, srcEnd; + length = nsLayoutUtils::CopyNewlineNormalizedUnicodeTo(text.BeginReading(srcStart), text.EndReading(srcEnd), str); + str.SetLength(length); + return DoAddLeaf(type, str); + } + else { + return DoAddLeaf(type, text); + } } NS_IMETHODIMP diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index b4ac938982c..d9d9166cb65 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -66,6 +66,7 @@ #include "nsIScrollableView.h" #include "nsHTMLAtoms.h" +#include "nsLayoutUtils.h" #include "nsIFrame.h" #include "nsICharsetConverterManager.h" #include "nsICharsetConverterManager2.h" @@ -1945,8 +1946,10 @@ SinkContext::AddText(const nsAReadableString& aText) return rv; } } - CopyUnicodeTo(aText, offset, &mText[mTextLength], amount); - mTextLength += amount; + mTextLength += nsLayoutUtils::CopyNewlineNormalizedUnicodeTo(aText, + offset, + &mText[mTextLength], + amount); offset += amount; addLen -= amount; } diff --git a/mozilla/content/html/document/src/nsHTMLFragmentContentSink.cpp b/mozilla/content/html/document/src/nsHTMLFragmentContentSink.cpp index 058e82b5da6..3fb33e52311 100644 --- a/mozilla/content/html/document/src/nsHTMLFragmentContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLFragmentContentSink.cpp @@ -43,6 +43,7 @@ #include "nsINodeInfo.h" #include "prmem.h" #include "nsReadableUtils.h" +#include "nsLayoutUtils.h" // // XXX THIS IS TEMPORARY CODE @@ -766,8 +767,10 @@ nsHTMLFragmentContentSink::AddText(const nsAReadableString& aString) return rv; } } - CopyUnicodeTo(aString, offset, &mText[mTextLength], amount); - mTextLength += amount; + mTextLength += nsLayoutUtils::CopyNewlineNormalizedUnicodeTo(aString, + offset, + &mText[mTextLength], + amount); offset += amount; addLen -= amount; } diff --git a/mozilla/content/xml/document/src/nsXMLContentSink.cpp b/mozilla/content/xml/document/src/nsXMLContentSink.cpp index b5624070ccb..f1beb9ad3bc 100644 --- a/mozilla/content/xml/document/src/nsXMLContentSink.cpp +++ b/mozilla/content/xml/document/src/nsXMLContentSink.cpp @@ -56,6 +56,7 @@ #include "nsICSSStyleSheet.h" #include "nsIHTMLContentContainer.h" #include "nsHTMLAtoms.h" +#include "nsLayoutUtils.h" #include "nsLayoutAtoms.h" #include "nsLayoutCID.h" #include "nsIScriptContext.h" @@ -1336,8 +1337,10 @@ nsXMLContentSink::AddText(const nsAReadableString& aString) } } } - CopyUnicodeTo(aString, offset, &mText[mTextLength], amount); - mTextLength += amount; + mTextLength += nsLayoutUtils::CopyNewlineNormalizedUnicodeTo(aString, + offset, + &mText[mTextLength], + amount); offset += amount; addLen -= amount; } diff --git a/mozilla/layout/base/nsLayoutUtils.cpp b/mozilla/layout/base/nsLayoutUtils.cpp index f7910ed824a..4f887d3e464 100644 --- a/mozilla/layout/base/nsLayoutUtils.cpp +++ b/mozilla/layout/base/nsLayoutUtils.cpp @@ -118,4 +118,156 @@ nsLayoutUtils::GetDynamicScriptContext(JSContext *aContext, (void**)aScriptContext); } +template +struct NormalizeNewlinesCharTraits { + public: + typedef typename OutputIterator::value_type value_type; + public: + NormalizeNewlinesCharTraits(OutputIterator& aIterator) : mIterator(aIterator) { } + void writechar(typename OutputIterator::value_type aChar) { + *mIterator++ = aChar; + } + + private: + OutputIterator mIterator; +}; + +#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION + +template +struct NormalizeNewlinesCharTraits { + public: + typedef CharT value_type; + + public: + NormalizeNewlinesCharTraits(CharT* aCharPtr) : mCharPtr(aCharPtr) { } + void writechar(CharT aChar) { + *mCharPtr++ = aChar; + } + + private: + CharT* mCharPtr; +}; + +#else + +NS_SPECIALIZE_TEMPLATE +struct NormalizeNewlinesCharTraits { + public: + typedef char value_type; + + public: + NormalizeNewlinesCharTraits(char* aCharPtr) : mCharPtr(aCharPtr) { } + void writechar(char aChar) { + *mCharPtr++ = aChar; + } + + private: + char* mCharPtr; +}; + +NS_SPECIALIZE_TEMPLATE +struct NormalizeNewlinesCharTraits { + public: + typedef PRUnichar value_type; + + public: + NormalizeNewlinesCharTraits(PRUnichar* aCharPtr) : mCharPtr(aCharPtr) { } + void writechar(PRUnichar aChar) { + *mCharPtr++ = aChar; + } + + private: + PRUnichar* mCharPtr; +}; + +#endif + +template +class CopyNormalizeNewlines +{ + public: + typedef typename OutputIterator::value_type value_type; + + public: + CopyNormalizeNewlines(OutputIterator* aDestination) : + mLastCharCR(PR_FALSE), + mDestination(aDestination), + mWritten(0) + { } + + PRUint32 GetCharsWritten() { + return mWritten; + } + + PRUint32 write(const typename OutputIterator::value_type* aSource, PRUint32 aSourceLength) { + // If the last source buffer ended with a CR... + if (mLastCharCR) { + // ..and if the next one is a LF, then skip it since + // we've already written out a newline + if (aSourceLength && (*aSource == value_type('\n'))) { + aSource++; + } + mLastCharCR = PR_FALSE; + } + + const typename OutputIterator::value_type* done_writing = aSource + aSourceLength; + PRUint32 num_written = 0; + while ( aSource < done_writing ) { + if (*aSource == value_type('\r')) { + mDestination->writechar('\n'); + aSource++; + // If we've reached the end of the buffer, record + // that we wrote out a CR + if (aSource == done_writing) { + mLastCharCR = PR_TRUE; + } + // If the next character is a LF, skip it + else if (*aSource == value_type('\n')) { + aSource++; + } + } + else { + mDestination->writechar(*aSource++); + } + num_written++; + } + + mWritten += num_written; + return aSourceLength; + } + + private: + PRBool mLastCharCR; + OutputIterator* mDestination; + PRUint32 mWritten; +}; + +// static +PRUint32 +nsLayoutUtils::CopyNewlineNormalizedUnicodeTo(const nsAReadableString& aSource, PRUint32 aSrcOffset, PRUnichar* aDest, PRUint32 aLength) +{ + typedef NormalizeNewlinesCharTraits sink_traits; + + sink_traits dest_traits(aDest); + CopyNormalizeNewlines normalizer(&dest_traits); + nsReadingIterator fromBegin, fromEnd; + copy_string(aSource.BeginReading(fromBegin).advance( PRInt32(aSrcOffset) ), aSource.BeginReading(fromEnd).advance( PRInt32(aSrcOffset+aLength) ), normalizer); + return normalizer.GetCharsWritten(); +} + +// static +PRUint32 +nsLayoutUtils::CopyNewlineNormalizedUnicodeTo(nsReadingIterator& aSrcStart, const nsReadingIterator& aSrcEnd, nsAWritableString& aDest) +{ + typedef nsWritingIterator WritingIterator; + typedef NormalizeNewlinesCharTraits sink_traits; + + WritingIterator iter; + aDest.BeginWriting(iter); + sink_traits dest_traits(iter); + CopyNormalizeNewlines normalizer(&dest_traits); + copy_string(aSrcStart, aSrcEnd, normalizer); + return normalizer.GetCharsWritten(); +} diff --git a/mozilla/layout/base/nsLayoutUtils.h b/mozilla/layout/base/nsLayoutUtils.h index 3b04cc63524..ab140c9a6b4 100644 --- a/mozilla/layout/base/nsLayoutUtils.h +++ b/mozilla/layout/base/nsLayoutUtils.h @@ -39,6 +39,7 @@ #include "nslayout.h" #include "jspubtd.h" +#include "nsAReadableString.h" class nsIScriptContext; class nsIScriptGlobalObject; @@ -62,6 +63,13 @@ public: static nsresult GetDynamicScriptContext(JSContext *aContext, nsIScriptContext** aScriptContext); + + static PRUint32 CopyNewlineNormalizedUnicodeTo(const nsAReadableString& aSource, + PRUint32 aSrcOffset, + PRUnichar* aDest, + PRUint32 aLength); + + static PRUint32 CopyNewlineNormalizedUnicodeTo(nsReadingIterator& aSrcStart, const nsReadingIterator& aSrcEnd, nsAWritableString& aDest); }; #endif /* nsLayoutUtils_h___ */ diff --git a/mozilla/layout/base/public/nsLayoutUtils.h b/mozilla/layout/base/public/nsLayoutUtils.h index 3b04cc63524..ab140c9a6b4 100644 --- a/mozilla/layout/base/public/nsLayoutUtils.h +++ b/mozilla/layout/base/public/nsLayoutUtils.h @@ -39,6 +39,7 @@ #include "nslayout.h" #include "jspubtd.h" +#include "nsAReadableString.h" class nsIScriptContext; class nsIScriptGlobalObject; @@ -62,6 +63,13 @@ public: static nsresult GetDynamicScriptContext(JSContext *aContext, nsIScriptContext** aScriptContext); + + static PRUint32 CopyNewlineNormalizedUnicodeTo(const nsAReadableString& aSource, + PRUint32 aSrcOffset, + PRUnichar* aDest, + PRUint32 aLength); + + static PRUint32 CopyNewlineNormalizedUnicodeTo(nsReadingIterator& aSrcStart, const nsReadingIterator& aSrcEnd, nsAWritableString& aDest); }; #endif /* nsLayoutUtils_h___ */ diff --git a/mozilla/layout/base/src/nsLayoutUtils.cpp b/mozilla/layout/base/src/nsLayoutUtils.cpp index f7910ed824a..4f887d3e464 100644 --- a/mozilla/layout/base/src/nsLayoutUtils.cpp +++ b/mozilla/layout/base/src/nsLayoutUtils.cpp @@ -118,4 +118,156 @@ nsLayoutUtils::GetDynamicScriptContext(JSContext *aContext, (void**)aScriptContext); } +template +struct NormalizeNewlinesCharTraits { + public: + typedef typename OutputIterator::value_type value_type; + public: + NormalizeNewlinesCharTraits(OutputIterator& aIterator) : mIterator(aIterator) { } + void writechar(typename OutputIterator::value_type aChar) { + *mIterator++ = aChar; + } + + private: + OutputIterator mIterator; +}; + +#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION + +template +struct NormalizeNewlinesCharTraits { + public: + typedef CharT value_type; + + public: + NormalizeNewlinesCharTraits(CharT* aCharPtr) : mCharPtr(aCharPtr) { } + void writechar(CharT aChar) { + *mCharPtr++ = aChar; + } + + private: + CharT* mCharPtr; +}; + +#else + +NS_SPECIALIZE_TEMPLATE +struct NormalizeNewlinesCharTraits { + public: + typedef char value_type; + + public: + NormalizeNewlinesCharTraits(char* aCharPtr) : mCharPtr(aCharPtr) { } + void writechar(char aChar) { + *mCharPtr++ = aChar; + } + + private: + char* mCharPtr; +}; + +NS_SPECIALIZE_TEMPLATE +struct NormalizeNewlinesCharTraits { + public: + typedef PRUnichar value_type; + + public: + NormalizeNewlinesCharTraits(PRUnichar* aCharPtr) : mCharPtr(aCharPtr) { } + void writechar(PRUnichar aChar) { + *mCharPtr++ = aChar; + } + + private: + PRUnichar* mCharPtr; +}; + +#endif + +template +class CopyNormalizeNewlines +{ + public: + typedef typename OutputIterator::value_type value_type; + + public: + CopyNormalizeNewlines(OutputIterator* aDestination) : + mLastCharCR(PR_FALSE), + mDestination(aDestination), + mWritten(0) + { } + + PRUint32 GetCharsWritten() { + return mWritten; + } + + PRUint32 write(const typename OutputIterator::value_type* aSource, PRUint32 aSourceLength) { + // If the last source buffer ended with a CR... + if (mLastCharCR) { + // ..and if the next one is a LF, then skip it since + // we've already written out a newline + if (aSourceLength && (*aSource == value_type('\n'))) { + aSource++; + } + mLastCharCR = PR_FALSE; + } + + const typename OutputIterator::value_type* done_writing = aSource + aSourceLength; + PRUint32 num_written = 0; + while ( aSource < done_writing ) { + if (*aSource == value_type('\r')) { + mDestination->writechar('\n'); + aSource++; + // If we've reached the end of the buffer, record + // that we wrote out a CR + if (aSource == done_writing) { + mLastCharCR = PR_TRUE; + } + // If the next character is a LF, skip it + else if (*aSource == value_type('\n')) { + aSource++; + } + } + else { + mDestination->writechar(*aSource++); + } + num_written++; + } + + mWritten += num_written; + return aSourceLength; + } + + private: + PRBool mLastCharCR; + OutputIterator* mDestination; + PRUint32 mWritten; +}; + +// static +PRUint32 +nsLayoutUtils::CopyNewlineNormalizedUnicodeTo(const nsAReadableString& aSource, PRUint32 aSrcOffset, PRUnichar* aDest, PRUint32 aLength) +{ + typedef NormalizeNewlinesCharTraits sink_traits; + + sink_traits dest_traits(aDest); + CopyNormalizeNewlines normalizer(&dest_traits); + nsReadingIterator fromBegin, fromEnd; + copy_string(aSource.BeginReading(fromBegin).advance( PRInt32(aSrcOffset) ), aSource.BeginReading(fromEnd).advance( PRInt32(aSrcOffset+aLength) ), normalizer); + return normalizer.GetCharsWritten(); +} + +// static +PRUint32 +nsLayoutUtils::CopyNewlineNormalizedUnicodeTo(nsReadingIterator& aSrcStart, const nsReadingIterator& aSrcEnd, nsAWritableString& aDest) +{ + typedef nsWritingIterator WritingIterator; + typedef NormalizeNewlinesCharTraits sink_traits; + + WritingIterator iter; + aDest.BeginWriting(iter); + sink_traits dest_traits(iter); + CopyNormalizeNewlines normalizer(&dest_traits); + copy_string(aSrcStart, aSrcEnd, normalizer); + return normalizer.GetCharsWritten(); +} diff --git a/mozilla/layout/base/src/nsPlainTextSerializer.cpp b/mozilla/layout/base/src/nsPlainTextSerializer.cpp index 9739669a776..2e75ff27fab 100644 --- a/mozilla/layout/base/src/nsPlainTextSerializer.cpp +++ b/mozilla/layout/base/src/nsPlainTextSerializer.cpp @@ -35,6 +35,7 @@ #include "nsITextContent.h" #include "nsTextFragment.h" #include "nsParserCIID.h" +#include "nsLayoutUtils.h" static NS_DEFINE_CID(kLWBrkCID, NS_LWBRK_CID); static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); @@ -363,11 +364,25 @@ nsPlainTextSerializer::CloseContainer(const nsIParserNode& aNode) NS_IMETHODIMP nsPlainTextSerializer::AddLeaf(const nsIParserNode& aNode) { - PRInt32 type = aNode.GetNodeType(); + eHTMLTags type = (eHTMLTags)aNode.GetNodeType(); const nsAReadableString& text = aNode.GetText(); mParserNode = NS_CONST_CAST(nsIParserNode *, &aNode); - return DoAddLeaf(type, text); + if ((type == eHTMLTag_text) || + (type == eHTMLTag_whitespace) || + (type == eHTMLTag_newline)) { + // Copy the text out, stripping out CRs + nsAutoString str; + PRUint32 length; + str.SetCapacity(text.Length()); + nsReadingIterator srcStart, srcEnd; + length = nsLayoutUtils::CopyNewlineNormalizedUnicodeTo(text.BeginReading(srcStart), text.EndReading(srcEnd), str); + str.SetLength(length); + return DoAddLeaf(type, str); + } + else { + return DoAddLeaf(type, text); + } } NS_IMETHODIMP diff --git a/mozilla/layout/html/document/src/nsHTMLContentSink.cpp b/mozilla/layout/html/document/src/nsHTMLContentSink.cpp index b4ac938982c..d9d9166cb65 100644 --- a/mozilla/layout/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/layout/html/document/src/nsHTMLContentSink.cpp @@ -66,6 +66,7 @@ #include "nsIScrollableView.h" #include "nsHTMLAtoms.h" +#include "nsLayoutUtils.h" #include "nsIFrame.h" #include "nsICharsetConverterManager.h" #include "nsICharsetConverterManager2.h" @@ -1945,8 +1946,10 @@ SinkContext::AddText(const nsAReadableString& aText) return rv; } } - CopyUnicodeTo(aText, offset, &mText[mTextLength], amount); - mTextLength += amount; + mTextLength += nsLayoutUtils::CopyNewlineNormalizedUnicodeTo(aText, + offset, + &mText[mTextLength], + amount); offset += amount; addLen -= amount; } diff --git a/mozilla/layout/html/document/src/nsHTMLFragmentContentSink.cpp b/mozilla/layout/html/document/src/nsHTMLFragmentContentSink.cpp index 058e82b5da6..3fb33e52311 100644 --- a/mozilla/layout/html/document/src/nsHTMLFragmentContentSink.cpp +++ b/mozilla/layout/html/document/src/nsHTMLFragmentContentSink.cpp @@ -43,6 +43,7 @@ #include "nsINodeInfo.h" #include "prmem.h" #include "nsReadableUtils.h" +#include "nsLayoutUtils.h" // // XXX THIS IS TEMPORARY CODE @@ -766,8 +767,10 @@ nsHTMLFragmentContentSink::AddText(const nsAReadableString& aString) return rv; } } - CopyUnicodeTo(aString, offset, &mText[mTextLength], amount); - mTextLength += amount; + mTextLength += nsLayoutUtils::CopyNewlineNormalizedUnicodeTo(aString, + offset, + &mText[mTextLength], + amount); offset += amount; addLen -= amount; } diff --git a/mozilla/layout/xml/document/src/nsXMLContentSink.cpp b/mozilla/layout/xml/document/src/nsXMLContentSink.cpp index b5624070ccb..f1beb9ad3bc 100644 --- a/mozilla/layout/xml/document/src/nsXMLContentSink.cpp +++ b/mozilla/layout/xml/document/src/nsXMLContentSink.cpp @@ -56,6 +56,7 @@ #include "nsICSSStyleSheet.h" #include "nsIHTMLContentContainer.h" #include "nsHTMLAtoms.h" +#include "nsLayoutUtils.h" #include "nsLayoutAtoms.h" #include "nsLayoutCID.h" #include "nsIScriptContext.h" @@ -1336,8 +1337,10 @@ nsXMLContentSink::AddText(const nsAReadableString& aString) } } } - CopyUnicodeTo(aString, offset, &mText[mTextLength], amount); - mTextLength += amount; + mTextLength += nsLayoutUtils::CopyNewlineNormalizedUnicodeTo(aString, + offset, + &mText[mTextLength], + amount); offset += amount; addLen -= amount; }