From 8f8938b90141907dd9e0609dfab06a296a52f6e0 Mon Sep 17 00:00:00 2001 From: "akkana%netscape.com" Date: Thu, 24 Aug 2000 19:37:48 +0000 Subject: [PATCH] 46333: fix whitespace between table cells and list items (nsbeta3+) 46452: linebreak for tr 49724 and 50150: potential infinite loop in EndLine Reviewed by Ben Bucksch, Daniel Bratell, and Kin Blas, and including some fixes contributed by each of them. git-svn-id: svn://10.0.0.236/trunk@77100 18797224-902f-48f8-a5cc-f745e15eee43 --- .../htmlparser/src/nsHTMLToTXTSinkStream.cpp | 124 ++++++++++-------- .../htmlparser/src/nsHTMLToTXTSinkStream.cpp | 124 ++++++++++-------- 2 files changed, 138 insertions(+), 110 deletions(-) diff --git a/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.cpp b/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.cpp index 2418d37ac73..9b38d704361 100644 --- a/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.cpp +++ b/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.cpp @@ -24,7 +24,6 @@ * Ben Bucksch * Pierre Phaneuf * Markus Kuhn - * */ /** @@ -282,7 +281,7 @@ nsHTMLToTXTSinkStream::Initialize(nsIOutputStream* aOutStream, { mCacheLine = PR_TRUE; } - + // Set the line break character: if ((mFlags & nsIDocumentEncoder::OutputCRLineBreak) && (mFlags & nsIDocumentEncoder::OutputLFLineBreak)) // Windows/mail @@ -495,10 +494,9 @@ PRBool nsHTMLToTXTSinkStream::DoOutput() /** - * This method is used to a general container. + * This method is used to open a general container. * This includes: OL,UL,DIR,SPAN,TABLE,H[1..6],etc. * - * @update 07/12/98 gpk * @param nsIParserNode reference to parser node interface * @return PR_TRUE if successful. */ @@ -598,6 +596,27 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode) if (type == eHTMLTag_p || type == eHTMLTag_pre) EnsureVerticalSpace(1); // Should this be 0 in unformatted case? + + else if (type == eHTMLTag_td || type == eHTMLTag_th) + { + // We must make sure that the content of two table cells get a + // space between them. + + // Fow now, I will only add a SPACE. Could be a TAB or something + // else but I'm not sure everything can handle the TAB so SPACE + // seems like a better solution. + if(!mInWhitespace) { + // Maybe add something else? Several spaces? A TAB? SPACE+TAB? + if(mCacheLine) { + AddToLine(NS_ConvertToString(" ").GetUnicode(), 1); + } else { + nsAutoString space(NS_ConvertToString(" ")); + WriteSimple(space); + } + mInWhitespace = PR_TRUE; + } + } + // Else make sure we'll separate block level tags, // even if we're about to leave, before doing any other formatting. else if (IsBlockLevel(type)) @@ -677,28 +696,10 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode) EnsureVerticalSpace(1); else if (type == eHTMLTag_dd) mIndent += gIndentSizeDD; - else if (type == eHTMLTag_td || type == eHTMLTag_th) - { - // We must make sure that the content of two table cells get a - // space between them. - - // Fow now, I will only add a SPACE. Could be a TAB or something - // else but I'm not sure everything can handle the TAB so SPACE - // seems like a better solution. - if(!mInWhitespace) { - // Maybe add something else? Several spaces? A TAB? SPACE+TAB? - if(mCacheLine) { - AddToLine(NS_ConvertToString(" ").GetUnicode(), 1); - } else { - nsAutoString space(NS_ConvertToString(" ")); - WriteSimple(space); - } - mInWhitespace = PR_TRUE; - } - } else if (type == eHTMLTag_blockquote) { - EnsureVerticalSpace(0); + EnsureVerticalSpace(1); + // Find out whether it's a type=cite, and insert "> " instead. // Eventually we should get the value of the pref controlling citations, // and handle AOL-style citations as well. @@ -716,6 +717,7 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode) else mIndent += gTabSize; // Check for some maximum value? } + else if (type == eHTMLTag_img) { /* Output (in decreasing order of preference) @@ -752,6 +754,7 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode) if (!temp.IsEmpty()) Write(temp); } + else if (type == eHTMLTag_a && !IsConverted(aNode)) { nsAutoString url; @@ -797,31 +800,36 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode) --mTagStackIndex; // End current line if we're ending a block level tag - if (IsBlockLevel(type)) { - if((type == eHTMLTag_body) || (type == eHTMLTag_html)) { - // We want the output to end with a new line, - // but in preformatted areas like text fields, - // we can't emit newlines that weren't there. - // So add the newline only in the case of formatted output. - if (mFlags & nsIDocumentEncoder::OutputFormatted) - EnsureVerticalSpace(0); - else - FlushLine(); - } else if ((type == eHTMLTag_tr) || - (type == eHTMLTag_li) || - (type == eHTMLTag_dt) || - (type == eHTMLTag_dd) || - (type == eHTMLTag_pre) || - (type == eHTMLTag_blockquote)) { + if((type == eHTMLTag_body) || (type == eHTMLTag_html)) { + // We want the output to end with a new line, + // but in preformatted areas like text fields, + // we can't emit newlines that weren't there. + // So add the newline only in the case of formatted output. + if (mFlags & nsIDocumentEncoder::OutputFormatted) EnsureVerticalSpace(0); - } else if (type != eHTMLTag_script) { - // All other blocks get 1 vertical space after them - // in formatted mode, otherwise 0. - // This is hard. Sometimes 0 is a better number, but - // how to know? - EnsureVerticalSpace((mFlags & nsIDocumentEncoder::OutputFormatted) - ? 1 : 0); - } + else + FlushLine(); + // We won't want to do anything with these in formatted mode either, + // so just return now: + return NS_OK; + } else if ((type == eHTMLTag_tr) || + (type == eHTMLTag_li) || + (type == eHTMLTag_pre) || + (type == eHTMLTag_dd) || + (type == eHTMLTag_dt)) { + // Items that should always end a line, but get no more whitespace + EnsureVerticalSpace(0); + } else if (IsBlockLevel(type) + && type != eHTMLTag_blockquote + && type != eHTMLTag_script + && type != eHTMLTag_markupDecl) + { + // All other blocks get 1 vertical space after them + // in formatted mode, otherwise 0. + // This is hard. Sometimes 0 is a better number, but + // how to know? + EnsureVerticalSpace((mFlags & nsIDocumentEncoder::OutputFormatted) + ? 1 : 0); } // The rest of this routine is formatted output stuff, @@ -859,7 +867,8 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode) } else if (type == eHTMLTag_blockquote) { - FlushLine(); + FlushLine(); // Is this needed? + nsString value; nsresult rv = GetValueOfAttribute(aNode, "type", value); if ( NS_SUCCEEDED(rv) ) @@ -869,6 +878,8 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode) mCiteQuoteLevel--; else mIndent -= gTabSize; + + EnsureVerticalSpace(1); } else if (type == eHTMLTag_a && !IsConverted(aNode) && !mURL.IsEmpty()) { @@ -1014,7 +1025,7 @@ nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode) } void nsHTMLToTXTSinkStream::EnsureBufferSize(PRInt32 aNewSize) -{ +{ if (mBufferSize < aNewSize) { nsMemory::Free(mBuffer); @@ -1259,9 +1270,10 @@ nsHTMLToTXTSinkStream::AddToLine(const PRUnichar * aLineFragment, PRInt32 aLineF mCurrentLine.Truncate(); // Space stuff new line? if(mFlags & nsIDocumentEncoder::OutputFormatFlowed) { - if((restOfLine[0] == '>') || - (restOfLine[0] == ' ') || - (!restOfLine.CompareWithConversion("From ",PR_FALSE,5))) { + if((restOfLine.Length()>0) && + ((restOfLine[0] == '>') || + (restOfLine[0] == ' ') || + (!restOfLine.CompareWithConversion("From ",PR_FALSE,5)))) { // Space stuffing a la RFC 2646 (format=flowed). mCurrentLine.AppendWithConversion(' '); } @@ -1292,8 +1304,10 @@ nsHTMLToTXTSinkStream::EndLine(PRBool softlinebreak) } WriteQuotesAndIndent(); // Remove SPACE from the end of the line. - while(' ' == mCurrentLine[mCurrentLine.Length()-1]) - mCurrentLine.SetLength(mCurrentLine.Length()-1); + PRUint32 linelength = mCurrentLine.Length(); + while(linelength > 0 && + ' ' == mCurrentLine[--linelength]) + mCurrentLine.SetLength(linelength); if(mFlags & nsIDocumentEncoder::OutputFormatFlowed) { // Add the soft part of the soft linebreak (RFC 2646 4.1) mCurrentLine.AppendWithConversion(' '); diff --git a/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.cpp b/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.cpp index 2418d37ac73..9b38d704361 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.cpp +++ b/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.cpp @@ -24,7 +24,6 @@ * Ben Bucksch * Pierre Phaneuf * Markus Kuhn - * */ /** @@ -282,7 +281,7 @@ nsHTMLToTXTSinkStream::Initialize(nsIOutputStream* aOutStream, { mCacheLine = PR_TRUE; } - + // Set the line break character: if ((mFlags & nsIDocumentEncoder::OutputCRLineBreak) && (mFlags & nsIDocumentEncoder::OutputLFLineBreak)) // Windows/mail @@ -495,10 +494,9 @@ PRBool nsHTMLToTXTSinkStream::DoOutput() /** - * This method is used to a general container. + * This method is used to open a general container. * This includes: OL,UL,DIR,SPAN,TABLE,H[1..6],etc. * - * @update 07/12/98 gpk * @param nsIParserNode reference to parser node interface * @return PR_TRUE if successful. */ @@ -598,6 +596,27 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode) if (type == eHTMLTag_p || type == eHTMLTag_pre) EnsureVerticalSpace(1); // Should this be 0 in unformatted case? + + else if (type == eHTMLTag_td || type == eHTMLTag_th) + { + // We must make sure that the content of two table cells get a + // space between them. + + // Fow now, I will only add a SPACE. Could be a TAB or something + // else but I'm not sure everything can handle the TAB so SPACE + // seems like a better solution. + if(!mInWhitespace) { + // Maybe add something else? Several spaces? A TAB? SPACE+TAB? + if(mCacheLine) { + AddToLine(NS_ConvertToString(" ").GetUnicode(), 1); + } else { + nsAutoString space(NS_ConvertToString(" ")); + WriteSimple(space); + } + mInWhitespace = PR_TRUE; + } + } + // Else make sure we'll separate block level tags, // even if we're about to leave, before doing any other formatting. else if (IsBlockLevel(type)) @@ -677,28 +696,10 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode) EnsureVerticalSpace(1); else if (type == eHTMLTag_dd) mIndent += gIndentSizeDD; - else if (type == eHTMLTag_td || type == eHTMLTag_th) - { - // We must make sure that the content of two table cells get a - // space between them. - - // Fow now, I will only add a SPACE. Could be a TAB or something - // else but I'm not sure everything can handle the TAB so SPACE - // seems like a better solution. - if(!mInWhitespace) { - // Maybe add something else? Several spaces? A TAB? SPACE+TAB? - if(mCacheLine) { - AddToLine(NS_ConvertToString(" ").GetUnicode(), 1); - } else { - nsAutoString space(NS_ConvertToString(" ")); - WriteSimple(space); - } - mInWhitespace = PR_TRUE; - } - } else if (type == eHTMLTag_blockquote) { - EnsureVerticalSpace(0); + EnsureVerticalSpace(1); + // Find out whether it's a type=cite, and insert "> " instead. // Eventually we should get the value of the pref controlling citations, // and handle AOL-style citations as well. @@ -716,6 +717,7 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode) else mIndent += gTabSize; // Check for some maximum value? } + else if (type == eHTMLTag_img) { /* Output (in decreasing order of preference) @@ -752,6 +754,7 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode) if (!temp.IsEmpty()) Write(temp); } + else if (type == eHTMLTag_a && !IsConverted(aNode)) { nsAutoString url; @@ -797,31 +800,36 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode) --mTagStackIndex; // End current line if we're ending a block level tag - if (IsBlockLevel(type)) { - if((type == eHTMLTag_body) || (type == eHTMLTag_html)) { - // We want the output to end with a new line, - // but in preformatted areas like text fields, - // we can't emit newlines that weren't there. - // So add the newline only in the case of formatted output. - if (mFlags & nsIDocumentEncoder::OutputFormatted) - EnsureVerticalSpace(0); - else - FlushLine(); - } else if ((type == eHTMLTag_tr) || - (type == eHTMLTag_li) || - (type == eHTMLTag_dt) || - (type == eHTMLTag_dd) || - (type == eHTMLTag_pre) || - (type == eHTMLTag_blockquote)) { + if((type == eHTMLTag_body) || (type == eHTMLTag_html)) { + // We want the output to end with a new line, + // but in preformatted areas like text fields, + // we can't emit newlines that weren't there. + // So add the newline only in the case of formatted output. + if (mFlags & nsIDocumentEncoder::OutputFormatted) EnsureVerticalSpace(0); - } else if (type != eHTMLTag_script) { - // All other blocks get 1 vertical space after them - // in formatted mode, otherwise 0. - // This is hard. Sometimes 0 is a better number, but - // how to know? - EnsureVerticalSpace((mFlags & nsIDocumentEncoder::OutputFormatted) - ? 1 : 0); - } + else + FlushLine(); + // We won't want to do anything with these in formatted mode either, + // so just return now: + return NS_OK; + } else if ((type == eHTMLTag_tr) || + (type == eHTMLTag_li) || + (type == eHTMLTag_pre) || + (type == eHTMLTag_dd) || + (type == eHTMLTag_dt)) { + // Items that should always end a line, but get no more whitespace + EnsureVerticalSpace(0); + } else if (IsBlockLevel(type) + && type != eHTMLTag_blockquote + && type != eHTMLTag_script + && type != eHTMLTag_markupDecl) + { + // All other blocks get 1 vertical space after them + // in formatted mode, otherwise 0. + // This is hard. Sometimes 0 is a better number, but + // how to know? + EnsureVerticalSpace((mFlags & nsIDocumentEncoder::OutputFormatted) + ? 1 : 0); } // The rest of this routine is formatted output stuff, @@ -859,7 +867,8 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode) } else if (type == eHTMLTag_blockquote) { - FlushLine(); + FlushLine(); // Is this needed? + nsString value; nsresult rv = GetValueOfAttribute(aNode, "type", value); if ( NS_SUCCEEDED(rv) ) @@ -869,6 +878,8 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode) mCiteQuoteLevel--; else mIndent -= gTabSize; + + EnsureVerticalSpace(1); } else if (type == eHTMLTag_a && !IsConverted(aNode) && !mURL.IsEmpty()) { @@ -1014,7 +1025,7 @@ nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode) } void nsHTMLToTXTSinkStream::EnsureBufferSize(PRInt32 aNewSize) -{ +{ if (mBufferSize < aNewSize) { nsMemory::Free(mBuffer); @@ -1259,9 +1270,10 @@ nsHTMLToTXTSinkStream::AddToLine(const PRUnichar * aLineFragment, PRInt32 aLineF mCurrentLine.Truncate(); // Space stuff new line? if(mFlags & nsIDocumentEncoder::OutputFormatFlowed) { - if((restOfLine[0] == '>') || - (restOfLine[0] == ' ') || - (!restOfLine.CompareWithConversion("From ",PR_FALSE,5))) { + if((restOfLine.Length()>0) && + ((restOfLine[0] == '>') || + (restOfLine[0] == ' ') || + (!restOfLine.CompareWithConversion("From ",PR_FALSE,5)))) { // Space stuffing a la RFC 2646 (format=flowed). mCurrentLine.AppendWithConversion(' '); } @@ -1292,8 +1304,10 @@ nsHTMLToTXTSinkStream::EndLine(PRBool softlinebreak) } WriteQuotesAndIndent(); // Remove SPACE from the end of the line. - while(' ' == mCurrentLine[mCurrentLine.Length()-1]) - mCurrentLine.SetLength(mCurrentLine.Length()-1); + PRUint32 linelength = mCurrentLine.Length(); + while(linelength > 0 && + ' ' == mCurrentLine[--linelength]) + mCurrentLine.SetLength(linelength); if(mFlags & nsIDocumentEncoder::OutputFormatFlowed) { // Add the soft part of the soft linebreak (RFC 2646 4.1) mCurrentLine.AppendWithConversion(' ');