Added support to encode the document as either a nsString or an nsIOutputStream.

In the case of the stream, the document is encoded using the document defined charset
or the user may override the charset.

Added constructors for creating a sink using a nsIOutputStream or an nsString.

Removed all HTML and TEXT encoding which relied on references to ostream. Using John McMullen's
platform independent streaming code in its place. :)
This commit is contained in:
kostello%netscape.com 1999-05-03 18:41:23 +00:00
parent d4a48d70d3
commit dbc32c5326
8 changed files with 960 additions and 934 deletions

View File

@ -42,6 +42,8 @@
#include "nsICharsetAlias.h" #include "nsICharsetAlias.h"
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
#include "nsICharsetConverterManager.h" #include "nsICharsetConverterManager.h"
#include "nsIOutputStream.h"
#include "nsFileStream.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
@ -51,7 +53,6 @@ static NS_DEFINE_IID(kIHTMLContentSinkIID, NS_IHTML_CONTENT_SINK_IID);
static char* gHeaderComment = "<!-- This page was created by the Gecko output system. -->"; static char* gHeaderComment = "<!-- This page was created by the Gecko output system. -->";
static char* gDocTypeHeader = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">"; static char* gDocTypeHeader = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">";
const int gTabSize=2; const int gTabSize=2;
static char gBuffer[1024];
static const char* UnicodeToEntity(PRInt32 aCode); static const char* UnicodeToEntity(PRInt32 aCode);
@ -332,18 +333,23 @@ NS_IMPL_RELEASE(nsHTMLContentSinkStream)
/** /**
* This method is defined in nsIParser. It is used to * Create an new sink
* cause the COM-like construction of an nsParser.
* *
* @update gess 4/8/98 * @update gpk 05/01/99
* @param nsIParser** ptr to newly instantiated parser
* @return NS_xxx error result * @return NS_xxx error result
*/ */
NS_HTMLPARS nsresult NS_HTMLPARS nsresult
NS_New_HTML_ContentSinkStream(nsIHTMLContentSink** aInstancePtrResult, NS_New_HTML_ContentSinkStream(nsIHTMLContentSink** aInstancePtrResult,
PRBool aDoFormat, nsIOutputStream* aOutStream,
PRBool aDoHeader) { const nsString* aCharsetOverride,
nsHTMLContentSinkStream* it = new nsHTMLContentSinkStream(aDoFormat,aDoHeader); PRBool aDoFormat,
PRBool aDoHeader)
{
nsHTMLContentSinkStream* it = new nsHTMLContentSinkStream(aOutStream,
nsnull,
aCharsetOverride,
aDoFormat,
aDoHeader);
if (nsnull == it) { if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -352,6 +358,32 @@ NS_New_HTML_ContentSinkStream(nsIHTMLContentSink** aInstancePtrResult,
} }
/**
* Create an new sink
*
* @update gpk 05/01/99
* @return NS_xxx error result
*/
NS_HTMLPARS nsresult
NS_New_HTML_ContentSinkStream(nsIHTMLContentSink** aInstancePtrResult,
nsString* aOutString,
PRBool aDoFormat,
PRBool aDoHeader)
{
nsHTMLContentSinkStream* it = new nsHTMLContentSinkStream(nsnull,
aOutString,
nsnull,
aDoFormat,
aDoHeader);
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
return it->QueryInterface(kIHTMLContentSinkIID, (void **)aInstancePtrResult);
}
/** /**
* Inits the encoder instance variable for the sink based on the charset * Inits the encoder instance variable for the sink based on the charset
@ -409,30 +441,12 @@ nsresult nsHTMLContentSinkStream::InitEncoder(const nsString& aCharset)
* @param * @param
* @return * @return
*/ */
nsHTMLContentSinkStream::nsHTMLContentSinkStream(PRBool aDoFormat,PRBool aDoHeader) { nsHTMLContentSinkStream::nsHTMLContentSinkStream(nsIOutputStream* aOutStream,
nsString* aOutString,
const nsString* aCharsetOverride,
PRBool aDoFormat,
PRBool aDoHeader) {
NS_INIT_REFCNT(); NS_INIT_REFCNT();
mOutput=&cout;
mLowerCaseTags = PR_TRUE;
memset(mHTMLTagStack,0,sizeof(mHTMLTagStack));
mHTMLStackPos = 0;
mColPos = 0;
mIndent = 0;
mDoFormat = aDoFormat;
mDoHeader = aDoHeader;
mBuffer = nsnull;
mBufferSize = 0;
mUnicodeEncoder = nsnull;
}
/**
* Construct a content sink stream.
* @update gess7/7/98
* @param
* @return
*/
nsHTMLContentSinkStream::nsHTMLContentSinkStream(ostream& aStream,PRBool aDoFormat,PRBool aDoHeader) {
NS_INIT_REFCNT();
mOutput = &aStream;
mLowerCaseTags = PR_TRUE; mLowerCaseTags = PR_TRUE;
memset(mHTMLTagStack,0,sizeof(mHTMLTagStack)); memset(mHTMLTagStack,0,sizeof(mHTMLTagStack));
mHTMLStackPos = 0; mHTMLStackPos = 0;
@ -443,6 +457,10 @@ nsHTMLContentSinkStream::nsHTMLContentSinkStream(ostream& aStream,PRBool aDoForm
mBuffer = nsnull; mBuffer = nsnull;
mBufferSize = 0; mBufferSize = 0;
mUnicodeEncoder = nsnull; mUnicodeEncoder = nsnull;
mStream = aOutStream;
mString = aOutString;
if (aCharsetOverride != nsnull)
mCharsetOverride = *aCharsetOverride;
} }
@ -498,82 +516,119 @@ void nsHTMLContentSinkStream::EnsureBufferSize(PRInt32 aNewSize)
} }
} }
void nsHTMLContentSinkStream::UnicodeToHTMLString(const nsString& aSrc)
void nsHTMLContentSinkStream::EncodeToBuffer(const nsString& aSrc)
{ {
PRInt32 length = aSrc.Length();
PRUnichar ch; NS_ASSERTION(mUnicodeEncoder != nsnull,"The unicode encoder needs to be initialized");
const char* entity = nsnull;
PRUint32 offset = 0;
PRUint32 addedLength = 0;
nsAutoString data;
if (mUnicodeEncoder == nsnull) if (mUnicodeEncoder == nsnull)
InitEncoder(""); return;
if (length > 0) #define CH_NBSP 160
PRInt32 length = aSrc.Length();
nsresult result;
if (mUnicodeEncoder != nsnull && length > 0)
{ {
// Step 1. Convert anything that maps to character entity to
// the entity value
EnsureBufferSize(length); EnsureBufferSize(length);
for (PRInt32 i = 0; i < length; i++) mBufferLength = mBufferSize;
{
ch = aSrc.CharAt(i);
entity = UnicodeToEntity(ch);
if (entity)
{
nsAutoString temp(entity);
temp.ToLowerCase();
data.Append('&');
data.Append(temp);
data.Append(';');
}
else
{
data.Append(ch);
}
}
// Step 2. Run the result through the converter
length = data.Length();
EnsureBufferSize(length);
PRInt32 bufferLength = mBufferSize;
mUnicodeEncoder->Reset(); mUnicodeEncoder->Reset();
nsresult result = mUnicodeEncoder->Convert(data.GetUnicode(), &length, mBuffer, &bufferLength); result = mUnicodeEncoder->Convert(aSrc.GetUnicode(), &length, mBuffer, &mBufferLength);
mBuffer[bufferLength] = 0; mBuffer[mBufferLength] = 0;
PRInt32 temp = bufferLength; PRInt32 temp = mBufferLength;
if (NS_SUCCEEDED(result)) if (NS_SUCCEEDED(result))
result = mUnicodeEncoder->Finish(mBuffer,&temp); result = mUnicodeEncoder->Finish(mBuffer,&temp);
}
for (PRInt32 i = 0; i < mBufferLength; i++)
{
if (mBuffer[i] == char(CH_NBSP))
mBuffer[i] = ' ';
}
}
} }
void nsHTMLContentSinkStream::Write(const nsString& aString)
{
// If a encoder is being used then convert first convert the input string
if (mUnicodeEncoder != nsnull)
{
EncodeToBuffer(aString);
if (mStream != nsnull)
{
nsOutputStream out(mStream);
out.write(mBuffer,mBufferLength);
}
if (mString != nsnull)
{
mString->Append(mBuffer);
}
}
else
{
if (mStream != nsnull)
{
nsOutputStream out(mStream);
const PRUnichar* unicode = aString.GetUnicode();
PRUint32 length = aString.Length();
out.write(unicode,length);
}
else
{
mString->Append(aString);
}
}
}
void nsHTMLContentSinkStream::Write(const char* aData)
{
if (mStream)
{
nsOutputStream out(mStream);
out << aData;
}
if (mString)
{
mString->Append(aData);
}
}
void nsHTMLContentSinkStream::Write(char aData)
{
if (mStream)
{
nsOutputStream out(mStream);
out << aData;
}
if (mString)
{
mString->Append(aData);
}
}
/** /**
* *
* @update gess7/7/98 * @update 04/30/99 gpk
* @param * @param
* @return * @return
*/ */
nsHTMLContentSinkStream::~nsHTMLContentSinkStream() { nsHTMLContentSinkStream::~nsHTMLContentSinkStream() {
NS_IF_RELEASE(mUnicodeEncoder); NS_IF_RELEASE(mUnicodeEncoder);
mOutput=0; //we don't own the stream we're given; just forget it.
} }
/**
*
* @update gess7/22/98
* @param
* @return
*/
NS_IMETHODIMP_(void)
nsHTMLContentSinkStream::SetOutputStream(ostream& aStream){
mOutput=&aStream;
}
/** /**
* *
@ -581,7 +636,7 @@ nsHTMLContentSinkStream::SetOutputStream(ostream& aStream){
* @param * @param
* @return * @return
*/ */
void nsHTMLContentSinkStream::WriteAttributes(const nsIParserNode& aNode,ostream& aStream) { void nsHTMLContentSinkStream::WriteAttributes(const nsIParserNode& aNode) {
int theCount=aNode.GetAttributeCount(); int theCount=aNode.GetAttributeCount();
if(theCount) { if(theCount) {
int i=0; int i=0;
@ -600,14 +655,20 @@ void nsHTMLContentSinkStream::WriteAttributes(const nsIParserNode& aNode,ostream
EnsureBufferSize(key.Length()); EnsureBufferSize(key.Length());
key.ToCString(mBuffer,mBufferSize); key.ToCString(mBuffer,mBufferSize);
aStream << " " << mBuffer << char(kEqual); // send to ouput " [KEY]="
Write(' ');
Write(mBuffer);
Write(char(kEqual));
mColPos += 1 + strlen(mBuffer) + 1; mColPos += 1 + strlen(mBuffer) + 1;
const nsString& value=aNode.GetValueAt(i); const nsString& value=aNode.GetValueAt(i);
UnicodeToHTMLString(value);
// send to ouput "\"[VALUE]\""
Write('\"');
Write(value);
Write('\"');
aStream << "\"" << mBuffer << "\"";
mColPos += 1 + strlen(mBuffer) + 1; mColPos += 1 + strlen(mBuffer) + 1;
} }
} }
@ -615,85 +676,31 @@ void nsHTMLContentSinkStream::WriteAttributes(const nsIParserNode& aNode,ostream
} }
/**
*
* @update gess7/5/98
* @param
* @return
*/
static
void OpenTagWithAttributes(const char* theTag,const nsIParserNode& aNode,int tab,ostream& aStream,PRBool aNewline) {
int i=0;
for(i=0;i<tab*gTabSize;i++)
aStream << " ";
aStream << (char)kLessThan << theTag;
// WriteAttributes(aNode,aStream);
aStream << (char)kGreaterThan;
if(aNewline)
aStream << endl;
}
/**
*
* @update gess7/5/98
* @param
* @return
*/
static
void OpenTag(const char* theTag,int tab,ostream& aStream,PRBool aNewline) {
int i=0;
for(i=0;i<tab*gTabSize;i++)
aStream << " ";
aStream << (char)kLessThan << theTag << (char)kGreaterThan;
if(aNewline)
aStream << endl;
}
/**
*
* @update gess7/5/98
* @param
* @return
*/
static
void CloseTag(const char* theTag,int tab,ostream& aStream) {
int i=0;
for(i=0;i<tab*gTabSize;i++)
aStream << " ";
aStream << (char)kLessThan << (char)kForwardSlash << theTag << (char)kGreaterThan << endl;
}
/**
*
* @update gess7/5/98
* @param
* @return
*/
static
void WritePair(eHTMLTags aTag,const nsString& theContent,int tab,ostream& aStream) {
const char* titleStr = GetTagName(aTag);
OpenTag(titleStr,tab,aStream,PR_FALSE);
theContent.ToCString(gBuffer,sizeof(gBuffer)-1);
aStream << gBuffer;
CloseTag(titleStr,0,aStream);
}
/** /**
* This method gets called by the parser when it encounters * This method gets called by the parser when it encounters
* a title tag and wants to set the document title in the sink. * a title tag and wants to set the document title in the sink.
* *
* @update 4/1/98 gess * @update 04/30/99 gpk
* @param nsString reference to new title value * @param nsString reference to new title value
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::SetTitle(const nsString& aValue){ nsHTMLContentSinkStream::SetTitle(const nsString& aValue){
if(mOutput) { const char* tagName = GetTagName(eHTMLTag_title);
WritePair(eHTMLTag_title,aValue,1+mTabLevel,*mOutput); Write(kLessThan);
} Write(tagName);
Write(kGreaterThan);
Write(aValue);
Write(kLessThan);
Write(kForwardSlash);
Write(tagName);
Write(kGreaterThan);
return NS_OK; return NS_OK;
} }
@ -701,17 +708,15 @@ nsHTMLContentSinkStream::SetTitle(const nsString& aValue){
/** /**
* This method is used to open the outer HTML container. * This method is used to open the outer HTML container.
* *
* @update 07/12/98 gpk * @update 04/30/99 gpk
* @param nsIParserNode reference to parser node interface * @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::OpenHTML(const nsIParserNode& aNode){ nsHTMLContentSinkStream::OpenHTML(const nsIParserNode& aNode){
if(mOutput) {
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
if (tag == eHTMLTag_html) if (tag == eHTMLTag_html)
AddStartTag(aNode,*mOutput); AddStartTag(aNode);
}
return NS_OK; return NS_OK;
} }
@ -719,18 +724,15 @@ nsHTMLContentSinkStream::OpenHTML(const nsIParserNode& aNode){
/** /**
* This method is used to close the outer HTML container. * This method is used to close the outer HTML container.
* *
* @update 07/12/98 gpk * @update 04/30/99 gpk
* @param nsIParserNode reference to parser node interface * @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::CloseHTML(const nsIParserNode& aNode){ nsHTMLContentSinkStream::CloseHTML(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_html)
if (tag == eHTMLTag_html) AddEndTag(aNode);
AddEndTag(aNode,*mOutput);
mOutput->flush();
}
return NS_OK; return NS_OK;
} }
@ -738,17 +740,15 @@ nsHTMLContentSinkStream::CloseHTML(const nsIParserNode& aNode){
/** /**
* This method is used to open the only HEAD container. * This method is used to open the only HEAD container.
* *
* @update 07/12/98 gpk * @update 04/30/99 gpk
* @param nsIParserNode reference to parser node interface * @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::OpenHead(const nsIParserNode& aNode){ nsHTMLContentSinkStream::OpenHead(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_head)
if (tag == eHTMLTag_head) AddStartTag(aNode);
AddStartTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -756,17 +756,15 @@ nsHTMLContentSinkStream::OpenHead(const nsIParserNode& aNode){
/** /**
* This method is used to close the only HEAD container. * This method is used to close the only HEAD container.
* *
* @update 07/12/98 gpk * @update 04/30/99 gpk
* @param nsIParserNode reference to parser node interface * @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::CloseHead(const nsIParserNode& aNode){ nsHTMLContentSinkStream::CloseHead(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_head)
if (tag == eHTMLTag_head) AddEndTag(aNode);
AddEndTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -774,17 +772,15 @@ nsHTMLContentSinkStream::CloseHead(const nsIParserNode& aNode){
/** /**
* This method is used to open the main BODY container. * This method is used to open the main BODY container.
* *
* @update 07/12/98 gpk * @update 04/30/99 gpk
* @param nsIParserNode reference to parser node interface * @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::OpenBody(const nsIParserNode& aNode){ nsHTMLContentSinkStream::OpenBody(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_body)
if (tag == eHTMLTag_body) AddStartTag(aNode);
AddStartTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -792,17 +788,15 @@ nsHTMLContentSinkStream::OpenBody(const nsIParserNode& aNode){
/** /**
* This method is used to close the main BODY container. * This method is used to close the main BODY container.
* *
* @update 07/12/98 gpk * @update 04/30/99 gpk
* @param nsIParserNode reference to parser node interface * @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::CloseBody(const nsIParserNode& aNode){ nsHTMLContentSinkStream::CloseBody(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_body)
if (tag == eHTMLTag_body) AddEndTag(aNode);
AddEndTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -816,11 +810,9 @@ nsHTMLContentSinkStream::CloseBody(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::OpenForm(const nsIParserNode& aNode){ nsHTMLContentSinkStream::OpenForm(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_form)
if (tag == eHTMLTag_form) AddStartTag(aNode);
AddStartTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -834,11 +826,9 @@ nsHTMLContentSinkStream::OpenForm(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::CloseForm(const nsIParserNode& aNode){ nsHTMLContentSinkStream::CloseForm(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_form)
if (tag == eHTMLTag_form) AddEndTag(aNode);
AddEndTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -851,11 +841,9 @@ nsHTMLContentSinkStream::CloseForm(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::OpenMap(const nsIParserNode& aNode){ nsHTMLContentSinkStream::OpenMap(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_map)
if (tag == eHTMLTag_map) AddStartTag(aNode);
AddStartTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -869,12 +857,10 @@ nsHTMLContentSinkStream::OpenMap(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::CloseMap(const nsIParserNode& aNode){ nsHTMLContentSinkStream::CloseMap(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_map)
if (tag == eHTMLTag_map) AddEndTag(aNode);
AddEndTag(aNode,*mOutput); return NS_OK;
}
return NS_OK;
} }
@ -887,11 +873,9 @@ nsHTMLContentSinkStream::CloseMap(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::OpenFrameset(const nsIParserNode& aNode){ nsHTMLContentSinkStream::OpenFrameset(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_frameset)
if (tag == eHTMLTag_frameset) AddStartTag(aNode);
AddStartTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -905,27 +889,26 @@ nsHTMLContentSinkStream::OpenFrameset(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::CloseFrameset(const nsIParserNode& aNode){ nsHTMLContentSinkStream::CloseFrameset(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_frameset)
if (tag == eHTMLTag_frameset) AddEndTag(aNode);
AddEndTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
void nsHTMLContentSinkStream::AddIndent(ostream& aStream) void nsHTMLContentSinkStream::AddIndent()
{ {
nsString padding(" ");
for (PRInt32 i = mIndent; --i >= 0; ) for (PRInt32 i = mIndent; --i >= 0; )
{ {
aStream << " "; Write(padding);
mColPos += 2; mColPos += 2;
} }
} }
void nsHTMLContentSinkStream::AddStartTag(const nsIParserNode& aNode, ostream& aStream) void nsHTMLContentSinkStream::AddStartTag(const nsIParserNode& aNode)
{ {
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
const nsString& name = aNode.GetText(); const nsString& name = aNode.GetText();
@ -942,37 +925,41 @@ void nsHTMLContentSinkStream::AddStartTag(const nsIParserNode& aNode, ostream& a
if (mColPos != 0 && BreakBeforeOpen(tag)) if (mColPos != 0 && BreakBeforeOpen(tag))
{ {
aStream << endl; Write('\n');
mColPos = 0; mColPos = 0;
} }
if (PermitWSBeforeOpen(tag)) if (PermitWSBeforeOpen(tag))
AddIndent(aStream); AddIndent();
EnsureBufferSize(tagName.Length());
tagName.ToCString(mBuffer,mBufferSize);
Write(kLessThan);
Write(mBuffer);
tagName.ToCString(gBuffer,sizeof(gBuffer)-1);
aStream << (char)kLessThan << gBuffer;
mColPos += 1 + tagName.Length(); mColPos += 1 + tagName.Length();
if (tag == eHTMLTag_style) if (tag == eHTMLTag_style)
{ {
aStream << (char)kGreaterThan << endl; Write(">\n");
const nsString& data = aNode.GetSkippedContent(); const nsString& data = aNode.GetSkippedContent();
PRInt32 size = data.Length(); PRInt32 size = data.Length();
char* buffer = new char[size+1]; char* buffer = new char[size+1];
data.ToCString(buffer,size+1); data.ToCString(buffer,size+1);
aStream << buffer; Write(buffer);
delete[] buffer; delete[] buffer;
} }
else else
{ {
WriteAttributes(aNode,aStream); WriteAttributes(aNode);
aStream << (char)kGreaterThan; Write(kGreaterThan);
mColPos += 1; mColPos += 1;
} }
if (BreakAfterOpen(tag)) if (BreakAfterOpen(tag))
{ {
aStream << endl; Write('\n');
mColPos = 0; mColPos = 0;
} }
@ -983,7 +970,7 @@ void nsHTMLContentSinkStream::AddStartTag(const nsIParserNode& aNode, ostream& a
void nsHTMLContentSinkStream::AddEndTag(const nsIParserNode& aNode, ostream& aStream) void nsHTMLContentSinkStream::AddEndTag(const nsIParserNode& aNode)
{ {
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
// const nsString& name = aNode.GetText(); // const nsString& name = aNode.GetText();
@ -1010,19 +997,25 @@ void nsHTMLContentSinkStream::AddEndTag(const nsIParserNode& aNode, ostream& aSt
{ {
if (mColPos != 0) if (mColPos != 0)
{ {
aStream << endl; Write('\n');
mColPos = 0; mColPos = 0;
} }
AddIndent(aStream); AddIndent();
} }
tagName.ToCString(gBuffer,sizeof(gBuffer)-1); EnsureBufferSize(tagName.Length());
aStream << (char)kLessThan << (char)kForwardSlash << gBuffer << (char)kGreaterThan; tagName.ToCString(mBuffer,mBufferSize);
mColPos += 1 + 1 + strlen(gBuffer) + 1;
Write(kLessThan);
Write(kForwardSlash);
Write(mBuffer);
Write(kGreaterThan);
mColPos += 1 + 1 + strlen(mBuffer) + 1;
if (BreakAfterClose(tag)) if (BreakAfterClose(tag))
{ {
aStream << endl; Write('\n');
mColPos = 0; mColPos = 0;
} }
mHTMLTagStack[--mHTMLStackPos] = eHTMLTag_unknown; mHTMLTagStack[--mHTMLStackPos] = eHTMLTag_unknown;
@ -1040,7 +1033,7 @@ void nsHTMLContentSinkStream::AddEndTag(const nsIParserNode& aNode, ostream& aSt
* @return * @return
*/ */
nsresult nsresult
nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode){
eHTMLTags type = (eHTMLTags)aNode.GetNodeType(); eHTMLTags type = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = eHTMLTag_unknown; eHTMLTags tag = eHTMLTag_unknown;
if (mHTMLStackPos > 0) if (mHTMLStackPos > 0)
@ -1062,14 +1055,16 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){
type == eHTMLTag_meta || type == eHTMLTag_meta ||
type == eHTMLTag_style) type == eHTMLTag_style)
{ {
AddStartTag(aNode,aStream); AddStartTag(aNode);
mHTMLTagStack[--mHTMLStackPos] = eHTMLTag_unknown; mHTMLTagStack[--mHTMLStackPos] = eHTMLTag_unknown;
} }
else if (type == eHTMLTag_entity) else if (type == eHTMLTag_entity)
{ {
const nsString& entity = aNode.GetText(); const nsString& entity = aNode.GetText();
UnicodeToHTMLString(entity); EncodeToBuffer(entity);
aStream << '&' << mBuffer << ';'; Write('&');
Write(mBuffer);
Write(';');
mColPos += entity.Length() + 2; mColPos += entity.Length() + 2;
} }
else if (type == eHTMLTag_text) else if (type == eHTMLTag_text)
@ -1077,8 +1072,7 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){
const nsString& text = aNode.GetText(); const nsString& text = aNode.GetText();
if ((mDoFormat == PR_FALSE) || preformatted == PR_TRUE) if ((mDoFormat == PR_FALSE) || preformatted == PR_TRUE)
{ {
UnicodeToHTMLString(text); Write(text);
aStream << mBuffer;
mColPos += text.Length(); mColPos += text.Length();
} }
else else
@ -1092,8 +1086,7 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){
// than the max then just add it // than the max then just add it
if (mColPos + length < mMaxColumn) if (mColPos + length < mMaxColumn)
{ {
UnicodeToHTMLString(text); Write(text);
aStream << mBuffer;
mColPos += text.Length(); mColPos += text.Length();
} }
else else
@ -1115,8 +1108,7 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){
// if there is no break than just add it // if there is no break than just add it
if (index == kNotFound) if (index == kNotFound)
{ {
UnicodeToHTMLString(str); Write(str);
aStream << mBuffer;
mColPos += str.Length(); mColPos += str.Length();
done = PR_TRUE; done = PR_TRUE;
} }
@ -1128,8 +1120,8 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){
first.Truncate(index); first.Truncate(index);
UnicodeToHTMLString(first); Write(first);
aStream << mBuffer << endl; Write('\n');
mColPos = 0; mColPos = 0;
// cut the string from the beginning to the index // cut the string from the beginning to the index
@ -1145,8 +1137,7 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){
if ((mDoFormat == PR_FALSE) || preformatted || IgnoreWS(tag) == PR_FALSE) if ((mDoFormat == PR_FALSE) || preformatted || IgnoreWS(tag) == PR_FALSE)
{ {
const nsString& text = aNode.GetText(); const nsString& text = aNode.GetText();
UnicodeToHTMLString(text); Write(text);
aStream << mBuffer;
mColPos += text.Length(); mColPos += text.Length();
} }
} }
@ -1155,8 +1146,7 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){
if ((mDoFormat == PR_FALSE) || preformatted) if ((mDoFormat == PR_FALSE) || preformatted)
{ {
const nsString& text = aNode.GetText(); const nsString& text = aNode.GetText();
UnicodeToHTMLString(text); Write(text);
aStream << mBuffer;
mColPos = 0; mColPos = 0;
} }
} }
@ -1215,25 +1205,26 @@ nsHTMLContentSinkStream::AddComment(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::OpenContainer(const nsIParserNode& aNode){ nsHTMLContentSinkStream::OpenContainer(const nsIParserNode& aNode){
if(mOutput)
const nsString& name = aNode.GetText();
if (name.Equals("XIF_DOC_INFO"))
{ {
const nsString& name = aNode.GetText(); PRInt32 count=aNode.GetAttributeCount();
if (name.Equals("XIF_DOC_INFO")) for(PRInt32 i=0;i<count;i++)
{ {
PRInt32 count=aNode.GetAttributeCount(); const nsString& key=aNode.GetKeyAt(i);
for(PRInt32 i=0;i<count;i++) const nsString& value=aNode.GetValueAt(i);
{
const nsString& key=aNode.GetKeyAt(i);
const nsString& value=aNode.GetValueAt(i);
if (key.Equals("charset")) if (key.Equals("charset"))
{
if (mCharsetOverride.Length() == 0)
InitEncoder(value); InitEncoder(value);
} }
} }
else }
{ else
AddStartTag(aNode,*mOutput); {
} AddStartTag(aNode);
} }
return NS_OK; return NS_OK;
} }
@ -1242,37 +1233,17 @@ nsHTMLContentSinkStream::OpenContainer(const nsIParserNode& aNode){
/** /**
* This method is used to close a generic container. * This method is used to close a generic container.
* *
* @update 07/12/98 gpk * @update 04/30/99 gpk
* @param nsIParserNode reference to parser node interface * @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::CloseContainer(const nsIParserNode& aNode){ nsHTMLContentSinkStream::CloseContainer(const nsIParserNode& aNode){
if(mOutput) { AddEndTag(aNode);
AddEndTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
/**
* This method is used to add a leaf to the currently
* open container.
*
* @update 07/12/98 gpk
* @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful.
*/
NS_IMETHODIMP
nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode){
nsresult result = NS_OK;
if(mOutput) {
result = AddLeaf(aNode,*mOutput);
}
return result;
}
/** /**
* This method gets called when the parser begins the process * This method gets called when the parser begins the process
* of building the content model via the content sink. * of building the content model via the content sink.
@ -1282,10 +1253,12 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode){
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::WillBuildModel(void){ nsHTMLContentSinkStream::WillBuildModel(void){
mTabLevel=-1; mTabLevel=-1;
if(mDoHeader && mOutput) { if(mDoHeader) {
(*mOutput) << gHeaderComment << endl; Write(gHeaderComment);
(*mOutput) << gDocTypeHeader << endl; Write('\n');
} Write(gDocTypeHeader);
Write('\n');
}
return NS_OK; return NS_OK;
} }

View File

@ -54,23 +54,24 @@ class ostream;
#endif #endif
class nsIUnicodeEncoder; class nsIUnicodeEncoder;
class nsIOutputStream;
class nsHTMLContentSinkStream : public nsIHTMLContentSink { class nsHTMLContentSinkStream : public nsIHTMLContentSink {
public: public:
/**
* Standard constructor
* @update gess7/7/98
*/
nsHTMLContentSinkStream(PRBool aDoFormat = PR_TRUE, PRBool aDoHeader = PR_TRUE);
/** /**
* Constructor with associated stream. If you use this, it means that you want * Constructor with associated stream. If you use this, it means that you want
* this class to emits its output to the stream you provide. * this class to emits its output to the stream you provide.
* @update gess7/7/98 * @update gpk 04/30/99
* @param aStream -- ref to stream where you want output sent * @param aOutStream -- stream where you want output sent
* @param aOutStream -- ref to string where you want output sent
*/ */
nsHTMLContentSinkStream(ostream& aStream,PRBool aDoFormat = PR_TRUE, PRBool aDoHeader = PR_TRUE); nsHTMLContentSinkStream(nsIOutputStream* aOutStream,
nsString* aOutString,
const nsString* aCharsetOverride,
PRBool aDoFormat = PR_TRUE,
PRBool aDoHeader = PR_TRUE);
/** /**
* virtual destructor * virtual destructor
@ -78,8 +79,6 @@ class nsHTMLContentSinkStream : public nsIHTMLContentSink {
*/ */
virtual ~nsHTMLContentSinkStream(); virtual ~nsHTMLContentSinkStream();
NS_IMETHOD_(void) SetOutputStream(ostream& aStream);
// nsISupports // nsISupports
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
@ -127,22 +126,26 @@ public:
protected: protected:
nsresult AddLeaf(const nsIParserNode& aNode, ostream& aStream); void WriteAttributes(const nsIParserNode& aNode);
void WriteAttributes(const nsIParserNode& aNode,ostream& aStream); void AddStartTag(const nsIParserNode& aNode);
void AddStartTag(const nsIParserNode& aNode, ostream& aStream); void AddEndTag(const nsIParserNode& aNode);
void AddEndTag(const nsIParserNode& aNode, ostream& aStream); void AddIndent();
void AddIndent(ostream& aStream);
void EnsureBufferSize(PRInt32 aNewSize); void EnsureBufferSize(PRInt32 aNewSize);
void UnicodeToHTMLString(const nsString& aSrc);
nsresult InitEncoder(const nsString& aCharset); nsresult InitEncoder(const nsString& aCharset);
void EncodeToBuffer(const nsString& aString);
void Write(const nsString& aString);
void Write(const char* aCharBuffer);
void Write(char aChar);
protected: protected:
ostream* mOutput; nsIOutputStream* mStream;
nsString* mString;
int mTabLevel; int mTabLevel;
PRInt32 mIndent; PRInt32 mIndent;
@ -155,13 +158,24 @@ protected:
PRBool mDoHeader; PRBool mDoHeader;
char* mBuffer; char* mBuffer;
PRInt32 mBufferSize; PRInt32 mBufferLength; // The length of the data in the buffer
PRInt32 mBufferSize; // The actual size of the buffer, regardless of the data
nsIUnicodeEncoder* mUnicodeEncoder; nsIUnicodeEncoder* mUnicodeEncoder;
nsString mCharsetOverride;
}; };
extern NS_HTMLPARS nsresult extern NS_HTMLPARS nsresult
NS_New_HTML_ContentSinkStream(nsIHTMLContentSink** aInstancePtrResult, NS_New_HTML_ContentSinkStream(nsIHTMLContentSink** aInstancePtrResult,
nsIOutputStream* aOutStream,
const nsString* aCharsetOverride=nsnull,
PRBool aDoFormat = PR_TRUE,
PRBool aDoHeader = PR_TRUE);
extern NS_HTMLPARS nsresult
NS_New_HTML_ContentSinkStream(nsIHTMLContentSink** aInstancePtrResult,
nsString* aOutString,
PRBool aDoFormat = PR_TRUE, PRBool aDoFormat = PR_TRUE,
PRBool aDoHeader = PR_TRUE); PRBool aDoHeader = PR_TRUE);

