diff --git a/mozilla/content/base/src/nsDocumentEncoder.cpp b/mozilla/content/base/src/nsDocumentEncoder.cpp index eb5298a77cd..351931eb281 100644 --- a/mozilla/content/base/src/nsDocumentEncoder.cpp +++ b/mozilla/content/base/src/nsDocumentEncoder.cpp @@ -102,7 +102,8 @@ nsHTMLEncoder::~nsHTMLEncoder() } NS_IMETHODIMP -nsHTMLEncoder::Init(nsIPresShell* aPresShell, nsIDocument* aDocument, nsString& aMimeType) +nsHTMLEncoder::Init(nsIPresShell* aPresShell, nsIDocument* aDocument, + nsString& aMimeType) { if (!aDocument) return NS_ERROR_INVALID_ARG; @@ -325,6 +326,7 @@ private: nsIPresShell* mPresShell; nsString mMimeType; nsString mCharset; + PRBool mPrettyPrint; }; @@ -384,6 +386,13 @@ nsresult nsTextEncoder::QueryInterface(REFNSIID aIID, return NS_OK; } +NS_IMETHODIMP +nsTextEncoder::PrettyPrint(PRBool aYes) +{ + mPrettyPrint = PR_TRUE; + return NS_OK; +} + NS_IMETHODIMP nsTextEncoder::SetSelection(nsIDOMSelection* aSelection) { @@ -410,8 +419,10 @@ nsTextEncoder::EncodeToString(nsString& aOutputString) // xxx Also make sure mString is a mime type "text/html" or "text/plain" - if (mPresShell) { - if (mDocument) { + if (mPresShell) + { + if (mDocument) + { nsString buffer; mDocument->CreateXIF(buffer,mSelection); @@ -421,29 +432,29 @@ nsTextEncoder::EncodeToString(nsString& aOutputString) static NS_DEFINE_IID(kCParserCID, NS_PARSER_IID); rv = nsComponentManager::CreateInstance(kCParserCID, - nsnull, - kCParserIID, - (void **)&parser); + nsnull, + kCParserIID, + (void **)&parser); - if (NS_OK == rv) { + if (NS_SUCCEEDED(rv)) + { nsIHTMLContentSink* sink = nsnull; - rv = NS_New_HTMLToTXT_SinkStream(&sink,&aOutputString); + rv = NS_New_HTMLToTXT_SinkStream(&sink, &aOutputString, mPrettyPrint); - if (sink && NS_SUCCEEDED(rv)) { - - if (NS_OK == rv) { - parser->SetContentSink(sink); + if (sink && NS_SUCCEEDED(rv)) + { + parser->SetContentSink(sink); - nsIDTD* dtd = nsnull; - rv = NS_NewXIFDTD(&dtd); - if (NS_OK == rv) { - parser->RegisterDTD(dtd); - parser->Parse(buffer, 0, "text/xif",PR_FALSE,PR_TRUE); - } - NS_IF_RELEASE(dtd); - NS_IF_RELEASE(sink); - } + nsIDTD* dtd = nsnull; + rv = NS_NewXIFDTD(&dtd); + if (NS_SUCCEEDED(rv)) + { + parser->RegisterDTD(dtd); + parser->Parse(buffer, 0, "text/xif",PR_FALSE,PR_TRUE); + } + NS_IF_RELEASE(dtd); + NS_IF_RELEASE(sink); } NS_RELEASE(parser); } @@ -481,25 +492,27 @@ nsTextEncoder::EncodeToStream(nsIOutputStream* aStream) static NS_DEFINE_IID(kCParserCID, NS_PARSER_IID); rv = nsComponentManager::CreateInstance(kCParserCID, - nsnull, - kCParserIID, - (void **)&parser); + nsnull, + kCParserIID, + (void **)&parser); if (NS_OK == rv) { nsIHTMLContentSink* sink = nsnull; - rv = NS_New_HTMLToTXT_SinkStream(&sink,aStream,charset); + rv = NS_New_HTMLToTXT_SinkStream(&sink,aStream,charset,mPrettyPrint); - if (sink && NS_SUCCEEDED(rv)) { - - if (NS_OK == rv) { + if (sink && NS_SUCCEEDED(rv)) + { + if (NS_SUCCEEDED(rv)) + { parser->SetContentSink(sink); nsIDTD* dtd = nsnull; rv = NS_NewXIFDTD(&dtd); - if (NS_OK == rv) { + if (NS_SUCCEEDED(rv)) + { parser->RegisterDTD(dtd); - parser->Parse(buffer, 0, "text/xif",PR_FALSE,PR_TRUE); + parser->Parse(buffer, 0, "text/xif", PR_FALSE, PR_TRUE); } NS_IF_RELEASE(dtd); NS_IF_RELEASE(sink); @@ -512,13 +525,6 @@ nsTextEncoder::EncodeToStream(nsIOutputStream* aStream) return rv; } - -NS_IMETHODIMP -nsTextEncoder::PrettyPrint(PRBool aYes) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - nsresult NS_NewTextEncoder(nsIDocumentEncoder** aResult) { @@ -530,10 +536,6 @@ NS_NewTextEncoder(nsIDocumentEncoder** aResult) } - - - - class nsDocumentEncoderFactory : public nsIFactory { public: diff --git a/mozilla/editor/base/nsTextEditor.cpp b/mozilla/editor/base/nsTextEditor.cpp index efeaa7ff650..b316622284b 100644 --- a/mozilla/editor/base/nsTextEditor.cpp +++ b/mozilla/editor/base/nsTextEditor.cpp @@ -19,14 +19,7 @@ #include "nsTextEditor.h" #include "nsEditorEventListeners.h" -#include "nsIStreamListener.h" -#include "nsIParser.h" -#include "nsParserCIID.h" #include "nsIDocument.h" -#include "nsIHTMLContentSink.h" -#include "nsHTMLContentSinkStream.h" -#include "nsHTMLToTXTSinkStream.h" -#include "nsXIFDTD.h" #include "nsFileSpec.h" #include "nsIDOMDocument.h" @@ -36,7 +29,6 @@ #include "nsIDOMDragListener.h" #include "nsIDOMFocusListener.h" #include "nsIDOMSelection.h" -#include "nsIDOMRange.h" #include "nsIDOMNodeList.h" #include "nsIDOMCharacterData.h" #include "nsIDOMElement.h" @@ -71,15 +63,14 @@ #include "nsIFileWidget.h" // Drag & Drop, Clipboard -#include "nsWidgetsCID.h" #include "nsIClipboard.h" #include "nsITransferable.h" -#include "nsIFormatConverter.h" +//#include "nsIFormatConverter.h" // Drag & Drop, Clipboard Support static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID); static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID); -static NS_DEFINE_IID(kCXIFFormatConverterCID, NS_XIFFORMATCONVERTER_CID); +//static NS_DEFINE_IID(kCXIFFormatConverterCID, NS_XIFFORMATCONVERTER_CID); // Document encoders static NS_DEFINE_CID(kHTMLEncoderCID, NS_HTML_ENCODER_CID); @@ -1585,11 +1576,14 @@ NS_IMETHODIMP nsTextEditor::OutputTextToString(nsString& aOutputString) nsCOMPtr shell; rv = GetPresShell(getter_AddRefs(shell)); - if (NS_SUCCEEDED(rv)) { - rv = encoder->Init(shell,doc, mimetype); - if (NS_FAILED(rv)) - return rv; - } + if (NS_FAILED(rv)) + return rv; + rv = encoder->Init(shell, doc, mimetype); + if (NS_FAILED(rv)) + return rv; + + // Try to turn on pretty printing, but don't panic if it doesn't work: + (void)encoder->PrettyPrint(PR_TRUE); rv = encoder->EncodeToString(aOutputString); } diff --git a/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.cpp b/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.cpp index b0661b4278a..e719032ca09 100644 --- a/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.cpp +++ b/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.cpp @@ -61,12 +61,8 @@ static PRBool IsBlockLevel(eHTMLTags aTag); */ nsresult nsHTMLToTXTSinkStream::InitEncoder(const nsString& aCharset) { - - - nsresult res = NS_OK; - // If the converter is ucs2, then do not use a converter nsString ucs2("ucs2"); if (aCharset.Equals(ucs2)) @@ -114,8 +110,6 @@ nsresult nsHTMLToTXTSinkStream::InitEncoder(const nsString& aCharset) } - - /** * This method gets called as part of our COM-like interfaces. * Its purpose is to create an interface to parser object @@ -163,13 +157,15 @@ NS_IMPL_RELEASE(nsHTMLToTXTSinkStream) NS_HTMLPARS nsresult NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult, nsIOutputStream* aStream, - const nsString* aCharsetOverride) { - + const nsString* aCharsetOverride, + PRBool aPrettyPrint) +{ NS_ASSERTION(aStream != nsnull, "a valid stream is required"); - nsHTMLToTXTSinkStream* it = new nsHTMLToTXTSinkStream(aStream,nsnull); + nsHTMLToTXTSinkStream* it = new nsHTMLToTXTSinkStream(aStream, nsnull); if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } + it->DoPrettyPrint(aPrettyPrint); if (aCharsetOverride != nsnull) it->SetCharsetOverride(aCharsetOverride); return it->QueryInterface(kIHTMLContentSinkIID, (void **)aInstancePtrResult); @@ -184,27 +180,29 @@ NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult, */ NS_HTMLPARS nsresult NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult, - nsString* aString) { - + nsString* aString, PRBool aPrettyPrint) +{ NS_ASSERTION(aString != nsnull, "a valid stream is required"); - nsHTMLToTXTSinkStream* it = new nsHTMLToTXTSinkStream(nsnull,aString); + nsHTMLToTXTSinkStream* it = new nsHTMLToTXTSinkStream(nsnull, aString); if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } + it->DoPrettyPrint(aPrettyPrint); nsString ucs2("ucs2"); it->SetCharsetOverride(&ucs2); return it->QueryInterface(kIHTMLContentSinkIID, (void **)aInstancePtrResult); } - /** * Construct a content sink stream. * @update gpk02/03/99 * @param * @return */ -nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream(nsIOutputStream* aStream, nsString* aString) { +nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream(nsIOutputStream* aStream, + nsString* aString) +{ NS_INIT_REFCNT(); mStream = aStream; mColPos = 0; @@ -216,21 +214,30 @@ nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream(nsIOutputStream* aStream, nsString* mUnicodeEncoder = nsnull; mStream = aStream; mString = aString; + mPrettyPrint = PR_FALSE; + mPreformatted = PR_FALSE; + mWrapColumn = 72; // XXX magic number, obviously needs to be settable } - /** * * @update gpk02/03/99 * @param * @return */ -nsHTMLToTXTSinkStream::~nsHTMLToTXTSinkStream() { +nsHTMLToTXTSinkStream::~nsHTMLToTXTSinkStream() +{ delete [] mBuffer; NS_IF_RELEASE(mUnicodeEncoder); } +NS_IMETHODIMP +nsHTMLToTXTSinkStream::DoPrettyPrint(PRBool aDoPrettyPrint) +{ + mPrettyPrint = aDoPrettyPrint; + return NS_OK; +} /** * @@ -580,7 +587,10 @@ nsHTMLToTXTSinkStream::AddProcessingInstruction(const nsIParserNode& aNode){ * @return */ NS_IMETHODIMP -nsHTMLToTXTSinkStream::AddComment(const nsIParserNode& aNode){ +nsHTMLToTXTSinkStream::AddComment(const nsIParserNode& aNode) +{ + // Skip comments in plaintext output + mDoOutput = PR_FALSE; return NS_OK; } @@ -594,7 +604,8 @@ nsHTMLToTXTSinkStream::AddComment(const nsIParserNode& aNode){ * @return PR_TRUE if successful. */ NS_IMETHODIMP -nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode){ +nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode) +{ eHTMLTags type = (eHTMLTags)aNode.GetNodeType(); const nsString& name = aNode.GetText(); if (name.Equals("XIF_DOC_INFO")) @@ -617,6 +628,23 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode){ if (type == eHTMLTag_body) mDoOutput = PR_TRUE; + + else if (mDoOutput && type == eHTMLTag_li) + { + nsString temp("*"); + Write(temp); + mColPos++; + } + else if (type == eHTMLTag_pre) + { + mPreformatted = PR_TRUE; + nsString temp(NS_LINEBREAK); + Write(temp); + mColPos = 0; + } + else if (type == eHTMLTag_blockquote) + mIndent += gTabSize; + return NS_OK; } @@ -629,26 +657,40 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode){ * @return PR_TRUE if successful. */ NS_IMETHODIMP -nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode){ +nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode) +{ eHTMLTags type = (eHTMLTags)aNode.GetNodeType(); - //const nsString& name = aNode.GetText(); if (type == eHTMLTag_body) mDoOutput = PR_FALSE; + else if (type == eHTMLTag_comment) + { + mDoOutput = PR_TRUE; + return NS_OK; + } + + else if (type == eHTMLTag_pre) + mPreformatted = PR_FALSE; + + else if (type == eHTMLTag_blockquote) + mIndent -= gTabSize; + if (IsBlockLevel(type)) { if (mColPos != 0) - { - nsString temp("\n"); - Write(temp); - mColPos = 0; + { + if (mPrettyPrint) + { + nsString temp(NS_LINEBREAK); + Write(temp); + mColPos = 0; + } } } return NS_OK; } - /** * This method is used to add a leaf to the currently * open container. @@ -658,7 +700,8 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode){ * @return PR_TRUE if successful. */ NS_IMETHODIMP -nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode){ +nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode) +{ eHTMLTags type = (eHTMLTags)aNode.GetNodeType(); nsString text = aNode.GetText(); @@ -666,9 +709,22 @@ nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode){ if (mDoOutput == PR_FALSE) return NS_OK; - if (type == eHTMLTag_text) { - Write(text); - mColPos += text.Length(); + if (type == eHTMLTag_text) + { + if (mColPos > mIndent) + { + nsString temp(" "); + Write(temp); + mColPos++; + } + + if (mPrettyPrint) + WriteWrapped(text); + else + { + Write(text); + mColPos += text.Length(); + } } else if (type == eHTMLTag_entity) { @@ -682,32 +738,113 @@ nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode){ mColPos++; } - else if (type == eHTMLTag_whitespace) + else if (type == eHTMLTag_br) { - if (PR_TRUE) + if (mPrettyPrint) + { + nsString temp (NS_LINEBREAK); + Write(temp); + mColPos = 0; + } + } + // The only time we want to pass along whitespace from the original + // html source is if we're prettyprinting and we're inside a
.
+  // Otherwise, either we're collapsing to minimal text, or we're
+  // prettyprinting to mimic the html format, and in neither case
+  // does the formatting of the html source help us.
+  else if (mPrettyPrint && mPreformatted && type == eHTMLTag_whitespace)
+  {
+    if (mPrettyPrint)
     {
       text = aNode.GetText();
       Write(text);
       mColPos += text.Length();
     }
   }
-  else if (type == eHTMLTag_br)
+  else if (mPrettyPrint && mPreformatted && type == eHTMLTag_newline)
   {
-    nsString temp("\n");
+    nsString temp(NS_LINEBREAK);
     Write(temp);
-    mColPos++;
+    mColPos = 0;
   }
-  else if (type == eHTMLTag_newline)
-  {
-    nsString temp("\n");
-    Write(text);
-    mColPos++;
-  }
-
 
   return NS_OK;
 }
 
