Mozilla/mozilla/layout/base/src/nsDocument.cpp
vidur%netscape.com fe0a023b26 Added epilog and prolog to document. Added processing instructions and CDATASections for XML. Completed document Node methods.
git-svn-id: svn://10.0.0.236/trunk@25744 18797224-902f-48f8-a5cc-f745e15eee43
1999-03-31 20:49:25 +00:00

2832 lines
75 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 "plstr.h"
#include "nsCOMPtr.h"
#include "nsDocument.h"
#include "nsIArena.h"
#include "nsIURL.h"
#include "nsIURLGroup.h"
#include "nsString.h"
#include "nsIContent.h"
#include "nsIDocumentObserver.h"
#include "nsIStyleSet.h"
#include "nsIStyleSheet.h"
#include "nsIPresShell.h"
#include "nsIDocumentObserver.h"
#include "nsEventListenerManager.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptContextOwner.h"
#include "nsIScriptEventListener.h"
#include "nsDOMEvent.h"
#include "nsDOMEventsIIDs.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIEventStateManager.h"
#include "nsContentList.h"
#include "nsIDOMEventListener.h"
#include "nsIDOMStyleSheet.h"
#include "nsIDOMStyleSheetCollection.h"
#include "nsDOMAttribute.h"
#include "nsDOMCID.h"
#include "nsIDOMScriptObjectFactory.h"
#include "nsIDOMDOMImplementation.h"
#include "nsGenericElement.h"
#include "nsCSSPropIDs.h"
#include "nsCSSProps.h"
#include "nsICSSStyleSheet.h"
#include "nsICSSStyleRule.h"
#include "nsICSSDeclaration.h"
#include "nsITextContent.h"
#include "nsXIFConverter.h"
#include "nsIDOMText.h"
#include "nsIDOMComment.h"
#include "nsINameSpaceManager.h"
#include "nsIServiceManager.h"
#include "nsLayoutCID.h"
#include "nsIDOMSelection.h"
#include "nsIDOMRange.h"
#include "nsIEnumerator.h"
static NS_DEFINE_IID(kIDOMTextIID, NS_IDOMTEXT_IID);
static NS_DEFINE_IID(kIDOMCommentIID, NS_IDOMCOMMENT_IID);
static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
#include "nsIDOMElement.h"
static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID);
static NS_DEFINE_IID(kIDOMNSDocumentIID, NS_IDOMNSDOCUMENT_IID);
static NS_DEFINE_IID(kIDOMNodeListIID, NS_IDOMNODELIST_IID);
static NS_DEFINE_IID(kIDOMAttrIID, NS_IDOMATTR_IID);
static NS_DEFINE_IID(kIScriptEventListenerIID, NS_ISCRIPTEVENTLISTENER_IID);
static NS_DEFINE_IID(kIDOMEventCapturerIID, NS_IDOMEVENTCAPTURER_IID);
static NS_DEFINE_IID(kIPrivateDOMEventIID, NS_IPRIVATEDOMEVENT_IID);
static NS_DEFINE_IID(kIEventListenerManagerIID, NS_IEVENTLISTENERMANAGER_IID);
static NS_DEFINE_IID(kIPostDataIID, NS_IPOSTDATA_IID);
static NS_DEFINE_IID(kIDOMStyleSheetCollectionIID, NS_IDOMSTYLESHEETCOLLECTION_IID);
static NS_DEFINE_IID(kIDOMStyleSheetIID, NS_IDOMSTYLESHEET_IID);
static NS_DEFINE_IID(kIDOMDOMImplementationIID, NS_IDOMDOMIMPLEMENTATION_IID);
static NS_DEFINE_IID(kIDocumentObserverIID, NS_IDOCUMENT_OBSERVER_IID);
static NS_DEFINE_IID(kICSSStyleSheetIID, NS_ICSS_STYLE_SHEET_IID);
static NS_DEFINE_IID(kCRangeCID, NS_RANGE_CID);
static NS_DEFINE_IID(kIDOMRange, NS_IDOMRANGE_IID);
static NS_DEFINE_IID(kCRangeListCID, NS_RANGELIST_CID);
static NS_DEFINE_IID(kIEnumeratorIID, NS_IENUMERATOR_IID);
static NS_DEFINE_IID(kIDOMScriptObjectFactoryIID, NS_IDOM_SCRIPT_OBJECT_FACTORY_IID);
static NS_DEFINE_IID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
#include "nsILineBreakerFactory.h"
#include "nsIWordBreakerFactory.h"
#include "nsLWBrkCIID.h"
static NS_DEFINE_IID(kLWBrkCID, NS_LWBRK_CID);
static NS_DEFINE_IID(kILineBreakerFactoryIID, NS_ILINEBREAKERFACTORY_IID);
static NS_DEFINE_IID(kIWordBreakerFactoryIID, NS_IWORDBREAKERFACTORY_IID);
class nsDOMStyleSheetCollection : public nsIDOMStyleSheetCollection,
public nsIScriptObjectOwner,
public nsIDocumentObserver
{
public:
nsDOMStyleSheetCollection(nsIDocument *aDocument);
virtual ~nsDOMStyleSheetCollection();
NS_DECL_ISUPPORTS
NS_DECL_IDOMSTYLESHEETCOLLECTION
NS_IMETHOD BeginUpdate(nsIDocument *aDocument) { return NS_OK; }
NS_IMETHOD EndUpdate(nsIDocument *aDocument) { return NS_OK; }
NS_IMETHOD BeginLoad(nsIDocument *aDocument) { return NS_OK; }
NS_IMETHOD EndLoad(nsIDocument *aDocument) { return NS_OK; }
NS_IMETHOD BeginReflow(nsIDocument *aDocument,
nsIPresShell* aShell) { return NS_OK; }
NS_IMETHOD EndReflow(nsIDocument *aDocument,
nsIPresShell* aShell) { return NS_OK; }
NS_IMETHOD ContentChanged(nsIDocument *aDocument,
nsIContent* aContent,
nsISupports* aSubContent) { return NS_OK; }
NS_IMETHOD ContentStateChanged(nsIDocument* aDocument,
nsIContent* aContent) { return NS_OK; }
NS_IMETHOD AttributeChanged(nsIDocument *aDocument,
nsIContent* aContent,
nsIAtom* aAttribute,
PRInt32 aHint) { return NS_OK; }
NS_IMETHOD ContentAppended(nsIDocument *aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{ return NS_OK; }
NS_IMETHOD ContentInserted(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer) { return NS_OK; }
NS_IMETHOD ContentReplaced(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aOldChild,
nsIContent* aNewChild,
PRInt32 aIndexInContainer) { return NS_OK; }
NS_IMETHOD ContentRemoved(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer) { return NS_OK; }
NS_IMETHOD StyleSheetAdded(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet);
NS_IMETHOD StyleSheetRemoved(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet);
NS_IMETHOD StyleSheetDisabledStateChanged(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
PRBool aDisabled) { return NS_OK; }
NS_IMETHOD StyleRuleChanged(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule,
PRInt32 aHint) { return NS_OK; }
NS_IMETHOD StyleRuleAdded(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule) { return NS_OK; }
NS_IMETHOD StyleRuleRemoved(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule) { return NS_OK; }
NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument);
// nsIScriptObjectOwner interface
NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject);
NS_IMETHOD SetScriptObject(void* aScriptObject);
protected:
PRInt32 mLength;
nsIDocument* mDocument;
void* mScriptObject;
};
nsDOMStyleSheetCollection::nsDOMStyleSheetCollection(nsIDocument *aDocument)
{
NS_INIT_REFCNT();
mLength = -1;
// Not reference counted to avoid circular references.
// The document will tell us when its going away.
mDocument = aDocument;
mDocument->AddObserver(this);
mScriptObject = nsnull;
}
nsDOMStyleSheetCollection::~nsDOMStyleSheetCollection()
{
if (nsnull != mDocument) {
mDocument->RemoveObserver(this);
}
mDocument = nsnull;
}
NS_IMPL_ADDREF(nsDOMStyleSheetCollection)
NS_IMPL_RELEASE(nsDOMStyleSheetCollection)
nsresult
nsDOMStyleSheetCollection::QueryInterface(REFNSIID aIID, void** aInstancePtrResult)
{
if (NULL == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
if (aIID.Equals(kIDOMStyleSheetCollectionIID)) {
nsIDOMStyleSheetCollection *tmp = this;
*aInstancePtrResult = (void*) tmp;
AddRef();
return NS_OK;
}
if (aIID.Equals(kIScriptObjectOwnerIID)) {
nsIScriptObjectOwner *tmp = this;
*aInstancePtrResult = (void*) tmp;
AddRef();
return NS_OK;
}
if (aIID.Equals(kIDocumentObserverIID)) {
nsIDocumentObserver *tmp = this;
*aInstancePtrResult = (void*) tmp;
AddRef();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
nsIDOMStyleSheetCollection *tmp = this;
nsISupports *tmp2 = tmp;
*aInstancePtrResult = (void*) tmp2;
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMETHODIMP
nsDOMStyleSheetCollection::GetLength(PRUint32* aLength)
{
if (nsnull != mDocument) {
// XXX Find the number and then cache it. We'll use the
// observer notification to figure out if new ones have
// been added or removed.
if (-1 == mLength) {
PRUint32 count = 0;
PRInt32 i, imax = mDocument->GetNumberOfStyleSheets();
for (i = 0; i < imax; i++) {
nsIStyleSheet *sheet = mDocument->GetStyleSheetAt(i);
nsIDOMStyleSheet *domss;
if (NS_OK == sheet->QueryInterface(kIDOMStyleSheetIID, (void **)&domss)) {
count++;
NS_RELEASE(domss);
}
NS_RELEASE(sheet);
}
mLength = count;
}
*aLength = mLength;
}
else {
*aLength = 0;
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMStyleSheetCollection::Item(PRUint32 aIndex, nsIDOMStyleSheet** aReturn)
{
*aReturn = nsnull;
if (nsnull != mDocument) {
PRUint32 count = 0;
PRInt32 i, imax = mDocument->GetNumberOfStyleSheets();
// XXX Not particularly efficient, but does anyone care?
for (i = 0; (i < imax) && (nsnull == *aReturn); i++) {
nsIStyleSheet *sheet = mDocument->GetStyleSheetAt(i);
nsIDOMStyleSheet *domss;
if (NS_OK == sheet->QueryInterface(kIDOMStyleSheetIID, (void **)&domss)) {
if (count++ == aIndex) {
*aReturn = domss;
NS_ADDREF(domss);
}
NS_RELEASE(domss);
}
NS_RELEASE(sheet);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMStyleSheetCollection::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject)
{
nsresult res = NS_OK;
if (nsnull == mScriptObject) {
nsISupports *supports = (nsISupports *)(nsIDOMStyleSheetCollection *)this;
nsISupports *parent = (nsISupports *)mDocument;
// XXX Should be done through factory
res = NS_NewScriptStyleSheetCollection(aContext,
supports,
parent,
(void**)&mScriptObject);
}
*aScriptObject = mScriptObject;
return res;
}
NS_IMETHODIMP
nsDOMStyleSheetCollection::SetScriptObject(void* aScriptObject)
{
mScriptObject = aScriptObject;
return NS_OK;
}
NS_IMETHODIMP
nsDOMStyleSheetCollection::StyleSheetAdded(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet)
{
if (-1 != mLength) {
nsIDOMStyleSheet *domss;
if (NS_OK == aStyleSheet->QueryInterface(kIDOMStyleSheetIID, (void **)&domss)) {
mLength++;
NS_RELEASE(domss);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMStyleSheetCollection::StyleSheetRemoved(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet)
{
if (-1 != mLength) {
nsIDOMStyleSheet *domss;
if (NS_OK == aStyleSheet->QueryInterface(kIDOMStyleSheetIID, (void **)&domss)) {
mLength--;
NS_RELEASE(domss);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMStyleSheetCollection::DocumentWillBeDestroyed(nsIDocument *aDocument)
{
if (nsnull != mDocument) {
aDocument->RemoveObserver(this);
mDocument = nsnull;
}
return NS_OK;
}
// ==================================================================
// =
// ==================================================================
class nsDOMImplementation : public nsIDOMDOMImplementation,
public nsIScriptObjectOwner
{
public:
nsDOMImplementation();
virtual ~nsDOMImplementation();
NS_DECL_ISUPPORTS
NS_IMETHOD HasFeature(const nsString& aFeature,
const nsString& aVersion,
PRBool* aReturn);
NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject);
NS_IMETHOD SetScriptObject(void *aScriptObject);
protected:
void *mScriptObject;
};
nsDOMImplementation::nsDOMImplementation()
{
NS_INIT_REFCNT();
mScriptObject = nsnull;
}
nsDOMImplementation::~nsDOMImplementation()
{
}
NS_IMPL_ADDREF(nsDOMImplementation)
NS_IMPL_RELEASE(nsDOMImplementation)
nsresult
nsDOMImplementation::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kIDOMDOMImplementationIID)) {
nsIDOMDOMImplementation* tmp = this;
*aInstancePtr = (void*) tmp;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kIScriptObjectOwnerIID)) {
nsIScriptObjectOwner* tmp = this;
*aInstancePtr = (void*) tmp;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
nsIDOMDOMImplementation* tmp = this;
nsISupports* tmp2 = tmp;
*aInstancePtr = (void*) tmp2;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMETHODIMP
nsDOMImplementation::HasFeature(const nsString& aFeature,
const nsString& aVersion,
PRBool* aReturn)
{
// XXX Currently this is hardcoded. In the future, we should
// probably figure out some of this by querying the registry??
if (aFeature.EqualsIgnoreCase("HTML") ||
aFeature.EqualsIgnoreCase("XML")) {
*aReturn = PR_TRUE;
}
else {
*aReturn = PR_FALSE;
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMImplementation::GetScriptObject(nsIScriptContext *aContext,
void** aScriptObject)
{
nsresult result = NS_OK;
if (nsnull == mScriptObject) {
nsIDOMScriptObjectFactory *factory;
result = nsServiceManager::GetService(kDOMScriptObjectFactoryCID,
kIDOMScriptObjectFactoryIID,
(nsISupports **)&factory);
if (NS_OK == result) {
nsIScriptGlobalObject *global = aContext->GetGlobalObject();
result = factory->NewScriptDOMImplementation(aContext, (nsISupports*)(nsIDOMDOMImplementation*)this,
global, &mScriptObject);
NS_RELEASE(global);
NS_RELEASE(factory);
}
}
*aScriptObject = mScriptObject;
return result;
}
NS_IMETHODIMP
nsDOMImplementation::SetScriptObject(void *aScriptObject)
{
mScriptObject = nsnull;
return NS_OK;
}
// ==================================================================
// =
// ==================================================================
NS_LAYOUT nsresult
NS_NewPostData(PRBool aIsFile, char* aData,
nsIPostData** aInstancePtrResult)
{
nsresult rv = NS_OK;
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtrResult = new nsPostData(aIsFile, aData);
if (nsnull != *aInstancePtrResult) {
NS_ADDREF(*aInstancePtrResult);
} else {
rv = NS_ERROR_OUT_OF_MEMORY;
}
return rv;
}
nsPostData::nsPostData(PRBool aIsFile, char* aData)
{
NS_INIT_REFCNT();
mData = nsnull;
mDataLen = 0;
mIsFile = aIsFile;
if (aData) {
mDataLen = PL_strlen(aData);
mData = aData;
}
}
nsPostData::~nsPostData()
{
if (nsnull != mData) {
delete [] mData;
mData = nsnull;
}
}
/*
* Implementation of ISupports methods...
*/
NS_IMPL_ISUPPORTS(nsPostData,kIPostDataIID);
PRBool nsPostData::IsFile()
{
return mIsFile;
}
const char* nsPostData::GetData()
{
return mData;
}
PRInt32 nsPostData::GetDataLength()
{
return mDataLen;
}
// ==================================================================
// =
// ==================================================================
nsDocumentChildNodes::nsDocumentChildNodes(nsIDocument* aDocument)
{
// We don't reference count our document reference (to avoid circular
// references). We'll be told when the document goes away.
mDocument = aDocument;
}
nsDocumentChildNodes::~nsDocumentChildNodes()
{
}
NS_IMETHODIMP
nsDocumentChildNodes::GetLength(PRUint32* aLength)
{
if (nsnull != mDocument) {
PRInt32 count;
mDocument->GetChildCount(count);
*aLength = (PRUint32)count;
}
else {
*aLength = 0;
}
return NS_OK;
}
NS_IMETHODIMP
nsDocumentChildNodes::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
{
nsresult result = NS_OK;
nsIContent* content = nsnull;
*aReturn = nsnull;
if (nsnull != mDocument) {
result = mDocument->ChildAt(aIndex, content);
if ((NS_OK == result) && (nsnull != content)) {
result = content->QueryInterface(kIDOMNodeIID, (void**)aReturn);
}
}
return result;
}
void
nsDocumentChildNodes::DropReference()
{
mDocument = nsnull;
}
// ==================================================================
// =
// ==================================================================
nsDocument::nsDocument()
{
NS_INIT_REFCNT();
mArena = nsnull;
mDocumentTitle = nsnull;
mDocumentURL = nsnull;
mDocumentURLGroup = nsnull;
mCharacterSet = nsnull;
mParentDocument = nsnull;
mRootContent = nsnull;
mScriptObject = nsnull;
mScriptContextOwner = nsnull;
mListenerManager = nsnull;
mDisplaySelection = PR_FALSE;
mInDestructor = PR_FALSE;
mDOMStyleSheets = nsnull;
mNameSpaceManager = nsnull;
mHeaderData = nsnull;
mLineBreaker = nsnull;
mProlog = nsnull;
mEpilog = nsnull;
mChildNodes = nsnull;
mWordBreaker = nsnull;
Init();/* XXX */
}
nsDocument::~nsDocument()
{
// XXX Inform any remaining observers that we are going away.
// Note that this currently contradicts the rule that all
// observers must hold on to live references to the document.
// This notification will occur only after the reference has
// been dropped.
mInDestructor = PR_TRUE;
PRInt32 index, count;
for (index = 0; index < mObservers.Count(); index++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers.ElementAt(index);
observer->DocumentWillBeDestroyed(this);
}
if (nsnull != mDocumentTitle) {
delete mDocumentTitle;
mDocumentTitle = nsnull;
}
NS_IF_RELEASE(mDocumentURL);
NS_IF_RELEASE(mDocumentURLGroup);
mParentDocument = nsnull;
// Delete references to sub-documents
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);
sheet->SetOwningDocument(nsnull);
NS_RELEASE(sheet);
}
nsIContent* content;
if (nsnull != mProlog) {
count = mProlog->Count();
for (index = 0; index < count; index++) {
content = (nsIContent*)mProlog->ElementAt(index);
NS_RELEASE(content);
}
delete mProlog;
}
if (nsnull != mEpilog) {
count = mEpilog->Count();
for (index = 0; index < count; index++) {
content = (nsIContent*)mEpilog->ElementAt(index);
NS_RELEASE(content);
}
delete mEpilog;
}
if (nsnull != mChildNodes) {
mChildNodes->DropReference();
NS_RELEASE(mChildNodes);
}
NS_IF_RELEASE(mArena);
NS_IF_RELEASE(mScriptContextOwner);
NS_IF_RELEASE(mListenerManager);
NS_IF_RELEASE(mDOMStyleSheets);
NS_IF_RELEASE(mNameSpaceManager);
if (nsnull != mHeaderData) {
delete mHeaderData;
mHeaderData = nsnull;
}
NS_IF_RELEASE(mLineBreaker);
NS_IF_RELEASE(mWordBreaker);
}
nsresult nsDocument::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kIDocumentIID)) {
nsIDocument* tmp = this;
*aInstancePtr = (void*) tmp;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kIDOMDocumentIID)) {
nsIDOMDocument* tmp = this;
*aInstancePtr = (void*) tmp;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kIDOMNSDocumentIID)) {
nsIDOMNSDocument* tmp = this;
*aInstancePtr = (void*) tmp;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kIScriptObjectOwnerIID)) {
nsIScriptObjectOwner* tmp = this;
*aInstancePtr = (void*) tmp;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kIJSScriptObjectIID)) {
nsIJSScriptObject* tmp = this;
*aInstancePtr = (void*) tmp;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kIDOMEventCapturerIID)) {
nsIDOMEventCapturer* tmp = this;
*aInstancePtr = (void*) tmp;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kIDOMEventReceiverIID)) {
nsIDOMEventReceiver* tmp = this;
*aInstancePtr = (void*) tmp;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kIDOMEventTargetIID)) {
nsIDOMEventTarget* tmp = this;
*aInstancePtr = (void*) tmp;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kIDOMNodeIID)) {
nsIDOMNode* 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;
nsISupports* tmp2 = tmp;
*aInstancePtr = (void*) tmp2;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMPL_ADDREF(nsDocument)
NS_IMPL_RELEASE(nsDocument)
nsresult nsDocument::Init()
{
nsresult rv = NS_NewHeapArena(&mArena, nsnull);
return rv;
}
nsIArena* nsDocument::GetArena()
{
if (nsnull != mArena) {
NS_ADDREF(mArena);
}
return mArena;
}
nsresult
nsDocument::Reset(nsIURL *aURL)
{
nsresult rv = NS_OK;
if (nsnull != mDocumentTitle) {
delete mDocumentTitle;
mDocumentTitle = nsnull;
}
NS_IF_RELEASE(mDocumentURL);
NS_IF_RELEASE(mDocumentURLGroup);
// Delete references to sub-documents
PRInt32 index = mSubDocuments.Count();
while (--index >= 0) {
nsIDocument* subdoc = (nsIDocument*) mSubDocuments.ElementAt(index);
NS_RELEASE(subdoc);
}
if (nsnull != mRootContent) {
// Ensure that document is nsnull to allow validity checks on content
mRootContent->SetDocument(nsnull, PR_TRUE);
ContentRemoved(nsnull, mRootContent, 0);
NS_IF_RELEASE(mRootContent);
}
// Delete references to style sheets
index = mStyleSheets.Count();
while (--index >= 0) {
nsIStyleSheet* sheet = (nsIStyleSheet*) mStyleSheets.ElementAt(index);
sheet->SetOwningDocument(nsnull);
PRInt32 pscount = mPresShells.Count();
PRInt32 psindex;
for (psindex = 0; psindex < pscount; psindex++) {
nsIPresShell* shell = (nsIPresShell*)mPresShells.ElementAt(psindex);
nsCOMPtr<nsIStyleSet> set;
if (NS_SUCCEEDED(shell->GetStyleSet(getter_AddRefs(set)))) {
if (set) {
set->RemoveDocStyleSheet(sheet);
}
}
}
// XXX Tell observers?
NS_RELEASE(sheet);
}
mStyleSheets.Clear();
NS_IF_RELEASE(mListenerManager);
NS_IF_RELEASE(mDOMStyleSheets);
NS_IF_RELEASE(mNameSpaceManager);
mDocumentURL = aURL;
if (nsnull != aURL) {
NS_ADDREF(aURL);
rv = aURL->GetURLGroup(&mDocumentURLGroup);
}
if (NS_OK == rv) {
rv = NS_NewNameSpaceManager(&mNameSpaceManager);
}
return rv;
}
nsresult
nsDocument::StartDocumentLoad(nsIURL *aURL,
nsIContentViewerContainer* aContainer,
nsIStreamListener **aDocListener,
const char* aCommand)
{
return Reset(aURL);
}
const nsString* nsDocument::GetDocumentTitle() const
{
return mDocumentTitle;
}
nsIURL* nsDocument::GetDocumentURL() const
{
NS_IF_ADDREF(mDocumentURL);
return mDocumentURL;
}
nsIURLGroup* nsDocument::GetDocumentURLGroup() const
{
NS_IF_ADDREF(mDocumentURLGroup);
return mDocumentURLGroup;
}
NS_IMETHODIMP
nsDocument::GetBaseURL(nsIURL*& aURL) const
{
aURL = mDocumentURL;
NS_IF_ADDREF(mDocumentURL);
return NS_OK;
}
nsString* nsDocument::GetDocumentCharacterSet() const
{
return mCharacterSet;
}
void nsDocument::SetDocumentCharacterSet(nsString* aCharSetID)
{
mCharacterSet = aCharSetID;
}
NS_IMETHODIMP nsDocument::GetLineBreaker(nsILineBreaker** aResult)
{
if(nsnull == mLineBreaker ) {
// no line breaker, find a default one
nsILineBreakerFactory *lf;
nsresult result;
result = nsServiceManager::GetService(kLWBrkCID,
kILineBreakerFactoryIID,
(nsISupports **)&lf);
if (NS_SUCCEEDED(result)) {
nsILineBreaker *lb = nsnull ;
nsAutoString lbarg("");
result = lf->GetBreaker(lbarg, &lb);
if(NS_SUCCEEDED(result)) {
mLineBreaker = lb;
}
result = nsServiceManager::ReleaseService(kLWBrkCID, lf);
}
}
*aResult = mLineBreaker;
NS_IF_ADDREF(mLineBreaker);
return NS_OK; // XXX we should do error handling here
}
NS_IMETHODIMP nsDocument::SetLineBreaker(nsILineBreaker* aLineBreaker)
{
NS_IF_RELEASE(mLineBreaker);
mLineBreaker = aLineBreaker;
NS_IF_ADDREF(mLineBreaker);
return NS_OK;
}
NS_IMETHODIMP nsDocument::GetWordBreaker(nsIWordBreaker** aResult)
{
if(nsnull == mWordBreaker ) {
// no line breaker, find a default one
nsIWordBreakerFactory *lf;
nsresult result;
result = nsServiceManager::GetService(kLWBrkCID,
kIWordBreakerFactoryIID,
(nsISupports **)&lf);
if (NS_SUCCEEDED(result)) {
nsIWordBreaker *lb = nsnull ;
nsAutoString lbarg("");
result = lf->GetBreaker(lbarg, &lb);
if(NS_SUCCEEDED(result)) {
mWordBreaker = lb;
}
result = nsServiceManager::ReleaseService(kLWBrkCID, lf);
}
}
*aResult = mWordBreaker;
NS_IF_ADDREF(mWordBreaker);
return NS_OK; // XXX we should do error handling here
}
NS_IMETHODIMP nsDocument::SetWordBreaker(nsIWordBreaker* aWordBreaker)
{
NS_IF_RELEASE(mWordBreaker);
mWordBreaker = aWordBreaker;
NS_IF_ADDREF(mWordBreaker);
return NS_OK;
}
NS_IMETHODIMP
nsDocument::GetHeaderData(nsIAtom* aHeaderField, nsString& aData) const
{
aData.Truncate();
const nsDocHeaderData* data = mHeaderData;
while (nsnull != data) {
if (data->mField == aHeaderField) {
aData = data->mData;
break;
}
data = data->mNext;
}
return NS_OK;
}
NS_IMETHODIMP
nsDocument::SetHeaderData(nsIAtom* aHeaderField, const nsString& aData)
{
if (nsnull != aHeaderField) {
if (nsnull == mHeaderData) {
if (0 < aData.Length()) { // don't bother storing empty string
mHeaderData = new nsDocHeaderData(aHeaderField, aData);
}
}
else {
nsDocHeaderData* data = mHeaderData;
nsDocHeaderData** lastPtr = &mHeaderData;
do { // look for existing and replace
if (data->mField == aHeaderField) {
if (0 < aData.Length()) {
data->mData = aData;
}
else { // don't store empty string
(*lastPtr)->mNext = data->mNext;
data->mNext = nsnull;
delete data;
}
return NS_OK;
}
lastPtr = &(data->mNext);
data = data->mNext;
} while (nsnull != data);
// didn't find, append
if (0 < aData.Length()) {
*lastPtr = new nsDocHeaderData(aHeaderField, aData);
}
}
return NS_OK;
}
return NS_ERROR_NULL_POINTER;
}
#if 0
// XXX Temp hack: moved to nsMarkupDocument
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;
}
#endif
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);
}
}
NS_IMETHODIMP
nsDocument::AppendToProlog(nsIContent* aContent)
{
if (nsnull == mProlog) {
mProlog = new nsVoidArray();
}
mProlog->AppendElement((void *)aContent);
NS_ADDREF(aContent);
return NS_OK;
}
NS_IMETHODIMP
nsDocument::AppendToEpilog(nsIContent* aContent)
{
if (nsnull == mEpilog) {
mEpilog = new nsVoidArray();
}
mEpilog->AppendElement((void *)aContent);
NS_ADDREF(aContent);
return NS_OK;
}
NS_IMETHODIMP
nsDocument::ChildAt(PRInt32 aIndex, nsIContent*& aResult) const
{
nsIContent* content = nsnull;
PRInt32 prolog = 0;
if (nsnull != mProlog) {
prolog = mProlog->Count();
if (aIndex < prolog) {
// It's in the prolog
content = (nsIContent*)mProlog->ElementAt(aIndex);
}
}
if (aIndex == prolog) {
// It's the document element
content = mRootContent;
}
else if ((aIndex > prolog) && (nsnull != mEpilog)) {
// It's in the epilog
content = (nsIContent*)mEpilog->ElementAt(aIndex-prolog-1);
}
NS_IF_ADDREF(content);
aResult = content;
return NS_OK;
}
NS_IMETHODIMP
nsDocument::IndexOf(nsIContent* aPossibleChild, PRInt32& aIndex) const
{
PRInt32 index = -1;
PRInt32 prolog = 0;
if (nsnull != mProlog) {
index = mProlog->IndexOf(aPossibleChild);
prolog = mProlog->Count();
}
if (-1 == index) {
if (aPossibleChild == mRootContent) {
index = prolog;
}
else if (nsnull != mEpilog) {
index = mEpilog->IndexOf(aPossibleChild);
if (-1 != index) {
index += (prolog+1);
}
}
}
aIndex = index;
return NS_OK;
}
NS_IMETHODIMP
nsDocument::GetChildCount(PRInt32& aCount)
{
aCount = 1;
if (nsnull != mProlog) {
aCount += mProlog->Count();
}
if (nsnull != mEpilog) {
aCount += mEpilog->Count();
}
return NS_OK;
}
PRInt32 nsDocument::GetNumberOfStyleSheets()
{
return mStyleSheets.Count();
}
nsIStyleSheet* nsDocument::GetStyleSheetAt(PRInt32 aIndex)
{
nsIStyleSheet* sheet = (nsIStyleSheet*)mStyleSheets.ElementAt(aIndex);
NS_IF_ADDREF(sheet);
return sheet;
}
PRInt32 nsDocument::GetIndexOfStyleSheet(nsIStyleSheet* aSheet)
{
return mStyleSheets.IndexOf(aSheet);
}
void nsDocument::InternalAddStyleSheet(nsIStyleSheet* aSheet) // subclass hook for sheet ordering
{
mStyleSheets.AppendElement(aSheet);
}
void nsDocument::AddStyleSheet(nsIStyleSheet* aSheet)
{
NS_PRECONDITION(nsnull != aSheet, "null arg");
InternalAddStyleSheet(aSheet);
NS_ADDREF(aSheet);
aSheet->SetOwningDocument(this);
PRBool enabled = PR_TRUE;
aSheet->GetEnabled(enabled);
if (enabled) {
PRInt32 count = mPresShells.Count();
PRInt32 index;
for (index = 0; index < count; index++) {
nsIPresShell* shell = (nsIPresShell*)mPresShells.ElementAt(index);
nsCOMPtr<nsIStyleSet> set;
if (NS_SUCCEEDED(shell->GetStyleSet(getter_AddRefs(set)))) {
if (set) {
set->AddDocStyleSheet(aSheet, this);
}
}
}
// XXX should observers be notified for disabled sheets??? I think not, but I could be wrong
for (index = 0; index < mObservers.Count(); index++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers.ElementAt(index);
observer->StyleSheetAdded(this, aSheet);
}
}
}
void nsDocument::SetStyleSheetDisabledState(nsIStyleSheet* aSheet,
PRBool aDisabled)
{
NS_PRECONDITION(nsnull != aSheet, "null arg");
PRInt32 index = mStyleSheets.IndexOf((void *)aSheet);
PRInt32 count;
// If we're actually in the document style sheet list
if (-1 != index) {
count = mPresShells.Count();
for (index = 0; index < count; index++) {
nsIPresShell* shell = (nsIPresShell*)mPresShells.ElementAt(index);
nsCOMPtr<nsIStyleSet> set;
if (NS_SUCCEEDED(shell->GetStyleSet(getter_AddRefs(set)))) {
if (set) {
if (aDisabled) {
set->RemoveDocStyleSheet(aSheet);
}
else {
set->AddDocStyleSheet(aSheet, this);
}
}
}
}
}
for (index = 0; index < mObservers.Count(); index++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers.ElementAt(index);
observer->StyleSheetDisabledStateChanged(this, aSheet, aDisabled);
}
}
nsIScriptContextOwner *nsDocument::GetScriptContextOwner()
{
if (nsnull != mScriptContextOwner) {
NS_ADDREF(mScriptContextOwner);
}
return mScriptContextOwner;
}
void nsDocument::SetScriptContextOwner(nsIScriptContextOwner *aScriptContextOwner)
{
// XXX HACK ALERT! If the script context owner is null, the document
// will soon be going away. So tell our content that to lose its
// reference to the document. This has to be done before we
// actually set the script context owner to null so that the
// content elements can remove references to their script objects.
if ((nsnull == aScriptContextOwner) && (nsnull != mRootContent)) {
mRootContent->SetDocument(nsnull, PR_TRUE);
}
if (nsnull != mScriptContextOwner) {
NS_RELEASE(mScriptContextOwner);
}
mScriptContextOwner = aScriptContextOwner;
if (nsnull != mScriptContextOwner) {
NS_ADDREF(mScriptContextOwner);
}
}
NS_IMETHODIMP
nsDocument::GetNameSpaceManager(nsINameSpaceManager*& aManager)
{
aManager = mNameSpaceManager;
NS_IF_ADDREF(aManager);
return NS_OK;
}
// 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)
{
// XXX Make sure the observer isn't already in the list
if (mObservers.IndexOf(aObserver) == -1) {
mObservers.AppendElement(aObserver);
}
}
PRBool nsDocument::RemoveObserver(nsIDocumentObserver* aObserver)
{
// If we're in the process of destroying the document (and we're
// informing the observers of the destruction), don't remove the
// observers from the list. This is not a big deal, since we
// don't hold a live reference to the observers.
if (!mInDestructor)
return mObservers.RemoveElement(aObserver);
else
return (mObservers.IndexOf(aObserver) != -1);
}
NS_IMETHODIMP
nsDocument::BeginLoad()
{
PRInt32 i;
// Get new value of count for every iteration in case
// observers remove themselves during the loop.
for (i = 0; i < mObservers.Count(); i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i];
observer->BeginLoad(this);
// Make sure that the observer didn't remove itself during the
// notification. If it did, update our index and count.
if (observer != (nsIDocumentObserver*)mObservers[i]) {
i--;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocument::EndLoad()
{
PRInt32 i;
// Get new value of count for every iteration in case
// observers remove themselves during the loop.
for (i = 0; i < mObservers.Count(); i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i];
observer->EndLoad(this);
// Make sure that the observer didn't remove itself during the
// notification. If it did, update our index and count.
if (observer != (nsIDocumentObserver*)mObservers[i]) {
i--;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocument::ContentChanged(nsIContent* aContent,
nsISupports* aSubContent)
{
PRInt32 i;
// Get new value of count for every iteration in case
// observers remove themselves during the loop.
for (i = 0; i < mObservers.Count(); i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->ContentChanged(this, aContent, aSubContent);
// Make sure that the observer didn't remove itself during the
// notification. If it did, update our index and count.
if (observer != (nsIDocumentObserver*)mObservers[i]) {
i--;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocument::ContentStateChanged(nsIContent* aContent)
{
PRInt32 i;
// Get new value of count for every iteration in case
// observers remove themselves during the loop.
for (i = 0; i < mObservers.Count(); i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->ContentStateChanged(this, aContent);
// Make sure that the observer didn't remove itself during the
// notification. If it did, update our index and count.
if (observer != (nsIDocumentObserver*)mObservers[i]) {
i--;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocument::ContentAppended(nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
PRInt32 i;
// Get new value of count for every iteration in case
// observers remove themselves during the loop.
for (i = 0; i < mObservers.Count(); i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->ContentAppended(this, aContainer, aNewIndexInContainer);
// Make sure that the observer didn't remove itself during the
// notification. If it did, update our index and count.
if (observer != (nsIDocumentObserver*)mObservers[i]) {
i--;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocument::ContentInserted(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
PRInt32 i;
// Get new value of count for every iteration in case
// observers remove themselves during the loop.
for (i = 0; i < mObservers.Count(); i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->ContentInserted(this, aContainer, aChild, aIndexInContainer);
// Make sure that the observer didn't remove itself during the
// notification. If it did, update our index and count.
if (observer != (nsIDocumentObserver*)mObservers[i]) {
i--;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocument::ContentReplaced(nsIContent* aContainer,
nsIContent* aOldChild,
nsIContent* aNewChild,
PRInt32 aIndexInContainer)
{
PRInt32 i;
// Get new value of count for every iteration in case
// observers remove themselves during the loop.
for (i = 0; i < mObservers.Count(); i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->ContentReplaced(this, aContainer, aOldChild, aNewChild,
aIndexInContainer);
// Make sure that the observer didn't remove itself during the
// notification. If it did, update our index and count.
if (observer != (nsIDocumentObserver*)mObservers[i]) {
i--;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocument::ContentRemoved(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
PRInt32 i;
// Get new value of count for every iteration in case
// observers remove themselves during the loop.
for (i = 0; i < mObservers.Count(); i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->ContentRemoved(this, aContainer,
aChild, aIndexInContainer);
// Make sure that the observer didn't remove itself during the
// notification. If it did, update our index and count.
if (observer != (nsIDocumentObserver*)mObservers[i]) {
i--;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocument::AttributeChanged(nsIContent* aChild,
nsIAtom* aAttribute,
PRInt32 aHint)
{
PRInt32 i;
// Get new value of count for every iteration in case
// observers remove themselves during the loop.
for (i = 0; i < mObservers.Count(); i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->AttributeChanged(this, aChild, aAttribute, aHint);
// Make sure that the observer didn't remove itself during the
// notification. If it did, update our index and count.
if (observer != (nsIDocumentObserver*)mObservers[i]) {
i--;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocument::StyleRuleChanged(nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule,
PRInt32 aHint)
{
PRInt32 i;
// Get new value of count for every iteration in case
// observers remove themselves during the loop.
for (i = 0; i < mObservers.Count(); i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->StyleRuleChanged(this, aStyleSheet, aStyleRule, aHint);
// Make sure that the observer didn't remove itself during the
// notification. If it did, update our index and count.
if (observer != (nsIDocumentObserver*)mObservers[i]) {
i--;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocument::StyleRuleAdded(nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule)
{
PRInt32 i;
// Get new value of count for every iteration in case
// observers remove themselves during the loop.
for (i = 0; i < mObservers.Count(); i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->StyleRuleAdded(this, aStyleSheet, aStyleRule);
// Make sure that the observer didn't remove itself during the
// notification. If it did, update our index and count.
if (observer != (nsIDocumentObserver*)mObservers[i]) {
i--;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocument::StyleRuleRemoved(nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule)
{
PRInt32 i;
// Get new value of count for every iteration in case
// observers remove themselves during the loop.
for (i = 0; i < mObservers.Count(); i++) {
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
observer->StyleRuleRemoved(this, aStyleSheet, aStyleRule);
// Make sure that the observer didn't remove itself during the
// notification. If it did, update our index and count.
if (observer != (nsIDocumentObserver*)mObservers[i]) {
i--;
}
}
return NS_OK;
}
nsresult nsDocument::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject)
{
nsresult res = NS_OK;
nsIScriptGlobalObject *global = aContext->GetGlobalObject();
if (nsnull == mScriptObject) {
res = NS_NewScriptDocument(aContext, (nsISupports *)(nsIDOMDocument *)this, global, (void**)&mScriptObject);
}
*aScriptObject = mScriptObject;
NS_RELEASE(global);
return res;
}
nsresult nsDocument::SetScriptObject(void *aScriptObject)
{
mScriptObject = aScriptObject;
return NS_OK;
}
//
// nsIDOMDocument interface
//
NS_IMETHODIMP
nsDocument::GetDoctype(nsIDOMDocumentType** aDoctype)
{
// Should be implemented by subclass
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocument::GetImplementation(nsIDOMDOMImplementation** aImplementation)
{
// For now, create a new implementation every time. This shouldn't
// be a high bandwidth operation
nsDOMImplementation* impl = new nsDOMImplementation();
if (nsnull == impl) {
return NS_ERROR_OUT_OF_MEMORY;
}
return impl->QueryInterface(kIDOMDOMImplementationIID, (void**)aImplementation);
}
NS_IMETHODIMP
nsDocument::GetDocumentElement(nsIDOMElement** aDocumentElement)
{
if (nsnull == aDocumentElement) {
return NS_ERROR_NULL_POINTER;
}
nsresult res = NS_ERROR_FAILURE;
if (nsnull != mRootContent) {
res = mRootContent->QueryInterface(kIDOMElementIID, (void**)aDocumentElement);
NS_ASSERTION(NS_OK == res, "Must be a DOM Element");
}
return res;
}
NS_IMETHODIMP
nsDocument::CreateElement(const nsString& aTagName,
nsIDOMElement** aReturn)
{
// Should be implemented by subclass
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocument::CreateTextNode(const nsString& aData, nsIDOMText** aReturn)
{
nsIContent* text = nsnull;
nsresult rv = NS_NewTextNode(&text);
if (NS_OK == rv) {
rv = text->QueryInterface(kIDOMTextIID, (void**)aReturn);
(*aReturn)->AppendData(aData);
NS_RELEASE(text);
}
return rv;
}
NS_IMETHODIMP
nsDocument::CreateDocumentFragment(nsIDOMDocumentFragment** aReturn)
{
return NS_NewDocumentFragment(aReturn, this);
}
NS_IMETHODIMP
nsDocument::CreateComment(const nsString& aData, nsIDOMComment** aReturn)
{
nsIContent* comment = nsnull;
nsresult rv = NS_NewCommentNode(&comment);
if (NS_OK == rv) {
rv = comment->QueryInterface(kIDOMCommentIID, (void**)aReturn);
(*aReturn)->AppendData(aData);
NS_RELEASE(comment);
}
return rv;
}
NS_IMETHODIMP
nsDocument::CreateCDATASection(const nsString& aData, nsIDOMCDATASection** aReturn)
{
// Should be implemented by subclass
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocument::CreateProcessingInstruction(const nsString& aTarget,
const nsString& aData,
nsIDOMProcessingInstruction** aReturn)
{
// Should be implemented by subclass
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocument::CreateAttribute(const nsString& aName,
nsIDOMAttr** aReturn)
{
nsAutoString value;
nsDOMAttribute* attribute;
value.Truncate();
attribute = new nsDOMAttribute(nsnull, aName, value);
if (nsnull == attribute) {
return NS_ERROR_OUT_OF_MEMORY;
}
return attribute->QueryInterface(kIDOMAttrIID, (void**)aReturn);
}
NS_IMETHODIMP
nsDocument::CreateEntityReference(const nsString& aName,
nsIDOMEntityReference** aReturn)
{
// Should be implemented by subclass
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocument::GetElementsByTagName(const nsString& aTagname,
nsIDOMNodeList** aReturn)
{
nsIAtom* nameAtom;
PRInt32 nameSpaceId;
nsresult result = NS_OK;
if (nsnull != mRootContent) {
result = mRootContent->ParseAttributeString(aTagname, nameAtom,
nameSpaceId);
if (NS_OK != result) {
return result;
}
}
else {
nameAtom = NS_NewAtom(aTagname);
nameSpaceId = kNameSpaceID_None;
}
nsContentList* list = new nsContentList(this, nameAtom, nameSpaceId);
NS_IF_RELEASE(nameAtom);
if (nsnull == list) {
return NS_ERROR_OUT_OF_MEMORY;
}
return list->QueryInterface(kIDOMNodeListIID, (void **)aReturn);
}
NS_IMETHODIMP
nsDocument::GetStyleSheets(nsIDOMStyleSheetCollection** aStyleSheets)
{
if (nsnull == mDOMStyleSheets) {
mDOMStyleSheets = new nsDOMStyleSheetCollection(this);
if (nsnull == mDOMStyleSheets) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(mDOMStyleSheets);
}
*aStyleSheets = mDOMStyleSheets;
NS_ADDREF(mDOMStyleSheets);
return NS_OK;
}
NS_IMETHODIMP
nsDocument::CreateElementWithNameSpace(const nsString& aTagName,
const nsString& aNameSpace,
nsIDOMElement** aReturn)
{
return NS_OK;
}
//
// nsIDOMNode methods
//
NS_IMETHODIMP
nsDocument::GetNodeName(nsString& aNodeName)
{
aNodeName.SetString("#document");
return NS_OK;
}
NS_IMETHODIMP
nsDocument::GetNodeValue(nsString& aNodeValue)
{
aNodeValue.Truncate();
return NS_OK;
}
NS_IMETHODIMP
nsDocument::SetNodeValue(const nsString& aNodeValue)
{
return NS_OK;
}
NS_IMETHODIMP
nsDocument::GetNodeType(PRUint16* aNodeType)
{
*aNodeType = nsIDOMNode::DOCUMENT_NODE;
return NS_OK;
}
NS_IMETHODIMP
nsDocument::GetParentNode(nsIDOMNode** aParentNode)
{
*aParentNode = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsDocument::GetChildNodes(nsIDOMNodeList** aChildNodes)
{
if (nsnull == mChildNodes) {
mChildNodes = new nsDocumentChildNodes(this);
if (nsnull == mChildNodes) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(mChildNodes);
}
return mChildNodes->QueryInterface(kIDOMNodeListIID, (void**)aChildNodes);
}
NS_IMETHODIMP
nsDocument::HasChildNodes(PRBool* aHasChildNodes)
{
*aHasChildNodes = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsDocument::GetFirstChild(nsIDOMNode** aFirstChild)
{
nsresult result = NS_OK;
if ((nsnull != mProlog) && (0 != mProlog->Count())) {
nsIContent* content;
content = (nsIContent *)mProlog->ElementAt(0);
if (nsnull != content) {
result = content->QueryInterface(kIDOMNodeIID, (void**)aFirstChild);
}
}
else {
nsIDOMElement* element;
result = GetDocumentElement(&element);
if (NS_OK == result) {
result = element->QueryInterface(kIDOMNodeIID, (void**)aFirstChild);
NS_RELEASE(element);
}
}
return result;
}
NS_IMETHODIMP
nsDocument::GetLastChild(nsIDOMNode** aLastChild)
{
nsresult result = NS_OK;
if ((nsnull != mEpilog) && (0 != mEpilog->Count())) {
nsIContent* content;
content = (nsIContent *)mEpilog->ElementAt(mEpilog->Count()-1);
if (nsnull != content) {
result = content->QueryInterface(kIDOMNodeIID, (void**)aLastChild);
}
}
else {
nsIDOMElement* element;
result = GetDocumentElement(&element);
if (NS_OK == result) {
result = element->QueryInterface(kIDOMNodeIID, (void**)aLastChild);
NS_RELEASE(element);
}
}
return result;
}
NS_IMETHODIMP
nsDocument::GetPreviousSibling(nsIDOMNode** aPreviousSibling)
{
*aPreviousSibling = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsDocument::GetNextSibling(nsIDOMNode** aNextSibling)
{
*aNextSibling = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsDocument::GetAttributes(nsIDOMNamedNodeMap** aAttributes)
{
*aAttributes = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsDocument::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNode** aReturn)
{
NS_ASSERTION(nsnull != aNewChild, "null ptr");
nsresult result = NS_OK;
PRInt32 index;
PRUint16 nodeType;
nsIContent *content, *refContent = nsnull;
if (nsnull == aNewChild) {
return NS_ERROR_INVALID_ARG;
}
aNewChild->GetNodeType(&nodeType);
if ((COMMENT_NODE != nodeType) && (PROCESSING_INSTRUCTION_NODE != nodeType)) {
return NS_ERROR_INVALID_ARG;
}
result = aNewChild->QueryInterface(kIContentIID, (void**)&content);
if (NS_OK != result) {
return result;
}
if (nsnull == aRefChild) {
AppendToEpilog(content);
}
else {
result = aRefChild->QueryInterface(kIContentIID, (void**)&refContent);
if (NS_OK != result) {
NS_RELEASE(content);
return result;
}
if ((nsnull != mProlog) && (0 != mProlog->Count())) {
index = mProlog->IndexOf(refContent);
if (-1 != index) {
mProlog->InsertElementAt(content, index);
NS_ADDREF(content);
}
}
if (refContent == mRootContent) {
AppendToProlog(content);
}
else if ((nsnull != mEpilog) && (0 != mEpilog->Count())) {
index = mEpilog->IndexOf(refContent);
if (-1 != index) {
mEpilog->InsertElementAt(content, index);
NS_ADDREF(content);
}
}
NS_RELEASE(refContent);
}
if (NS_OK == result) {
content->SetDocument(this, PR_TRUE);
*aReturn = aNewChild;
NS_ADDREF(aNewChild);
}
else {
*aReturn = nsnull;
}
NS_RELEASE(content);
return result;
}
NS_IMETHODIMP
nsDocument::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
{
NS_ASSERTION(((nsnull != aNewChild) && (nsnull != aOldChild)), "null ptr");
nsresult result = NS_OK;
PRInt32 index;
PRUint16 nodeType;
nsIContent *content, *refContent;
if ((nsnull == aNewChild) || (nsnull == aOldChild)) {
return NS_ERROR_INVALID_ARG;
}
aNewChild->GetNodeType(&nodeType);
if ((COMMENT_NODE != nodeType) && (PROCESSING_INSTRUCTION_NODE != nodeType)) {
return NS_ERROR_INVALID_ARG;
}
result = aNewChild->QueryInterface(kIContentIID, (void**)&content);
if (NS_OK != result) {
return result;
}
result = aOldChild->QueryInterface(kIContentIID, (void**)&refContent);
if (NS_OK != result) {
NS_RELEASE(content);
return result;
}
if ((nsnull != mProlog) && (0 != mProlog->Count())) {
index = mProlog->IndexOf(refContent);
if (-1 != index) {
nsIContent* oldContent;
oldContent = (nsIContent*)mProlog->ElementAt(index);
NS_RELEASE(oldContent);
mProlog->ReplaceElementAt(content, index);
NS_ADDREF(content);
}
}
if (refContent == mRootContent) {
result = NS_ERROR_INVALID_ARG;
}
else if ((nsnull != mEpilog) && (0 != mEpilog->Count())) {
index = mEpilog->IndexOf(refContent);
if (-1 != index) {
nsIContent* oldContent;
oldContent = (nsIContent*)mEpilog->ElementAt(index);
NS_RELEASE(oldContent);
mEpilog->ReplaceElementAt(content, index);
NS_ADDREF(content);
}
}
if (NS_OK == result) {
content->SetDocument(this, PR_TRUE);
refContent->SetDocument(nsnull, PR_TRUE);
*aReturn = aNewChild;
NS_ADDREF(aNewChild);
}
else {
*aReturn = nsnull;
}
NS_RELEASE(content);
NS_RELEASE(refContent);
return result;
}
NS_IMETHODIMP
nsDocument::RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
{
NS_ASSERTION(nsnull != aOldChild, "null ptr");
nsresult result = NS_OK;
PRInt32 index;
nsIContent *content;
if (nsnull == aOldChild) {
return NS_ERROR_INVALID_ARG;
}
result = aOldChild->QueryInterface(kIContentIID, (void**)&content);
if (NS_OK != result) {
return result;
}
if ((nsnull != mProlog) && (0 != mProlog->Count())) {
index = mProlog->IndexOf(content);
if (-1 != index) {
// Don't drop reference count since we're going
// to return this element anyway.
mProlog->RemoveElementAt(index);
}
}
if (content == mRootContent) {
result = NS_ERROR_INVALID_ARG;
}
else if ((nsnull != mEpilog) && (0 != mEpilog->Count())) {
index = mEpilog->IndexOf(content);
if (-1 != index) {
mEpilog->RemoveElementAt(index);
}
}
if (NS_OK == result) {
content->SetDocument(nsnull, PR_TRUE);
*aReturn = aOldChild;
}
else {
*aReturn = nsnull;
}
NS_RELEASE(content);
return result;
}
NS_IMETHODIMP
nsDocument::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
{
return InsertBefore(aNewChild, nsnull, aReturn);
}
NS_IMETHODIMP
nsDocument::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
{
// We don't allow cloning of a document
*aReturn = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsDocument::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
{
return QueryInterface(kIDOMDocumentIID, (void **)aOwnerDocument);
}
nsresult nsDocument::GetListenerManager(nsIEventListenerManager **aInstancePtrResult)
{
if (nsnull != mListenerManager) {
return mListenerManager->QueryInterface(kIEventListenerManagerIID, (void**) aInstancePtrResult);;
}
if (NS_OK == NS_NewEventListenerManager(aInstancePtrResult)) {
mListenerManager = *aInstancePtrResult;
NS_ADDREF(mListenerManager);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
nsresult nsDocument::GetNewListenerManager(nsIEventListenerManager **aInstancePtrResult)
{
return NS_NewEventListenerManager(aInstancePtrResult);
}
nsresult nsDocument::HandleDOMEvent(nsIPresContext& aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus& aEventStatus)
{
nsresult mRet = NS_OK;
nsIDOMEvent* mDOMEvent = nsnull;
if (NS_EVENT_FLAG_INIT == aFlags) {
aDOMEvent = &mDOMEvent;
}
//Capturing stage
if (NS_EVENT_FLAG_BUBBLE != aFlags) {
//XXX Check window capture here
}
//Local handling stage
if (nsnull != mListenerManager) {
mListenerManager->HandleEvent(aPresContext, aEvent, aDOMEvent, aFlags, aEventStatus);
}
//Bubbling stage
if (NS_EVENT_FLAG_CAPTURE != aFlags && nsnull != mScriptContextOwner) {
nsIScriptGlobalObject* mGlobal;
if (NS_OK == mScriptContextOwner->GetScriptGlobalObject(&mGlobal)) {
mGlobal->HandleDOMEvent(aPresContext, aEvent, aDOMEvent, NS_EVENT_FLAG_BUBBLE, aEventStatus);
NS_RELEASE(mGlobal);
}
}
if (NS_EVENT_FLAG_INIT == aFlags) {
// We're leaving the DOM event loop so if we created a DOM event, release here.
if (nsnull != *aDOMEvent) {
nsrefcnt rc;
NS_RELEASE2(*aDOMEvent, rc);
if (0 != rc) {
//Okay, so someone in the DOM loop (a listener, JS object) still has a ref to the DOM Event but
//the internal data hasn't been malloc'd. Force a copy of the data here so the DOM Event is still valid.
nsIPrivateDOMEvent *mPrivateEvent;
if (NS_OK == (*aDOMEvent)->QueryInterface(kIPrivateDOMEventIID, (void**)&mPrivateEvent)) {
mPrivateEvent->DuplicatePrivateData();
NS_RELEASE(mPrivateEvent);
}
}
}
aDOMEvent = nsnull;
}
return mRet;
}
nsresult nsDocument::AddEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID)
{
nsIEventListenerManager *manager;
if (NS_OK == GetListenerManager(&manager)) {
manager->AddEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE);
NS_RELEASE(manager);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
nsresult nsDocument::RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID)
{
if (nsnull != mListenerManager) {
mListenerManager->RemoveEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
nsresult nsDocument::AddEventListener(const nsString& aType, nsIDOMEventListener* aListener,
PRBool aPostProcess, PRBool aUseCapture)
{
nsIEventListenerManager *manager;
if (NS_OK == GetListenerManager(&manager)) {
PRInt32 flags = (aPostProcess ? NS_EVENT_FLAG_POST_PROCESS : NS_EVENT_FLAG_NONE) |
(aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE);
manager->AddEventListenerByType(aListener, aType, flags);
NS_RELEASE(manager);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
nsresult nsDocument::RemoveEventListener(const nsString& aType, nsIDOMEventListener* aListener,
PRBool aPostProcess, PRBool aUseCapture)
{
if (nsnull != mListenerManager) {
PRInt32 flags = (aPostProcess ? NS_EVENT_FLAG_POST_PROCESS : NS_EVENT_FLAG_NONE) |
(aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE);
mListenerManager->RemoveEventListenerByType(aListener, aType, flags);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
nsresult nsDocument::CaptureEvent(const nsString& aType)
{
nsIEventListenerManager *mManager;
if (NS_OK == GetListenerManager(&mManager)) {
//mManager->CaptureEvent(aListener);
NS_RELEASE(mManager);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
nsresult nsDocument::ReleaseEvent(const nsString& aType)
{
if (nsnull != mListenerManager) {
//mListenerManager->ReleaseEvent(aListener);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
PRBool nsDocument::AddProperty(JSContext *aContext, jsval aID, jsval *aVp)
{
return PR_TRUE;
}
PRBool nsDocument::DeleteProperty(JSContext *aContext, jsval aID, jsval *aVp)
{
return PR_TRUE;
}
PRBool nsDocument::GetProperty(JSContext *aContext, jsval aID, jsval *aVp)
{
PRBool result = PR_TRUE;
if (JSVAL_IS_STRING(aID) &&
PL_strcmp("location", JS_GetStringBytes(JS_ValueToString(aContext, aID))) == 0) {
if (nsnull != mScriptContextOwner) {
nsIScriptGlobalObject *global;
mScriptContextOwner->GetScriptGlobalObject(&global);
if (nsnull != global) {
nsIJSScriptObject *window;
if (NS_OK == global->QueryInterface(kIJSScriptObjectIID, (void **)&window)) {
result = window->GetProperty(aContext, aID, aVp);
NS_RELEASE(window);
}
else {
result = PR_FALSE;
}
NS_RELEASE(global);
}
}
}
return result;
}
PRBool nsDocument::SetProperty(JSContext *aContext, jsval aID, jsval *aVp)
{
PRBool result = PR_TRUE;
if (JS_TypeOfValue(aContext, *aVp) == JSTYPE_FUNCTION && JSVAL_IS_STRING(aID)) {
nsAutoString mPropName, mPrefix;
mPropName.SetString(JS_GetStringChars(JS_ValueToString(aContext, aID)));
mPrefix.SetString(mPropName, 2);
if (mPrefix == "on") {
nsIEventListenerManager *mManager = nsnull;
if (mPropName == "onmousedown" || mPropName == "onmouseup" || mPropName == "onclick" ||
mPropName == "onmouseover" || mPropName == "onmouseout") {
if (NS_OK == GetListenerManager(&mManager)) {
nsIScriptContext *mScriptCX = (nsIScriptContext *)JS_GetContextPrivate(aContext);
if (NS_OK != mManager->RegisterScriptEventListener(mScriptCX, this, kIDOMMouseListenerIID)) {
NS_RELEASE(mManager);
return PR_FALSE;
}
}
}
else if (mPropName == "onkeydown" || mPropName == "onkeyup" || mPropName == "onkeypress") {
if (NS_OK == GetListenerManager(&mManager)) {
nsIScriptContext *mScriptCX = (nsIScriptContext *)JS_GetContextPrivate(aContext);
if (NS_OK != mManager->RegisterScriptEventListener(mScriptCX, this, kIDOMKeyListenerIID)) {
NS_RELEASE(mManager);
return PR_FALSE;
}
}
}
else if (mPropName == "onmousemove") {
if (NS_OK == GetListenerManager(&mManager)) {
nsIScriptContext *mScriptCX = (nsIScriptContext *)JS_GetContextPrivate(aContext);
if (NS_OK != mManager->RegisterScriptEventListener(mScriptCX, this, kIDOMMouseMotionListenerIID)) {
NS_RELEASE(mManager);
return PR_FALSE;
}
}
}
else if (mPropName == "onfocus" || mPropName == "onblur") {
if (NS_OK == GetListenerManager(&mManager)) {
nsIScriptContext *mScriptCX = (nsIScriptContext *)JS_GetContextPrivate(aContext);
if (NS_OK != mManager->RegisterScriptEventListener(mScriptCX, this, kIDOMFocusListenerIID)) {
NS_RELEASE(mManager);
return PR_FALSE;
}
}
}
else if (mPropName == "onsubmit" || mPropName == "onreset" || mPropName == "onchange") {
if (NS_OK == GetListenerManager(&mManager)) {
nsIScriptContext *mScriptCX = (nsIScriptContext *)JS_GetContextPrivate(aContext);
if (NS_OK != mManager->RegisterScriptEventListener(mScriptCX, this, kIDOMFormListenerIID)) {
NS_RELEASE(mManager);
return PR_FALSE;
}
}
}
else if (mPropName == "onload" || mPropName == "onunload" || mPropName == "onabort" ||
mPropName == "onerror") {
if (NS_OK == GetListenerManager(&mManager)) {
nsIScriptContext *mScriptCX = (nsIScriptContext *)JS_GetContextPrivate(aContext);
if (NS_OK != mManager->RegisterScriptEventListener(mScriptCX, this, kIDOMLoadListenerIID)) {
NS_RELEASE(mManager);
return PR_FALSE;
}
}
}
else if (mPropName == "onpaint") {
if (NS_OK == GetListenerManager(&mManager)) {
nsIScriptContext *mScriptCX = (nsIScriptContext *)
JS_GetContextPrivate(aContext);
if (NS_OK != mManager->RegisterScriptEventListener(mScriptCX, this,
kIDOMPaintListenerIID)) {
NS_RELEASE(mManager);
return PR_FALSE;
}
}
}
NS_IF_RELEASE(mManager);
}
}
else if (JSVAL_IS_STRING(aID) &&
PL_strcmp("location", JS_GetStringBytes(JS_ValueToString(aContext, aID))) == 0) {
if (nsnull != mScriptContextOwner) {
nsIScriptGlobalObject *global;
mScriptContextOwner->GetScriptGlobalObject(&global);
if (nsnull != global) {
nsIJSScriptObject *window;
if (NS_OK == global->QueryInterface(kIJSScriptObjectIID, (void **)&window)) {
result = window->SetProperty(aContext, aID, aVp);
NS_RELEASE(window);
}
else {
result = PR_FALSE;
}
NS_RELEASE(global);
}
}
}
return result;
}
PRBool nsDocument::EnumerateProperty(JSContext *aContext)
{
return PR_TRUE;
}
PRBool nsDocument::Resolve(JSContext *aContext, jsval aID)
{
return PR_TRUE;
}
PRBool nsDocument::Convert(JSContext *aContext, jsval aID)
{
return PR_TRUE;
}
void nsDocument::Finalize(JSContext *aContext)
{
}
/**
* Returns the Selection Object
*/
NS_IMETHODIMP nsDocument::GetSelection(nsIDOMSelection ** aSelection) {
if (!aSelection)
return NS_ERROR_NULL_POINTER;
return NS_ERROR_FAILURE;
}
/**
* Selects all the Content
*/
NS_IMETHODIMP nsDocument::SelectAll() {
nsIContent * start = nsnull;
nsIContent * end = nsnull;
nsIContent * body = nsnull;
nsString bodyStr("BODY");
PRInt32 i, n;
mRootContent->ChildCount(n);
for (i=0;i<n;i++) {
nsIContent * child;
mRootContent->ChildAt(i, child);
PRBool isSynthetic;
child->IsSynthetic(isSynthetic);
if (!isSynthetic) {
nsIAtom * atom;
child->GetTag(atom);
if (bodyStr.EqualsIgnoreCase(atom)) {
body = child;
break;
}
NS_IF_RELEASE(atom);
}
NS_RELEASE(child);
}
if (body == nsnull) {
return NS_ERROR_FAILURE;
}
start = body;
// Find Very first Piece of Content
NS_ADDREF(start); //to balance release below
for (;;) {
start->ChildCount(n);
if (n <= 0) {
break;
}
nsIContent * child = start;
child->ChildAt(0, start);
NS_RELEASE(child);
}
end = body;
NS_ADDREF(end); //to balance release below
// Last piece of Content
for (;;) {
end->ChildCount(n);
if (n <= 0) {
break;
}
nsIContent * child = end;
child->ChildAt(n-1, end);
NS_RELEASE(child);
}
NS_RELEASE(body);
SetDisplaySelection(PR_TRUE);
return NS_OK;
}
/**
* Finds text in content
*/
NS_IMETHODIMP nsDocument::FindNext(const nsString &aSearchStr, PRBool aMatchCase, PRBool aSearchDown, PRBool &aIsFound)
{
aIsFound = PR_FALSE;
return NS_ERROR_FAILURE;
}
void nsDocument::BeginConvertToXIF(nsXIFConverter& aConverter, nsIDOMNode* aNode)
{
nsIContent* content = nsnull;
nsresult isContent = aNode->QueryInterface(kIContentIID, (void**)&content);
PRBool isSynthetic = PR_TRUE;
// Begin Conversion
if (NS_OK == isContent)
{
content->IsSynthetic(isSynthetic);
if (PR_FALSE == isSynthetic)
{
content->BeginConvertToXIF(aConverter);
content->ConvertContentToXIF(aConverter);
}
NS_RELEASE(content);
}
}
void nsDocument::ConvertChildrenToXIF(nsXIFConverter& aConverter, nsIDOMNode* aNode)
{
// Iterate through the children, convertion child nodes
nsresult result = NS_OK;
nsIDOMNode* child = nsnull;
result = aNode->GetFirstChild(&child);
while ((result == NS_OK) && (child != nsnull))
{
nsIDOMNode* temp = child;
ToXIF(aConverter,child);
result = child->GetNextSibling(&child);
NS_RELEASE(temp);
}
}
void nsDocument::FinishConvertToXIF(nsXIFConverter& aConverter, nsIDOMNode* aNode)
{
nsIContent* content = nsnull;
nsresult isContent = aNode->QueryInterface(kIContentIID, (void**)&content);
PRBool isSynthetic = PR_TRUE;
if (NS_OK == isContent)
{
content->IsSynthetic(isSynthetic);
if (PR_FALSE == isSynthetic)
content->FinishConvertToXIF(aConverter);
NS_RELEASE(content);
}
}
void nsDocument::ToXIF(nsXIFConverter& aConverter, nsIDOMNode* aNode)
{
nsIDOMSelection* sel = aConverter.GetSelection();
if (sel != nsnull)
{
nsIContent* content = nsnull;
nsresult isContent = aNode->QueryInterface(kIContentIID, (void**)&content);
if (isContent != nsnull)
{
PRBool isInSelection = IsInSelection(sel,content);
if (isInSelection == PR_TRUE)
{
BeginConvertToXIF(aConverter,aNode);
ConvertChildrenToXIF(aConverter,aNode);
FinishConvertToXIF(aConverter,aNode);
}
else
{
ConvertChildrenToXIF(aConverter,aNode);
}
NS_RELEASE(content);
}
}
else
{
BeginConvertToXIF(aConverter,aNode);
ConvertChildrenToXIF(aConverter,aNode);
FinishConvertToXIF(aConverter,aNode);
}
}
void nsDocument::CreateXIF(nsString & aBuffer, nsIDOMSelection* aSelection)
{
nsXIFConverter converter(aBuffer);
// call the function
converter.SetSelection(aSelection);
converter.AddStartTag("section");
converter.AddStartTag("section_head");
converter.AddEndTag("section_head");
converter.AddStartTag("section_body");
nsIDOMElement* root = nsnull;
if (NS_OK == GetDocumentElement(&root))
{
ToXIF(converter,root);
NS_RELEASE(root);
}
converter.AddEndTag("section_body");
converter.AddEndTag("section");
converter.Write();
}
nsIContent* nsDocument::FindContent(const nsIContent* aStartNode,
const nsIContent* aTest1,
const nsIContent* aTest2) const
{
PRInt32 count;
aStartNode->ChildCount(count);
PRInt32 index;
for(index = 0; index < count;index++)
{
nsIContent* child;
aStartNode->ChildAt(index, child);
nsIContent* content = FindContent(child,aTest1,aTest2);
if (content != nsnull) {
NS_IF_RELEASE(child);
return content;
}
if (child == aTest1 || child == aTest2) {
NS_IF_RELEASE(content);
return child;
}
NS_IF_RELEASE(child);
NS_IF_RELEASE(content);
}
return nsnull;
}
PRBool nsDocument::IsInRange(const nsIContent *aStartContent, const nsIContent* aEndContent, const nsIContent* aContent) const
{
PRBool result;
if (aStartContent == aEndContent)
{
return PRBool(aContent == aStartContent);
}
else if (aStartContent == aContent || aEndContent == aContent)
{
result = PR_TRUE;
}
else
{
result = IsBefore(aStartContent,aContent);
if (result == PR_TRUE)
result = IsBefore(aContent,aEndContent);
}
return result;
}
/**
* Determines if the content is found within the selection
*
* @update gpk 1/8/99
* @param param -- description
* @param param -- description
* @return PR_TRUE if the content is found within the selection
*/
PRBool nsDocument::IsInSelection(nsIDOMSelection* aSelection, const nsIContent* aContent) const
{
PRBool result = PR_FALSE;
if (aSelection != nsnull) {
//traverses through an iterator to see if the acontent is in the ranges
nsIEnumerator *enumerator;
if (NS_SUCCEEDED(aSelection->QueryInterface(kIEnumeratorIID, (void **)&enumerator)))
{
for (enumerator->First();NS_OK != enumerator->IsDone() ; enumerator->Next()) {
nsIDOMRange* range = nsnull;
if (NS_SUCCEEDED(enumerator->CurrentItem((nsISupports**)&range)))
{
nsIDOMNode* startNode = nsnull;
nsIDOMNode* endNode = nsnull;
range->GetStartParent(&startNode);
range->GetEndParent(&endNode);
if (startNode && endNode)
{
nsIContent* start;
nsIContent* end;
if (NS_SUCCEEDED(startNode->QueryInterface(kIContentIID, (void **)&start)) &&
NS_SUCCEEDED(endNode->QueryInterface(kIContentIID, (void **)&end)) )
{
result = IsInRange(start,end,aContent);
}
NS_IF_RELEASE(start);
NS_IF_RELEASE(end);
}
NS_IF_RELEASE(startNode);
NS_IF_RELEASE(endNode);
NS_RELEASE(range);
}
if (result) break;
}
NS_IF_RELEASE(enumerator);
}
}
return result;
}
PRBool nsDocument::IsBefore(const nsIContent *aNewContent, const nsIContent* aCurrentContent) const
{
PRBool result = PR_FALSE;
if (nsnull != aNewContent && nsnull != aCurrentContent && aNewContent != aCurrentContent)
{
nsIContent* test = FindContent(mRootContent,aNewContent,aCurrentContent);
if (test == aNewContent)
result = PR_TRUE;
NS_RELEASE(test);
}
return result;
}
nsIContent* nsDocument::GetPrevContent(const nsIContent *aContent) const
{
nsIContent* result = nsnull;
// Look at previous sibling
if (nsnull != aContent)
{
nsIContent* parent;
aContent->GetParent(parent);
if (parent != nsnull && parent != mRootContent)
{
PRInt32 index;
parent->IndexOf((nsIContent*)aContent, index);
if (index > 0)
parent->ChildAt(index-1, result);
else
result = GetPrevContent(parent);
}
NS_IF_RELEASE(parent);
}
return result;
}
nsIContent* nsDocument::GetNextContent(const nsIContent *aContent) const
{
nsIContent* result = nsnull;
if (nsnull != aContent)
{
// Look at next sibling
nsIContent* parent;
aContent->GetParent(parent);
if (parent != nsnull && parent != mRootContent)
{
PRInt32 index;
parent->IndexOf((nsIContent*)aContent, index);
PRInt32 count;
parent->ChildCount(count);
if (index+1 < count) {
parent->ChildAt(index+1, result);
// Get first child down the tree
for (;;) {
PRInt32 n;
result->ChildCount(n);
if (n <= 0) {
break;
}
nsIContent * old = result;
old->ChildAt(0, result);
NS_RELEASE(old);
result->ChildCount(n);
}
} else {
result = GetNextContent(parent);
}
}
NS_IF_RELEASE(parent);
}
return result;
}
void nsDocument::SetDisplaySelection(PRBool aToggle)
{
mDisplaySelection = aToggle;
}
PRBool nsDocument::GetDisplaySelection() const
{
return mDisplaySelection;
}