View File

@ -39,6 +39,8 @@
#include "nsICharsetAlias.h" #include "nsICharsetAlias.h"
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
#include "nsICharsetConverterManager.h" #include "nsICharsetConverterManager.h"
#include "nsIOutputStream.h"
#include "nsFileStream.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIContentSinkIID, NS_ICONTENT_SINK_IID); static NS_DEFINE_IID(kIContentSinkIID, NS_ICONTENT_SINK_IID);
@ -60,7 +62,19 @@ static PRBool IsBlockLevel(eHTMLTags aTag);
nsresult nsHTMLToTXTSinkStream::InitEncoder(const nsString& aCharset) nsresult nsHTMLToTXTSinkStream::InitEncoder(const nsString& aCharset)
{ {
nsresult res = NS_OK; nsresult res = NS_OK;
// If the converter is ucs2, then do not use a converter
nsString ucs2("ucs2");
if (aCharset.Equals(ucs2))
{
NS_IF_RELEASE(mUnicodeEncoder);
return res;
}
nsICharsetAlias* calias = nsnull; nsICharsetAlias* calias = nsnull;
res = nsServiceManager::GetService(kCharsetAliasCID, res = nsServiceManager::GetService(kCharsetAliasCID,
@ -141,58 +155,71 @@ NS_IMPL_RELEASE(nsHTMLToTXTSinkStream)
/** /**
* This method is defined in nsIParser. It is used to * This method creates a new sink, it sets the stream used
* cause the COM-like construction of an nsParser. * for the sink to aStream
* *
* @update gpk02/03/99 * @update gpk 04/30/99
* @param nsIParser** ptr to newly instantiated parser
* @return NS_xxx error result
*/ */
NS_HTMLPARS nsresult NS_HTMLPARS nsresult
NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult) { NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult,
nsHTMLToTXTSinkStream* it = new nsHTMLToTXTSinkStream(); nsIOutputStream* aStream,
const nsString* aCharsetOverride) {
NS_ASSERTION(aStream != nsnull, "a valid stream is required");
nsHTMLToTXTSinkStream* it = new nsHTMLToTXTSinkStream(aStream,nsnull);
if (nsnull == it) { if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
if (aCharsetOverride != nsnull)
it->SetCharsetOverride(aCharsetOverride);
return it->QueryInterface(kIHTMLContentSinkIID, (void **)aInstancePtrResult); return it->QueryInterface(kIHTMLContentSinkIID, (void **)aInstancePtrResult);
} }
/** /**
* Construct a content sink stream. * This method creates a new sink, it sets the stream used
* @update gpk02/03/99 * for the sink to aStream
* @param *
* @return * @update gpk 04/30/99
*/ */
nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream() { NS_HTMLPARS nsresult
NS_INIT_REFCNT(); NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult,
mOutput=&cout; nsString* aString) {
mColPos = 0;
mIndent = 0; NS_ASSERTION(aString != nsnull, "a valid stream is required");
mDoOutput = PR_FALSE; nsHTMLToTXTSinkStream* it = new nsHTMLToTXTSinkStream(nsnull,aString);
mBufferSize = 0; if (nsnull == it) {
mBuffer = nsnull; return NS_ERROR_OUT_OF_MEMORY;
mUnicodeEncoder = nsnull; }
nsString ucs2("ucs2");
it->SetCharsetOverride(&ucs2);
return it->QueryInterface(kIHTMLContentSinkIID, (void **)aInstancePtrResult);
} }
/** /**
* Construct a content sink stream. * Construct a content sink stream.
* @update gpk02/03/99 * @update gpk02/03/99
* @param * @param
* @return * @return
*/ */
nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream(ostream& aStream) { nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream(nsIOutputStream* aStream, nsString* aString) {
NS_INIT_REFCNT(); NS_INIT_REFCNT();
mOutput = &aStream; mStream = aStream;
mColPos = 0; mColPos = 0;
mIndent = 0; mIndent = 0;
mDoOutput = PR_FALSE; mDoOutput = PR_FALSE;
mBufferSize = 0; mBufferSize = 0;
mBufferLength = 0;
mBuffer = nsnull; mBuffer = nsnull;
mUnicodeEncoder = nsnull; mUnicodeEncoder = nsnull;
mStream = aStream;
mString = aString;
} }
/** /**
* *
* @update gpk02/03/99 * @update gpk02/03/99
@ -200,7 +227,6 @@ nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream(ostream& aStream) {
* @return * @return
*/ */
nsHTMLToTXTSinkStream::~nsHTMLToTXTSinkStream() { nsHTMLToTXTSinkStream::~nsHTMLToTXTSinkStream() {
mOutput=0; //we don't own the stream we're given; just forget it.
delete [] mBuffer; delete [] mBuffer;
NS_IF_RELEASE(mUnicodeEncoder); NS_IF_RELEASE(mUnicodeEncoder);
} }
@ -208,50 +234,24 @@ nsHTMLToTXTSinkStream::~nsHTMLToTXTSinkStream() {
/** /**
* *
* @update gpk02/03/99 * @update gpk04/30/99
* @param * @param
* @return * @return
*/ */
NS_IMETHODIMP_(void)
nsHTMLToTXTSinkStream::SetOutputStream(ostream& aStream){ NS_IMETHODIMP
mOutput=&aStream; nsHTMLToTXTSinkStream::SetCharsetOverride(const nsString* aCharset)
{
if (aCharset)
{
mCharsetOverride = *aCharset;
InitEncoder(mCharsetOverride);
}
return NS_OK;
} }
/**
*
* @update gpk02/03/99
* @param
* @return
*/
static
void OpenTagWithAttributes(const char* theTag,const nsIParserNode& aNode,int tab,ostream& aStream,PRBool aNewline) {
}
/**
*
* @update gpk02/03/99
* @param
* @return
*/
static
void OpenTag(const char* theTag,int tab,ostream& aStream,PRBool aNewline) {
}
/**
*
* @update gpk02/03/99
* @param
* @return
*/
static
void CloseTag(const char* theTag,int tab,ostream& aStream) {
}
/** /**
* This method gets called by the parser when it encounters * This method gets called by the parser when it encounters
* a title tag and wants to set the document title in the sink. * a title tag and wants to set the document title in the sink.
@ -463,38 +463,38 @@ void nsHTMLToTXTSinkStream::EnsureBufferSize(PRInt32 aNewSize)
mBufferSize = 2*aNewSize+1; // make the twice as large mBufferSize = 2*aNewSize+1; // make the twice as large
mBuffer = new char[mBufferSize]; mBuffer = new char[mBufferSize];
mBuffer[0] = 0; mBuffer[0] = 0;
mBufferLength = 0;
} }
} }
void nsHTMLToTXTSinkStream::UnicodeToTXTString(const nsString& aSrc) void nsHTMLToTXTSinkStream::EncodeToBuffer(const nsString& aSrc)
{ {
NS_ASSERTION(mUnicodeEncoder != nsnull,"The unicode encoder needs to be initialized");
if (mUnicodeEncoder == nsnull)
return;
#define CH_NBSP 160 #define CH_NBSP 160
PRInt32 length = aSrc.Length(); PRInt32 length = aSrc.Length();
nsresult result; nsresult result;
PRInt32 bufferLength;
if (mUnicodeEncoder == nsnull) if (mUnicodeEncoder != nsnull && length > 0)
InitEncoder("");
if (length > 0)
{ {
EnsureBufferSize(length); EnsureBufferSize(length);
bufferLength = mBufferSize; mBufferLength = mBufferSize;
mUnicodeEncoder->Reset(); mUnicodeEncoder->Reset();
result = mUnicodeEncoder->Convert(aSrc.GetUnicode(), &length, mBuffer, &bufferLength); result = mUnicodeEncoder->Convert(aSrc.GetUnicode(), &length, mBuffer, &mBufferLength);
mBuffer[bufferLength] = 0; mBuffer[mBufferLength] = 0;
PRInt32 temp = bufferLength; PRInt32 temp = mBufferLength;
if (NS_SUCCEEDED(result)) if (NS_SUCCEEDED(result))
result = mUnicodeEncoder->Finish(mBuffer,&temp); result = mUnicodeEncoder->Finish(mBuffer,&temp);
for (PRInt32 i = 0; i < bufferLength; i++) for (PRInt32 i = 0; i < mBufferLength; i++)
{ {
if (mBuffer[i] == char(CH_NBSP)) if (mBuffer[i] == char(CH_NBSP))
mBuffer[i] = ' '; mBuffer[i] = ' ';
@ -504,76 +504,47 @@ void nsHTMLToTXTSinkStream::UnicodeToTXTString(const nsString& aSrc)
} }
NS_IMETHODIMP
nsHTMLToTXTSinkStream::GetStringBuffer(nsString & aStrBuffer)
{
aStrBuffer = mStrBuffer;
return NS_OK;
}
/** /**
* This gets called by the parser when you want to add * Write places the contents of aString into either the output stream
* a leaf node to the current container in the content * or the output string.
* model. * When going to the stream, all data is run through the encoder
* *
* @updated gpk 06/18/98 * @updated gpk02/03/99
* @param * @param
* @return * @return
*/ */
nsresult void nsHTMLToTXTSinkStream::Write(const nsString& aString)
nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream)
{ {
eHTMLTags type = (eHTMLTags)aNode.GetNodeType();
const nsString& text = aNode.GetText();
if (mDoOutput == PR_FALSE) // If a encoder is being used then convert first convert the input string
return NS_OK; if (mUnicodeEncoder != nsnull)
if (type == eHTMLTag_text) {
UnicodeToTXTString(text);
aStream << mBuffer;
mStrBuffer.Append(mBuffer);
mColPos += text.Length();
}
else if (type == eHTMLTag_entity)
{ {
const nsString& text = aNode.GetText(); EncodeToBuffer(aString);
UnicodeToTXTString(text); if (mStream != nsnull)
PRInt32 entity = NS_EntityToUnicode(mBuffer);
if (entity < 256)
{ {
char ch = (char)entity; nsOutputStream out(mStream);
aStream << ch; out.write(mBuffer,mBufferLength);
mColPos++; }
if (mString != nsnull)
{
mString->Append(mBuffer);
} }
} }
else if (type == eHTMLTag_whitespace) else
{ {
if (PR_TRUE) if (mStream != nsnull)
{ {
const nsString& text = aNode.GetText(); nsOutputStream out(mStream);
UnicodeToTXTString(text); const PRUnichar* unicode = aString.GetUnicode();
aStream << mBuffer; PRUint32 length = aString.Length();
mStrBuffer.Append(mBuffer); out.write(unicode,length);
mColPos += text.Length(); }
else
{
mString->Append(aString);
} }
} }
else if (type == eHTMLTag_br)
{
if (PR_TRUE)
{
aStream << endl;
mStrBuffer.Append("\n");
mColPos += 1;
}
}
return NS_OK;
} }
@ -628,7 +599,10 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode){
const nsString& value=aNode.GetValueAt(i); const nsString& value=aNode.GetValueAt(i);
if (key.Equals("charset")) if (key.Equals("charset"))
InitEncoder(value); {
if (mCharsetOverride.Length() == 0)
InitEncoder(value);
}
} }
} }
@ -657,9 +631,8 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode){
{ {
if (mColPos != 0) if (mColPos != 0)
{ {
if (mOutput) nsString temp("\n");
*mOutput << endl; Write(temp);
mStrBuffer.Append("\n");
mColPos = 0; mColPos = 0;
} }
} }
@ -677,11 +650,53 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode){ nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode){
nsresult result = NS_OK; eHTMLTags type = (eHTMLTags)aNode.GetNodeType();
if(mOutput) {
result = AddLeaf(aNode,*mOutput); const nsString& text = aNode.GetText();
if (mDoOutput == PR_FALSE)
return NS_OK;
if (type == eHTMLTag_text) {
Write(text);
mColPos += text.Length();
}
else if (type == eHTMLTag_entity)
{
const nsString& text = aNode.GetText();
EncodeToBuffer(text);
PRUnichar entity = NS_EntityToUnicode(mBuffer);
nsString temp;
temp.Append(entity);
Write(temp);
mColPos++;
} }
return result; else if (type == eHTMLTag_whitespace)
{
if (PR_TRUE)
{
const nsString& text = aNode.GetText();
Write(text);
mColPos += text.Length();
}
}
else if (type == eHTMLTag_br)
{
nsString temp("\n");
Write(text);
mColPos++;
}
else if (type == eHTMLTag_newline)
{
nsString temp("\n");
Write(text);
mColPos++;
}
return NS_OK;
} }

