From 972a33874a699ee69f69d62590233c8325e802ba Mon Sep 17 00:00:00 2001 From: "rhp%netscape.com" Date: Wed, 15 Dec 1999 03:35:34 +0000 Subject: [PATCH] Performance fix for message display - Bug #: 21203 - r: xxxxx --- .../mime/emitters/resources/skin/MANIFEST | 3 - .../mime/emitters/resources/skin/Makefile.in | 3 - .../emitters/resources/skin/mailheader.css | 16 - .../mime/emitters/resources/skin/makefile.win | 6 - mailnews/mime/emitters/src/nsEmitterUtils.cpp | 13 - mailnews/mime/emitters/src/nsEmitterUtils.h | 2 - .../mime/emitters/src/nsMimeBaseEmitter.cpp | 803 +++++++++++++----- .../mime/emitters/src/nsMimeBaseEmitter.h | 101 ++- .../mime/emitters/src/nsMimeHtmlEmitter.cpp | 115 +-- .../mime/emitters/src/nsMimeHtmlEmitter.h | 5 +- .../mime/emitters/src/nsMimeXULEmitter.cpp | 551 ++++-------- mailnews/mime/emitters/src/nsMimeXULEmitter.h | 53 +- .../mime/emitters/src/nsMimeXmlEmitter.cpp | 6 - mailnews/mime/src/mimemoz2.cpp | 47 +- mailnews/mime/src/mimemoz2.h | 3 + mailnews/mime/src/mimetpfl.cpp | 21 +- mailnews/mime/src/mimetpla.cpp | 15 +- mailnews/mime/src/modlmime.h | 2 + mailnews/mime/src/nsStreamConverter.cpp | 8 + mailnews/mime/tests/mimetest/mimetest.cpp | 5 +- 20 files changed, 908 insertions(+), 870 deletions(-) diff --git a/mailnews/mime/emitters/resources/skin/MANIFEST b/mailnews/mime/emitters/resources/skin/MANIFEST index 57f383f1e8a..0974fb0b16d 100644 --- a/mailnews/mime/emitters/resources/skin/MANIFEST +++ b/mailnews/mime/emitters/resources/skin/MANIFEST @@ -21,8 +21,5 @@ # mailheader.css -mailheader-micro.css -mailheader-normal.css -mailheader-all.css addcard.gif attach.gif diff --git a/mailnews/mime/emitters/resources/skin/Makefile.in b/mailnews/mime/emitters/resources/skin/Makefile.in index 04cb4af57e5..5a3278b59b2 100644 --- a/mailnews/mime/emitters/resources/skin/Makefile.in +++ b/mailnews/mime/emitters/resources/skin/Makefile.in @@ -28,9 +28,6 @@ include $(DEPTH)/config/autoconf.mk EXPORT_RESOURCES = \ $(srcdir)/mailheader.css \ - $(srcdir)/mailheader-micro.css \ - $(srcdir)/mailheader-normal.css \ - $(srcdir)/mailheader-all.css \ $(srcdir)/addcard.gif \ $(srcdir)/attach.gif \ $(NULL) diff --git a/mailnews/mime/emitters/resources/skin/mailheader.css b/mailnews/mime/emitters/resources/skin/mailheader.css index f12888f20e9..e69de29bb2d 100644 --- a/mailnews/mime/emitters/resources/skin/mailheader.css +++ b/mailnews/mime/emitters/resources/skin/mailheader.css @@ -1,16 +0,0 @@ -/* - * Window behavior for scrolling and general header color - * attributes - */ -window { overflow: auto; } -mailheader { display: block; } -mailattachcount { display: none; } - -box[name=header-attachment] { background-color: #EFEFEF; border: 0px solid #EFEFEF; border-left-width: 4px; } -box[name=header-part1] { background-color: #EFEFEF; border: 0px solid #EFEFEF; border-left-width: 4px; } -box[name=header-part2] { background-color: #DEDEDE; border: 0px solid #DEDEDE; border-left-width: 4px; } -box[name=header-part3] { background-color: #DEDEDE; border: 0px solid #DEDEDE; border-left-width: 4px; } -box[name=header-seamonkey] { background-color: #DEDEDE; border: 0px solid #DEDEDE; border-left-width: 4px; } - -menubar[name=attachment-menubar] { background-color: #EFEFEF; border: 0px solid #EFEFEF; } -menu[name=attachment-menu] { background-color: #EFEFEF; border: 0px solid #EFEFEF; } diff --git a/mailnews/mime/emitters/resources/skin/makefile.win b/mailnews/mime/emitters/resources/skin/makefile.win index 3d400960f39..1579a915934 100644 --- a/mailnews/mime/emitters/resources/skin/makefile.win +++ b/mailnews/mime/emitters/resources/skin/makefile.win @@ -26,16 +26,10 @@ include <$(DEPTH)\config\rules.mak> install:: $(MAKE_INSTALL) mailheader.css $(DIST)\bin\chrome\messenger\skin\default - $(MAKE_INSTALL) mailheader-micro.css $(DIST)\bin\chrome\messenger\skin\default - $(MAKE_INSTALL) mailheader-normal.css $(DIST)\bin\chrome\messenger\skin\default - $(MAKE_INSTALL) mailheader-all.css $(DIST)\bin\chrome\messenger\skin\default $(MAKE_INSTALL) addcard.gif $(DIST)\bin\chrome\messenger\skin\default $(MAKE_INSTALL) attach.gif $(DIST)\bin\chrome\messenger\skin\default clobber:: rm -f $(DIST)\bin\chrome\messenger\skin\default\mailheader.css - rm -f $(DIST)\bin\chrome\messenger\skin\default\mailheader-micro.css - rm -f $(DIST)\bin\chrome\messenger\skin\default\mailheader-normal.css - rm -f $(DIST)\bin\chrome\messenger\skin\default\mailheader-all.css rm -f $(DIST)\bin\chrome\messenger\skin\default\addcard.gif rm -f $(DIST)\bin\chrome\messenger\skin\default\attach.gif diff --git a/mailnews/mime/emitters/src/nsEmitterUtils.cpp b/mailnews/mime/emitters/src/nsEmitterUtils.cpp index c5490006871..4ac413fc30f 100644 --- a/mailnews/mime/emitters/src/nsEmitterUtils.cpp +++ b/mailnews/mime/emitters/src/nsEmitterUtils.cpp @@ -134,16 +134,3 @@ nsMsgCreateTempFileName(char *tFileName) else return tString; } - -char * -nsMimePlatformFileToURL (nsFileSpec aFileSpec) -{ - nsFileURL tURL(aFileSpec); - const char *tPtr = nsnull; - - tPtr = tURL.GetURLString(); - if (tPtr) - return nsCRT::strdup(tPtr); - else - return nsnull; -} diff --git a/mailnews/mime/emitters/src/nsEmitterUtils.h b/mailnews/mime/emitters/src/nsEmitterUtils.h index 8a141dc753a..0ee96bcc771 100644 --- a/mailnews/mime/emitters/src/nsEmitterUtils.h +++ b/mailnews/mime/emitters/src/nsEmitterUtils.h @@ -34,7 +34,5 @@ extern "C" PRBool EmitThisHeaderForPrefSetting(PRInt32 dispType, const char *h nsFileSpec *nsMsgCreateTempFileSpec(char *tFileName); char *nsMsgCreateTempFileName(char *tFileName); -char *nsMimePlatformFileToURL (nsFileSpec aFileSpec); - #endif // _nsEmitterUtils_h_ diff --git a/mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp b/mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp index f9506f447bd..a4d5be11e77 100644 --- a/mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp +++ b/mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp @@ -39,7 +39,9 @@ #include "nsFileSpec.h" #include "nsIRegistry.h" -static NS_DEFINE_CID(kPrefCID, NS_PREF_CID); +#define MIME_URL "chrome://messenger/locale/mimeheader.properties" +static NS_DEFINE_CID(kPrefCID, NS_PREF_CID); +static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); NS_IMPL_ISUPPORTS2(nsMimeBaseEmitter, nsIMimeEmitter, nsIPipeObserver) @@ -47,18 +49,39 @@ nsMimeBaseEmitter::nsMimeBaseEmitter() { NS_INIT_REFCNT(); + // Initialize data output vars... mBufferMgr = NULL; mTotalWritten = 0; mTotalRead = 0; - mDocHeader = PR_FALSE; - m_stringBundle = nsnull; - mInputStream = nsnull; mOutStream = nsnull; mOutListener = nsnull; + + // Display output control vars... + mDocHeader = PR_FALSE; + m_stringBundle = nsnull; mURL = nsnull; mHeaderDisplayType = nsMimeHeaderDisplayTypes::NormalHeaders; + // Setup array for attachments + mAttachCount = 0; + mAttachArray = new nsVoidArray(); + mCurrentAttachment = nsnull; + + // Header cache... + mHeaderArray = new nsVoidArray(); + + // Embedded Header Cache... + mEmbeddedHeaderArray = nsnull; + + // HTML Header Data... + mHTMLHeaders = ""; + + // Init the body... + mBodyStarted = PR_FALSE; + mBody = ""; + + // Do prefs last since we can live without this if it fails... nsresult rv = nsServiceManager::GetService(kPrefCID, nsIPref::GetIID(), (nsISupports**)&(mPrefs)); if (! (mPrefs && NS_SUCCEEDED(rv))) return; @@ -69,249 +92,62 @@ nsMimeBaseEmitter::nsMimeBaseEmitter() nsMimeBaseEmitter::~nsMimeBaseEmitter(void) { + PRInt32 i; + + // Delete the buffer manager... if (mBufferMgr) delete mBufferMgr; - // Release the prefs service + // Release the prefs service... if (mPrefs) nsServiceManager::ReleaseService(kPrefCID, mPrefs); -} -NS_IMETHODIMP -nsMimeBaseEmitter::SetPipe(nsIInputStream * aInputStream, nsIOutputStream *outStream) -{ - mInputStream = aInputStream; - mOutStream = outStream; - return NS_OK; -} - -// Note - these is setup only...you should not write -// anything to the stream since these may be image data -// output streams, etc... -NS_IMETHODIMP -nsMimeBaseEmitter::Initialize(nsIURI *url, nsIChannel * aChannel) -{ - // set the url - mURL = url; - mChannel = aChannel; - - // Create rebuffering object - mBufferMgr = new MimeRebuffer(); - - // Counters for output stream - mTotalWritten = 0; - mTotalRead = 0; - - return NS_OK; -} - -NS_IMETHODIMP -nsMimeBaseEmitter::SetOutputListener(nsIStreamListener *listener) -{ - mOutListener = listener; - return NS_OK; -} - -// Note - this is teardown only...you should not write -// anything to the stream since these may be image data -// output streams, etc... -NS_IMETHODIMP -nsMimeBaseEmitter::Complete() -{ - // If we are here and still have data to write, we should try - // to flush it...if we try and fail, we should probably return - // an error! - PRUint32 written; - while ( (mBufferMgr) && (mBufferMgr->GetSize() > 0)) - Write("", 0, &written); - - if (mOutListener) + // Clean up the attachment array structures... + if (mAttachArray) { - PRUint32 bytesInStream; - mInputStream->Available(&bytesInStream); - mOutListener->OnDataAvailable(mChannel, mURL, mInputStream, 0, bytesInStream); - } - - return NS_OK; -} - -// Header handling routines. -NS_IMETHODIMP -nsMimeBaseEmitter::StartHeader(PRBool rootMailHeader, PRBool headerOnly, const char *msgID, - const char *outCharset) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMimeBaseEmitter::AddHeaderField(const char *field, const char *value) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMimeBaseEmitter::EndHeader() -{ - return NS_OK; -} - -// Attachment handling routines -NS_IMETHODIMP -nsMimeBaseEmitter::StartAttachment(const char *name, const char *contentType, const char *url) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMimeBaseEmitter::AddAttachmentField(const char *field, const char *value) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMimeBaseEmitter::EndAttachment() -{ - return NS_OK; -} - -// body handling routines -NS_IMETHODIMP -nsMimeBaseEmitter::StartBody(PRBool bodyOnly, const char *msgID, const char *outCharset) -{ - return NS_OK; -} - - -NS_IMETHODIMP -nsMimeBaseEmitter::WriteBody(const char *buf, PRUint32 size, PRUint32 *amountWritten) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMimeBaseEmitter::EndBody() -{ - return NS_OK; -} - - -NS_IMETHODIMP -nsMimeBaseEmitter::UtilityWrite(const char *buf) -{ - PRInt32 tmpLen = nsCRT::strlen(buf); - PRUint32 written; - - Write(buf, tmpLen, &written); - - return NS_OK; -} - -NS_IMETHODIMP -nsMimeBaseEmitter::UtilityWriteCRLF(const char *buf) -{ - PRInt32 tmpLen = nsCRT::strlen(buf); - PRUint32 written; - - Write(buf, tmpLen, &written); - Write(CRLF, 2, &written); - - return NS_OK; -} - -//////////////////////////////////////////////////////////////////////////////// -// These are routines necessary for the C based routines in libmime -// to access the new world streams. -//////////////////////////////////////////////////////////////////////////////// -NS_IMETHODIMP -nsMimeBaseEmitter::Write(const char *buf, PRUint32 size, PRUint32 *amountWritten) -{ - unsigned int written = 0; - PRUint32 rc = 0; - PRUint32 needToWrite; - - // - // Make sure that the buffer we are "pushing" into has enough room - // for the write operation. If not, we have to buffer, return, and get - // it on the next time through - // - *amountWritten = 0; - - needToWrite = mBufferMgr->GetSize(); - // First, handle any old buffer data... - if (needToWrite > 0) - { - rc += mOutStream->Write(mBufferMgr->GetBuffer(), - needToWrite, &written); - - mTotalWritten += written; - mBufferMgr->ReduceBuffer(written); - *amountWritten = written; - - // if we couldn't write all the old data, buffer the new data - // and return - if (mBufferMgr->GetSize() > 0) + for (i=0; iCount(); i++) { - mBufferMgr->IncreaseBuffer(buf, size); - return NS_OK; + attachmentInfoType *attachInfo = (attachmentInfoType *)mAttachArray->ElementAt(i); + if (!attachInfo) + continue; + + PR_FREEIF(attachInfo->contentType); + PR_FREEIF(attachInfo->displayName); + PR_FREEIF(attachInfo->urlSpec); + delete attachInfo; } + delete mAttachArray; } + // Cleanup allocated header arrays... + CleanupHeaderArray(mHeaderArray); + mHeaderArray = nsnull; - // if we get here, we are dealing with new data...try to write - // and then do the right thing... - rc = mOutStream->Write(buf, size, &written); - *amountWritten = written; - mTotalWritten += written; - - if (written < size) - mBufferMgr->IncreaseBuffer(buf+written, (size-written)); - - return rc; + CleanupHeaderArray(mEmbeddedHeaderArray); + mEmbeddedHeaderArray = nsnull; } - -NS_IMETHODIMP nsMimeBaseEmitter::OnWrite(nsIPipe* aPipe, PRUint32 aCount) +void +nsMimeBaseEmitter::CleanupHeaderArray(nsVoidArray *aArray) { - return NS_OK; -} + if (!aArray) + return; -NS_IMETHODIMP nsMimeBaseEmitter::OnEmpty(nsIPipe* aPipe) -{ - return NS_OK; -} - - -NS_IMETHODIMP nsMimeBaseEmitter::OnFull(nsIPipe* /* aPipe */) -{ - // the pipe is full so we should flush our data to the converter's listener - // in order to make more room. - - // since we only have one pipe per mime emitter, i can ignore the pipe param and use - // my outStream object directly (it will be the same thing as what we'd get from aPipe. - - nsresult rv = NS_OK; - if (mOutListener && mInputStream) + for (PRInt32 i=0; iCount(); i++) { - PRUint32 bytesAvailable = 0; - mInputStream->Available(&bytesAvailable); - rv = mOutListener->OnDataAvailable(mChannel, mURL, mInputStream, 0, bytesAvailable); + headerInfoType *headerInfo = (headerInfoType *)aArray->ElementAt(i); + if (!headerInfo) + continue; + + PR_FREEIF(headerInfo->name); + PR_FREEIF(headerInfo->value); + delete headerInfo; } - else - rv = NS_ERROR_NULL_POINTER; - - return rv; } // -// This should be part of the base class to optimize the performance of the -// calls to get localized strings. +// This is the next generation string retrieval call // - -/* This is the next generation string retrieval call */ -static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); - -#define MIME_URL "chrome://messenger/locale/mimeheader.properties" - char * nsMimeBaseEmitter::MimeGetStringByName(const char *aHeaderName) { @@ -372,3 +208,520 @@ nsMimeBaseEmitter::LocalizeHeaderName(const char *aHeaderName, const char *aDefa else return nsCRT::strdup(aDefaultName); } + +/////////////////////////////////////////////////////////////////////////// +// nsIPipeObserver Interface +/////////////////////////////////////////////////////////////////////////// + +NS_IMETHODIMP nsMimeBaseEmitter::OnWrite(nsIPipe* aPipe, PRUint32 aCount) +{ + return NS_OK; +} + +NS_IMETHODIMP nsMimeBaseEmitter::OnEmpty(nsIPipe* aPipe) +{ + return NS_OK; +} + + +NS_IMETHODIMP nsMimeBaseEmitter::OnFull(nsIPipe* /* aPipe */) +{ + // the pipe is full so we should flush our data to the converter's listener + // in order to make more room. + + // since we only have one pipe per mime emitter, i can ignore the pipe param and use + // my outStream object directly (it will be the same thing as what we'd get from aPipe. + + nsresult rv = NS_OK; + if (mOutListener && mInputStream) + { + PRUint32 bytesAvailable = 0; + mInputStream->Available(&bytesAvailable); + rv = mOutListener->OnDataAvailable(mChannel, mURL, mInputStream, 0, bytesAvailable); + } + else + rv = NS_ERROR_NULL_POINTER; + + return rv; +} + +/////////////////////////////////////////////////////////////////////////// +// nsMimeBaseEmitter Interface +/////////////////////////////////////////////////////////////////////////// +NS_IMETHODIMP +nsMimeBaseEmitter::SetPipe(nsIInputStream * aInputStream, nsIOutputStream *outStream) +{ + mInputStream = aInputStream; + mOutStream = outStream; + return NS_OK; +} + +// Note - these is setup only...you should not write +// anything to the stream since these may be image data +// output streams, etc... +NS_IMETHODIMP +nsMimeBaseEmitter::Initialize(nsIURI *url, nsIChannel * aChannel) +{ + // set the url + mURL = url; + mChannel = aChannel; + + // Create rebuffering object + mBufferMgr = new MimeRebuffer(); + + // Counters for output stream + mTotalWritten = 0; + mTotalRead = 0; + + return NS_OK; +} + +NS_IMETHODIMP +nsMimeBaseEmitter::SetOutputListener(nsIStreamListener *listener) +{ + mOutListener = listener; + return NS_OK; +} + +// Attachment handling routines +nsresult +nsMimeBaseEmitter::StartAttachment(const char *name, const char *contentType, const char *url) +{ + // Ok, now we will setup the attachment info + mCurrentAttachment = (attachmentInfoType *) PR_NEWZAP(attachmentInfoType); + if ( (mCurrentAttachment) && mAttachArray) + { + ++mAttachCount; + + mCurrentAttachment->displayName = nsCRT::strdup(name); + mCurrentAttachment->urlSpec = nsCRT::strdup(url); + mCurrentAttachment->contentType = nsCRT::strdup(contentType); + } + + return NS_OK; +} + +nsresult +nsMimeBaseEmitter::EndAttachment() +{ + // Ok, add the attachment info to the attachment array... + if ( (mCurrentAttachment) && (mAttachArray) ) + { + mAttachArray->AppendElement(mCurrentAttachment); + mCurrentAttachment = nsnull; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsMimeBaseEmitter::AddAttachmentField(const char *field, const char *value) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMimeBaseEmitter::UtilityWrite(const char *buf) +{ + PRInt32 tmpLen = nsCRT::strlen(buf); + PRUint32 written; + + Write(buf, tmpLen, &written); + + return NS_OK; +} + +NS_IMETHODIMP +nsMimeBaseEmitter::UtilityWriteCRLF(const char *buf) +{ + PRInt32 tmpLen = nsCRT::strlen(buf); + PRUint32 written; + + Write(buf, tmpLen, &written); + Write(CRLF, 2, &written); + + return NS_OK; +} + +NS_IMETHODIMP +nsMimeBaseEmitter::Write(const char *buf, PRUint32 size, PRUint32 *amountWritten) +{ + unsigned int written = 0; + PRUint32 rc = 0; + PRUint32 needToWrite; + + // + // Make sure that the buffer we are "pushing" into has enough room + // for the write operation. If not, we have to buffer, return, and get + // it on the next time through + // + *amountWritten = 0; + + needToWrite = mBufferMgr->GetSize(); + // First, handle any old buffer data... + if (needToWrite > 0) + { + rc += mOutStream->Write(mBufferMgr->GetBuffer(), + needToWrite, &written); + + mTotalWritten += written; + mBufferMgr->ReduceBuffer(written); + *amountWritten = written; + + // if we couldn't write all the old data, buffer the new data + // and return + if (mBufferMgr->GetSize() > 0) + { + mBufferMgr->IncreaseBuffer(buf, size); + return NS_OK; + } + } + + + // if we get here, we are dealing with new data...try to write + // and then do the right thing... + rc = mOutStream->Write(buf, size, &written); + *amountWritten = written; + mTotalWritten += written; + + if (written < size) + mBufferMgr->IncreaseBuffer(buf+written, (size-written)); + + return rc; +} + +// +// Find a cached header! Note: Do NOT free this value! +// +char * +nsMimeBaseEmitter::GetHeaderValue(const char *aHeaderName, + nsVoidArray *aArray) +{ + PRInt32 i; + char *retVal = nsnull; + + if (!aArray) + return nsnull; + + for (i=0; iCount(); i++) + { + headerInfoType *headerInfo = (headerInfoType *)aArray->ElementAt(i); + if ( (!headerInfo) || (!headerInfo->name) || (!(*headerInfo->name)) ) + continue; + + if (!nsCRT::strcasecmp(aHeaderName, headerInfo->name)) + { + retVal = headerInfo->value; + break; + } + } + + return retVal; +} + +// +// This is called at the start of the header block for all header information in ANY +// AND ALL MESSAGES (yes, quoted, attached, etc...) +// +NS_IMETHODIMP +nsMimeBaseEmitter::StartHeader(PRBool rootMailHeader, PRBool headerOnly, const char *msgID, + const char *outCharset) +{ + mDocHeader = rootMailHeader; + + // If this is not the mail messages header, then we need to create + // the mEmbeddedHeaderArray structure for use with this internal header + // structure. + if (!mDocHeader) + { + if (mEmbeddedHeaderArray) + CleanupHeaderArray(mEmbeddedHeaderArray); + + mEmbeddedHeaderArray = new nsVoidArray(); + if (!mEmbeddedHeaderArray) + return NS_ERROR_OUT_OF_MEMORY; + } + + return NS_OK; +} + +// +// This will be called for every header field regardless if it is in an +// internal body or the outer message. +// +NS_IMETHODIMP +nsMimeBaseEmitter::AddHeaderField(const char *field, const char *value) +{ + if ( (!field) || (!value) ) + return NS_OK; + + nsVoidArray *tPtr; + if (mDocHeader) + tPtr = mHeaderArray; + else + tPtr = mEmbeddedHeaderArray; + + // This is a header so we need to cache and output later. + // Ok, now we will setup the header info for the header array! + headerInfoType *ptr = (headerInfoType *) PR_NEWZAP(headerInfoType); + if ( (ptr) && tPtr) + { + ptr->name = nsCRT::strdup(field); + ptr->value = nsCRT::strdup(value); + tPtr->AppendElement(ptr); + } + + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// +// The following code is responsible for formatting headers in a manner that is +// identical to the normal XUL output. +//////////////////////////////////////////////////////////////////////////////// +nsresult +nsMimeBaseEmitter::WriteHeaderFieldHTML(const char *field, const char *value) +{ + if ( (!field) || (!value) ) + return NS_OK; + + // + // This is a check to see what the pref is for header display. If + // We should only output stuff that corresponds with that setting. + // + if (!EmitThisHeaderForPrefSetting(mHeaderDisplayType, field)) + return NS_OK; + + char *newValue = nsEscapeHTML(value); + if (!newValue) + return NS_OK; + + mHTMLHeaders.Append(""); + mHTMLHeaders.Append(""); + + mHTMLHeaders.Append("
"); + + // Here is where we are going to try to L10N the tagName so we will always + // get a field name next to an emitted header value. Note: Default will always + // be the name of the header itself. + // + nsCAutoString newTagName(field); + newTagName.CompressWhitespace(PR_TRUE, PR_TRUE); + newTagName.ToUpperCase(); + + char *l10nTagName = LocalizeHeaderName((const char *) newTagName, field); + if ( (!l10nTagName) || (!*l10nTagName) ) + mHTMLHeaders.Append(field); + else + { + mHTMLHeaders.Append(l10nTagName); + PR_FREEIF(l10nTagName); + } + + mHTMLHeaders.Append(": "); + mHTMLHeaders.Append("
"); + + // Now write out the actual value itself and move on! + // + mHTMLHeaders.Append(newValue); + mHTMLHeaders.Append(""); + + mHTMLHeaders.Append(""); + + PR_FREEIF(newValue); + return NS_OK; +} + +nsresult +nsMimeBaseEmitter::WriteHeaderFieldHTMLPrefix() +{ + mHTMLHeaders.Append(""); + return NS_OK; +} + +nsresult +nsMimeBaseEmitter::WriteHeaderFieldHTMLPostfix() +{ + mHTMLHeaders.Append("