+//
+// Write a string, wrapping appropriately to mWrapColumn.
+//
+void
+nsHTMLToTXTSinkStream::WriteWrapped(const nsString& aString)
+{
+  int totLen = aString.Length();
+  int charsLeft = totLen;
+  while (charsLeft > 0)     // Loop over lines
+  {
+    // Indent at the beginning of the line, if necessary
+    if (mColPos == 0 && mIndent > 0)
+    {
+      char* spaces = new char[mIndent+1];
+      for (int i=0; i totLen)
+      eol = totLen;
+    else
+    {
+      // We need to wrap, so search backward to find last IsSpace char:
+      int lastSpace = eol;
+      while (lastSpace > bol && !nsString::IsSpace(aString[lastSpace]))
+        --lastSpace;
+      if (lastSpace == bol)
+      {
+        // If we reached the bol, it might just be because we were close
+        // to the end already and should have wrapped last time.
+        // In that case, write a linebreak and come around again.
+        if (mColPos > mIndent)
+        {
+          nsAutoString linebreak(NS_LINEBREAK);
+          Write(linebreak);
+          mColPos = 0;
+          continue;
+        }
+        // Else apparently we really can't break this line at whitespace --
+        // so scan forward to the next space (if any) and dump a long line:
+        while (eol > totLen && !nsString::IsSpace(aString[lastSpace]))
+          ++eol;
+      }
+      else if (lastSpace > bol && lastSpace < eol)
+        eol = lastSpace+1;
+#ifdef DEBUG_akkana
+      else
+        printf("Wrapping: bol = %d, eol = %d, lastSpace = %d, totLen = %d\n",
+               bol, eol, lastSpace, totLen);
+#endif
+    }
+
+    nsAutoString lineStr;
+    aString.Mid(lineStr, bol, eol-bol);
+
+    if (eol != totLen)      // we're wrapping
+    {
+      lineStr.Append(NS_LINEBREAK);
+      mColPos = 0;
+    }
+    else
+      mColPos += lineStr.Length();
+    Write(lineStr);
+    charsLeft = totLen - eol;
+  }
+}
 
 /**
   * This method gets called when the parser begins the process
@@ -804,6 +941,7 @@ PRBool IsInline(eHTMLTags aTag)
     case  eHTMLTag_td:
     case  eHTMLTag_textarea:
     case  eHTMLTag_tt:
+    case  eHTMLTag_u:
     case  eHTMLTag_var:
     case  eHTMLTag_wbr:
            
diff --git a/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.h b/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.h
index 72c3331b329..fd6205ef12c 100644
--- a/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.h
+++ b/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.h
@@ -37,13 +37,10 @@
 #ifndef  NS_HTMLTOTEXTSINK_STREAM
 #define  NS_HTMLTOTEXTSINK_STREAM
 
-#include "nsIParserNode.h"
 #include "nsIHTMLContentSink.h"
-#include "nshtmlpars.h"
-#include "nsHTMLTokens.h"
 
 
-#define NS_HTMLTOTEXTSINK_STREAM_IID  \
+#define NS_HTMLTOTEXTSINK_STREAM_CID  \
   {0xa39c6bff, 0x15f0, 0x11d2, \
   {0x80, 0x41, 0x0, 0x10, 0x4b, 0x98, 0x3f, 0xd4}}
 
@@ -51,14 +48,15 @@
 class nsIUnicodeEncoder;
 class nsIOutputStream;
 
-class nsHTMLToTXTSinkStream : public nsIHTMLContentSink {
+class nsHTMLToTXTSinkStream : public nsIHTMLContentSink
+{
   public:
 
   /**
    * Standard constructor
    * @update	gpk02/03/99
    */
-  nsHTMLToTXTSinkStream(nsIOutputStream* aOutStream, nsString* aOutString); 
+  nsHTMLToTXTSinkStream(nsIOutputStream* aOutStream, nsString* aOutString);
 
   /**
    * virtual destructor
@@ -109,47 +107,46 @@ class nsHTMLToTXTSinkStream : public nsIHTMLContentSink {
   NS_IMETHOD BeginContext(PRInt32 aPosition);
   NS_IMETHOD EndContext(PRInt32 aPosition);
 
-
+  NS_IMETHOD DoPrettyPrint(PRBool aDoPrettyPrint);
 
 protected:
+  void EnsureBufferSize(PRInt32 aNewSize);
 
-    
-    void EnsureBufferSize(PRInt32 aNewSize);
-
-    nsresult InitEncoder(const nsString& aCharset);
-
-    void Write(const nsString& aString);
-    void EncodeToBuffer(const nsString& aString);
-    
-
+  nsresult InitEncoder(const nsString& aCharset);
 
+  void Write(const nsString& aString);
+  void WriteWrapped(const nsString& aString);
+  void EncodeToBuffer(const nsString& aString);
 
 protected:
-    nsIOutputStream* mStream;
-    nsString*        mString;
+  nsIOutputStream* mStream;
+  nsString*        mString;
 
-    PRInt32         mIndent;
-    PRInt32         mColPos;
-    PRBool          mDoOutput;
+  PRInt32          mIndent;
+  PRInt32          mColPos;
+  PRBool           mDoOutput;
+  PRBool           mPreformatted;
+  PRBool           mPrettyPrint;
+  PRInt32          mWrapColumn;
 
-    char*           mBuffer;
-    PRInt32         mBufferLength;  // The length of the data in the buffer
-    PRInt32         mBufferSize;    // The actual size of the buffer, regardless of the data
-
-    nsIUnicodeEncoder*  mUnicodeEncoder;
-    nsString            mCharsetOverride;
-   
+  char*            mBuffer;
+  PRInt32          mBufferLength;  // The length of the data in the buffer
+  PRInt32          mBufferSize;    // The actual size of the buffer, regardless of the data
 
+  nsIUnicodeEncoder*  mUnicodeEncoder;
+  nsString            mCharsetOverride;
 };
 
 extern NS_HTMLPARS nsresult
 NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult, 
                             nsIOutputStream* aOutStream,
-                            const nsString* aCharsetOverride=nsnull);
+                            const nsString* aCharsetOverride=nsnull,
+                            PRBool aPrettyPrint=PR_FALSE);
 
 extern NS_HTMLPARS nsresult
 NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult, 
-                            nsString* aOutString);
+                            nsString* aOutString,
+                            PRBool aPrettyPrint=PR_FALSE);
 
 #endif
 
diff --git a/mozilla/layout/base/src/nsDocumentEncoder.cpp b/mozilla/layout/base/src/nsDocumentEncoder.cpp
index eb5298a77cd..351931eb281 100644
--- a/mozilla/layout/base/src/nsDocumentEncoder.cpp
+++ b/mozilla/layout/base/src/nsDocumentEncoder.cpp
@@ -102,7 +102,8 @@ nsHTMLEncoder::~nsHTMLEncoder()
 }
 
 NS_IMETHODIMP
-nsHTMLEncoder::Init(nsIPresShell* aPresShell, nsIDocument* aDocument, nsString& aMimeType)
+nsHTMLEncoder::Init(nsIPresShell* aPresShell, nsIDocument* aDocument,
+                    nsString& aMimeType)
 {
   if (!aDocument)
     return NS_ERROR_INVALID_ARG;
@@ -325,6 +326,7 @@ private:
   nsIPresShell*     mPresShell;
   nsString          mMimeType;
   nsString          mCharset;
+  PRBool            mPrettyPrint;
 };
 
 
@@ -384,6 +386,13 @@ nsresult nsTextEncoder::QueryInterface(REFNSIID aIID,
   return NS_OK;   
 }
 
+NS_IMETHODIMP
+nsTextEncoder::PrettyPrint(PRBool aYes)
+{
+  mPrettyPrint = PR_TRUE;
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 nsTextEncoder::SetSelection(nsIDOMSelection* aSelection)
 {
@@ -410,8 +419,10 @@ nsTextEncoder::EncodeToString(nsString& aOutputString)
 
   // xxx Also make sure mString is a mime type "text/html" or "text/plain"
   
-  if (mPresShell) {
-    if (mDocument) {
+  if (mPresShell)
+  {
+    if (mDocument)
+    {
       nsString buffer;
 
       mDocument->CreateXIF(buffer,mSelection);
@@ -421,29 +432,29 @@ nsTextEncoder::EncodeToString(nsString& aOutputString)
       static NS_DEFINE_IID(kCParserCID, NS_PARSER_IID);
 
       rv = nsComponentManager::CreateInstance(kCParserCID, 
-                                                 nsnull, 
-                                                 kCParserIID, 
-                                                 (void **)&parser);
+                                              nsnull, 
+                                              kCParserIID, 
+                                              (void **)&parser);
 
-      if (NS_OK == rv) {
+      if (NS_SUCCEEDED(rv))
+      {
         nsIHTMLContentSink* sink = nsnull;
 
-        rv = NS_New_HTMLToTXT_SinkStream(&sink,&aOutputString);
+        rv = NS_New_HTMLToTXT_SinkStream(&sink, &aOutputString, mPrettyPrint);
   
-      	if (sink && NS_SUCCEEDED(rv)) {
-
-	        if (NS_OK == rv) {
-	          parser->SetContentSink(sink);
+      	if (sink && NS_SUCCEEDED(rv))
+        {
+          parser->SetContentSink(sink);
 	   
-	          nsIDTD* dtd = nsnull;
-	          rv = NS_NewXIFDTD(&dtd);
-	          if (NS_OK == rv) {
-	            parser->RegisterDTD(dtd);
-	            parser->Parse(buffer, 0, "text/xif",PR_FALSE,PR_TRUE);           
-	          }
-	          NS_IF_RELEASE(dtd);
-	          NS_IF_RELEASE(sink);
-	        }
+          nsIDTD* dtd = nsnull;
+          rv = NS_NewXIFDTD(&dtd);
+          if (NS_SUCCEEDED(rv))
+          {
+            parser->RegisterDTD(dtd);
+            parser->Parse(buffer, 0, "text/xif",PR_FALSE,PR_TRUE);           
+          }
+          NS_IF_RELEASE(dtd);
+          NS_IF_RELEASE(sink);
         }
         NS_RELEASE(parser);
       }
@@ -481,25 +492,27 @@ nsTextEncoder::EncodeToStream(nsIOutputStream* aStream)
       static NS_DEFINE_IID(kCParserCID, NS_PARSER_IID);
 
       rv = nsComponentManager::CreateInstance(kCParserCID, 
-                                                 nsnull, 
-                                                 kCParserIID, 
-                                                 (void **)&parser);
+                                              nsnull, 
+                                              kCParserIID, 
+                                              (void **)&parser);
 
       if (NS_OK == rv) {
         nsIHTMLContentSink* sink = nsnull;
 
-        rv = NS_New_HTMLToTXT_SinkStream(&sink,aStream,charset);
+        rv = NS_New_HTMLToTXT_SinkStream(&sink,aStream,charset,mPrettyPrint);
   
-      	if (sink && NS_SUCCEEDED(rv)) {
-
-	        if (NS_OK == rv) {
+      	if (sink && NS_SUCCEEDED(rv))
+        {
+	        if (NS_SUCCEEDED(rv))
+          {
 	          parser->SetContentSink(sink);
 
             nsIDTD* dtd = nsnull;
 	          rv = NS_NewXIFDTD(&dtd);
-	          if (NS_OK == rv) {
+	          if (NS_SUCCEEDED(rv))
+            {
 	            parser->RegisterDTD(dtd);
-	            parser->Parse(buffer, 0, "text/xif",PR_FALSE,PR_TRUE);           
+	            parser->Parse(buffer, 0, "text/xif", PR_FALSE, PR_TRUE);
 	          }
 	          NS_IF_RELEASE(dtd);
 	          NS_IF_RELEASE(sink);
@@ -512,13 +525,6 @@ nsTextEncoder::EncodeToStream(nsIOutputStream* aStream)
   return rv;
 }
 
-              
-NS_IMETHODIMP
-nsTextEncoder::PrettyPrint(PRBool aYes)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
 nsresult
 NS_NewTextEncoder(nsIDocumentEncoder** aResult)
 {
@@ -530,10 +536,6 @@ NS_NewTextEncoder(nsIDocumentEncoder** aResult)
 }
 
 
-
-
-
-
 class nsDocumentEncoderFactory : public nsIFactory
 {
 public:   
diff --git a/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.cpp b/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.cpp
index b0661b4278a..e719032ca09 100644
--- a/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.cpp
+++ b/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.cpp
@@ -61,12 +61,8 @@ static PRBool IsBlockLevel(eHTMLTags aTag);
  */
 nsresult nsHTMLToTXTSinkStream::InitEncoder(const nsString& aCharset)
 {
-
- 
-
   nsresult res = NS_OK;
   
-  
   // If the converter is ucs2, then do not use a converter
   nsString ucs2("ucs2");
   if (aCharset.Equals(ucs2))
@@ -114,8 +110,6 @@ nsresult nsHTMLToTXTSinkStream::InitEncoder(const nsString& aCharset)
 }
 
 
-
-
 /**
  *  This method gets called as part of our COM-like interfaces.
  *  Its purpose is to create an interface to parser object
@@ -163,13 +157,15 @@ NS_IMPL_RELEASE(nsHTMLToTXTSinkStream)
 NS_HTMLPARS nsresult
 NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult, 
                             nsIOutputStream* aStream,
-                            const nsString* aCharsetOverride) {
-
+                            const nsString* aCharsetOverride,
+                            PRBool aPrettyPrint)
+{
   NS_ASSERTION(aStream != nsnull, "a valid stream is required");
-  nsHTMLToTXTSinkStream* it = new nsHTMLToTXTSinkStream(aStream,nsnull);
+  nsHTMLToTXTSinkStream* it = new nsHTMLToTXTSinkStream(aStream, nsnull);
   if (nsnull == it) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
+  it->DoPrettyPrint(aPrettyPrint);
   if (aCharsetOverride != nsnull)
     it->SetCharsetOverride(aCharsetOverride);
   return it->QueryInterface(kIHTMLContentSinkIID, (void **)aInstancePtrResult);
@@ -184,27 +180,29 @@ NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult,
  */
 NS_HTMLPARS nsresult
 NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult, 
-                            nsString* aString) {
-
+                            nsString* aString, PRBool aPrettyPrint)
+{
   NS_ASSERTION(aString != nsnull, "a valid stream is required");
-  nsHTMLToTXTSinkStream* it = new nsHTMLToTXTSinkStream(nsnull,aString);
+  nsHTMLToTXTSinkStream* it = new nsHTMLToTXTSinkStream(nsnull, aString);
   if (nsnull == it) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
+  it->DoPrettyPrint(aPrettyPrint);
   nsString ucs2("ucs2");
   it->SetCharsetOverride(&ucs2);
   return it->QueryInterface(kIHTMLContentSinkIID, (void **)aInstancePtrResult);
 }
 
 