View File

@ -47,12 +47,9 @@
{0xa39c6bff, 0x15f0, 0x11d2, \ {0xa39c6bff, 0x15f0, 0x11d2, \
{0x80, 0x41, 0x0, 0x10, 0x4b, 0x98, 0x3f, 0xd4}} {0x80, 0x41, 0x0, 0x10, 0x4b, 0x98, 0x3f, 0xd4}}
#ifndef XP_MAC
class ostream;
#endif
class nsIUnicodeEncoder; class nsIUnicodeEncoder;
class nsIOutputStream;
class nsHTMLToTXTSinkStream : public nsIHTMLContentSink { class nsHTMLToTXTSinkStream : public nsIHTMLContentSink {
public: public:
@ -61,8 +58,7 @@ class nsHTMLToTXTSinkStream : public nsIHTMLContentSink {
* Standard constructor * Standard constructor
* @update gpk02/03/99 * @update gpk02/03/99
*/ */
nsHTMLToTXTSinkStream(); nsHTMLToTXTSinkStream(nsIOutputStream* aOutStream, nsString* aOutString);
nsHTMLToTXTSinkStream(ostream& aStream);
/** /**
* virtual destructor * virtual destructor
@ -70,8 +66,8 @@ class nsHTMLToTXTSinkStream : public nsIHTMLContentSink {
*/ */
virtual ~nsHTMLToTXTSinkStream(); virtual ~nsHTMLToTXTSinkStream();
NS_IMETHOD_(void) SetOutputStream(ostream& aStream); NS_IMETHOD SetCharsetOverride(const nsString* aCharset);
NS_IMETHOD GetStringBuffer(nsString & aStrBuffer);
// nsISupports // nsISupports
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
@ -113,32 +109,47 @@ class nsHTMLToTXTSinkStream : public nsIHTMLContentSink {
NS_IMETHOD BeginContext(PRInt32 aPosition); NS_IMETHOD BeginContext(PRInt32 aPosition);
NS_IMETHOD EndContext(PRInt32 aPosition); NS_IMETHOD EndContext(PRInt32 aPosition);
protected: protected:
nsresult AddLeaf(const nsIParserNode& aNode, ostream& aStream);
void WriteAttributes(const nsIParserNode& aNode,ostream& aStream);
void EnsureBufferSize(PRInt32 aNewSize); void EnsureBufferSize(PRInt32 aNewSize);
void UnicodeToTXTString(const nsString& aSrc);
nsresult InitEncoder(const nsString& aCharset); nsresult InitEncoder(const nsString& aCharset);
void Write(const nsString& aString);
void EncodeToBuffer(const nsString& aString);
protected: protected:
ostream* mOutput; nsIOutputStream* mStream;
nsString* mString;
PRInt32 mIndent; PRInt32 mIndent;
PRInt32 mColPos; PRInt32 mColPos;
PRBool mDoOutput; PRBool mDoOutput;
char* mBuffer;
PRInt32 mBufferSize;
nsString mStrBuffer; 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; nsIUnicodeEncoder* mUnicodeEncoder;
nsString mCharsetOverride;
}; };
extern NS_HTMLPARS nsresult extern NS_HTMLPARS nsresult
NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult); NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult,
nsIOutputStream* aOutStream,
const nsString* aCharsetOverride=nsnull);
extern NS_HTMLPARS nsresult
NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult,
nsString* aOutString);
#endif #endif