"); + return NS_OK; +} + +nsresult +nsMimeBaseEmitter::WriteHTMLHeaders() +{ + WriteHeaderFieldHTMLPrefix(); + + // Start with the subject, from date info! + DumpSubjectFromDate(); + + // Continue with the to and cc headers + DumpToCC(); + + // Do the rest of the headers, but these will only be written if + // the user has the "show all headers" pref set + DumpRestOfHeaders(); + + WriteHeaderFieldHTMLPostfix(); + + // Now, we need to either append the headers we built up to the + // overall body or output to the stream. + if (mDocHeader) + UtilityWriteCRLF(mHTMLHeaders); + else + mBody.Append(mHTMLHeaders); + + return NS_OK; +} + +nsresult +nsMimeBaseEmitter::DumpSubjectFromDate() +{ + mHTMLHeaders.Append(""); + + // This is the envelope information + OutputGenericHeader(HEADER_SUBJECT); + OutputGenericHeader(HEADER_FROM); + OutputGenericHeader(HEADER_DATE); + + mHTMLHeaders.Append("
"); + + return NS_OK; +} + +nsresult +nsMimeBaseEmitter::DumpToCC() +{ + char * toField = GetHeaderValue(HEADER_TO, mHeaderArray); + char * ccField = GetHeaderValue(HEADER_CC, mHeaderArray); + char * bccField = GetHeaderValue(HEADER_BCC, mHeaderArray); + char * newsgroupField = GetHeaderValue(HEADER_NEWSGROUPS, mHeaderArray); + + // only dump these fields if we have at least one of them! When displaying news + // messages that didn't have a to or cc field, we'd always get an empty box + // which looked weird. + if (toField || ccField || bccField || newsgroupField) + { + mHTMLHeaders.Append(""); + + OutputGenericHeader(HEADER_TO); + OutputGenericHeader(HEADER_CC); + OutputGenericHeader(HEADER_BCC); + OutputGenericHeader(HEADER_NEWSGROUPS); + + mHTMLHeaders.Append("
"); + } + + return NS_OK; +} + +nsresult +nsMimeBaseEmitter::DumpRestOfHeaders() +{ + PRInt32 i; + + if (mHeaderDisplayType != nsMimeHeaderDisplayTypes::AllHeaders) + return NS_OK; + + mHTMLHeaders.Append(""); + + for (i=0; iCount(); i++) + { + headerInfoType *headerInfo = (headerInfoType *)mHeaderArray->ElementAt(i); + if ( (!headerInfo) || (!headerInfo->name) || (!(*headerInfo->name)) || + (!headerInfo->value) || (!(*headerInfo->value))) + continue; + + if ( (!nsCRT::strcasecmp(HEADER_SUBJECT, headerInfo->name)) || + (!nsCRT::strcasecmp(HEADER_DATE, headerInfo->name)) || + (!nsCRT::strcasecmp(HEADER_FROM, headerInfo->name)) || + (!nsCRT::strcasecmp(HEADER_TO, headerInfo->name)) || + (!nsCRT::strcasecmp(HEADER_CC, headerInfo->name)) ) + continue; + + WriteHeaderFieldHTML(headerInfo->name, headerInfo->value); + } + + mHTMLHeaders.Append("
"); + return NS_OK; +} + +nsresult +nsMimeBaseEmitter::OutputGenericHeader(const char *aHeaderVal) +{ + char *val = nsnull; + nsresult rv; + + if (mDocHeader) + val = GetHeaderValue(aHeaderVal, mHeaderArray); + else + val = GetHeaderValue(aHeaderVal, mEmbeddedHeaderArray); + + if (val) + { + rv = WriteHeaderFieldHTML(aHeaderVal, val); + return rv; + } + else + return NS_ERROR_FAILURE; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// These are the methods that should be implemented by the child class! +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +// +// This should be implemented by the child class if special processing +// needs to be done when the entire message is read. +// +NS_IMETHODIMP +nsMimeBaseEmitter::Complete() +{ + // If we are here and still have data to write, we should try + // to flush it...if we try and fail, we should probably return + // an error! + PRUint32 written; + while ( (mBufferMgr) && (mBufferMgr->GetSize() > 0)) + Write("", 0, &written); + + if (mOutListener) + { + PRUint32 bytesInStream; + mInputStream->Available(&bytesInStream); + mOutListener->OnDataAvailable(mChannel, mURL, mInputStream, 0, bytesInStream); + } + + return NS_OK; +} + +// +// This needs to do the right thing with the stored information. It only +// has to do the output functions, this base class will take care of the +// memory cleanup +// +NS_IMETHODIMP +nsMimeBaseEmitter::EndHeader() +{ + return NS_OK; +} + +// body handling routines +NS_IMETHODIMP +nsMimeBaseEmitter::StartBody(PRBool bodyOnly, const char *msgID, const char *outCharset) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMimeBaseEmitter::WriteBody(const char *buf, PRUint32 size, PRUint32 *amountWritten) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMimeBaseEmitter::EndBody() +{ + return NS_OK; +} diff --git a/mailnews/mime/emitters/src/nsMimeBaseEmitter.h b/mailnews/mime/emitters/src/nsMimeBaseEmitter.h index bda34c14019..8b6387b6ccc 100644 --- a/mailnews/mime/emitters/src/nsMimeBaseEmitter.h +++ b/mailnews/mime/emitters/src/nsMimeBaseEmitter.h @@ -38,50 +38,109 @@ #include "nsIPipe.h" #include "nsIStringBundle.h" #include "nsCOMPtr.h" +#include "nsVoidArray.h" + +// +// The base emitter will serve as the place to do all of the caching, +// sorting, etc... of mail headers and bodies for this internally developed +// emitter library. The other emitter classes in this file (nsMimeHTMLEmitter, etc.) +// will only be concerned with doing output processing ONLY. +// + +// +// Used for keeping track of the attachment information... +// +typedef struct { + char *displayName; + char *urlSpec; + char *contentType; +} attachmentInfoType; + +// +// For header info... +// +typedef struct { + char *name; + char *value; +} headerInfoType; class nsMimeBaseEmitter : public nsIMimeEmitter, nsIPipeObserver { public: - nsMimeBaseEmitter (); - virtual ~nsMimeBaseEmitter (void); + nsMimeBaseEmitter (); + virtual ~nsMimeBaseEmitter (void); - // nsISupports interface - NS_DECL_ISUPPORTS + // nsISupports interface + NS_DECL_ISUPPORTS - NS_DECL_NSIMIMEEMITTER - NS_DECL_NSIPIPEOBSERVER + NS_DECL_NSIMIMEEMITTER + NS_DECL_NSIPIPEOBSERVER - NS_IMETHOD UtilityWriteCRLF(const char *buf); + // Utility output functions... + NS_IMETHOD UtilityWriteCRLF(const char *buf); - // For cacheing string bundles... - char *MimeGetStringByName(const char *aHeaderName); - char *LocalizeHeaderName(const char *aHeaderName, const char *aDefaultName); + // For string bundle usage... + char *MimeGetStringByName(const char *aHeaderName); + char *LocalizeHeaderName(const char *aHeaderName, const char *aDefaultName); + + // For header processing... + char *GetHeaderValue(const char *aHeaderName, + nsVoidArray *aArray); + + // To write out a stored header array as HTML + nsresult WriteHeaderFieldHTMLPrefix(); + nsresult WriteHeaderFieldHTML(const char *field, const char *value); + nsresult WriteHeaderFieldHTMLPostfix(); + nsresult WriteHTMLHeaders(); protected: - // For buffer management on output - MimeRebuffer *mBufferMgr; + // Internal methods... + void CleanupHeaderArray(nsVoidArray *aArray); - nsCOMPtr m_stringBundle; // For string bundle usage... + // For header output... + nsresult DumpSubjectFromDate(); + nsresult DumpToCC(); + nsresult DumpRestOfHeaders(); + nsresult OutputGenericHeader(const char *aHeaderVal); + // For string bundle usage... + nsCOMPtr m_stringBundle; // For string bundle usage... - // mscott - dont ref count the streams....the emitter is owned by the converter + // For buffer management on output + MimeRebuffer *mBufferMgr; + + // mscott + // dont ref count the streams....the emitter is owned by the converter // which owns these streams... + // nsIOutputStream *mOutStream; nsIInputStream *mInputStream; nsIStreamListener *mOutListener; nsIChannel *mChannel; + // For gathering statistics on processing... PRUint32 mTotalWritten; PRUint32 mTotalRead; - // For header determination... - PRBool mDocHeader; + // Output control and info... + nsIPref *mPrefs; // Connnection to prefs service manager + PRBool mDocHeader; // For header determination... + nsIURI *mURL; // the url for the data being processed... + PRInt32 mHeaderDisplayType; // The setting for header output... + nsCString mHTMLHeaders; // HTML Header Data... - // the url for the data being processed... - nsIURI *mURL; + // For attachment processing... + PRInt32 mAttachCount; + nsVoidArray *mAttachArray; + attachmentInfoType *mCurrentAttachment; - // The setting for header output... - nsIPref *mPrefs; /* Connnection to prefs service manager */ - PRInt32 mHeaderDisplayType; + // For header caching... + nsVoidArray *mHeaderArray; + nsVoidArray *mEmbeddedHeaderArray; + nsCOMPtr mHeaderParser; + + // For body caching... + PRBool mBodyStarted; + nsCString mBody; }; #endif /* _nsMimeBaseEmitter_h_ */ diff --git a/mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp b/mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp index c038f0308e8..1896cdf1414 100644 --- a/mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp +++ b/mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp @@ -43,91 +43,26 @@ nsresult NS_NewMimeHtmlEmitter(const nsIID& iid, void **result) */ nsMimeHtmlEmitter::nsMimeHtmlEmitter() { + mFirst = PR_TRUE; } nsMimeHtmlEmitter::~nsMimeHtmlEmitter(void) { } -// Header handling routines. -nsresult -nsMimeHtmlEmitter::StartHeader(PRBool rootMailHeader, PRBool headerOnly, const char *msgID, - const char *outCharset) -{ - mDocHeader = rootMailHeader; - - if (mDocHeader) - { - UtilityWrite(""); - } - else - UtilityWrite("
"); - return NS_OK; -} - -nsresult -nsMimeHtmlEmitter::AddHeaderField(const char *field, const char *value) -{ - if ( (!field) || (!value) ) - return NS_OK; - - // - // This is a check to see what the pref is for header display. If - // We should only output stuff that corresponds with that setting. - // - if (!EmitThisHeaderForPrefSetting(mHeaderDisplayType, field)) - return NS_OK; - - char *newValue = nsEscapeHTML(value); - if (!newValue) - return NS_OK; - - UtilityWrite(""); - - UtilityWrite(""); - - UtilityWrite(""); - - UtilityWrite(""); - - PR_FREEIF(newValue); - nsCRT::free(upCaseField); - return NS_OK; -} - nsresult nsMimeHtmlEmitter::EndHeader() { - UtilityWrite("
"); - UtilityWrite("
"); - UtilityWrite(""); - - // Here is where we are going to try to L10N the tagName so we will always - // get a field name next to an emitted header value. Note: Default will always - // be the name of the header itself. - // - nsString newTagName(field); - newTagName.CompressWhitespace(PR_TRUE, PR_TRUE); - newTagName.ToUpperCase(); - char *upCaseField = newTagName.ToNewCString(); - - char *l10nTagName = LocalizeHeaderName(upCaseField, field); - if ( (!l10nTagName) || (!*l10nTagName) ) - UtilityWrite(field); - else - { - UtilityWrite(l10nTagName); - PR_FREEIF(l10nTagName); - } - - // Now write out the actual value itself and move on! - // - UtilityWrite(":"); - UtilityWrite(""); - UtilityWrite("
"); - UtilityWrite("
"); - UtilityWrite(newValue); - UtilityWrite("
"); + if (mDocHeader) + { + // Stylesheet info! + UtilityWriteCRLF(""); + + // Make it look consistent... + UtilityWriteCRLF(""); + } + + WriteHTMLHeaders(); return NS_OK; } @@ -139,14 +74,22 @@ nsMimeHtmlEmitter::EndHeader() nsresult nsMimeHtmlEmitter::StartAttachment(const char *name, const char *contentType, const char *url) { + if (mFirst) + UtilityWrite("
"); + + mFirst = PR_FALSE; + UtilityWrite("
"); - UtilityWrite(""); + UtilityWrite("
"); UtilityWrite(""); UtilityWrite(""); @@ -162,16 +105,19 @@ nsMimeHtmlEmitter::AddAttachmentField(const char *field, const char *value) if ( (!value) || (!*value) ) return NS_OK; + // Don't output this ugly header... + if (!nsCRT::strcmp(field, HEADER_X_MOZILLA_PART_URL)) + return NS_OK; + char *newValue = nsEscapeHTML(value); UtilityWrite(""); UtilityWrite(""); UtilityWrite(""); - - UtilityWrite(""); - - UtilityWrite(""); - - UtilityWrite(""); - - PR_FREEIF(newValue); + + registry->Close(); + return NS_OK; } -// -// Find a cached header! Note: Do NOT free this value! -// -char * -nsMimeXULEmitter::GetHeaderValue(const char *aHeaderName) +nsIMimeMiscStatus * +nsMimeXULEmitter::GetStatusObjForProgID(nsCString aProgID) { - PRInt32 i; - char *retVal = nsnull; + nsresult rv = NS_OK; + nsISupports *obj = nsnull; - if (!mHeaderArray) + NS_WITH_SERVICE(nsIComponentManager, comMgr, kComponentManagerCID, &rv); + if (NS_FAILED(rv)) + return nsnull; + + nsCID cid; + rv = comMgr->ProgIDToCLSID(aProgID, &cid); + if (NS_FAILED(rv)) return nsnull; - for (i=0; iCount(); i++) - { - headerInfoType *headerInfo = (headerInfoType *)mHeaderArray->ElementAt(i); - if ( (!headerInfo) || (!headerInfo->name) || (!(*headerInfo->name)) ) - continue; - - if (!nsCRT::strcasecmp(aHeaderName, headerInfo->name)) - { - retVal = headerInfo->value; - break; - } - } - - return retVal; + rv = comMgr->CreateInstance(cid, nsnull, NS_GET_IID(nsIMimeMiscStatus), (void**)&obj); + if (NS_FAILED(rv)) + return nsnull; + else + return (nsIMimeMiscStatus *)obj; } ////////////////////////////////////////////////////////////////////////////// @@ -310,24 +248,11 @@ nsMimeXULEmitter::GetHeaderValue(const char *aHeaderName) // display. This will include style sheet information, etc... // nsresult -nsMimeXULEmitter::WriteXULHeader(const char *msgID) +nsMimeXULEmitter::WriteXULHeader() { - if ( (!msgID) || (!*msgID) ) - msgID = "none"; - - char *newValue = nsEscapeHTML(msgID); - if (!newValue) - return NS_ERROR_OUT_OF_MEMORY; - UtilityWriteCRLF(""); UtilityWriteCRLF(""); - if (mHeaderDisplayType == nsMimeHeaderDisplayTypes::MicroHeaders) - UtilityWriteCRLF(""); - else if (mHeaderDisplayType == nsMimeHeaderDisplayTypes::NormalHeaders) - UtilityWriteCRLF(""); - else /* AllHeaders */ - UtilityWriteCRLF(""); // Make it look consistent... UtilityWriteCRLF(""); @@ -341,12 +266,6 @@ nsMimeXULEmitter::WriteXULHeader(const char *msgID) DoWindowStatusProcessing(); UtilityWriteCRLF("align=\"vertical\" flex=\"1\"> "); - // Output the message ID to make it query-able via the DOM - UtilityWrite(""); - // Now, the JavaScript... UtilityWriteCRLF(""); UtilityWriteCRLF(""); @@ -355,30 +274,6 @@ nsMimeXULEmitter::WriteXULHeader(const char *msgID) return NS_OK; } -// -// This is called at the start of the header block for all header information in ANY -// AND ALL MESSAGES (yes, quoted, attached, etc...) So, we need to handle these differently -// if they are the rood message as opposed to quoted message. If rootMailHeader is set to -// PR_TRUE, this is the root document, else it is a header in the body somewhere -// -nsresult -nsMimeXULEmitter::StartHeader(PRBool rootMailHeader, PRBool headerOnly, const char *msgID, - const char *outCharset) -{ - mDocHeader = rootMailHeader; - - if (!mDocHeader) - { - UtilityWriteCRLF("
"); UtilityWrite("
"); - UtilityWrite("Attachment: "); + UtilityWrite("
"); + UtilityWrite(name); + + UtilityWrite("
"); UtilityWrite("
"); UtilityWrite("
"); - UtilityWrite("
"); - UtilityWrite(""); + UtilityWrite("
"); + UtilityWrite(field); UtilityWrite(":"); - UtilityWrite(""); UtilityWrite("
"); UtilityWrite("
"); @@ -198,13 +144,6 @@ nsMimeHtmlEmitter::EndAttachment() return NS_OK; } -// Attachment handling routines -nsresult -nsMimeHtmlEmitter::StartBody(PRBool bodyOnly, const char *msgID, const char *outCharset) -{ - return NS_OK; -} - nsresult nsMimeHtmlEmitter::WriteBody(const char *buf, PRUint32 size, PRUint32 *amountWritten) { diff --git a/mailnews/mime/emitters/src/nsMimeHtmlEmitter.h b/mailnews/mime/emitters/src/nsMimeHtmlEmitter.h index e7953ba7fc1..b473e6a9321 100644 --- a/mailnews/mime/emitters/src/nsMimeHtmlEmitter.h +++ b/mailnews/mime/emitters/src/nsMimeHtmlEmitter.h @@ -39,9 +39,6 @@ public: virtual ~nsMimeHtmlEmitter (void); // Header handling routines. - NS_IMETHOD StartHeader(PRBool rootMailHeader, PRBool headerOnly, const char *msgID, - const char *outCharset); - NS_IMETHOD AddHeaderField(const char *field, const char *value); NS_IMETHOD EndHeader(); // Attachment handling routines @@ -50,10 +47,10 @@ public: NS_IMETHOD EndAttachment(); // Body handling routines - NS_IMETHOD StartBody(PRBool bodyOnly, const char *msgID, const char *outCharset); NS_IMETHOD WriteBody(const char *buf, PRUint32 size, PRUint32 *amountWritten); protected: + PRBool mFirst; // Attachment flag... }; /* this function will be used by the factory to generate an class access object....*/ diff --git a/mailnews/mime/emitters/src/nsMimeXULEmitter.cpp b/mailnews/mime/emitters/src/nsMimeXULEmitter.cpp index 454c5859ab7..0c41bd0f629 100644 --- a/mailnews/mime/emitters/src/nsMimeXULEmitter.cpp +++ b/mailnews/mime/emitters/src/nsMimeXULEmitter.cpp @@ -65,14 +65,6 @@ nsMimeXULEmitter::nsMimeXULEmitter() { mCutoffValue = 3; - // Header cache... - mHeaderArray = new nsVoidArray(); - - // Setup array for attachments - mAttachCount = 0; - mAttachArray = new nsVoidArray(); - mCurrentAttachment = nsnull; - // Vars to handle the body... mBody = ""; mBodyStarted = PR_FALSE; @@ -92,38 +84,7 @@ nsMimeXULEmitter::nsMimeXULEmitter() nsMimeXULEmitter::~nsMimeXULEmitter(void) { - PRInt32 i; - - if (mAttachArray) - { - for (i=0; iCount(); i++) - { - attachmentInfoType *attachInfo = (attachmentInfoType *)mAttachArray->ElementAt(i); - if (!attachInfo) - continue; - - PR_FREEIF(attachInfo->contentType); - PR_FREEIF(attachInfo->displayName); - PR_FREEIF(attachInfo->urlSpec); - delete attachInfo; - } - delete mAttachArray; - } - - if (mHeaderArray) - { - for (i=0; iCount(); i++) - { - headerInfoType *headerInfo = (headerInfoType *)mHeaderArray->ElementAt(i); - if (!headerInfo) - continue; - - PR_FREEIF(headerInfo->name); - PR_FREEIF(headerInfo->value); - delete headerInfo; - } - delete mHeaderArray; - } + PRInt32 i; if (mMiscStatusArray) { @@ -134,54 +95,27 @@ nsMimeXULEmitter::~nsMimeXULEmitter(void) continue; NS_IF_RELEASE(statusInfo->obj); - delete statusInfo; + delete statusInfo; } delete mMiscStatusArray; } } -// Attachment handling routines -nsresult -nsMimeXULEmitter::StartAttachment(const char *name, const char *contentType, const char *url) -{ - // Ok, now we will setup the attachment info - mCurrentAttachment = (attachmentInfoType *) PR_NEWZAP(attachmentInfoType); - if ( (mCurrentAttachment) && mAttachArray) - { - ++mAttachCount; - - mCurrentAttachment->displayName = nsCRT::strdup(name); - mCurrentAttachment->urlSpec = nsCRT::strdup(url); - mCurrentAttachment->contentType = nsCRT::strdup(contentType); - } - - return NS_OK; -} - -nsresult -nsMimeXULEmitter::EndAttachment() -{ - // Ok, add the attachment info to the attachment array... - if ( (mCurrentAttachment) && (mAttachArray) ) - { - mAttachArray->AppendElement(mCurrentAttachment); - mCurrentAttachment = nsnull; - } - - return NS_OK; -} - // Attachment handling routines nsresult nsMimeXULEmitter::StartBody(PRBool bodyOnly, const char *msgID, const char *outCharset) { + // Setup everything for META tags and stylesheet info! mBody.Append(""); - mBody.Append(""); + // Now for some style... + mBody.Append(""); + mBody.Append(""); + mBodyStarted = PR_TRUE; return NS_OK; } @@ -201,9 +135,6 @@ nsMimeXULEmitter::WriteBody(const char *buf, PRUint32 size, PRUint32 *amountWrit return NS_OK; } -#define TEMP_FILE_PREFIX "nsMimeBody" - - nsresult nsMimeXULEmitter::EndBody() { @@ -213,88 +144,95 @@ nsMimeXULEmitter::EndBody() } nsresult -nsMimeXULEmitter::AddHeaderFieldHTML(const char *field, const char *value) +nsMimeXULEmitter::BuildListOfStatusProviders() { - if ( (!field) || (!value) ) - return NS_OK; + nsresult rv; - // - // This is a check to see what the pref is for header display. If - // We should only output stuff that corresponds with that setting. - // - if (!EmitThisHeaderForPrefSetting(mHeaderDisplayType, field)) - return NS_OK; + // enumerate the registry subkeys + nsRegistryKey key; + nsCOMPtr components; + miscStatusType *newInfo = nsnull; - char *newValue = nsEscapeHTML(value); - if (!newValue) - return NS_OK; - - UtilityWrite("
"); - UtilityWrite("
"); - UtilityWrite(""); - - // Here is where we are going to try to L10N the tagName so we will always - // get a field name next to an emitted header value. Note: Default will always - // be the name of the header itself. - // - nsCAutoString newTagName(field); - newTagName.CompressWhitespace(PR_TRUE, PR_TRUE); - newTagName.ToUpperCase(); - - char *l10nTagName = LocalizeHeaderName((const char *) newTagName, field); - if ( (!l10nTagName) || (!*l10nTagName) ) - UtilityWrite(field); - else + NS_WITH_SERVICE(nsIRegistry, registry, NS_REGISTRY_PROGID, &rv); + if (NS_FAILED(rv)) + return rv; + + rv = registry->OpenWellKnownRegistry(nsIRegistry::ApplicationComponentRegistry); + if (NS_FAILED(rv)) + return rv; + + rv = registry->GetSubtree(nsIRegistry::Common, NS_IMIME_MISC_STATUS_KEY, &key); + if (NS_FAILED(rv)) + return rv; + + rv = registry->EnumerateSubtrees(key, getter_AddRefs(components)); + if (NS_FAILED(rv)) + return rv; + + // go ahead and enumerate through. + nsCAutoString actualProgID; + rv = components->First(); + while (NS_SUCCEEDED(rv) && (NS_OK != components->IsDone())) { - UtilityWrite(l10nTagName); - PR_FREEIF(l10nTagName); + nsCOMPtr base; + + rv = components->CurrentItem(getter_AddRefs(base)); + if (NS_FAILED(rv)) + return rv; + + nsCOMPtr node; + node = do_QueryInterface(base, &rv); + if (NS_FAILED(rv)) + return rv; + + nsXPIDLCString name; + rv = node->GetName(getter_Copies(name)); + if (NS_FAILED(rv)) + return rv; + + actualProgID = NS_IMIME_MISC_STATUS_KEY; + actualProgID.Append(name); + + // now we've got the PROGID, let's add it to the list... + newInfo = (miscStatusType *)PR_NEWZAP(miscStatusType); + if (newInfo) + { + newInfo->obj = GetStatusObjForProgID(actualProgID); + if (newInfo->obj) + { + newInfo->progID = actualProgID; + mMiscStatusArray->AppendElement(newInfo); + } + } + + rv = components->Next(); } - - // Now write out the actual value itself and move on! - // - UtilityWrite(":"); - UtilityWrite(""); - UtilityWrite("
"); - UtilityWrite("
"); - UtilityWrite(newValue); - UtilityWrite("
"); - } - else - { - WriteXULHeader(msgID); - } - - return NS_OK; -} - nsresult nsMimeXULEmitter::DoSpecialSenderProcessing(const char *field, const char *value) { @@ -393,46 +288,22 @@ nsMimeXULEmitter::DoSpecialSenderProcessing(const char *field, const char *value return rv; } -// -// This will be called for every header field...for now, we are calling the WriteXULTag for -// each of these calls. -// -nsresult -nsMimeXULEmitter::AddHeaderField(const char *field, const char *value) -{ - if ( (!field) || (!value) ) - return NS_OK; - - if ( (mDocHeader) && (!nsCRT::strcmp(field, HEADER_FROM)) ) - DoSpecialSenderProcessing(field, value); - - if (!mDocHeader) - return AddHeaderFieldHTML(field, value); - else - { - // This is the main header so we do caching for XUL later! - // Ok, now we will setup the header info for the header array! - headerInfoType *ptr = (headerInfoType *) PR_NEWZAP(headerInfoType); - if ( (ptr) && mHeaderArray) - { - ptr->name = nsCRT::strdup(field); - ptr->value = nsCRT::strdup(value); - mHeaderArray->AppendElement(ptr); - } - - return NS_OK; - } -} - // // This finalizes the header field being parsed. // nsresult nsMimeXULEmitter::EndHeader() { + // + // If this is NOT the mail messages's header, then we need to write + // out the contents of the headers in HTML form. + // if (!mDocHeader) - UtilityWriteCRLF("
"); - + { + WriteHTMLHeaders(); + return NS_OK; + } + // Nothing to do in the case of the actual Envelope. This will be done // on Complete(). @@ -449,6 +320,9 @@ nsMimeXULEmitter::EndHeader() nsresult nsMimeXULEmitter::Complete() { + // First the top of the document... + WriteXULHeader(); + // Start off the header as a toolbox! UtilityWriteCRLF(""); @@ -474,6 +348,18 @@ nsMimeXULEmitter::Complete() return nsMimeBaseEmitter::Complete(); } +// +// This will be called for every header field regardless if it is in an +// internal body or the outer message. If it is the +// +NS_IMETHODIMP +nsMimeXULEmitter::AddHeaderField(const char *field, const char *value) +{ + if (mDocHeader) + DoSpecialSenderProcessing(field, value); + + return nsMimeBaseEmitter::AddHeaderField(field, value); +} nsresult nsMimeXULEmitter::DumpAttachmentMenu() @@ -628,12 +514,12 @@ nsMimeXULEmitter::DumpBody() { // Now we will write out the XUL/IFRAME line for the mBody // - // remove nsMimePlatformFileToURL? UtilityWrite(""); @@ -643,7 +529,7 @@ nsMimeXULEmitter::DumpBody() nsresult nsMimeXULEmitter::OutputGenericHeader(const char *aHeaderVal) { - char *val = GetHeaderValue(aHeaderVal); + char *val = GetHeaderValue(aHeaderVal, mHeaderArray); nsresult rv; if (val) @@ -679,7 +565,7 @@ nsMimeXULEmitter::DumpSubjectFromDate() UtilityWriteCRLF(""); // Now the addbook and attachment icons need to be displayed - DumpAddBookIcon(GetHeaderValue(HEADER_FROM)); + DumpAddBookIcon(GetHeaderValue(HEADER_FROM, mHeaderArray)); DumpAttachmentMenu(); UtilityWriteCRLF(""); @@ -694,10 +580,10 @@ nsMimeXULEmitter::DumpSubjectFromDate() nsresult nsMimeXULEmitter::DumpToCC() { - char * toField = GetHeaderValue(HEADER_TO); - char * ccField = GetHeaderValue(HEADER_CC); - char * bccField = GetHeaderValue(HEADER_BCC); - char * newsgroupField = GetHeaderValue(HEADER_NEWSGROUPS); + char * toField = GetHeaderValue(HEADER_TO, mHeaderArray); + char * ccField = GetHeaderValue(HEADER_CC, mHeaderArray); + char * bccField = GetHeaderValue(HEADER_BCC, mHeaderArray); + char * newsgroupField = GetHeaderValue(HEADER_NEWSGROUPS, mHeaderArray); // only dump these fields if we have at least one of them! When displaying news // messages that didn't have a to or cc field, we'd always get an empty box @@ -723,12 +609,12 @@ nsresult nsMimeXULEmitter::DumpRestOfHeaders() { PRInt32 i; - + if (mHeaderDisplayType != nsMimeHeaderDisplayTypes::AllHeaders) { // For now, lets advertise the fact that 5.0 sent this message. - char *userAgent = nsMimeXULEmitter::GetHeaderValue(HEADER_USER_AGENT); - + char *userAgent = nsMimeXULEmitter::GetHeaderValue(HEADER_USER_AGENT, mHeaderArray); + if (userAgent) { char *compVal = "Mozilla 5.0"; @@ -743,36 +629,34 @@ nsMimeXULEmitter::DumpRestOfHeaders() UtilityWriteCRLF(""); } } - + return NS_OK; } - - UtilityWriteCRLF(""); - - UtilityWriteCRLF(""); - - for (i=0; iCount(); i++) - { - headerInfoType *headerInfo = (headerInfoType *)mHeaderArray->ElementAt(i); - if ( (!headerInfo) || (!headerInfo->name) || (!(*headerInfo->name)) || - (!headerInfo->value) || (!(*headerInfo->value))) - continue; + UtilityWriteCRLF(""); + UtilityWriteCRLF(""); + + for (i=0; iCount(); i++) + { + headerInfoType *headerInfo = (headerInfoType *)mHeaderArray->ElementAt(i); + if ( (!headerInfo) || (!headerInfo->name) || (!(*headerInfo->name)) || + (!headerInfo->value) || (!(*headerInfo->value))) + continue; - if ( (!nsCRT::strcasecmp(HEADER_SUBJECT, headerInfo->name)) || - (!nsCRT::strcasecmp(HEADER_DATE, headerInfo->name)) || - (!nsCRT::strcasecmp(HEADER_FROM, headerInfo->name)) || - (!nsCRT::strcasecmp(HEADER_TO, headerInfo->name)) || - (!nsCRT::strcasecmp(HEADER_CC, headerInfo->name)) ) - continue; - - UtilityWriteCRLF(""); - WriteXULTag(headerInfo->name, headerInfo->value); - UtilityWriteCRLF(""); - } - + if ( (!nsCRT::strcasecmp(HEADER_SUBJECT, headerInfo->name)) || + (!nsCRT::strcasecmp(HEADER_DATE, headerInfo->name)) || + (!nsCRT::strcasecmp(HEADER_FROM, headerInfo->name)) || + (!nsCRT::strcasecmp(HEADER_TO, headerInfo->name)) || + (!nsCRT::strcasecmp(HEADER_CC, headerInfo->name)) ) + continue; + + UtilityWriteCRLF(""); + WriteXULTag(headerInfo->name, headerInfo->value); UtilityWriteCRLF(""); - + } + + UtilityWriteCRLF(""); + UtilityWriteCRLF(""); return NS_OK; } @@ -895,7 +779,6 @@ nsMimeXULEmitter::WriteMiscXULTag(const char *tagName, const char *value) { UtilityWrite(value); } - //// UtilityWriteCRLF(""); @@ -1119,153 +1002,3 @@ nsMimeXULEmitter::ProcessSingleEmailEntry(const char *curHeader, char *curName, return NS_OK; } - -nsresult -nsMimeXULEmitter::BuildListOfStatusProviders() -{ - nsresult rv; - - // enumerate the registry subkeys - nsRegistryKey key; - nsCOMPtr components; - miscStatusType *newInfo = nsnull; - - NS_WITH_SERVICE(nsIRegistry, registry, NS_REGISTRY_PROGID, &rv); - if (NS_FAILED(rv)) - return rv; - - rv = registry->OpenWellKnownRegistry(nsIRegistry::ApplicationComponentRegistry); - if (NS_FAILED(rv)) - return rv; - - rv = registry->GetSubtree(nsIRegistry::Common, NS_IMIME_MISC_STATUS_KEY, &key); - if (NS_FAILED(rv)) - return rv; - - rv = registry->EnumerateSubtrees(key, getter_AddRefs(components)); - if (NS_FAILED(rv)) - return rv; - - // go ahead and enumerate through. - nsCAutoString actualProgID; - rv = components->First(); - while (NS_SUCCEEDED(rv) && (NS_OK != components->IsDone())) - { - nsCOMPtr base; - - rv = components->CurrentItem(getter_AddRefs(base)); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr node; - node = do_QueryInterface(base, &rv); - if (NS_FAILED(rv)) - return rv; - - nsXPIDLCString name; - rv = node->GetName(getter_Copies(name)); - if (NS_FAILED(rv)) - return rv; - - actualProgID = NS_IMIME_MISC_STATUS_KEY; - actualProgID.Append(name); - - // now we've got the PROGID, let's add it to the list... - newInfo = (miscStatusType *)PR_NEWZAP(miscStatusType); - if (newInfo) - { - newInfo->obj = GetStatusObjForProgID(actualProgID); - if (newInfo->obj) - { - newInfo->progID = actualProgID; - mMiscStatusArray->AppendElement(newInfo); - } - } - - rv = components->Next(); - } - - registry->Close(); - - return NS_OK; -} - -nsIMimeMiscStatus * -nsMimeXULEmitter::GetStatusObjForProgID(nsCString aProgID) -{ - nsresult rv = NS_OK; - nsISupports *obj = nsnull; - - NS_WITH_SERVICE(nsIComponentManager, comMgr, kComponentManagerCID, &rv); - if (NS_FAILED(rv)) - return nsnull; - - nsCID cid; - rv = comMgr->ProgIDToCLSID(aProgID, &cid); - if (NS_FAILED(rv)) - return nsnull; - - rv = comMgr->CreateInstance(cid, nsnull, NS_GET_IID(nsIMimeMiscStatus), (void**)&obj); - if (NS_FAILED(rv)) - return nsnull; - else - return (nsIMimeMiscStatus *)obj; -} - -NS_IMETHODIMP -nsMimeXULEmitter::Write(const char *buf, PRUint32 size, PRUint32 *amountWritten) -{ - unsigned int written = 0; - PRUint32 rc = 0; - PRUint32 needToWrite; - - // - // Make sure that the buffer we are "pushing" into has enough room - // for the write operation. If not, we have to buffer, return, and get - // it on the next time through - // - *amountWritten = 0; - - needToWrite = mBufferMgr->GetSize(); - // First, handle any old buffer data... - if (needToWrite > 0) - { - rc += mOutStream->Write(mBufferMgr->GetBuffer(), - needToWrite, &written); - mTotalWritten += written; - mBufferMgr->ReduceBuffer(written); - - *amountWritten = written; - - // if we couldn't write all the old data, buffer the new data - // and return - if (mBufferMgr->GetSize() > 0) - { - mBufferMgr->IncreaseBuffer(buf, size); - return NS_OK; - } - } - - // if we get here, we are dealing with new data...try to write - // and then do the right thing... - // - // Note: if the body has been started, we shouldn't write to the - // output stream, but rather, just append to the body buffer. - // - if (mBodyStarted) - { - mBody.Append(buf, size); - rc = size; - written = size; - } - else - rc = mOutStream->Write(buf, size, &written); - - *amountWritten = written; - mTotalWritten += written; - - if (written < size) - mBufferMgr->IncreaseBuffer(buf+written, (size-written)); - - return rc; -} diff --git a/mailnews/mime/emitters/src/nsMimeXULEmitter.h b/mailnews/mime/emitters/src/nsMimeXULEmitter.h index 8e4f7113b99..c405606094b 100644 --- a/mailnews/mime/emitters/src/nsMimeXULEmitter.h +++ b/mailnews/mime/emitters/src/nsMimeXULEmitter.h @@ -37,19 +37,6 @@ #include "nsIMsgHeaderParser.h" #include "nsCOMPtr.h" -// -// Used for keeping track of the attachment information... -// -typedef struct { - char *displayName; - char *urlSpec; - char *contentType; -} attachmentInfoType; - -typedef struct { - char *name; - char *value; -} headerInfoType; typedef struct { nsString progID; @@ -61,30 +48,22 @@ public: nsMimeXULEmitter (); virtual ~nsMimeXULEmitter (void); - NS_IMETHOD Complete(); - - // Header handling routines. - NS_IMETHOD StartHeader(PRBool rootMailHeader, PRBool headerOnly, const char *msgID, - const char *outCharset); + // Header handling output routines. NS_IMETHOD AddHeaderField(const char *field, const char *value); NS_IMETHOD EndHeader(); - NS_IMETHOD AddHeaderFieldHTML(const char *field, const char *value); - - // Attachment handling routines - NS_IMETHOD StartAttachment(const char *name, const char *contentType, const char *url); - NS_IMETHOD EndAttachment(); // Body handling routines NS_IMETHOD StartBody(PRBool bodyOnly, const char *msgID, const char *outCharset); NS_IMETHOD WriteBody(const char *buf, PRUint32 size, PRUint32 *amountWritten); NS_IMETHOD EndBody(); - // Generic write routine. This is necessary for output that - // libmime needs to pass through without any particular parsing - // involved (i.e. decoded images, HTML Body Text, etc... - NS_IMETHOD Write(const char *buf, PRUint32 size, PRUint32 *amountWritten); + // Complete() the emitter operation. + NS_IMETHOD Complete(); - NS_IMETHOD WriteXULHeader(const char *msgID); + // + // XUL Specific Output methods + // + NS_IMETHOD WriteXULHeader(); NS_IMETHOD WriteXULTag(const char *tagName, const char *value); NS_IMETHOD WriteMiscXULTag(const char *tagName, const char *value); NS_IMETHOD WriteEmailAddrXULTag(const char *tagName, const char *value); @@ -92,7 +71,6 @@ public: nsresult ProcessSingleEmailEntry(const char *curHeader, char *curName, char *curAddress); nsresult WriteXULTagPrefix(const char *tagName, const char *value); nsresult WriteXULTagPostfix(const char *tagName, const char *value); - nsresult OhTheHumanityCleanupTempFileHack(); // For Interesting XUL output! nsresult DumpAttachmentMenu(); @@ -105,29 +83,18 @@ public: // For storing recipient info in the history database... nsresult DoSpecialSenderProcessing(const char *field, const char *value); + + // For per-email address status processing... nsresult DoGlobalStatusProcessing(); nsresult DoWindowStatusProcessing(); nsresult BuildListOfStatusProviders(); nsIMimeMiscStatus *GetStatusObjForProgID(nsCString aProgID); - char *GetHeaderValue(const char *aHeaderName); - protected: PRInt32 mCutoffValue; - // For attachment processing... - PRInt32 mAttachCount; - nsVoidArray *mAttachArray; - attachmentInfoType *mCurrentAttachment; - - // For body caching... - PRBool mBodyStarted; - nsCString mBody; - - // For header caching... - nsVoidArray *mHeaderArray; + // For fancy per-email status! nsVoidArray *mMiscStatusArray; - nsCOMPtr mHeaderParser; }; diff --git a/mailnews/mime/emitters/src/nsMimeXmlEmitter.cpp b/mailnews/mime/emitters/src/nsMimeXmlEmitter.cpp index d3343ff6a37..2af76fdde56 100644 --- a/mailnews/mime/emitters/src/nsMimeXmlEmitter.cpp +++ b/mailnews/mime/emitters/src/nsMimeXmlEmitter.cpp @@ -86,12 +86,6 @@ nsMimeXmlEmitter::WriteXMLHeader(const char *msgID) UtilityWrite(""); UtilityWriteCRLF(""); - if (mHeaderDisplayType == nsMimeHeaderDisplayTypes::MicroHeaders) - UtilityWrite(""); - else if (mHeaderDisplayType == nsMimeHeaderDisplayTypes::NormalHeaders) - UtilityWrite(""); - else /* AllHeaders */ - UtilityWrite(""); UtilityWrite("format_out == nsMimeOutput::nsMimeMessageQuoting) + if ( (opt->format_out == nsMimeOutput::nsMimeMessageQuoting) || + (opt->format_out == nsMimeOutput::nsMimeMessagePrintOutput) ) { mimeEmitterAddAttachmentField(opt, HEADER_CONTENT_DESCRIPTION, tmp->description); mimeEmitterAddAttachmentField(opt, HEADER_CONTENT_TYPE, tmp->real_type); @@ -625,6 +629,14 @@ mime_display_stream_complete (nsMIMESession *stream) int status; PRBool abortNow = PR_FALSE; + // Release the prefs service + if ( (obj->options) && (obj->options->prefs) ) + nsServiceManager::ReleaseService(kPrefCID, obj->options->prefs); + + // Release the conversion object + if ( (obj->options) && (obj->options->conv) ) + NS_RELEASE(obj->options->conv); + if ((obj->options) && (obj->options->headers == MimeHeadersOnly)) abortNow = PR_TRUE; @@ -661,11 +673,7 @@ mime_display_stream_complete (nsMIMESession *stream) msd->options = 0; } } - - // Release the prefs service - if ( (obj) && (obj->options) && (obj->options->prefs) ) - nsServiceManager::ReleaseService(kPrefCID, obj->options->prefs); - + if (msd->headers) MimeHeaders_free (msd->headers); @@ -1047,6 +1055,16 @@ GetPrefServiceManager(MimeDisplayOptions *opt) return opt->prefs; } +// Get the text converter... +mozITXTToHTMLConv * +GetTextConverter(MimeDisplayOptions *opt) +{ + if (!opt) + return nsnull; + + return opt->conv; +} + //////////////////////////////////////////////////////////////// // Bridge routines for new stream converter XP-COM interface //////////////////////////////////////////////////////////////// @@ -1111,6 +1129,17 @@ mime_bridge_create_display_stream( return nsnull; } + // Need the text converter... + rv = nsComponentManager::CreateInstance(kTXTToHTMLConvCID, + NULL, nsCOMTypeInfo::GetIID(), + (void **)&(msd->options->conv)); + if (NS_FAILED(rv)) + { + nsServiceManager::ReleaseService(kPrefCID, msd->options->prefs); + PR_FREEIF(msd); + return nsnull; + } + // // Set the defaults, based on the context, and the output-type. // @@ -1126,7 +1155,8 @@ mime_bridge_create_display_stream( msd->options->fancy_links_p = PR_TRUE; break; - case nsMimeOutput::nsMimeMessageQuoting: // all HTML quoted output + case nsMimeOutput::nsMimeMessageQuoting: // all HTML quoted/printed output + case nsMimeOutput::nsMimeMessagePrintOutput: msd->options->fancy_headers_p = PR_TRUE; msd->options->fancy_links_p = PR_TRUE; break; @@ -1193,7 +1223,8 @@ mime_bridge_create_display_stream( // // For quoting, don't mess with citatation... - if (format_out == nsMimeOutput::nsMimeMessageQuoting || format_out == nsMimeOutput::nsMimeMessageBodyQuoting) + if ( format_out == nsMimeOutput::nsMimeMessageQuoting || format_out == nsMimeOutput::nsMimeMessageBodyQuoting || + format_out == nsMimeOutput::nsMimeMessagePrintOutput ) { msd->options->charset_conversion_fn = mime_insert_html_convert_charset; msd->options->dont_touch_citations_p = PR_TRUE; diff --git a/mailnews/mime/src/mimemoz2.h b/mailnews/mime/src/mimemoz2.h index e658b4e8553..fb95e7c4297 100644 --- a/mailnews/mime/src/mimemoz2.h +++ b/mailnews/mime/src/mimemoz2.h @@ -147,6 +147,9 @@ extern "C" nsresult mimeEmitterStartHeader(MimeDisplayOptions *opt, PRBool r /* To Get the connnection to prefs service manager */ extern "C" nsIPref *GetPrefServiceManager(MimeDisplayOptions *opt); +// Get the text converter... +mozITXTToHTMLConv *GetTextConverter(MimeDisplayOptions *opt); + /* This is the next generation string retrieval call */ extern "C" char *MimeGetStringByID(PRInt32 stringID); diff --git a/mailnews/mime/src/mimetpfl.cpp b/mailnews/mime/src/mimetpfl.cpp index cfdcd62f78a..dacb600f3a3 100644 --- a/mailnews/mime/src/mimetpfl.cpp +++ b/mailnews/mime/src/mimetpfl.cpp @@ -30,9 +30,9 @@ #include "nsMimeStringResources.h" #include "nsIPref.h" #include "nsIServiceManager.h" +#include "mimemoz2.h" static NS_DEFINE_CID(kPrefCID, NS_PREF_CID); -static NS_DEFINE_CID(kTXTToHTMLConvCID, MOZITXTTOHTMLCONV_CID); #define MIME_SUPERCLASS mimeInlineTextClass MimeDefClass(MimeInlineTextPlainFlowed, MimeInlineTextPlainFlowedClass, @@ -275,26 +275,23 @@ MimeInlineTextPlainFlowed_parse_line (char *line, PRInt32 length, MimeObject *ob linep++; } } - - // If we have been told not to mess with this text, then don't do this search! - PRBool skipScanning = (obj->options && obj->options->force_user_charset) || + + mozITXTToHTMLConv *conv = GetTextConverter(obj->options); + + // If we have been told not to mess with this text, then don't do this search..or if the converter + // is null for some reason + PRBool skipScanning = (!conv) || + (obj->options && obj->options->force_user_charset) || (obj->options && (obj->options->format_out == nsMimeOutput::nsMimeMessageQuoting)) || (obj->options && (obj->options->format_out == nsMimeOutput::nsMimeMessageBodyQuoting)); if (!skipScanning) { - nsCOMPtr conv; - nsresult rv = nsComponentManager::CreateInstance(kTXTToHTMLConvCID, - NULL, nsCOMTypeInfo::GetIID(), - (void **) getter_AddRefs(conv)); - if (NS_FAILED(rv)) - return -1; - //XXX I18N Converting char* to PRUnichar* nsString strline(linep, (length - (linep - line)) ); PRUnichar* wresult; - rv = conv->ScanTXT(strline.GetUnicode(), + nsresult rv = conv->ScanTXT(strline.GetUnicode(), obj->options->dont_touch_citations_p /*XXX This is pref abuse. ScanTXT does nothing with citations. Add prefs.*/ ? conv->kURLs : ~PRUint32(0), diff --git a/mailnews/mime/src/mimetpla.cpp b/mailnews/mime/src/mimetpla.cpp index ad68a21ce35..f3a92caa2e2 100644 --- a/mailnews/mime/src/mimetpla.cpp +++ b/mailnews/mime/src/mimetpla.cpp @@ -30,6 +30,7 @@ #include "nsIComponentManager.h" #include "nsString.h" #include "nsMimeStringResources.h" +#include "mimemoz2.h" static NS_DEFINE_CID(kTXTToHTMLConvCID, MOZITXTTOHTMLCONV_CID); @@ -150,24 +151,20 @@ MimeInlineTextPlain_parse_line (char *line, PRInt32 length, MimeObject *obj) */ *obj->obuffer = 0; + mozITXTToHTMLConv *conv = GetTextConverter(obj->options); + // If we have been told not to mess with this text, then don't do this search! - PRBool skipScanning = (obj->options && obj->options->force_user_charset) || + PRBool skipScanning = (!conv) || + (obj->options && obj->options->force_user_charset) || (obj->options && (obj->options->format_out == nsMimeOutput::nsMimeMessageQuoting)) || (obj->options && (obj->options->format_out == nsMimeOutput::nsMimeMessageBodyQuoting)); if (!skipScanning) { - nsCOMPtr conv; - nsresult rv = nsComponentManager::CreateInstance(kTXTToHTMLConvCID, - NULL, nsCOMTypeInfo::GetIID(), - (void **) getter_AddRefs(conv)); - if (NS_FAILED(rv)) - return -1; - nsString strline(line, length); PRUnichar* wresult; - rv = conv->ScanTXT(strline.GetUnicode(), + nsresult rv = conv->ScanTXT(strline.GetUnicode(), obj->options->dont_touch_citations_p /*XXX This is pref abuse. ScanTXT does nothing with citations. Add prefs.*/ ? conv->kURLs : ~PRUint32(0), diff --git a/mailnews/mime/src/modlmime.h b/mailnews/mime/src/modlmime.h index 650dd24c900..069cdbb88ed 100644 --- a/mailnews/mime/src/modlmime.h +++ b/mailnews/mime/src/modlmime.h @@ -31,6 +31,7 @@ #include "nsMailHeaders.h" #include "nsIMimeStreamConverter.h" #include "nsIPref.h" +#include "mozITXTToHTMLConv.h" #define MIME_DRAFTS @@ -140,6 +141,7 @@ typedef char *(*MimeHTMLGeneratorFunction) (const char *data, void *closure, struct MimeDisplayOptions { + mozITXTToHTMLConv *conv; // For text conversion... nsIPref *prefs; /* Connnection to prefs service manager */ nsMimeOutputType format_out; // The format out type diff --git a/mailnews/mime/src/nsStreamConverter.cpp b/mailnews/mime/src/nsStreamConverter.cpp index 9666bc85417..18f61ed255b 100644 --- a/mailnews/mime/src/nsStreamConverter.cpp +++ b/mailnews/mime/src/nsStreamConverter.cpp @@ -245,6 +245,7 @@ nsStreamConverter::DetermineOutputFormat(const char *url, nsMimeOutputType *aNe char *ptr3 = PL_strcasestr ("quote", (header+lenOfHeader)); char *ptr4 = PL_strcasestr ("quotebody", (header+lenOfHeader)); char *ptr5 = PL_strcasestr ("none", (header+lenOfHeader)); + char *ptr6 = PL_strcasestr ("print", (header+lenOfHeader)); if (ptr5) { PR_FREEIF(mOutputFormat); @@ -269,6 +270,12 @@ nsStreamConverter::DetermineOutputFormat(const char *url, nsMimeOutputType *aNe mOutputFormat = nsCRT::strdup("text/html"); *aNewType = nsMimeOutput::nsMimeMessageBodyQuoting; } + else if (ptr6) + { + PR_FREEIF(mOutputFormat); + mOutputFormat = nsCRT::strdup("text/html"); + *aNewType = nsMimeOutput::nsMimeMessagePrintOutput; + } } else { @@ -397,6 +404,7 @@ NS_IMETHODIMP nsStreamConverter::Init(nsIURI *aURI, nsIStreamListener * aOutList case nsMimeOutput::nsMimeMessageQuoting: // all HTML quoted output case nsMimeOutput::nsMimeMessageBodyQuoting: // only HTML body quoted output + case nsMimeOutput::nsMimeMessagePrintOutput: // all Printing output PR_FREEIF(mOutputFormat); mOutputFormat = nsCRT::strdup("text/html"); break; diff --git a/mailnews/mime/tests/mimetest/mimetest.cpp b/mailnews/mime/tests/mimetest/mimetest.cpp index 259863b27a1..28ca3e65035 100644 --- a/mailnews/mime/tests/mimetest/mimetest.cpp +++ b/mailnews/mime/tests/mimetest/mimetest.cpp @@ -192,6 +192,7 @@ public: { if ((mOutFormat == nsMimeOutput::nsMimeMessageSplitDisplay) || (mOutFormat == nsMimeOutput::nsMimeMessageBodyDisplay) || + (mOutFormat == nsMimeOutput::nsMimeMessagePrintOutput) || (mOutFormat == nsMimeOutput::nsMimeMessageQuoting)) { char *note = "\n


Anything after the above horizontal line is diagnostic output
and is not part of the HTML stream!
\n";
@@ -498,7 +499,7 @@ DoRFC822toHTMLConversion(char *filename, int numArgs)
   if (numArgs >= 3)
     outFormat = nsMimeOutput::nsMimeMessageXULDisplay;
   else
-    outFormat = nsMimeOutput::nsMimeMessageQuoting;
+    outFormat = nsMimeOutput::nsMimeMessagePrintOutput;
 
   char *opts = PL_strchr(filename, '?');
   char save;
@@ -621,7 +622,7 @@ DoFormattingOnly(char *filename)
   nsMimeOutputType  outFormat;
   char              *contentType = nsnull;
 
-  outFormat = nsMimeOutput::nsMimeMessageQuoting;
+  outFormat = nsMimeOutput::nsMimeMessagePrintOutput;
 
   char *opts = PL_strchr(filename, '?');
   char save;