From eea6214816bb00a96f77afec704e2668e78dc9ba Mon Sep 17 00:00:00 2001 From: "sfraser%netscape.com" Date: Fri, 7 May 1999 04:59:23 +0000 Subject: [PATCH] Implement nsIDiskDocument interface for editable documents. git-svn-id: svn://10.0.0.236/trunk@30664 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/src/nsDocument.cpp | 208 +++++++++++++++++++++++- mozilla/content/base/src/nsDocument.h | 45 +++++ mozilla/layout/base/src/nsDocument.cpp | 208 +++++++++++++++++++++++- mozilla/layout/base/src/nsDocument.h | 45 +++++ 4 files changed, 496 insertions(+), 10 deletions(-) diff --git a/mozilla/content/base/src/nsDocument.cpp b/mozilla/content/base/src/nsDocument.cpp index d93e0235980..6e91ce8f567 100644 --- a/mozilla/content/base/src/nsDocument.cpp +++ b/mozilla/content/base/src/nsDocument.cpp @@ -55,7 +55,14 @@ #include "nsITextContent.h" #include "nsXIFConverter.h" - +#include "nsIHTMLContentSink.h" +#include "nsHTMLContentSinkStream.h" +#include "nsHTMLToTXTSinkStream.h" +#include "nsXIFDTD.h" +#include "nsIParser.h" +#include "nsParserCIID.h" +#include "nsFileSpec.h" +#include "nsFileStream.h" #include "nsIDOMText.h" #include "nsIDOMComment.h" @@ -631,7 +638,8 @@ nsDocument::nsDocument() mEpilog = nsnull; mChildNodes = nsnull; mWordBreaker = nsnull; - + mModCount = 0; + mFileSpec = nsnull; Init();/* XXX */ } @@ -709,6 +717,15 @@ nsDocument::~nsDocument() } NS_IF_RELEASE(mLineBreaker); NS_IF_RELEASE(mWordBreaker); + +#ifdef DEBUG + if (mModCount > 0) + { + NS_WARNING("Disposing an unsaved modified document"); + } +#endif + delete mFileSpec; + } nsresult nsDocument::QueryInterface(REFNSIID aIID, void** aInstancePtr) @@ -770,6 +787,12 @@ nsresult nsDocument::QueryInterface(REFNSIID aIID, void** aInstancePtr) NS_ADDREF_THIS(); return NS_OK; } + if (aIID.Equals(nsIDiskDocument::GetIID())) { + nsIDiskDocument* tmp = this; + *aInstancePtr = (void*) tmp; + NS_ADDREF_THIS(); + return NS_OK; + } static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); if (aIID.Equals(kISupportsIID)) { nsIDocument* tmp = this; @@ -2634,9 +2657,6 @@ void nsDocument::CreateXIF(nsString & aBuffer, nsIDOMSelection* aSelection) converter.AddEndTag("section_head"); converter.AddStartTag("section_body"); - - - nsIDOMElement* root = nsnull; if (NS_OK == GetDocumentElement(&root)) { @@ -2651,6 +2671,184 @@ void nsDocument::CreateXIF(nsString & aBuffer, nsIDOMSelection* aSelection) } +static NS_DEFINE_IID(kCParserIID, NS_IPARSER_IID); +static NS_DEFINE_IID(kCParserCID, NS_PARSER_IID); + + +nsresult +nsDocument::OutputDocumentAs(nsIOutputStream* aStream, nsIDOMSelection* selection, EOutputFormat aOutputFormat, const nsString& aCharset) +{ + nsresult rv = NS_OK; + + nsAutoString charsetStr = aCharset; + if (charsetStr.Length() == 0) + { + rv = GetDocumentCharacterSet(charsetStr); + if(NS_FAILED(rv)) { + charsetStr = "ISO-8859-1"; + } + } + + nsCOMPtr parser; + rv = nsComponentManager::CreateInstance(kCParserCID, + nsnull, + kCParserIID, + getter_AddRefs(parser)); + if (NS_SUCCEEDED(rv)) + { + nsString buffer; + CreateXIF(buffer, selection); // if selection is null, ignores the selection + + nsCOMPtr sink; + + switch (aOutputFormat) + { + case eOutputText: + rv = NS_New_HTMLToTXT_SinkStream(getter_AddRefs(sink), aStream, &charsetStr); + break; + case eOutputHTML: + rv = NS_New_HTML_ContentSinkStream(getter_AddRefs(sink), aStream, &charsetStr); + break; + default: + rv = NS_ERROR_INVALID_ARG; + } + + if (NS_SUCCEEDED(rv) && sink) + { + parser->SetContentSink(sink); + parser->SetDocumentCharset(charsetStr, kCharsetFromPreviousLoading); + nsCOMPtr dtd; + rv = NS_NewXIFDTD(getter_AddRefs(dtd)); + if (NS_SUCCEEDED(rv) && dtd) + { + parser->RegisterDTD(dtd); + parser->Parse(buffer, 0, "text/xif", PR_FALSE, PR_TRUE); + } + } + } + + return rv; +} + +nsresult +nsDocument::OutputDocumentAsHTML(nsIOutputStream* aStream, nsIDOMSelection* selection, const nsString& aCharset) +{ + return OutputDocumentAs(aStream, selection, eOutputHTML, aCharset); +} + +nsresult +nsDocument::OutputDocumentAsText(nsIOutputStream* aStream, nsIDOMSelection* selection, const nsString& aCharset) +{ + return OutputDocumentAs(aStream, selection, eOutputText, aCharset); +} + + +NS_IMETHODIMP +nsDocument::InitDiskDocument(nsFileSpec* aFileSpec) +{ + mFileSpec = nsnull; + + if (aFileSpec) + { + mFileSpec = new nsFileSpec(*aFileSpec); + if (!mFileSpec) + return NS_ERROR_OUT_OF_MEMORY; + } + + mModCount = 0; + return NS_OK; +} + + + +NS_IMETHODIMP +nsDocument::SaveFile( nsFileSpec* aFileSpec, + PRBool aReplaceExisting, + PRBool aSaveCopy, + ESaveFileType aSaveFileType, + const nsString& aSaveCharset) +{ + + if (!aFileSpec) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_OK; + + // if we're not replacing an existing file but the file + // exists, somethine is wrong + if (!aReplaceExisting && aFileSpec->Exists()) + return NS_ERROR_FAILURE; // where are the file I/O errors? + + nsOutputFileStream stream(*aFileSpec); + // if the stream didn't open, something went wrong + if (!stream.is_open()) + return NS_BASE_STREAM_CLOSED; + + // convert to our internal enum. Shame we have to do this. + EOutputFormat outputFormat = eOutputHTML; + switch (aSaveFileType) + { + case eSaveFileText: outputFormat = eOutputText; break; + case eSaveFileHTML: outputFormat = eOutputHTML; break; + } + + rv = OutputDocumentAs(stream.GetIStream(), nsnull, outputFormat, aSaveCharset); + if (NS_SUCCEEDED(rv)) + { + // if everything went OK and we're not just saving off a copy, + // store the new fileSpec in the doc + if (!aSaveCopy) + { + delete mFileSpec; + mFileSpec = new nsFileSpec(*aFileSpec); + if (!mFileSpec) + return NS_ERROR_OUT_OF_MEMORY; + + // and mark the document as clean + ResetModCount(); + } + } + + return rv; +} + +NS_IMETHODIMP +nsDocument::GetFileSpec(nsFileSpec& aFileSpec) +{ + if (mFileSpec) + { + aFileSpec = *mFileSpec; + return NS_OK; + } + + return NS_ERROR_NOT_INITIALIZED; +} + + +NS_IMETHODIMP +nsDocument::GetModCount(PRInt32 *outModCount) +{ + if (!outModCount) + return NS_ERROR_NULL_POINTER; + + *outModCount = mModCount; + return NS_OK; +} + + +NS_IMETHODIMP +nsDocument::ResetModCount() +{ + mModCount = 0; + return NS_OK; +} + +NS_IMETHODIMP +nsDocument::IncrementModCount() +{ + mModCount++; + return NS_OK; +} nsIContent* nsDocument::FindContent(const nsIContent* aStartNode, const nsIContent* aTest1, diff --git a/mozilla/content/base/src/nsDocument.h b/mozilla/content/base/src/nsDocument.h index e442e604edc..d388a348fa9 100644 --- a/mozilla/content/base/src/nsDocument.h +++ b/mozilla/content/base/src/nsDocument.h @@ -22,6 +22,7 @@ #include "nsVoidArray.h" #include "nsIDOMDocument.h" #include "nsIDOMNSDocument.h" +#include "nsIDiskDocument.h" #include "nsIScriptObjectOwner.h" #include "nsIScriptContextOwner.h" #include "nsIDOMEventCapturer.h" @@ -34,6 +35,7 @@ class nsIEventListenerManager; class nsDOMStyleSheetCollection; class nsIDOMSelection; +class nsIOutputStream; class nsDocument; class nsPostData : public nsIPostData { @@ -99,6 +101,7 @@ protected: class nsDocument : public nsIDocument, public nsIDOMDocument, public nsIDOMNSDocument, + public nsIDiskDocument, public nsIScriptObjectOwner, public nsIDOMEventCapturer, public nsIJSScriptObject @@ -351,6 +354,19 @@ public: NS_IMETHOD GetListenerManager(nsIEventListenerManager** aInstancePtrResult); NS_IMETHOD GetNewListenerManager(nsIEventListenerManager **aInstancePtrResult); + // nsIDiskDocument inteface + NS_IMETHOD InitDiskDocument(nsFileSpec *aFileSpec); + NS_IMETHOD SaveFile( nsFileSpec* aFileSpec, + PRBool aReplaceExisting, + PRBool aSaveCopy, + ESaveFileType aSaveFileType, + const nsString& aSaveCharset); + + NS_IMETHOD GetFileSpec(nsFileSpec& aFileSpec); + NS_IMETHOD GetModCount(PRInt32 *outModCount); + NS_IMETHOD ResetModCount(); + NS_IMETHOD IncrementModCount(); + // nsIDOMEventTarget interface NS_IMETHOD AddEventListener(const nsString& aType, nsIDOMEventListener* aListener, PRBool aPostProcess, PRBool aUseCapture); @@ -383,12 +399,36 @@ public: virtual PRBool Convert(JSContext *aContext, jsval aID); virtual void Finalize(JSContext *aContext); + /** + * Methods to output the document contents as Text or HTML, outputting into + * the given output stream. If charset is not an empty string, the contents + * will be converted into the given charset. + * + * If the selection is passed in is not null, only the selected content + * will be output. Note that the selection is stored on a per-presentation + * shell basis, not per document, hence it is a parameter here. + * These should be exposed in an interface, but aren't yet. + */ + + virtual nsresult OutputDocumentAsText(nsIOutputStream* aStream, nsIDOMSelection* selection, const nsString& aCharset); + virtual nsresult OutputDocumentAsHTML(nsIOutputStream* aStream, nsIDOMSelection* selection, const nsString& aCharset); + protected: nsIContent* FindContent(const nsIContent* aStartNode, const nsIContent* aTest1, const nsIContent* aTest2) const; virtual nsresult Reset(nsIURL* aURL); + // this enum is temporary; there should be no knowledge of HTML in + // nsDocument. That will be fixed when content sink stream factories + // are available. + enum EOutputFormat { + eOutputText, + eOutputHTML + }; + + virtual nsresult OutputDocumentAs(nsIOutputStream* aStream, nsIDOMSelection* selection, EOutputFormat aOutputFormat, const nsString& aCharset); + protected: virtual void InternalAddStyleSheet(nsIStyleSheet* aSheet); // subclass hook for sheet ordering @@ -421,6 +461,11 @@ protected: nsVoidArray *mEpilog; nsDocumentChildNodes* mChildNodes; nsIWordBreaker* mWordBreaker; + + // disk file members + nsFileSpec* mFileSpec; + PRInt32 mModCount; + }; #endif /* nsDocument_h___ */ diff --git a/mozilla/layout/base/src/nsDocument.cpp b/mozilla/layout/base/src/nsDocument.cpp index d93e0235980..6e91ce8f567 100644 --- a/mozilla/layout/base/src/nsDocument.cpp +++ b/mozilla/layout/base/src/nsDocument.cpp @@ -55,7 +55,14 @@ #include "nsITextContent.h" #include "nsXIFConverter.h" - +#include "nsIHTMLContentSink.h" +#include "nsHTMLContentSinkStream.h" +#include "nsHTMLToTXTSinkStream.h" +#include "nsXIFDTD.h" +#include "nsIParser.h" +#include "nsParserCIID.h" +#include "nsFileSpec.h" +#include "nsFileStream.h" #include "nsIDOMText.h" #include "nsIDOMComment.h" @@ -631,7 +638,8 @@ nsDocument::nsDocument() mEpilog = nsnull; mChildNodes = nsnull; mWordBreaker = nsnull; - + mModCount = 0; + mFileSpec = nsnull; Init();/* XXX */ } @@ -709,6 +717,15 @@ nsDocument::~nsDocument() } NS_IF_RELEASE(mLineBreaker); NS_IF_RELEASE(mWordBreaker); + +#ifdef DEBUG + if (mModCount > 0) + { + NS_WARNING("Disposing an unsaved modified document"); + } +#endif + delete mFileSpec; + } nsresult nsDocument::QueryInterface(REFNSIID aIID, void** aInstancePtr) @@ -770,6 +787,12 @@ nsresult nsDocument::QueryInterface(REFNSIID aIID, void** aInstancePtr) NS_ADDREF_THIS(); return NS_OK; } + if (aIID.Equals(nsIDiskDocument::GetIID())) { + nsIDiskDocument* tmp = this; + *aInstancePtr = (void*) tmp; + NS_ADDREF_THIS(); + return NS_OK; + } static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); if (aIID.Equals(kISupportsIID)) { nsIDocument* tmp = this; @@ -2634,9 +2657,6 @@ void nsDocument::CreateXIF(nsString & aBuffer, nsIDOMSelection* aSelection) converter.AddEndTag("section_head"); converter.AddStartTag("section_body"); - - - nsIDOMElement* root = nsnull; if (NS_OK == GetDocumentElement(&root)) { @@ -2651,6 +2671,184 @@ void nsDocument::CreateXIF(nsString & aBuffer, nsIDOMSelection* aSelection) } +static NS_DEFINE_IID(kCParserIID, NS_IPARSER_IID); +static NS_DEFINE_IID(kCParserCID, NS_PARSER_IID); + + +nsresult +nsDocument::OutputDocumentAs(nsIOutputStream* aStream, nsIDOMSelection* selection, EOutputFormat aOutputFormat, const nsString& aCharset) +{ + nsresult rv = NS_OK; + + nsAutoString charsetStr = aCharset; + if (charsetStr.Length() == 0) + { + rv = GetDocumentCharacterSet(charsetStr); + if(NS_FAILED(rv)) { + charsetStr = "ISO-8859-1"; + } + } + + nsCOMPtr parser; + rv = nsComponentManager::CreateInstance(kCParserCID, + nsnull, + kCParserIID, + getter_AddRefs(parser)); + if (NS_SUCCEEDED(rv)) + { + nsString buffer; + CreateXIF(buffer, selection); // if selection is null, ignores the selection + + nsCOMPtr sink; + + switch (aOutputFormat) + { + case eOutputText: + rv = NS_New_HTMLToTXT_SinkStream(getter_AddRefs(sink), aStream, &charsetStr); + break; + case eOutputHTML: + rv = NS_New_HTML_ContentSinkStream(getter_AddRefs(sink), aStream, &charsetStr); + break; + default: + rv = NS_ERROR_INVALID_ARG; + } + + if (NS_SUCCEEDED(rv) && sink) + { + parser->SetContentSink(sink); + parser->SetDocumentCharset(charsetStr, kCharsetFromPreviousLoading); + nsCOMPtr dtd; + rv = NS_NewXIFDTD(getter_AddRefs(dtd)); + if (NS_SUCCEEDED(rv) && dtd) + { + parser->RegisterDTD(dtd); + parser->Parse(buffer, 0, "text/xif", PR_FALSE, PR_TRUE); + } + } + } + + return rv; +} + +nsresult +nsDocument::OutputDocumentAsHTML(nsIOutputStream* aStream, nsIDOMSelection* selection, const nsString& aCharset) +{ + return OutputDocumentAs(aStream, selection, eOutputHTML, aCharset); +} + +nsresult +nsDocument::OutputDocumentAsText(nsIOutputStream* aStream, nsIDOMSelection* selection, const nsString& aCharset) +{ + return OutputDocumentAs(aStream, selection, eOutputText, aCharset); +} + + +NS_IMETHODIMP +nsDocument::InitDiskDocument(nsFileSpec* aFileSpec) +{ + mFileSpec = nsnull; + + if (aFileSpec) + { + mFileSpec = new nsFileSpec(*aFileSpec); + if (!mFileSpec) + return NS_ERROR_OUT_OF_MEMORY; + } + + mModCount = 0; + return NS_OK; +} + + + +NS_IMETHODIMP +nsDocument::SaveFile( nsFileSpec* aFileSpec, + PRBool aReplaceExisting, + PRBool aSaveCopy, + ESaveFileType aSaveFileType, + const nsString& aSaveCharset) +{ + + if (!aFileSpec) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_OK; + + // if we're not replacing an existing file but the file + // exists, somethine is wrong + if (!aReplaceExisting && aFileSpec->Exists()) + return NS_ERROR_FAILURE; // where are the file I/O errors? + + nsOutputFileStream stream(*aFileSpec); + // if the stream didn't open, something went wrong + if (!stream.is_open()) + return NS_BASE_STREAM_CLOSED; + + // convert to our internal enum. Shame we have to do this. + EOutputFormat outputFormat = eOutputHTML; + switch (aSaveFileType) + { + case eSaveFileText: outputFormat = eOutputText; break; + case eSaveFileHTML: outputFormat = eOutputHTML; break; + } + + rv = OutputDocumentAs(stream.GetIStream(), nsnull, outputFormat, aSaveCharset); + if (NS_SUCCEEDED(rv)) + { + // if everything went OK and we're not just saving off a copy, + // store the new fileSpec in the doc + if (!aSaveCopy) + { + delete mFileSpec; + mFileSpec = new nsFileSpec(*aFileSpec); + if (!mFileSpec) + return NS_ERROR_OUT_OF_MEMORY; + + // and mark the document as clean + ResetModCount(); + } + } + + return rv; +} + +NS_IMETHODIMP +nsDocument::GetFileSpec(nsFileSpec& aFileSpec) +{ + if (mFileSpec) + { + aFileSpec = *mFileSpec; + return NS_OK; + } + + return NS_ERROR_NOT_INITIALIZED; +} + + +NS_IMETHODIMP +nsDocument::GetModCount(PRInt32 *outModCount) +{ + if (!outModCount) + return NS_ERROR_NULL_POINTER; + + *outModCount = mModCount; + return NS_OK; +} + + +NS_IMETHODIMP +nsDocument::ResetModCount() +{ + mModCount = 0; + return NS_OK; +} + +NS_IMETHODIMP +nsDocument::IncrementModCount() +{ + mModCount++; + return NS_OK; +} nsIContent* nsDocument::FindContent(const nsIContent* aStartNode, const nsIContent* aTest1, diff --git a/mozilla/layout/base/src/nsDocument.h b/mozilla/layout/base/src/nsDocument.h index e442e604edc..d388a348fa9 100644 --- a/mozilla/layout/base/src/nsDocument.h +++ b/mozilla/layout/base/src/nsDocument.h @@ -22,6 +22,7 @@ #include "nsVoidArray.h" #include "nsIDOMDocument.h" #include "nsIDOMNSDocument.h" +#include "nsIDiskDocument.h" #include "nsIScriptObjectOwner.h" #include "nsIScriptContextOwner.h" #include "nsIDOMEventCapturer.h" @@ -34,6 +35,7 @@ class nsIEventListenerManager; class nsDOMStyleSheetCollection; class nsIDOMSelection; +class nsIOutputStream; class nsDocument; class nsPostData : public nsIPostData { @@ -99,6 +101,7 @@ protected: class nsDocument : public nsIDocument, public nsIDOMDocument, public nsIDOMNSDocument, + public nsIDiskDocument, public nsIScriptObjectOwner, public nsIDOMEventCapturer, public nsIJSScriptObject @@ -351,6 +354,19 @@ public: NS_IMETHOD GetListenerManager(nsIEventListenerManager** aInstancePtrResult); NS_IMETHOD GetNewListenerManager(nsIEventListenerManager **aInstancePtrResult); + // nsIDiskDocument inteface + NS_IMETHOD InitDiskDocument(nsFileSpec *aFileSpec); + NS_IMETHOD SaveFile( nsFileSpec* aFileSpec, + PRBool aReplaceExisting, + PRBool aSaveCopy, + ESaveFileType aSaveFileType, + const nsString& aSaveCharset); + + NS_IMETHOD GetFileSpec(nsFileSpec& aFileSpec); + NS_IMETHOD GetModCount(PRInt32 *outModCount); + NS_IMETHOD ResetModCount(); + NS_IMETHOD IncrementModCount(); + // nsIDOMEventTarget interface NS_IMETHOD AddEventListener(const nsString& aType, nsIDOMEventListener* aListener, PRBool aPostProcess, PRBool aUseCapture); @@ -383,12 +399,36 @@ public: virtual PRBool Convert(JSContext *aContext, jsval aID); virtual void Finalize(JSContext *aContext); + /** + * Methods to output the document contents as Text or HTML, outputting into + * the given output stream. If charset is not an empty string, the contents + * will be converted into the given charset. + * + * If the selection is passed in is not null, only the selected content + * will be output. Note that the selection is stored on a per-presentation + * shell basis, not per document, hence it is a parameter here. + * These should be exposed in an interface, but aren't yet. + */ + + virtual nsresult OutputDocumentAsText(nsIOutputStream* aStream, nsIDOMSelection* selection, const nsString& aCharset); + virtual nsresult OutputDocumentAsHTML(nsIOutputStream* aStream, nsIDOMSelection* selection, const nsString& aCharset); + protected: nsIContent* FindContent(const nsIContent* aStartNode, const nsIContent* aTest1, const nsIContent* aTest2) const; virtual nsresult Reset(nsIURL* aURL); + // this enum is temporary; there should be no knowledge of HTML in + // nsDocument. That will be fixed when content sink stream factories + // are available. + enum EOutputFormat { + eOutputText, + eOutputHTML + }; + + virtual nsresult OutputDocumentAs(nsIOutputStream* aStream, nsIDOMSelection* selection, EOutputFormat aOutputFormat, const nsString& aCharset); + protected: virtual void InternalAddStyleSheet(nsIStyleSheet* aSheet); // subclass hook for sheet ordering @@ -421,6 +461,11 @@ protected: nsVoidArray *mEpilog; nsDocumentChildNodes* mChildNodes; nsIWordBreaker* mWordBreaker; + + // disk file members + nsFileSpec* mFileSpec; + PRInt32 mModCount; + }; #endif /* nsDocument_h___ */