View File

@ -42,6 +42,8 @@
#include "nsICharsetAlias.h" #include "nsICharsetAlias.h"
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
#include "nsICharsetConverterManager.h" #include "nsICharsetConverterManager.h"
#include "nsIOutputStream.h"
#include "nsFileStream.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
@ -51,7 +53,6 @@ static NS_DEFINE_IID(kIHTMLContentSinkIID, NS_IHTML_CONTENT_SINK_IID);
static char* gHeaderComment = "<!-- This page was created by the Gecko output system. -->"; static char* gHeaderComment = "<!-- This page was created by the Gecko output system. -->";
static char* gDocTypeHeader = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">"; static char* gDocTypeHeader = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">";
const int gTabSize=2; const int gTabSize=2;
static char gBuffer[1024];
static const char* UnicodeToEntity(PRInt32 aCode); static const char* UnicodeToEntity(PRInt32 aCode);
@ -332,18 +333,23 @@ NS_IMPL_RELEASE(nsHTMLContentSinkStream)
/** /**
* This method is defined in nsIParser. It is used to * Create an new sink
* cause the COM-like construction of an nsParser.
* *
* @update gess 4/8/98 * @update gpk 05/01/99
* @param nsIParser** ptr to newly instantiated parser
* @return NS_xxx error result * @return NS_xxx error result
*/ */
NS_HTMLPARS nsresult NS_HTMLPARS nsresult
NS_New_HTML_ContentSinkStream(nsIHTMLContentSink** aInstancePtrResult, NS_New_HTML_ContentSinkStream(nsIHTMLContentSink** aInstancePtrResult,
PRBool aDoFormat, nsIOutputStream* aOutStream,
PRBool aDoHeader) { const nsString* aCharsetOverride,
nsHTMLContentSinkStream* it = new nsHTMLContentSinkStream(aDoFormat,aDoHeader); PRBool aDoFormat,
PRBool aDoHeader)
{
nsHTMLContentSinkStream* it = new nsHTMLContentSinkStream(aOutStream,
nsnull,
aCharsetOverride,
aDoFormat,
aDoHeader);
if (nsnull == it) { if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -352,6 +358,32 @@ NS_New_HTML_ContentSinkStream(nsIHTMLContentSink** aInstancePtrResult,
} }
/**
* Create an new sink
*
* @update gpk 05/01/99
* @return NS_xxx error result
*/
NS_HTMLPARS nsresult
NS_New_HTML_ContentSinkStream(nsIHTMLContentSink** aInstancePtrResult,
nsString* aOutString,
PRBool aDoFormat,
PRBool aDoHeader)
{
nsHTMLContentSinkStream* it = new nsHTMLContentSinkStream(nsnull,
aOutString,
nsnull,
aDoFormat,
aDoHeader);
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
return it->QueryInterface(kIHTMLContentSinkIID, (void **)aInstancePtrResult);
}
/** /**
* Inits the encoder instance variable for the sink based on the charset * Inits the encoder instance variable for the sink based on the charset
@ -409,30 +441,12 @@ nsresult nsHTMLContentSinkStream::InitEncoder(const nsString& aCharset)
* @param * @param
* @return * @return
*/ */
nsHTMLContentSinkStream::nsHTMLContentSinkStream(PRBool aDoFormat,PRBool aDoHeader) { nsHTMLContentSinkStream::nsHTMLContentSinkStream(nsIOutputStream* aOutStream,
nsString* aOutString,
const nsString* aCharsetOverride,
PRBool aDoFormat,
PRBool aDoHeader) {
NS_INIT_REFCNT(); NS_INIT_REFCNT();
mOutput=&cout;
mLowerCaseTags = PR_TRUE;
memset(mHTMLTagStack,0,sizeof(mHTMLTagStack));
mHTMLStackPos = 0;
mColPos = 0;
mIndent = 0;
mDoFormat = aDoFormat;
mDoHeader = aDoHeader;
mBuffer = nsnull;
mBufferSize = 0;
mUnicodeEncoder = nsnull;
}
/**
* Construct a content sink stream.
* @update gess7/7/98
* @param
* @return
*/
nsHTMLContentSinkStream::nsHTMLContentSinkStream(ostream& aStream,PRBool aDoFormat,PRBool aDoHeader) {
NS_INIT_REFCNT();
mOutput = &aStream;
mLowerCaseTags = PR_TRUE; mLowerCaseTags = PR_TRUE;
memset(mHTMLTagStack,0,sizeof(mHTMLTagStack)); memset(mHTMLTagStack,0,sizeof(mHTMLTagStack));
mHTMLStackPos = 0; mHTMLStackPos = 0;
@ -443,6 +457,10 @@ nsHTMLContentSinkStream::nsHTMLContentSinkStream(ostream& aStream,PRBool aDoForm
mBuffer = nsnull; mBuffer = nsnull;
mBufferSize = 0; mBufferSize = 0;
mUnicodeEncoder = nsnull; mUnicodeEncoder = nsnull;
mStream = aOutStream;
mString = aOutString;
if (aCharsetOverride != nsnull)
mCharsetOverride = *aCharsetOverride;
} }
@ -498,82 +516,119 @@ void nsHTMLContentSinkStream::EnsureBufferSize(PRInt32 aNewSize)
} }
} }
void nsHTMLContentSinkStream::UnicodeToHTMLString(const nsString& aSrc)
void nsHTMLContentSinkStream::EncodeToBuffer(const nsString& aSrc)
{ {
PRInt32 length = aSrc.Length();
PRUnichar ch; NS_ASSERTION(mUnicodeEncoder != nsnull,"The unicode encoder needs to be initialized");
const char* entity = nsnull;
PRUint32 offset = 0;
PRUint32 addedLength = 0;
nsAutoString data;
if (mUnicodeEncoder == nsnull) if (mUnicodeEncoder == nsnull)
InitEncoder(""); return;
if (length > 0) #define CH_NBSP 160
PRInt32 length = aSrc.Length();
nsresult result;
if (mUnicodeEncoder != nsnull && length > 0)
{ {
// Step 1. Convert anything that maps to character entity to
// the entity value
EnsureBufferSize(length); EnsureBufferSize(length);
for (PRInt32 i = 0; i < length; i++) mBufferLength = mBufferSize;
{
ch = aSrc.CharAt(i);
entity = UnicodeToEntity(ch);
if (entity)
{
nsAutoString temp(entity);
temp.ToLowerCase();
data.Append('&');
data.Append(temp);
data.Append(';');
}
else
{
data.Append(ch);
}
}
// Step 2. Run the result through the converter
length = data.Length();
EnsureBufferSize(length);
PRInt32 bufferLength = mBufferSize;
mUnicodeEncoder->Reset(); mUnicodeEncoder->Reset();
nsresult result = mUnicodeEncoder->Convert(data.GetUnicode(), &length, mBuffer, &bufferLength); result = mUnicodeEncoder->Convert(aSrc.GetUnicode(), &length, mBuffer, &mBufferLength);
mBuffer[bufferLength] = 0; mBuffer[mBufferLength] = 0;
PRInt32 temp = bufferLength; PRInt32 temp = mBufferLength;
if (NS_SUCCEEDED(result)) if (NS_SUCCEEDED(result))
result = mUnicodeEncoder->Finish(mBuffer,&temp); result = mUnicodeEncoder->Finish(mBuffer,&temp);
}
for (PRInt32 i = 0; i < mBufferLength; i++)
{
if (mBuffer[i] == char(CH_NBSP))
mBuffer[i] = ' ';
}
}
} }
void nsHTMLContentSinkStream::Write(const nsString& aString)
{
// If a encoder is being used then convert first convert the input string
if (mUnicodeEncoder != nsnull)
{
EncodeToBuffer(aString);
if (mStream != nsnull)
{
nsOutputStream out(mStream);
out.write(mBuffer,mBufferLength);
}
if (mString != nsnull)
{
mString->Append(mBuffer);
}
}
else
{
if (mStream != nsnull)
{
nsOutputStream out(mStream);
const PRUnichar* unicode = aString.GetUnicode();
PRUint32 length = aString.Length();
out.write(unicode,length);
}
else
{
mString->Append(aString);
}
}
}
void nsHTMLContentSinkStream::Write(const char* aData)
{
if (mStream)
{
nsOutputStream out(mStream);
out << aData;
}
if (mString)
{
mString->Append(aData);
}
}
void nsHTMLContentSinkStream::Write(char aData)
{
if (mStream)
{
nsOutputStream out(mStream);
out << aData;
}
if (mString)
{
mString->Append(aData);
}
}
/** /**
* *
* @update gess7/7/98 * @update 04/30/99 gpk
* @param * @param
* @return * @return
*/ */
nsHTMLContentSinkStream::~nsHTMLContentSinkStream() { nsHTMLContentSinkStream::~nsHTMLContentSinkStream() {
NS_IF_RELEASE(mUnicodeEncoder); NS_IF_RELEASE(mUnicodeEncoder);
mOutput=0; //we don't own the stream we're given; just forget it.
} }
/**
*
* @update gess7/22/98
* @param
* @return
*/
NS_IMETHODIMP_(void)
nsHTMLContentSinkStream::SetOutputStream(ostream& aStream){
mOutput=&aStream;
}
/** /**
* *
@ -581,7 +636,7 @@ nsHTMLContentSinkStream::SetOutputStream(ostream& aStream){
* @param * @param
* @return * @return
*/ */
void nsHTMLContentSinkStream::WriteAttributes(const nsIParserNode& aNode,ostream& aStream) { void nsHTMLContentSinkStream::WriteAttributes(const nsIParserNode& aNode) {
int theCount=aNode.GetAttributeCount(); int theCount=aNode.GetAttributeCount();
if(theCount) { if(theCount) {
int i=0; int i=0;
@ -600,14 +655,20 @@ void nsHTMLContentSinkStream::WriteAttributes(const nsIParserNode& aNode,ostream
EnsureBufferSize(key.Length()); EnsureBufferSize(key.Length());
key.ToCString(mBuffer,mBufferSize); key.ToCString(mBuffer,mBufferSize);
aStream << " " << mBuffer << char(kEqual); // send to ouput " [KEY]="
Write(' ');
Write(mBuffer);
Write(char(kEqual));
mColPos += 1 + strlen(mBuffer) + 1; mColPos += 1 + strlen(mBuffer) + 1;
const nsString& value=aNode.GetValueAt(i); const nsString& value=aNode.GetValueAt(i);
UnicodeToHTMLString(value);
// send to ouput "\"[VALUE]\""
Write('\"');
Write(value);
Write('\"');
aStream << "\"" << mBuffer << "\"";
mColPos += 1 + strlen(mBuffer) + 1; mColPos += 1 + strlen(mBuffer) + 1;
} }
} }
@ -615,85 +676,31 @@ void nsHTMLContentSinkStream::WriteAttributes(const nsIParserNode& aNode,ostream
} }
/**
*
* @update gess7/5/98
* @param
* @return
*/
static
void OpenTagWithAttributes(const char* theTag,const nsIParserNode& aNode,int tab,ostream& aStream,PRBool aNewline) {
int i=0;
for(i=0;i<tab*gTabSize;i++)
aStream << " ";
aStream << (char)kLessThan << theTag;
// WriteAttributes(aNode,aStream);
aStream << (char)kGreaterThan;
if(aNewline)
aStream << endl;
}
/**
*
* @update gess7/5/98
* @param
* @return
*/
static
void OpenTag(const char* theTag,int tab,ostream& aStream,PRBool aNewline) {
int i=0;
for(i=0;i<tab*gTabSize;i++)
aStream << " ";
aStream << (char)kLessThan << theTag << (char)kGreaterThan;
if(aNewline)
aStream << endl;
}
/**
*
* @update gess7/5/98
* @param
* @return
*/
static
void CloseTag(const char* theTag,int tab,ostream& aStream) {
int i=0;
for(i=0;i<tab*gTabSize;i++)
aStream << " ";
aStream << (char)kLessThan << (char)kForwardSlash << theTag << (char)kGreaterThan << endl;
}
/**
*
* @update gess7/5/98
* @param
* @return
*/
static
void WritePair(eHTMLTags aTag,const nsString& theContent,int tab,ostream& aStream) {
const char* titleStr = GetTagName(aTag);
OpenTag(titleStr,tab,aStream,PR_FALSE);
theContent.ToCString(gBuffer,sizeof(gBuffer)-1);
aStream << gBuffer;
CloseTag(titleStr,0,aStream);
}
/** /**
* This method gets called by the parser when it encounters * This method gets called by the parser when it encounters
* a title tag and wants to set the document title in the sink. * a title tag and wants to set the document title in the sink.
* *
* @update 4/1/98 gess * @update 04/30/99 gpk
* @param nsString reference to new title value * @param nsString reference to new title value
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::SetTitle(const nsString& aValue){ nsHTMLContentSinkStream::SetTitle(const nsString& aValue){
if(mOutput) { const char* tagName = GetTagName(eHTMLTag_title);
WritePair(eHTMLTag_title,aValue,1+mTabLevel,*mOutput); Write(kLessThan);
} Write(tagName);
Write(kGreaterThan);
Write(aValue);
Write(kLessThan);
Write(kForwardSlash);
Write(tagName);
Write(kGreaterThan);
return NS_OK; return NS_OK;
} }
@ -701,17 +708,15 @@ nsHTMLContentSinkStream::SetTitle(const nsString& aValue){
/** /**
* This method is used to open the outer HTML container. * This method is used to open the outer HTML container.
* *
* @update 07/12/98 gpk * @update 04/30/99 gpk
* @param nsIParserNode reference to parser node interface * @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::OpenHTML(const nsIParserNode& aNode){ nsHTMLContentSinkStream::OpenHTML(const nsIParserNode& aNode){
if(mOutput) {
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
if (tag == eHTMLTag_html) if (tag == eHTMLTag_html)
AddStartTag(aNode,*mOutput); AddStartTag(aNode);
}
return NS_OK; return NS_OK;
} }
@ -719,18 +724,15 @@ nsHTMLContentSinkStream::OpenHTML(const nsIParserNode& aNode){
/** /**
* This method is used to close the outer HTML container. * This method is used to close the outer HTML container.
* *
* @update 07/12/98 gpk * @update 04/30/99 gpk
* @param nsIParserNode reference to parser node interface * @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::CloseHTML(const nsIParserNode& aNode){ nsHTMLContentSinkStream::CloseHTML(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_html)
if (tag == eHTMLTag_html) AddEndTag(aNode);
AddEndTag(aNode,*mOutput);
mOutput->flush();
}
return NS_OK; return NS_OK;
} }
@ -738,17 +740,15 @@ nsHTMLContentSinkStream::CloseHTML(const nsIParserNode& aNode){
/** /**
* This method is used to open the only HEAD container. * This method is used to open the only HEAD container.
* *
* @update 07/12/98 gpk * @update 04/30/99 gpk
* @param nsIParserNode reference to parser node interface * @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::OpenHead(const nsIParserNode& aNode){ nsHTMLContentSinkStream::OpenHead(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_head)
if (tag == eHTMLTag_head) AddStartTag(aNode);
AddStartTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -756,17 +756,15 @@ nsHTMLContentSinkStream::OpenHead(const nsIParserNode& aNode){
/** /**
* This method is used to close the only HEAD container. * This method is used to close the only HEAD container.
* *
* @update 07/12/98 gpk * @update 04/30/99 gpk
* @param nsIParserNode reference to parser node interface * @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::CloseHead(const nsIParserNode& aNode){ nsHTMLContentSinkStream::CloseHead(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_head)
if (tag == eHTMLTag_head) AddEndTag(aNode);
AddEndTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -774,17 +772,15 @@ nsHTMLContentSinkStream::CloseHead(const nsIParserNode& aNode){
/** /**
* This method is used to open the main BODY container. * This method is used to open the main BODY container.
* *
* @update 07/12/98 gpk * @update 04/30/99 gpk
* @param nsIParserNode reference to parser node interface * @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::OpenBody(const nsIParserNode& aNode){ nsHTMLContentSinkStream::OpenBody(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_body)
if (tag == eHTMLTag_body) AddStartTag(aNode);
AddStartTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -792,17 +788,15 @@ nsHTMLContentSinkStream::OpenBody(const nsIParserNode& aNode){
/** /**
* This method is used to close the main BODY container. * This method is used to close the main BODY container.
* *
* @update 07/12/98 gpk * @update 04/30/99 gpk
* @param nsIParserNode reference to parser node interface * @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::CloseBody(const nsIParserNode& aNode){ nsHTMLContentSinkStream::CloseBody(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_body)
if (tag == eHTMLTag_body) AddEndTag(aNode);
AddEndTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -816,11 +810,9 @@ nsHTMLContentSinkStream::CloseBody(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::OpenForm(const nsIParserNode& aNode){ nsHTMLContentSinkStream::OpenForm(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_form)
if (tag == eHTMLTag_form) AddStartTag(aNode);
AddStartTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -834,11 +826,9 @@ nsHTMLContentSinkStream::OpenForm(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::CloseForm(const nsIParserNode& aNode){ nsHTMLContentSinkStream::CloseForm(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_form)
if (tag == eHTMLTag_form) AddEndTag(aNode);
AddEndTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -851,11 +841,9 @@ nsHTMLContentSinkStream::CloseForm(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::OpenMap(const nsIParserNode& aNode){ nsHTMLContentSinkStream::OpenMap(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_map)
if (tag == eHTMLTag_map) AddStartTag(aNode);
AddStartTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -869,12 +857,10 @@ nsHTMLContentSinkStream::OpenMap(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::CloseMap(const nsIParserNode& aNode){ nsHTMLContentSinkStream::CloseMap(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_map)
if (tag == eHTMLTag_map) AddEndTag(aNode);
AddEndTag(aNode,*mOutput); return NS_OK;
}
return NS_OK;
} }
@ -887,11 +873,9 @@ nsHTMLContentSinkStream::CloseMap(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::OpenFrameset(const nsIParserNode& aNode){ nsHTMLContentSinkStream::OpenFrameset(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_frameset)
if (tag == eHTMLTag_frameset) AddStartTag(aNode);
AddStartTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
@ -905,27 +889,26 @@ nsHTMLContentSinkStream::OpenFrameset(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::CloseFrameset(const nsIParserNode& aNode){ nsHTMLContentSinkStream::CloseFrameset(const nsIParserNode& aNode){
if(mOutput) { eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); if (tag == eHTMLTag_frameset)
if (tag == eHTMLTag_frameset) AddEndTag(aNode);
AddEndTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
void nsHTMLContentSinkStream::AddIndent(ostream& aStream) void nsHTMLContentSinkStream::AddIndent()
{ {
nsString padding(" ");
for (PRInt32 i = mIndent; --i >= 0; ) for (PRInt32 i = mIndent; --i >= 0; )
{ {
aStream << " "; Write(padding);
mColPos += 2; mColPos += 2;
} }
} }
void nsHTMLContentSinkStream::AddStartTag(const nsIParserNode& aNode, ostream& aStream) void nsHTMLContentSinkStream::AddStartTag(const nsIParserNode& aNode)
{ {
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
const nsString& name = aNode.GetText(); const nsString& name = aNode.GetText();
@ -942,37 +925,41 @@ void nsHTMLContentSinkStream::AddStartTag(const nsIParserNode& aNode, ostream& a
if (mColPos != 0 && BreakBeforeOpen(tag)) if (mColPos != 0 && BreakBeforeOpen(tag))
{ {
aStream << endl; Write('\n');
mColPos = 0; mColPos = 0;
} }
if (PermitWSBeforeOpen(tag)) if (PermitWSBeforeOpen(tag))
AddIndent(aStream); AddIndent();
EnsureBufferSize(tagName.Length());
tagName.ToCString(mBuffer,mBufferSize);
Write(kLessThan);
Write(mBuffer);
tagName.ToCString(gBuffer,sizeof(gBuffer)-1);
aStream << (char)kLessThan << gBuffer;
mColPos += 1 + tagName.Length(); mColPos += 1 + tagName.Length();
if (tag == eHTMLTag_style) if (tag == eHTMLTag_style)
{ {
aStream << (char)kGreaterThan << endl; Write(">\n");
const nsString& data = aNode.GetSkippedContent(); const nsString& data = aNode.GetSkippedContent();
PRInt32 size = data.Length(); PRInt32 size = data.Length();
char* buffer = new char[size+1]; char* buffer = new char[size+1];
data.ToCString(buffer,size+1); data.ToCString(buffer,size+1);
aStream << buffer; Write(buffer);
delete[] buffer; delete[] buffer;
} }
else else
{ {
WriteAttributes(aNode,aStream); WriteAttributes(aNode);
aStream << (char)kGreaterThan; Write(kGreaterThan);
mColPos += 1; mColPos += 1;
} }
if (BreakAfterOpen(tag)) if (BreakAfterOpen(tag))
{ {
aStream << endl; Write('\n');
mColPos = 0; mColPos = 0;
} }
@ -983,7 +970,7 @@ void nsHTMLContentSinkStream::AddStartTag(const nsIParserNode& aNode, ostream& a
void nsHTMLContentSinkStream::AddEndTag(const nsIParserNode& aNode, ostream& aStream) void nsHTMLContentSinkStream::AddEndTag(const nsIParserNode& aNode)
{ {
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
// const nsString& name = aNode.GetText(); // const nsString& name = aNode.GetText();
@ -1010,19 +997,25 @@ void nsHTMLContentSinkStream::AddEndTag(const nsIParserNode& aNode, ostream& aSt
{ {
if (mColPos != 0) if (mColPos != 0)
{ {
aStream << endl; Write('\n');
mColPos = 0; mColPos = 0;
} }
AddIndent(aStream); AddIndent();
} }
tagName.ToCString(gBuffer,sizeof(gBuffer)-1); EnsureBufferSize(tagName.Length());
aStream << (char)kLessThan << (char)kForwardSlash << gBuffer << (char)kGreaterThan; tagName.ToCString(mBuffer,mBufferSize);
mColPos += 1 + 1 + strlen(gBuffer) + 1;
Write(kLessThan);
Write(kForwardSlash);
Write(mBuffer);
Write(kGreaterThan);
mColPos += 1 + 1 + strlen(mBuffer) + 1;
if (BreakAfterClose(tag)) if (BreakAfterClose(tag))
{ {
aStream << endl; Write('\n');
mColPos = 0; mColPos = 0;
} }
mHTMLTagStack[--mHTMLStackPos] = eHTMLTag_unknown; mHTMLTagStack[--mHTMLStackPos] = eHTMLTag_unknown;
@ -1040,7 +1033,7 @@ void nsHTMLContentSinkStream::AddEndTag(const nsIParserNode& aNode, ostream& aSt
* @return * @return
*/ */
nsresult nsresult
nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode){
eHTMLTags type = (eHTMLTags)aNode.GetNodeType(); eHTMLTags type = (eHTMLTags)aNode.GetNodeType();
eHTMLTags tag = eHTMLTag_unknown; eHTMLTags tag = eHTMLTag_unknown;
if (mHTMLStackPos > 0) if (mHTMLStackPos > 0)
@ -1062,14 +1055,16 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){
type == eHTMLTag_meta || type == eHTMLTag_meta ||
type == eHTMLTag_style) type == eHTMLTag_style)
{ {
AddStartTag(aNode,aStream); AddStartTag(aNode);
mHTMLTagStack[--mHTMLStackPos] = eHTMLTag_unknown; mHTMLTagStack[--mHTMLStackPos] = eHTMLTag_unknown;
} }
else if (type == eHTMLTag_entity) else if (type == eHTMLTag_entity)
{ {
const nsString& entity = aNode.GetText(); const nsString& entity = aNode.GetText();
UnicodeToHTMLString(entity); EncodeToBuffer(entity);
aStream << '&' << mBuffer << ';'; Write('&');
Write(mBuffer);
Write(';');
mColPos += entity.Length() + 2; mColPos += entity.Length() + 2;
} }
else if (type == eHTMLTag_text) else if (type == eHTMLTag_text)
@ -1077,8 +1072,7 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){
const nsString& text = aNode.GetText(); const nsString& text = aNode.GetText();
if ((mDoFormat == PR_FALSE) || preformatted == PR_TRUE) if ((mDoFormat == PR_FALSE) || preformatted == PR_TRUE)
{ {
UnicodeToHTMLString(text); Write(text);
aStream << mBuffer;
mColPos += text.Length(); mColPos += text.Length();
} }
else else
@ -1092,8 +1086,7 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){
// than the max then just add it // than the max then just add it
if (mColPos + length < mMaxColumn) if (mColPos + length < mMaxColumn)
{ {
UnicodeToHTMLString(text); Write(text);
aStream << mBuffer;
mColPos += text.Length(); mColPos += text.Length();
} }
else else
@ -1115,8 +1108,7 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){
// if there is no break than just add it // if there is no break than just add it
if (index == kNotFound) if (index == kNotFound)
{ {
UnicodeToHTMLString(str); Write(str);
aStream << mBuffer;
mColPos += str.Length(); mColPos += str.Length();
done = PR_TRUE; done = PR_TRUE;
} }
@ -1128,8 +1120,8 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){
first.Truncate(index); first.Truncate(index);
UnicodeToHTMLString(first); Write(first);
aStream << mBuffer << endl; Write('\n');
mColPos = 0; mColPos = 0;
// cut the string from the beginning to the index // cut the string from the beginning to the index
@ -1145,8 +1137,7 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){
if ((mDoFormat == PR_FALSE) || preformatted || IgnoreWS(tag) == PR_FALSE) if ((mDoFormat == PR_FALSE) || preformatted || IgnoreWS(tag) == PR_FALSE)
{ {
const nsString& text = aNode.GetText(); const nsString& text = aNode.GetText();
UnicodeToHTMLString(text); Write(text);
aStream << mBuffer;
mColPos += text.Length(); mColPos += text.Length();
} }
} }
@ -1155,8 +1146,7 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream){
if ((mDoFormat == PR_FALSE) || preformatted) if ((mDoFormat == PR_FALSE) || preformatted)
{ {
const nsString& text = aNode.GetText(); const nsString& text = aNode.GetText();
UnicodeToHTMLString(text); Write(text);
aStream << mBuffer;
mColPos = 0; mColPos = 0;
} }
} }
@ -1215,25 +1205,26 @@ nsHTMLContentSinkStream::AddComment(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::OpenContainer(const nsIParserNode& aNode){ nsHTMLContentSinkStream::OpenContainer(const nsIParserNode& aNode){
if(mOutput)
const nsString& name = aNode.GetText();
if (name.Equals("XIF_DOC_INFO"))
{ {
const nsString& name = aNode.GetText(); PRInt32 count=aNode.GetAttributeCount();
if (name.Equals("XIF_DOC_INFO")) for(PRInt32 i=0;i<count;i++)
{ {
PRInt32 count=aNode.GetAttributeCount(); const nsString& key=aNode.GetKeyAt(i);
for(PRInt32 i=0;i<count;i++) const nsString& value=aNode.GetValueAt(i);
{
const nsString& key=aNode.GetKeyAt(i);
const nsString& value=aNode.GetValueAt(i);
if (key.Equals("charset")) if (key.Equals("charset"))
{
if (mCharsetOverride.Length() == 0)
InitEncoder(value); InitEncoder(value);
} }
} }
else }
{ else
AddStartTag(aNode,*mOutput); {
} AddStartTag(aNode);
} }
return NS_OK; return NS_OK;
} }
@ -1242,37 +1233,17 @@ nsHTMLContentSinkStream::OpenContainer(const nsIParserNode& aNode){
/** /**
* This method is used to close a generic container. * This method is used to close a generic container.
* *
* @update 07/12/98 gpk * @update 04/30/99 gpk
* @param nsIParserNode reference to parser node interface * @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful. * @return PR_TRUE if successful.
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::CloseContainer(const nsIParserNode& aNode){ nsHTMLContentSinkStream::CloseContainer(const nsIParserNode& aNode){
if(mOutput) { AddEndTag(aNode);
AddEndTag(aNode,*mOutput);
}
return NS_OK; return NS_OK;
} }
/**
* This method is used to add a leaf to the currently
* open container.
*
* @update 07/12/98 gpk
* @param nsIParserNode reference to parser node interface
* @return PR_TRUE if successful.
*/
NS_IMETHODIMP
nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode){
nsresult result = NS_OK;
if(mOutput) {
result = AddLeaf(aNode,*mOutput);
}
return result;
}
/** /**
* This method gets called when the parser begins the process * This method gets called when the parser begins the process
* of building the content model via the content sink. * of building the content model via the content sink.
@ -1282,10 +1253,12 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode){
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSinkStream::WillBuildModel(void){ nsHTMLContentSinkStream::WillBuildModel(void){
mTabLevel=-1; mTabLevel=-1;
if(mDoHeader && mOutput) { if(mDoHeader) {
(*mOutput) << gHeaderComment << endl; Write(gHeaderComment);
(*mOutput) << gDocTypeHeader << endl; Write('\n');
} Write(gDocTypeHeader);
Write('\n');
}
return NS_OK; return NS_OK;
} }

View File

@ -54,23 +54,24 @@ class ostream;
#endif #endif
class nsIUnicodeEncoder; class nsIUnicodeEncoder;
class nsIOutputStream;
class nsHTMLContentSinkStream : public nsIHTMLContentSink { class nsHTMLContentSinkStream : public nsIHTMLContentSink {
public: public:
/**
* Standard constructor
* @update gess7/7/98
*/
nsHTMLContentSinkStream(PRBool aDoFormat = PR_TRUE, PRBool aDoHeader = PR_TRUE);
/** /**
* Constructor with associated stream. If you use this, it means that you want * Constructor with associated stream. If you use this, it means that you want
* this class to emits its output to the stream you provide. * this class to emits its output to the stream you provide.
* @update gess7/7/98 * @update gpk 04/30/99
* @param aStream -- ref to stream where you want output sent * @param aOutStream -- stream where you want output sent
* @param aOutStream -- ref to string where you want output sent
*/ */
nsHTMLContentSinkStream(ostream& aStream,PRBool aDoFormat = PR_TRUE, PRBool aDoHeader = PR_TRUE); nsHTMLContentSinkStream(nsIOutputStream* aOutStream,
nsString* aOutString,
const nsString* aCharsetOverride,
PRBool aDoFormat = PR_TRUE,
PRBool aDoHeader = PR_TRUE);
/** /**
* virtual destructor * virtual destructor
@ -78,8 +79,6 @@ class nsHTMLContentSinkStream : public nsIHTMLContentSink {
*/ */
virtual ~nsHTMLContentSinkStream(); virtual ~nsHTMLContentSinkStream();
NS_IMETHOD_(void) SetOutputStream(ostream& aStream);
// nsISupports // nsISupports
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
@ -127,22 +126,26 @@ public:
protected: protected:
nsresult AddLeaf(const nsIParserNode& aNode, ostream& aStream); void WriteAttributes(const nsIParserNode& aNode);
void WriteAttributes(const nsIParserNode& aNode,ostream& aStream); void AddStartTag(const nsIParserNode& aNode);
void AddStartTag(const nsIParserNode& aNode, ostream& aStream); void AddEndTag(const nsIParserNode& aNode);
void AddEndTag(const nsIParserNode& aNode, ostream& aStream); void AddIndent();
void AddIndent(ostream& aStream);
void EnsureBufferSize(PRInt32 aNewSize); void EnsureBufferSize(PRInt32 aNewSize);
void UnicodeToHTMLString(const nsString& aSrc);
nsresult InitEncoder(const nsString& aCharset); nsresult InitEncoder(const nsString& aCharset);
void EncodeToBuffer(const nsString& aString);
void Write(const nsString& aString);
void Write(const char* aCharBuffer);
void Write(char aChar);
protected: protected:
ostream* mOutput; nsIOutputStream* mStream;
nsString* mString;
int mTabLevel; int mTabLevel;
PRInt32 mIndent; PRInt32 mIndent;
@ -155,13 +158,24 @@ protected:
PRBool mDoHeader; PRBool mDoHeader;
char* mBuffer; char* mBuffer;
PRInt32 mBufferSize; PRInt32 mBufferLength; // The length of the data in the buffer
PRInt32 mBufferSize; // The actual size of the buffer, regardless of the data
nsIUnicodeEncoder* mUnicodeEncoder; nsIUnicodeEncoder* mUnicodeEncoder;
nsString mCharsetOverride;
}; };
extern NS_HTMLPARS nsresult extern NS_HTMLPARS nsresult
NS_New_HTML_ContentSinkStream(nsIHTMLContentSink** aInstancePtrResult, NS_New_HTML_ContentSinkStream(nsIHTMLContentSink** aInstancePtrResult,
nsIOutputStream* aOutStream,
const nsString* aCharsetOverride=nsnull,
PRBool aDoFormat = PR_TRUE,
PRBool aDoHeader = PR_TRUE);
extern NS_HTMLPARS nsresult
NS_New_HTML_ContentSinkStream(nsIHTMLContentSink** aInstancePtrResult,
nsString* aOutString,
PRBool aDoFormat = PR_TRUE, PRBool aDoFormat = PR_TRUE,
PRBool aDoHeader = PR_TRUE); PRBool aDoHeader = PR_TRUE);

