Files
Mozilla/mozilla/layout/base/src/nsDocument.cpp
kipp 324c12a6d4 Cleaned up the API
git-svn-id: svn://10.0.0.236/trunk@648 18797224-902f-48f8-a5cc-f745e15eee43
1998-04-25 18:32:59 +00:00

631 lines
15 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsDocument.h"
#include "nsIArena.h"
#include "nsIURL.h"
#include "nsString.h"
#include "nsIContent.h"
#include "nsIStyleSet.h"
#include "nsIStyleSheet.h"
#include "nsIPresShell.h"
#include "nsIDocumentObserver.h"
static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
#include "nsIDOMElement.h"
static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID);
static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID);
static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID);
static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID);
static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID);
nsDocument::nsDocument()
{
NS_INIT_REFCNT();
mArena = nsnull;
mDocumentTitle = nsnull;
mDocumentURL = nsnull;
mCharacterSet = eCharSetID_IsoLatin1;
mParentDocument = nsnull;
mRootContent = nsnull;
mScriptObject = nsnull;
Init();/* XXX */
}
nsDocument::~nsDocument()
{
if (nsnull != mDocumentTitle) {
delete mDocumentTitle;
mDocumentTitle = nsnull;
}
NS_IF_RELEASE(mDocumentURL);
mParentDocument = nsnull;
// Delete references to sub-documents
PRInt32 index = mSubDocuments.Count();
while (--index >= 0) {
nsIDocument* subdoc = (nsIDocument*) mSubDocuments.ElementAt(index);
NS_RELEASE(subdoc);
}
NS_IF_RELEASE(mRootContent);
// Delete references to style sheets
index = mStyleSheets.Count();
while (--index >= 0) {
nsIStyleSheet* sheet = (nsIStyleSheet*) mStyleSheets.ElementAt(index);
NS_RELEASE(sheet);
}
NS_IF_RELEASE(mArena);
}
nsresult nsDocument::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kIDocumentIID)) {
*aInstancePtr = (void*)(nsIDocument*)this;
AddRef();
return NS_OK;
}
if (aIID.Equals(kIDOMDocumentIID)) {
*aInstancePtr = (void*)(nsIDOMDocument*)this;
AddRef();
return NS_OK;
}
if (aIID.Equals(kIScriptObjectOwnerIID)) {
*aInstancePtr = (void*)(nsIScriptObjectOwner*)this;
AddRef();
return NS_OK;
}
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*)(nsISupports*)(nsIDocument*)this;
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMPL_ADDREF(nsDocument)
NS_IMPL_RELEASE(nsDocument)
nsresult nsDocument::Init()
{
nsresult rv = NS_NewHeapArena(&mArena, nsnull);
if (NS_OK != rv) {
return rv;
}
return NS_OK;
}
nsIArena* nsDocument::GetArena()
{
if (nsnull != mArena) {
NS_ADDREF(mArena);
}
return mArena;
}
void nsDocument::StartDocumentLoad()
{
}
void nsDocument::PauseDocumentLoad()
{
}
void nsDocument::StopDocumentLoad()
{
}
void nsDocument::WaitForDocumentLoad()
{
}
PRBool nsDocument::IsDocumentLoaded()
{
return PR_TRUE;
}
const nsString* nsDocument::GetDocumentTitle() const
{
return mDocumentTitle;
}
nsIURL* nsDocument::GetDocumentURL() const
{
NS_IF_ADDREF(mDocumentURL);
return mDocumentURL;
}
nsCharSetID nsDocument::GetDocumentCharacterSet() const
{
return mCharacterSet;
}
void nsDocument::SetDocumentCharacterSet(nsCharSetID aCharSetID)
{
mCharacterSet = aCharSetID;
}
nsresult nsDocument::CreateShell(nsIPresContext* aContext,
nsIViewManager* aViewManager,
nsIStyleSet* aStyleSet,
nsIPresShell** aInstancePtrResult)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
nsIPresShell* shell;
nsresult rv = NS_NewPresShell(&shell);
if (NS_OK != rv) {
return rv;
}
if (NS_OK != shell->Init(this, aContext, aViewManager, aStyleSet)) {
NS_RELEASE(shell);
return rv;
}
// Note: we don't hold a ref to the shell (it holds a ref to us)
mPresShells.AppendElement(shell);
*aInstancePtrResult = shell;
return NS_OK;
}
PRBool nsDocument::DeleteShell(nsIPresShell* aShell)
{
return mPresShells.RemoveElement(aShell);
}
PRInt32 nsDocument::GetNumberOfShells()
{
return mPresShells.Count();
}
nsIPresShell* nsDocument::GetShellAt(PRInt32 aIndex)
{
nsIPresShell* shell = (nsIPresShell*) mPresShells.ElementAt(aIndex);
if (nsnull != shell) {
NS_ADDREF(shell);
}
return shell;
}
nsIDocument* nsDocument::GetParentDocument()
{
if (nsnull != mParentDocument) {
NS_ADDREF(mParentDocument);
}
return mParentDocument;
}
/**
* Note that we do *not* AddRef our parent because that would
* create a circular reference.
*/
void nsDocument::SetParentDocument(nsIDocument* aParent)
{
mParentDocument = aParent;
}
void nsDocument::AddSubDocument(nsIDocument* aSubDoc)
{
NS_ADDREF(aSubDoc);
mSubDocuments.AppendElement(aSubDoc);
}
PRInt32 nsDocument::GetNumberOfSubDocuments()
{
return mSubDocuments.Count();
}
nsIDocument* nsDocument::GetSubDocumentAt(PRInt32 aIndex)
{
nsIDocument* doc = (nsIDocument*) mSubDocuments.ElementAt(aIndex);
if (nsnull != doc) {
NS_ADDREF(doc);
}
return doc;
}
nsIContent* nsDocument::GetRootContent()
{
if (nsnull != mRootContent) {
NS_ADDREF(mRootContent);
}
return mRootContent;
}
void nsDocument::SetRootContent(nsIContent* aRoot)
{
NS_IF_RELEASE(mRootContent);
if (nsnull != aRoot) {
mRootContent = aRoot;
NS_ADDREF(aRoot);
}
}
PRInt32 nsDocument::GetNumberOfStyleSheets()
{
return mStyleSheets.Count();
}
nsIStyleSheet* nsDocument::GetStyleSheetAt(PRInt32 aIndex)
{
nsIStyleSheet* sheet = (nsIStyleSheet*)mStyleSheets.ElementAt(aIndex);
NS_IF_ADDREF(sheet);
return sheet;
}
void nsDocument::AddStyleSheetToSet(nsIStyleSheet* aSheet, nsIStyleSet* aSet)
{
aSet->AppendDocStyleSheet(aSheet);
}
void nsDocument::AddStyleSheet(nsIStyleSheet* aSheet)
{
NS_PRECONDITION(nsnull != aSheet, "null arg");
mStyleSheets.AppendElement(aSheet);
NS_ADDREF(aSheet);
PRInt32 count = mPresShells.Count();
PRInt32 index;
for (index = 0; index < count; index++) {
nsIPresShell* shell = (nsIPresShell*)mPresShells.ElementAt(index);
nsIStyleSet* set = shell->GetStyleSet();
if (nsnull != set) {
AddStyleSheetToSet(aSheet, set);
NS_RELEASE(set);
}
}
count = mObservers.Count();
for (index = 0; index < count; index++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers.ElementAt(index);
observer->StyleSheetAdded(aSheet);
}
}
// Note: We don't hold a reference to the document observer; we assume
// that it has a live reference to the document.
void nsDocument::AddObserver(nsIDocumentObserver* aObserver)
{
mObservers.AppendElement(aObserver);
}
PRBool nsDocument::RemoveObserver(nsIDocumentObserver* aObserver)
{
return mObservers.RemoveElement(aObserver);
}
void nsDocument::ContentChanged(nsIContent* aContent,
nsISubContent* aSubContent,
PRInt32 aChangeType)
{
PRInt32 count = mObservers.Count();
for (PRInt32 i = 0; i < count; i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->ContentChanged(aContent, aSubContent, aChangeType);
}
}
void nsDocument::ContentAppended(nsIContent* aContainer)
{
PRInt32 count = mObservers.Count();
for (PRInt32 i = 0; i < count; i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->ContentAppended(aContainer);
}
}
void nsDocument::ContentInserted(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
PRInt32 count = mObservers.Count();
for (PRInt32 i = 0; i < count; i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->ContentInserted(aContainer, aChild, aIndexInContainer);
}
}
void nsDocument::ContentReplaced(nsIContent* aContainer,
nsIContent* aOldChild,
nsIContent* aNewChild,
PRInt32 aIndexInContainer)
{
PRInt32 count = mObservers.Count();
for (PRInt32 i = 0; i < count; i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->ContentReplaced(aContainer, aOldChild, aNewChild,
aIndexInContainer);
}
}
void nsDocument::ContentWillBeRemoved(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
PRInt32 count = mObservers.Count();
for (PRInt32 i = 0; i < count; i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->ContentWillBeRemoved(aContainer, aChild, aIndexInContainer);
}
}
void nsDocument::ContentHasBeenRemoved(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
PRInt32 count = mObservers.Count();
for (PRInt32 i = 0; i < count; i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->ContentHasBeenRemoved(aContainer, aChild, aIndexInContainer);
}
}
nsresult nsDocument::GetScriptObject(JSContext *aContext, void** aScriptObject)
{
nsresult res = NS_OK;
if (nsnull == mScriptObject) {
res = NS_NewScriptDocument(aContext, this, nsnull, (JSObject**)&mScriptObject);
}
*aScriptObject = mScriptObject;
return res;
}
nsresult nsDocument::ResetScriptObject()
{
mScriptObject = nsnull;
return NS_OK;
}
//
// nsIDOMDocument interface
//
nsresult nsDocument::GetNodeType(PRInt32 *aType)
{
*aType = nsIDOMNode::DOCUMENT;
return NS_OK;
}
nsresult nsDocument::GetParentNode(nsIDOMNode **aNode)
{
return NS_ERROR_FAILURE;
}
nsresult nsDocument::GetChildNodes(nsIDOMNodeIterator **aIterator)
{
//XXX TBI
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsDocument::HasChildNodes()
{
if (nsnull != mRootContent) {
return NS_OK;
}
else {
return NS_ERROR_FAILURE;
}
}
nsresult nsDocument::GetFirstChild(nsIDOMNode **aNode)
{
if (nsnull != mRootContent) {
nsresult res = mRootContent->QueryInterface(kIDOMNodeIID, (void**)aNode);
NS_ASSERTION(NS_OK == res, "Must be a DOM Node");
return res;
}
return NS_ERROR_FAILURE;
}
nsresult nsDocument::GetPreviousSibling(nsIDOMNode **aNode)
{
// no siblings
return NS_ERROR_FAILURE;
}
nsresult nsDocument::GetNextSibling(nsIDOMNode **aNode)
{
// no siblings
return NS_ERROR_FAILURE;
}
nsresult nsDocument::InsertBefore(nsIDOMNode *newChild, nsIDOMNode *refChild)
{
// a document has only one child
return NS_ERROR_FAILURE;
}
nsresult nsDocument::ReplaceChild(nsIDOMNode *newChild, nsIDOMNode *oldChild)
{
NS_PRECONDITION(nsnull != newChild && nsnull != oldChild, "null arg");
nsIContent* content;
nsresult res = oldChild->QueryInterface(kIContentIID, (void**)&content);
if (NS_OK == res) {
// check that we are replacing the root content
if (content == mRootContent) {
nsIContent* newContent;
res = newChild->QueryInterface(kIContentIID, (void**)&newContent);
if (NS_OK == res) {
SetRootContent(newContent);
NS_RELEASE(newContent);
}
else NS_ASSERTION(0, "Must be an nsIContent"); // nsIContent not supported. Who are you?
}
NS_RELEASE(content);
}
else NS_ASSERTION(0, "Must be an nsIContent"); // nsIContent not supported. Who are you?
return res;
}
nsresult nsDocument::RemoveChild(nsIDOMNode *oldChild)
{
NS_PRECONDITION(nsnull != oldChild, "null arg");
nsIContent* content;
nsresult res = oldChild->QueryInterface(kIContentIID, (void**)&content);
if (NS_OK == res) {
if (content == mRootContent) {
NS_RELEASE(mRootContent);
mRootContent = nsnull;
}
}
return res;
}
nsresult nsDocument::GetMasterDoc(nsIDOMDocument **aDocument)
{
AddRef();
*aDocument = (nsIDOMDocument*)this;
return NS_OK;
}
nsresult nsDocument::SetMasterDoc(nsIDOMDocument *aDocument)
{
//XXX TBI
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsDocument::GetDocumentType(nsIDOMNode **aDocType)
{
//XXX TBI
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsDocument::SetDocumentType(nsIDOMNode *aNode)
{
//XXX TBI
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsDocument::GetDocumentElement(nsIDOMElement **aElement)
{
nsresult res = NS_ERROR_FAILURE;
if (nsnull != mRootContent) {
res = mRootContent->QueryInterface(kIDOMElementIID, (void**)aElement);
NS_ASSERTION(NS_OK == res, "Must be a DOM Element");
}
return res;
}
nsresult nsDocument::SetDocumentElement(nsIDOMElement *aElement)
{
NS_PRECONDITION(nsnull != aElement, "null arg");
nsIContent* content;
nsresult res = aElement->QueryInterface(kIContentIID, (void**)&content);
if (NS_OK == res) {
SetRootContent(content);
NS_RELEASE(content);
}
else NS_ASSERTION(0, "Must be an nsIContent"); // nsIContent not supported. Who are you?
return res;
}
nsresult nsDocument::GetDocumentContext(nsIDOMDocumentContext **aDocContext)
{
//XXX TBI
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsDocument::SetDocumentContext(nsIDOMDocumentContext *aContext)
{
//XXX TBI
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsDocument::CreateDocumentContext(nsIDOMDocumentContext **aDocContext)
{
//XXX TBI
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsDocument::CreateElement(nsString &aTagName,
nsIDOMAttributeList *aAttributes,
nsIDOMElement **aElement)
{
//XXX TBI
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsDocument::CreateTextNode(nsString &aData, nsIDOMText** aTextNode)
{
//XXX TBI
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsDocument::CreateComment(nsString &aData, nsIDOMComment **aComment)
{
//XXX TBI
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsDocument::CreatePI(nsString &aName, nsString &aData, nsIDOMPI **aPI)
{
//XXX TBI
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsDocument::CreateAttribute(nsString &aName,
nsIDOMNode *value,
nsIDOMAttribute **aAttribute)
{
//XXX TBI
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsDocument::CreateAttributeList(nsIDOMAttributeList **aAttributesList)
{
//XXX TBI
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsDocument::CreateTreeIterator(nsIDOMNode **aNode, nsIDOMTreeIterator **aTreeIterator)
{
//XXX TBI
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsDocument::GetElementsByTagName(nsString &aTagname, nsIDOMNodeIterator **aIterator)
{
//XXX TBI
return NS_ERROR_NOT_IMPLEMENTED;
}