-
 /**
  * Construct a content sink stream.
  * @update	gpk02/03/99
  * @param 
  * @return
  */
-nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream(nsIOutputStream* aStream, nsString* aString)  {
+nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream(nsIOutputStream* aStream,
+                                             nsString* aString)
+{
   NS_INIT_REFCNT();
   mStream = aStream;
   mColPos = 0;
@@ -216,21 +214,30 @@ nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream(nsIOutputStream* aStream, nsString*
   mUnicodeEncoder = nsnull;
   mStream = aStream;
   mString = aString;
+  mPrettyPrint = PR_FALSE;
+  mPreformatted = PR_FALSE;
+  mWrapColumn = 72;     // XXX magic number, obviously needs to be settable
 }
 
 
-
 /**
  * 
  * @update	gpk02/03/99
  * @param 
  * @return
  */
-nsHTMLToTXTSinkStream::~nsHTMLToTXTSinkStream() {
+nsHTMLToTXTSinkStream::~nsHTMLToTXTSinkStream()
+{
   delete [] mBuffer;
   NS_IF_RELEASE(mUnicodeEncoder);
 }
 
+NS_IMETHODIMP
+nsHTMLToTXTSinkStream::DoPrettyPrint(PRBool aDoPrettyPrint)
+{
+  mPrettyPrint = aDoPrettyPrint;
+  return NS_OK;
+}
 
 /**
  * 
@@ -580,7 +587,10 @@ nsHTMLToTXTSinkStream::AddProcessingInstruction(const nsIParserNode& aNode){
  *  @return  
  */
 NS_IMETHODIMP
-nsHTMLToTXTSinkStream::AddComment(const nsIParserNode& aNode){
+nsHTMLToTXTSinkStream::AddComment(const nsIParserNode& aNode)
+{
+  // Skip comments in plaintext output
+  mDoOutput = PR_FALSE;
   return NS_OK;
 }
 
@@ -594,7 +604,8 @@ nsHTMLToTXTSinkStream::AddComment(const nsIParserNode& aNode){
   * @return PR_TRUE if successful. 
   */     
 NS_IMETHODIMP
-nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode){
+nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode)
+{
   eHTMLTags type = (eHTMLTags)aNode.GetNodeType();
   const nsString&   name = aNode.GetText();
   if (name.Equals("XIF_DOC_INFO"))
@@ -617,6 +628,23 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode){
 
   if (type == eHTMLTag_body)
     mDoOutput = PR_TRUE;
+
+  else if (mDoOutput && type == eHTMLTag_li)
+  {
+    nsString temp("*");
+    Write(temp);
+    mColPos++;
+  }
+  else if (type == eHTMLTag_pre)
+  {
+    mPreformatted = PR_TRUE;
+    nsString temp(NS_LINEBREAK);
+    Write(temp);
+    mColPos = 0;
+  }
+  else if (type == eHTMLTag_blockquote)
+    mIndent += gTabSize;
+
   return NS_OK;
 }
 
@@ -629,26 +657,40 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode){
   * @return PR_TRUE if successful. 
   */     
 NS_IMETHODIMP
-nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode){
+nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode)
+{
   eHTMLTags type = (eHTMLTags)aNode.GetNodeType();
-  //const nsString&   name = aNode.GetText();
 
   if (type == eHTMLTag_body)
     mDoOutput = PR_FALSE;
 
+  else if (type == eHTMLTag_comment)
+  {
+    mDoOutput = PR_TRUE;
+    return NS_OK;
+  }
+
+  else if (type == eHTMLTag_pre)
+    mPreformatted = PR_FALSE;
+
+  else if (type == eHTMLTag_blockquote)
+    mIndent -= gTabSize;
+
   if (IsBlockLevel(type))
   {
     if (mColPos != 0)
-    {  
-      nsString temp("\n");
-      Write(temp);
-      mColPos = 0;
+    {
+      if (mPrettyPrint)
+      {
+        nsString temp(NS_LINEBREAK);
+        Write(temp);
+        mColPos = 0;
+      }
     }
   }
   return NS_OK;
 }
 
-
 /**
   * This method is used to add a leaf to the currently 
   * open container.
@@ -658,7 +700,8 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode){
   * @return PR_TRUE if successful. 
   */     
 NS_IMETHODIMP
-nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode){
+nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode)
+{
    eHTMLTags type = (eHTMLTags)aNode.GetNodeType();
   
   nsString text = aNode.GetText();
@@ -666,9 +709,22 @@ nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode){
   if (mDoOutput == PR_FALSE)
     return NS_OK;
 
-  if (type == eHTMLTag_text) {
-    Write(text);
-    mColPos += text.Length();
+  if (type == eHTMLTag_text)
+  {
+    if (mColPos > mIndent)
+    {
+      nsString temp(" ");
+      Write(temp);
+      mColPos++;
+    }
+
+    if (mPrettyPrint)
+      WriteWrapped(text);
+    else
+    {
+      Write(text);
+      mColPos += text.Length();
+    }
   } 
   else if (type == eHTMLTag_entity)
   {
@@ -682,32 +738,113 @@ nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode){
 
     mColPos++;
   }
-  else if (type == eHTMLTag_whitespace)
+  else if (type == eHTMLTag_br)
   {
-    if (PR_TRUE)
+    if (mPrettyPrint)
+    {
+      nsString temp (NS_LINEBREAK);
+      Write(temp);
+      mColPos = 0;
+    }
+  }
+  // The only time we want to pass along whitespace from the original
+  // html source is if we're prettyprinting and we're inside a 
.
+  // Otherwise, either we're collapsing to minimal text, or we're
+  // prettyprinting to mimic the html format, and in neither case
+  // does the formatting of the html source help us.
+  else if (mPrettyPrint && mPreformatted && type == eHTMLTag_whitespace)
+  {
+    if (mPrettyPrint)
     {
       text = aNode.GetText();
       Write(text);
       mColPos += text.Length();
     }
   }
-  else if (type == eHTMLTag_br)
+  else if (mPrettyPrint && mPreformatted && type == eHTMLTag_newline)
   {
-    nsString temp("\n");
+    nsString temp(NS_LINEBREAK);
     Write(temp);
-    mColPos++;
+    mColPos = 0;
   }
-  else if (type == eHTMLTag_newline)
-  {
-    nsString temp("\n");
-    Write(text);
-    mColPos++;
-  }
-
 
   return NS_OK;
 }
 
+//
+// Write a string, wrapping appropriately to mWrapColumn.
+//
+void
+nsHTMLToTXTSinkStream::WriteWrapped(const nsString& aString)
+{
+  int totLen = aString.Length();
+  int charsLeft = totLen;
+  while (charsLeft > 0)     // Loop over lines
+  {
+    // Indent at the beginning of the line, if necessary
+    if (mColPos == 0 && mIndent > 0)
+    {
+      char* spaces = new char[mIndent+1];
+      for (int i=0; i totLen)
+      eol = totLen;
+    else
+    {
+      // We need to wrap, so search backward to find last IsSpace char:
+      int lastSpace = eol;
+      while (lastSpace > bol && !nsString::IsSpace(aString[lastSpace]))
+        --lastSpace;
+      if (lastSpace == bol)
+      {
+        // If we reached the bol, it might just be because we were close
+        // to the end already and should have wrapped last time.
+        // In that case, write a linebreak and come around again.
+        if (mColPos > mIndent)
+        {
+          nsAutoString linebreak(NS_LINEBREAK);
+          Write(linebreak);
+          mColPos = 0;
+          continue;
+        }
+        // Else apparently we really can't break this line at whitespace --
+        // so scan forward to the next space (if any) and dump a long line:
+        while (eol > totLen && !nsString::IsSpace(aString[lastSpace]))
+          ++eol;
+      }
+      else if (lastSpace > bol && lastSpace < eol)
+        eol = lastSpace+1;
+#ifdef DEBUG_akkana
+      else
+        printf("Wrapping: bol = %d, eol = %d, lastSpace = %d, totLen = %d\n",
+               bol, eol, lastSpace, totLen);
+#endif
+    }
+
+    nsAutoString lineStr;
+    aString.Mid(lineStr, bol, eol-bol);
+
+    if (eol != totLen)      // we're wrapping
+    {
+      lineStr.Append(NS_LINEBREAK);
+      mColPos = 0;
+    }
+    else
+      mColPos += lineStr.Length();
+    Write(lineStr);
+    charsLeft = totLen - eol;
+  }
+}
 
 /**
   * This method gets called when the parser begins the process
@@ -804,6 +941,7 @@ PRBool IsInline(eHTMLTags aTag)
     case  eHTMLTag_td:
     case  eHTMLTag_textarea:
     case  eHTMLTag_tt:
+    case  eHTMLTag_u:
     case  eHTMLTag_var:
     case  eHTMLTag_wbr:
            
diff --git a/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.h b/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.h
index 72c3331b329..fd6205ef12c 100644
--- a/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.h
+++ b/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.h
@@ -37,13 +37,10 @@
 #ifndef  NS_HTMLTOTEXTSINK_STREAM
 #define  NS_HTMLTOTEXTSINK_STREAM
 
-#include "nsIParserNode.h"
 #include "nsIHTMLContentSink.h"
-#include "nshtmlpars.h"
-#include "nsHTMLTokens.h"
 
 
-#define NS_HTMLTOTEXTSINK_STREAM_IID  \
+#define NS_HTMLTOTEXTSINK_STREAM_CID  \
   {0xa39c6bff, 0x15f0, 0x11d2, \
   {0x80, 0x41, 0x0, 0x10, 0x4b, 0x98, 0x3f, 0xd4}}
 
@@ -51,14 +48,15 @@
 class nsIUnicodeEncoder;
 class nsIOutputStream;
 
-class nsHTMLToTXTSinkStream : public nsIHTMLContentSink {
+class nsHTMLToTXTSinkStream : public nsIHTMLContentSink
+{
   public:
 
   /**
    * Standard constructor
    * @update	gpk02/03/99
    */
-  nsHTMLToTXTSinkStream(nsIOutputStream* aOutStream, nsString* aOutString); 
+  nsHTMLToTXTSinkStream(nsIOutputStream* aOutStream, nsString* aOutString);
 
   /**
    * virtual destructor
@@ -109,47 +107,46 @@ class nsHTMLToTXTSinkStream : public nsIHTMLContentSink {
   NS_IMETHOD BeginContext(PRInt32 aPosition);
   NS_IMETHOD EndContext(PRInt32 aPosition);
 
-
+  NS_IMETHOD DoPrettyPrint(PRBool aDoPrettyPrint);
 
 protected:
+  void EnsureBufferSize(PRInt32 aNewSize);
 
-    
-    void EnsureBufferSize(PRInt32 aNewSize);
-
-    nsresult InitEncoder(const nsString& aCharset);
-
-    void Write(const nsString& aString);
-    void EncodeToBuffer(const nsString& aString);
-    
-
+  nsresult InitEncoder(const nsString& aCharset);
 
+  void Write(const nsString& aString);
+  void WriteWrapped(const nsString& aString);
+  void EncodeToBuffer(const nsString& aString);
 
 protected:
-    nsIOutputStream* mStream;
-    nsString*        mString;
+  nsIOutputStream* mStream;
+  nsString*        mString;
 
-    PRInt32         mIndent;
-    PRInt32         mColPos;
-    PRBool          mDoOutput;
+  PRInt32          mIndent;
+  PRInt32          mColPos;
+  PRBool           mDoOutput;
+  PRBool           mPreformatted;
+  PRBool           mPrettyPrint;
+  PRInt32          mWrapColumn;
 
-    char*           mBuffer;
-    PRInt32         mBufferLength;  // The length of the data in the buffer
-    PRInt32         mBufferSize;    // The actual size of the buffer, regardless of the data
-
-    nsIUnicodeEncoder*  mUnicodeEncoder;
-    nsString            mCharsetOverride;
-   
+  char*            mBuffer;
+  PRInt32          mBufferLength;  // The length of the data in the buffer
+  PRInt32          mBufferSize;    // The actual size of the buffer, regardless of the data
 
+  nsIUnicodeEncoder*  mUnicodeEncoder;
+  nsString            mCharsetOverride;
 };
 
 extern NS_HTMLPARS nsresult
 NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult, 
                             nsIOutputStream* aOutStream,
-                            const nsString* aCharsetOverride=nsnull);
+                            const nsString* aCharsetOverride=nsnull,
+                            PRBool aPrettyPrint=PR_FALSE);
 
 extern NS_HTMLPARS nsresult
 NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult, 
-                            nsString* aOutString);
+                            nsString* aOutString,
+                            PRBool aPrettyPrint=PR_FALSE);
 
 #endif