View File

@ -39,6 +39,8 @@
#include "nsICharsetAlias.h" #include "nsICharsetAlias.h"
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
#include "nsICharsetConverterManager.h" #include "nsICharsetConverterManager.h"
#include "nsIOutputStream.h"
#include "nsFileStream.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIContentSinkIID, NS_ICONTENT_SINK_IID); static NS_DEFINE_IID(kIContentSinkIID, NS_ICONTENT_SINK_IID);
@ -60,7 +62,19 @@ static PRBool IsBlockLevel(eHTMLTags aTag);
nsresult nsHTMLToTXTSinkStream::InitEncoder(const nsString& aCharset) nsresult nsHTMLToTXTSinkStream::InitEncoder(const nsString& aCharset)
{ {
nsresult res = NS_OK; nsresult res = NS_OK;
// If the converter is ucs2, then do not use a converter
nsString ucs2("ucs2");
if (aCharset.Equals(ucs2))
{
NS_IF_RELEASE(mUnicodeEncoder);
return res;
}
nsICharsetAlias* calias = nsnull; nsICharsetAlias* calias = nsnull;
res = nsServiceManager::GetService(kCharsetAliasCID, res = nsServiceManager::GetService(kCharsetAliasCID,
@ -141,58 +155,71 @@ NS_IMPL_RELEASE(nsHTMLToTXTSinkStream)
/** /**
* This method is defined in nsIParser. It is used to * This method creates a new sink, it sets the stream used
* cause the COM-like construction of an nsParser. * for the sink to aStream
* *
* @update gpk02/03/99 * @update gpk 04/30/99
* @param nsIParser** ptr to newly instantiated parser
* @return NS_xxx error result
*/ */
NS_HTMLPARS nsresult NS_HTMLPARS nsresult
NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult) { NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult,
nsHTMLToTXTSinkStream* it = new nsHTMLToTXTSinkStream(); nsIOutputStream* aStream,
const nsString* aCharsetOverride) {
NS_ASSERTION(aStream != nsnull, "a valid stream is required");
nsHTMLToTXTSinkStream* it = new nsHTMLToTXTSinkStream(aStream,nsnull);
if (nsnull == it) { if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
if (aCharsetOverride != nsnull)
it->SetCharsetOverride(aCharsetOverride);
return it->QueryInterface(kIHTMLContentSinkIID, (void **)aInstancePtrResult); return it->QueryInterface(kIHTMLContentSinkIID, (void **)aInstancePtrResult);
} }
/** /**
* Construct a content sink stream. * This method creates a new sink, it sets the stream used
* @update gpk02/03/99 * for the sink to aStream
* @param *
* @return * @update gpk 04/30/99
*/ */
nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream() { NS_HTMLPARS nsresult
NS_INIT_REFCNT(); NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult,
mOutput=&cout; nsString* aString) {
mColPos = 0;
mIndent = 0; NS_ASSERTION(aString != nsnull, "a valid stream is required");
mDoOutput = PR_FALSE; nsHTMLToTXTSinkStream* it = new nsHTMLToTXTSinkStream(nsnull,aString);
mBufferSize = 0; if (nsnull == it) {
mBuffer = nsnull; return NS_ERROR_OUT_OF_MEMORY;
mUnicodeEncoder = nsnull; }
nsString ucs2("ucs2");
it->SetCharsetOverride(&ucs2);
return it->QueryInterface(kIHTMLContentSinkIID, (void **)aInstancePtrResult);
} }
/** /**
* Construct a content sink stream. * Construct a content sink stream.
* @update gpk02/03/99 * @update gpk02/03/99
* @param * @param
* @return * @return
*/ */
nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream(ostream& aStream) { nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream(nsIOutputStream* aStream, nsString* aString) {
NS_INIT_REFCNT(); NS_INIT_REFCNT();
mOutput = &aStream; mStream = aStream;
mColPos = 0; mColPos = 0;
mIndent = 0; mIndent = 0;
mDoOutput = PR_FALSE; mDoOutput = PR_FALSE;
mBufferSize = 0; mBufferSize = 0;
mBufferLength = 0;
mBuffer = nsnull; mBuffer = nsnull;
mUnicodeEncoder = nsnull; mUnicodeEncoder = nsnull;
mStream = aStream;
mString = aString;
} }
/** /**
* *
* @update gpk02/03/99 * @update gpk02/03/99
@ -200,7 +227,6 @@ nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream(ostream& aStream) {
* @return * @return
*/ */
nsHTMLToTXTSinkStream::~nsHTMLToTXTSinkStream() { nsHTMLToTXTSinkStream::~nsHTMLToTXTSinkStream() {
mOutput=0; //we don't own the stream we're given; just forget it.
delete [] mBuffer; delete [] mBuffer;
NS_IF_RELEASE(mUnicodeEncoder); NS_IF_RELEASE(mUnicodeEncoder);
} }
@ -208,50 +234,24 @@ nsHTMLToTXTSinkStream::~nsHTMLToTXTSinkStream() {
/** /**
* *
* @update gpk02/03/99 * @update gpk04/30/99
* @param * @param
* @return * @return
*/ */
NS_IMETHODIMP_(void)
nsHTMLToTXTSinkStream::SetOutputStream(ostream& aStream){ NS_IMETHODIMP
mOutput=&aStream; nsHTMLToTXTSinkStream::SetCharsetOverride(const nsString* aCharset)
{
if (aCharset)
{
mCharsetOverride = *aCharset;
InitEncoder(mCharsetOverride);
}
return NS_OK;
} }
/**
*
* @update gpk02/03/99
* @param
* @return
*/
static
void OpenTagWithAttributes(const char* theTag,const nsIParserNode& aNode,int tab,ostream& aStream,PRBool aNewline) {
}
/**
*
* @update gpk02/03/99
* @param
* @return
*/
static
void OpenTag(const char* theTag,int tab,ostream& aStream,PRBool aNewline) {
}
/**
*
* @update gpk02/03/99
* @param
* @return
*/
static
void CloseTag(const char* theTag,int tab,ostream& aStream) {
}
/** /**
* This method gets called by the parser when it encounters * This method gets called by the parser when it encounters
* a title tag and wants to set the document title in the sink. * a title tag and wants to set the document title in the sink.
@ -463,38 +463,38 @@ void nsHTMLToTXTSinkStream::EnsureBufferSize(PRInt32 aNewSize)
mBufferSize = 2*aNewSize+1; // make the twice as large mBufferSize = 2*aNewSize+1; // make the twice as large
mBuffer = new char[mBufferSize]; mBuffer = new char[mBufferSize];
mBuffer[0] = 0; mBuffer[0] = 0;
mBufferLength = 0;
} }
} }
void nsHTMLToTXTSinkStream::UnicodeToTXTString(const nsString& aSrc) void nsHTMLToTXTSinkStream::EncodeToBuffer(const nsString& aSrc)
{ {
NS_ASSERTION(mUnicodeEncoder != nsnull,"The unicode encoder needs to be initialized");
if (mUnicodeEncoder == nsnull)
return;
#define CH_NBSP 160 #define CH_NBSP 160
PRInt32 length = aSrc.Length(); PRInt32 length = aSrc.Length();
nsresult result; nsresult result;
PRInt32 bufferLength;
if (mUnicodeEncoder == nsnull) if (mUnicodeEncoder != nsnull && length > 0)
InitEncoder("");
if (length > 0)
{ {
EnsureBufferSize(length); EnsureBufferSize(length);
bufferLength = mBufferSize; mBufferLength = mBufferSize;
mUnicodeEncoder->Reset(); mUnicodeEncoder->Reset();
result = mUnicodeEncoder->Convert(aSrc.GetUnicode(), &length, mBuffer, &bufferLength); result = mUnicodeEncoder->Convert(aSrc.GetUnicode(), &length, mBuffer, &mBufferLength);
mBuffer[bufferLength] = 0; mBuffer[mBufferLength] = 0;
PRInt32 temp = bufferLength; PRInt32 temp = mBufferLength;
if (NS_SUCCEEDED(result)) if (NS_SUCCEEDED(result))
result = mUnicodeEncoder->Finish(mBuffer,&temp); result = mUnicodeEncoder->Finish(mBuffer,&temp);
for (PRInt32 i = 0; i < bufferLength; i++) for (PRInt32 i = 0; i < mBufferLength; i++)
{ {
if (mBuffer[i] == char(CH_NBSP)) if (mBuffer[i] == char(CH_NBSP))
mBuffer[i] = ' '; mBuffer[i] = ' ';
@ -504,76 +504,47 @@ void nsHTMLToTXTSinkStream::UnicodeToTXTString(const nsString& aSrc)
} }
NS_IMETHODIMP
nsHTMLToTXTSinkStream::GetStringBuffer(nsString & aStrBuffer)
{
aStrBuffer = mStrBuffer;
return NS_OK;
}
/** /**
* This gets called by the parser when you want to add * Write places the contents of aString into either the output stream
* a leaf node to the current container in the content * or the output string.
* model. * When going to the stream, all data is run through the encoder
* *
* @updated gpk 06/18/98 * @updated gpk02/03/99
* @param * @param
* @return * @return
*/ */
nsresult void nsHTMLToTXTSinkStream::Write(const nsString& aString)
nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode, ostream& aStream)
{ {
eHTMLTags type = (eHTMLTags)aNode.GetNodeType();
const nsString& text = aNode.GetText();
if (mDoOutput == PR_FALSE) // If a encoder is being used then convert first convert the input string
return NS_OK; if (mUnicodeEncoder != nsnull)
if (type == eHTMLTag_text) {
UnicodeToTXTString(text);
aStream << mBuffer;
mStrBuffer.Append(mBuffer);
mColPos += text.Length();
}
else if (type == eHTMLTag_entity)
{ {
const nsString& text = aNode.GetText(); EncodeToBuffer(aString);
UnicodeToTXTString(text); if (mStream != nsnull)
PRInt32 entity = NS_EntityToUnicode(mBuffer);
if (entity < 256)
{ {
char ch = (char)entity; nsOutputStream out(mStream);
aStream << ch; out.write(mBuffer,mBufferLength);
mColPos++; }
if (mString != nsnull)
{
mString->Append(mBuffer);
} }
} }
else if (type == eHTMLTag_whitespace) else
{ {
if (PR_TRUE) if (mStream != nsnull)
{ {
const nsString& text = aNode.GetText(); nsOutputStream out(mStream);
UnicodeToTXTString(text); const PRUnichar* unicode = aString.GetUnicode();
aStream << mBuffer; PRUint32 length = aString.Length();
mStrBuffer.Append(mBuffer); out.write(unicode,length);
mColPos += text.Length(); }
else
{
mString->Append(aString);
} }
} }
else if (type == eHTMLTag_br)
{
if (PR_TRUE)
{
aStream << endl;
mStrBuffer.Append("\n");
mColPos += 1;
}
}
return NS_OK;
} }
@ -628,7 +599,10 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode){
const nsString& value=aNode.GetValueAt(i); const nsString& value=aNode.GetValueAt(i);
if (key.Equals("charset")) if (key.Equals("charset"))
InitEncoder(value); {
if (mCharsetOverride.Length() == 0)
InitEncoder(value);
}
} }
} }
@ -657,9 +631,8 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode){
{ {
if (mColPos != 0) if (mColPos != 0)
{ {
if (mOutput) nsString temp("\n");
*mOutput << endl; Write(temp);
mStrBuffer.Append("\n");
mColPos = 0; mColPos = 0;
} }
} }
@ -677,11 +650,53 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode){
*/ */
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode){ nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode){
nsresult result = NS_OK; eHTMLTags type = (eHTMLTags)aNode.GetNodeType();
if(mOutput) {
result = AddLeaf(aNode,*mOutput); const nsString& text = aNode.GetText();
if (mDoOutput == PR_FALSE)
return NS_OK;
if (type == eHTMLTag_text) {
Write(text);
mColPos += text.Length();
}
else if (type == eHTMLTag_entity)
{
const nsString& text = aNode.GetText();
EncodeToBuffer(text);
PRUnichar entity = NS_EntityToUnicode(mBuffer);
nsString temp;
temp.Append(entity);
Write(temp);
mColPos++;
} }
return result; else if (type == eHTMLTag_whitespace)
{
if (PR_TRUE)
{
const nsString& text = aNode.GetText();
Write(text);
mColPos += text.Length();
}
}
else if (type == eHTMLTag_br)
{
nsString temp("\n");
Write(text);
mColPos++;
}
else if (type == eHTMLTag_newline)
{
nsString temp("\n");
Write(text);
mColPos++;
}
return NS_OK;
} }

