13750,13753,14075,15293,13873,12551:

- Rewrite wrapping logic for plaintext output sink,
  and run all output through the wrapping/formatting Write method
  (which now has logic to determine when we should be wrapping).
- Handle blockquote type=cite mail quotes.
- Write several new regression tests for plaintext output bugs,
  and include those tests and their expected output into the
  automated output test.
r=sfraser,harishd


git-svn-id: svn://10.0.0.236/trunk@50072 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
akkana%netscape.com
1999-10-07 01:10:32 +00:00
parent 0a81ee7839
commit bc8b6d116e
18 changed files with 566 additions and 116 deletions

View File

@@ -164,6 +164,7 @@ nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream()
NS_INIT_REFCNT();
mColPos = 0;
mIndent = 0;
mCiteQuote = PR_FALSE;
mDoOutput = PR_FALSE;
mBufferSize = 0;
mBufferLength = 0;
@@ -355,6 +356,24 @@ nsHTMLToTXTSinkStream::AddComment(const nsIParserNode& aNode)
return NS_OK;
}
NS_IMETHODIMP
nsHTMLToTXTSinkStream::GetValueOfAttribute(const nsIParserNode& aNode,
char* aMatchKey,
nsString& aValueRet)
{
nsAutoString matchKey (aMatchKey);
PRInt32 count=aNode.GetAttributeCount();
for (PRInt32 i=0;i<count;i++)
{
const nsString& key = aNode.GetKeyAt(i);
if (key == matchKey)
{
aValueRet = aNode.GetValueAt(i);
return NS_OK;
}
}
return NS_ERROR_NOT_AVAILABLE;
}
/**
* This method is used to a general container.
@@ -371,19 +390,13 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode)
const nsString& name = aNode.GetText();
if (name.Equals("XIF_DOC_INFO"))
{
PRInt32 count=aNode.GetAttributeCount();
for(PRInt32 i=0;i<count;i++)
nsString value;
if (NS_SUCCEEDED(GetValueOfAttribute(aNode, "charset", value)))
{
const nsString& key=aNode.GetKeyAt(i);
const nsString& value=aNode.GetValueAt(i);
if (key.Equals("charset"))
{
if (mCharsetOverride.Length() == 0)
InitEncoder(value);
else
InitEncoder(mCharsetOverride);
}
if (mCharsetOverride.Length() == 0)
InitEncoder(value);
else
InitEncoder(mCharsetOverride);
}
}
@@ -427,7 +440,17 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode)
mColPos++;
}
else if (type == eHTMLTag_blockquote)
mIndent += gTabSize;
{
// 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.
nsString value;
if (NS_SUCCEEDED(GetValueOfAttribute(aNode, "type", value))
&& value.StripChars("\"").Equals("cite", PR_TRUE))
mCiteQuote = PR_TRUE;
else
mIndent += gTabSize;
}
else if (type == eHTMLTag_pre)
{
nsAutoString temp(NS_LINEBREAK);
@@ -489,14 +512,19 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode)
--mOLStackIndex;
else if (type == eHTMLTag_blockquote)
mIndent -= gTabSize;
{
if (mCiteQuote)
mCiteQuote = PR_FALSE;
else
mIndent -= gTabSize;
}
// End current line if we're ending a block level tag
if (IsBlockLevel(type))
{
if (mColPos != 0)
{
if (mFlags & nsIDocumentEncoder::OutputFormatted)
//if (mFlags & nsIDocumentEncoder::OutputFormatted)
{
nsAutoString temp(NS_LINEBREAK);
Write(temp);
@@ -538,15 +566,7 @@ nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode)
}
#endif
if ((mFlags & nsIDocumentEncoder::OutputFormatted
|| mFlags & nsIDocumentEncoder::OutputWrap)
&& mWrapColumn > 0)
WriteWrapped(text);
else
{
Write(text);
mColPos += text.Length();
}
Write(text);
}
else if (type == eHTMLTag_entity)
{
@@ -650,15 +670,16 @@ void nsHTMLToTXTSinkStream::EncodeToBuffer(const nsString& aSrc)
/**
* Write places the contents of aString into either the output stream
* WriteSimple places the contents of aString into either the output stream
* or the output string.
* When going to the stream, all data is run through the encoder
* When going to the stream, all data is run through the encoder.
* No formatting or wrapping is done here; that happens in ::Write.
*
* @updated gpk02/03/99
* @param
* @return
*/
void nsHTMLToTXTSinkStream::Write(const nsString& aString)
void nsHTMLToTXTSinkStream::WriteSimple(const nsString& aString)
{
// If a encoder is being used then convert first convert the input string
if (mUnicodeEncoder != nsnull)
@@ -696,51 +717,86 @@ void nsHTMLToTXTSinkStream::Write(const nsString& aString)
//
// Write a string, wrapping appropriately to mWrapColumn.
// This routine also handles indentation and mail-quoting,
// and so should be used for formatted output even if we're not wrapping.
//
void
nsHTMLToTXTSinkStream::WriteWrapped(const nsString& aString)
nsHTMLToTXTSinkStream::Write(const nsString& aString)
{
#ifdef DEBUG_wrapping
char* foo = aString.ToNewCString();
printf("WriteWrapped(%s): wrap col = %d\n", foo, mWrapColumn);
printf("Write(%s): wrap col = %d, mColPos = %d\n", foo, mWrapColumn, mColPos);
nsAllocator::Free(foo);
#endif
PRInt32 bol = 0;
int totLen = aString.Length();
while (bol < totLen) // Loop over lines
{
#ifdef DEBUG_wrapping
nsString remaining;
aString.Right(remaining, totLen - bol);
foo = remaining.ToNewCString();
printf("Next line: bol = %d, totLen = %d, string = '%s'\n",
bol, totLen, foo);
nsAllocator::Free(foo);
#endif
// Indent at the beginning of the line, if necessary
if (mColPos == 0 && mIndent > 0)
// Put the mail quote "> " chars in, if appropriate:
if (mColPos == 0)
{
if (mCiteQuote)
{
nsAutoString temp("> ");
WriteSimple(temp);
mColPos += 2;
}
// Indent if necessary
if (mIndent > 0)
{
char* spaces = NS_STATIC_CAST(char*, nsAllocator::Alloc(mIndent+1));
for (int i=0; i<mIndent; ++i)
spaces[i] = ' ';
spaces[mIndent] = '\0';
nsAutoString temp(spaces);
Write (temp);
WriteSimple(temp);
mColPos += mIndent;
nsAllocator::Free(spaces);
}
}
// See if there's a newline in the string:
PRInt32 newline = aString.FindCharInSet("\n\r", bol);
// Don't wrap mail-quoted text
PRUint32 wrapcol = (mCiteQuote ? 0 : mWrapColumn);
// See if there's a newline in the string:
PRInt32 newline = aString.FindCharInSet("\n\r", bol);
if ((!(mFlags & nsIDocumentEncoder::OutputFormatted)
&& !(mFlags & nsIDocumentEncoder::OutputWrap))
|| wrapcol == 0)
{
WriteSimple(aString);
// Simple attempt to be smart about col pos:
if (newline >= 0)
mColPos = totLen - newline - 1;
else
mColPos += totLen;
#ifdef DEBUG_wrapping
printf("No wrapping: newline is %d, totLen is %d; leaving mColPos = %d\n",
newline, totLen, mColPos);
#endif
return;
}
while (bol < totLen) // Loop over lines
{
#ifdef DEBUG_wrapping
nsString remaining;
aString.Right(remaining, totLen - bol);
foo = remaining.ToNewCString();
printf("Next line: bol = %d, newline = %d, totLen = %d, string = '%s'\n",
bol, newline, totLen, foo);
nsAllocator::Free(foo);
#endif
// Set eol to the end of the string or the first newline,
// whichever comes first:
int eol = bol + mWrapColumn - mColPos;
int eol = bol + wrapcol - mColPos;
if (eol > totLen || wrapcol == 0)
eol = bol + totLen;
if (eol > totLen)
eol = totLen;
else if (newline > 0 && eol > newline)
eol = newline;
// else we have to wrap
@@ -773,11 +829,11 @@ nsHTMLToTXTSinkStream::WriteWrapped(const nsString& aString)
if (mColPos > mIndent)
{
nsAutoString linebreak(NS_LINEBREAK);
Write(linebreak);
WriteSimple(linebreak);
mColPos = 0;
continue;
}
#endif /* CONFUSED */
#endif /* NOTSURE */
// Else apparently we really can't break this line at whitespace --
// so scan forward to the next space or newline, and dump a long line.
@@ -786,9 +842,8 @@ nsHTMLToTXTSinkStream::WriteWrapped(const nsString& aString)
&& (newline < 0 || eol < newline))
{
#ifdef DEBUG_wrapping
nsString linestr;
aString.Mid(linestr, bol, lastSpace - bol);
foo = linestr.ToNewCString();
aString.Mid(remaining, bol, lastSpace - bol);
foo = remaining.ToNewCString();
printf("Searching foreward: '%c' is not a space\n line = '%s'\n",
(char)aString[lastSpace], foo);
nsAllocator::Free(foo);
@@ -817,8 +872,16 @@ nsHTMLToTXTSinkStream::WriteWrapped(const nsString& aString)
}
else // Not wrapping and not writing a newline
mColPos += lineStr.Length();
Write(lineStr);
WriteSimple(lineStr);
#ifdef DEBUG_wrapping
foo = lineStr.ToNewCString();
printf("Calling WriteSimple(%s), leaving mColPos = %d\n", foo, mColPos);
nsAllocator::Free(foo);
#endif
// Reset bol and newline:
bol = eol+1;
newline = aString.FindCharInSet("\n\r", bol);
} // Continue looping over the string
}