View File

@ -47,12 +47,9 @@
{0xa39c6bff, 0x15f0, 0x11d2, \ {0xa39c6bff, 0x15f0, 0x11d2, \
{0x80, 0x41, 0x0, 0x10, 0x4b, 0x98, 0x3f, 0xd4}} {0x80, 0x41, 0x0, 0x10, 0x4b, 0x98, 0x3f, 0xd4}}
#ifndef XP_MAC
class ostream;
#endif
class nsIUnicodeEncoder; class nsIUnicodeEncoder;
class nsIOutputStream;
class nsHTMLToTXTSinkStream : public nsIHTMLContentSink { class nsHTMLToTXTSinkStream : public nsIHTMLContentSink {
public: public:
@ -61,8 +58,7 @@ class nsHTMLToTXTSinkStream : public nsIHTMLContentSink {
* Standard constructor * Standard constructor
* @update gpk02/03/99 * @update gpk02/03/99
*/ */
nsHTMLToTXTSinkStream(); nsHTMLToTXTSinkStream(nsIOutputStream* aOutStream, nsString* aOutString);
nsHTMLToTXTSinkStream(ostream& aStream);
/** /**
* virtual destructor * virtual destructor
@ -70,8 +66,8 @@ class nsHTMLToTXTSinkStream : public nsIHTMLContentSink {
*/ */
virtual ~nsHTMLToTXTSinkStream(); virtual ~nsHTMLToTXTSinkStream();
NS_IMETHOD_(void) SetOutputStream(ostream& aStream); NS_IMETHOD SetCharsetOverride(const nsString* aCharset);
NS_IMETHOD GetStringBuffer(nsString & aStrBuffer);
// nsISupports // nsISupports
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
@ -113,32 +109,47 @@ class nsHTMLToTXTSinkStream : public nsIHTMLContentSink {
NS_IMETHOD BeginContext(PRInt32 aPosition); NS_IMETHOD BeginContext(PRInt32 aPosition);
NS_IMETHOD EndContext(PRInt32 aPosition); NS_IMETHOD EndContext(PRInt32 aPosition);
protected: protected:
nsresult AddLeaf(const nsIParserNode& aNode, ostream& aStream);
void WriteAttributes(const nsIParserNode& aNode,ostream& aStream);
void EnsureBufferSize(PRInt32 aNewSize); void EnsureBufferSize(PRInt32 aNewSize);
void UnicodeToTXTString(const nsString& aSrc);
nsresult InitEncoder(const nsString& aCharset); nsresult InitEncoder(const nsString& aCharset);
void Write(const nsString& aString);
void EncodeToBuffer(const nsString& aString);
protected: protected:
ostream* mOutput; nsIOutputStream* mStream;
nsString* mString;
PRInt32 mIndent; PRInt32 mIndent;
PRInt32 mColPos; PRInt32 mColPos;
PRBool mDoOutput; PRBool mDoOutput;
char* mBuffer;
PRInt32 mBufferSize;
nsString mStrBuffer; 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; nsIUnicodeEncoder* mUnicodeEncoder;
nsString mCharsetOverride;
}; };
extern NS_HTMLPARS nsresult extern NS_HTMLPARS nsresult
NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult); NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult,
nsIOutputStream* aOutStream,
const nsString* aCharsetOverride=nsnull);
extern NS_HTMLPARS nsresult
NS_New_HTMLToTXT_SinkStream(nsIHTMLContentSink** aInstancePtrResult,
nsString* aOutString);
#endif #endif