3433 lines
92 KiB
C++
3433 lines
92 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 "License"); you may not use this file except in
|
|
* compliance with the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS"
|
|
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
|
* the License for the specific language governing rights and limitations
|
|
* under the License.
|
|
*
|
|
* The Original Code is Mozilla Communicator client code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape Communications
|
|
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
|
* Netscape Communications Corporation. All Rights Reserved.
|
|
*/
|
|
#include "nsGenericHTMLElement.h"
|
|
|
|
#include "nsIAtom.h"
|
|
#include "nsICSSParser.h"
|
|
#include "nsICSSStyleRule.h"
|
|
#include "nsICSSDeclaration.h"
|
|
#include "nsIDocument.h"
|
|
#include "nsIDOMAttribute.h"
|
|
#include "nsIDOMEventReceiver.h"
|
|
#include "nsIDOMNamedNodeMap.h"
|
|
#include "nsIDOMNodeList.h"
|
|
#include "nsIEventListenerManager.h"
|
|
#include "nsIHTMLAttributes.h"
|
|
#include "nsIHTMLStyleSheet.h"
|
|
#include "nsIHTMLDocument.h"
|
|
#include "nsIHTMLContent.h"
|
|
#include "nsILinkHandler.h"
|
|
#include "nsIScriptContextOwner.h"
|
|
#include "nsIScriptGlobalObject.h"
|
|
#include "nsIScriptObjectOwner.h"
|
|
#include "nsISizeOfHandler.h"
|
|
#include "nsIStyleContext.h"
|
|
#include "nsIStyleRule.h"
|
|
#include "nsISupportsArray.h"
|
|
#include "nsIURL.h"
|
|
#include "nsStyleConsts.h"
|
|
#include "nsXIFConverter.h"
|
|
#include "nsFrame.h"
|
|
#include "nsIPresShell.h"
|
|
#include "nsIView.h"
|
|
#include "nsIViewManager.h"
|
|
|
|
#include "nsHTMLParts.h"
|
|
#include "nsString.h"
|
|
#include "nsHTMLAtoms.h"
|
|
#include "nsDOMEventsIIDs.h"
|
|
#include "nsIEventStateManager.h"
|
|
#include "nsDOMEvent.h"
|
|
#include "nsIPrivateDOMEvent.h"
|
|
#include "nsBodyFrame.h"
|
|
#include "nsDOMCID.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsIDOMScriptObjectFactory.h"
|
|
#include "nsIDOMCSSStyleDeclaration.h"
|
|
#include "nsDOMCSSDeclaration.h"
|
|
#include "prprf.h"
|
|
#include "prmem.h"
|
|
|
|
// XXX todo: add in missing out-of-memory checks
|
|
|
|
NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID);
|
|
NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID);
|
|
NS_DEFINE_IID(kIDOMHTMLElementIID, NS_IDOMHTMLELEMENT_IID);
|
|
NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID);
|
|
NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID);
|
|
NS_DEFINE_IID(kIJSScriptObjectIID, NS_IJSSCRIPTOBJECT_IID);
|
|
NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|
NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID);
|
|
//NS_DEFINE_IID(kIHTMLContentIID, NS_IHTMLCONTENT_IID);
|
|
|
|
static NS_DEFINE_IID(kIDOMAttributeIID, NS_IDOMATTRIBUTE_IID);
|
|
static NS_DEFINE_IID(kIDOMNamedNodeMapIID, NS_IDOMNAMEDNODEMAP_IID);
|
|
static NS_DEFINE_IID(kIPrivateDOMEventIID, NS_IPRIVATEDOMEVENT_IID);
|
|
static NS_DEFINE_IID(kIStyleRuleIID, NS_ISTYLE_RULE_IID);
|
|
static NS_DEFINE_IID(kIHTMLDocumentIID, NS_IHTMLDOCUMENT_IID);
|
|
static NS_DEFINE_IID(kICSSStyleRuleIID, NS_ICSS_STYLE_RULE_IID);
|
|
static NS_DEFINE_IID(kIDOMNodeListIID, NS_IDOMNODELIST_IID);
|
|
static NS_DEFINE_IID(kIDOMCSSStyleDeclarationIID, NS_IDOMCSSSTYLEDECLARATION_IID);
|
|
|
|
// Attribute helper class used to wrap up an attribute with a dom
|
|
// object that implements nsIDOMAttribute and nsIDOMNode and
|
|
// nsIScriptObjectOwner
|
|
class DOMAttribute : public nsIDOMAttribute, public nsIScriptObjectOwner {
|
|
public:
|
|
DOMAttribute(const nsString &aName, const nsString &aValue);
|
|
~DOMAttribute();
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_IMETHOD GetScriptObject(nsIScriptContext* aContext, void** aScriptObject);
|
|
NS_IMETHOD SetScriptObject(void *aScriptObject);
|
|
|
|
// nsIDOMAttribute interface
|
|
NS_IMETHOD GetSpecified(PRBool* aSpecified);
|
|
NS_IMETHOD SetSpecified(PRBool aSpecified);
|
|
NS_IMETHOD GetName(nsString& aReturn);
|
|
NS_IMETHOD GetValue(nsString& aReturn);
|
|
|
|
// nsIDOMNode interface
|
|
NS_IMETHOD GetNodeName(nsString& aNodeName);
|
|
NS_IMETHOD GetNodeValue(nsString& aNodeValue);
|
|
NS_IMETHOD SetNodeValue(const nsString& aNodeValue);
|
|
NS_IMETHOD GetNodeType(PRInt32* aNodeType);
|
|
NS_IMETHOD GetParentNode(nsIDOMNode** aParentNode);
|
|
NS_IMETHOD GetChildNodes(nsIDOMNodeList** aChildNodes);
|
|
NS_IMETHOD GetHasChildNodes(PRBool* aHasChildNodes);
|
|
NS_IMETHOD GetFirstChild(nsIDOMNode** aFirstChild);
|
|
NS_IMETHOD GetLastChild(nsIDOMNode** aLastChild);
|
|
NS_IMETHOD GetPreviousSibling(nsIDOMNode** aPreviousSibling);
|
|
NS_IMETHOD GetNextSibling(nsIDOMNode** aNextSibling);
|
|
NS_IMETHOD GetAttributes(nsIDOMNamedNodeMap** aAttributes);
|
|
NS_IMETHOD InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
|
|
nsIDOMNode** aReturn);
|
|
NS_IMETHOD ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
|
nsIDOMNode** aReturn);
|
|
NS_IMETHOD RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn);
|
|
NS_IMETHOD AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn);
|
|
NS_IMETHOD CloneNode(nsIDOMNode** aReturn);
|
|
NS_IMETHOD Equals(nsIDOMNode* aNode, PRBool aDeep, PRBool* aReturn);
|
|
|
|
private:
|
|
nsString mName;
|
|
nsString mValue;
|
|
void* mScriptObject;
|
|
};
|
|
|
|
// Another helper class that implements the nsIDOMNamedNodeMap interface.
|
|
class DOMAttributeMap : public nsIDOMNamedNodeMap,
|
|
public nsIScriptObjectOwner
|
|
{
|
|
public:
|
|
DOMAttributeMap(nsIHTMLContent* aContent);
|
|
virtual ~DOMAttributeMap();
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_IMETHOD GetScriptObject(nsIScriptContext* aContext, void** aScriptObject);
|
|
NS_IMETHOD SetScriptObject(void *aScriptObject);
|
|
|
|
// nsIDOMNamedNodeMap interface
|
|
NS_IMETHOD GetLength(PRUint32* aSize);
|
|
NS_IMETHOD GetNamedItem(const nsString& aName, nsIDOMNode** aReturn);
|
|
NS_IMETHOD SetNamedItem(nsIDOMNode* aNode);
|
|
NS_IMETHOD RemoveNamedItem(const nsString& aName, nsIDOMNode** aReturn);
|
|
NS_IMETHOD Item(PRUint32 aIndex, nsIDOMNode** aReturn);
|
|
|
|
private:
|
|
nsIHTMLContent* mContent;
|
|
void* mScriptObject;
|
|
};
|
|
|
|
|
|
// Class that holds the child list of a content element and also
|
|
// implements the nsIDOMNodeList interface.
|
|
class nsChildContentList : public nsIDOMNodeList,
|
|
public nsIScriptObjectOwner
|
|
{
|
|
public:
|
|
nsChildContentList(nsGenericHTMLContainerElement *aContent);
|
|
virtual ~nsChildContentList() {}
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject);
|
|
NS_IMETHOD SetScriptObject(void *aScriptObject);
|
|
|
|
// nsIDOMNodeList interface
|
|
NS_DECL_IDOMNODELIST
|
|
|
|
void DropReference();
|
|
|
|
private:
|
|
nsGenericHTMLContainerElement *mContent;
|
|
void *mScriptObject;
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
DOMAttribute::DOMAttribute(const nsString& aName, const nsString& aValue)
|
|
: mName(aName), mValue(aValue)
|
|
{
|
|
mRefCnt = 1;
|
|
mScriptObject = nsnull;
|
|
}
|
|
|
|
DOMAttribute::~DOMAttribute()
|
|
{
|
|
}
|
|
|
|
nsresult
|
|
DOMAttribute::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|
{
|
|
if (NULL == aInstancePtr) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
if (aIID.Equals(kIDOMAttributeIID)) {
|
|
nsIDOMAttribute* 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)) {
|
|
nsIDOMAttribute* tmp1 = this;
|
|
nsISupports* tmp2 = tmp1;
|
|
*aInstancePtr = (void*)tmp2;
|
|
NS_ADDREF_THIS();
|
|
return NS_OK;
|
|
}
|
|
return NS_NOINTERFACE;
|
|
}
|
|
|
|
NS_IMPL_ADDREF(DOMAttribute)
|
|
|
|
NS_IMPL_RELEASE(DOMAttribute)
|
|
|
|
nsresult
|
|
DOMAttribute::GetScriptObject(nsIScriptContext *aContext,
|
|
void** aScriptObject)
|
|
{
|
|
nsresult res = NS_OK;
|
|
if (nsnull == mScriptObject) {
|
|
res = NS_NewScriptAttribute(aContext,
|
|
(nsISupports *)(nsIDOMAttribute *)this,
|
|
nsnull,
|
|
(void **)&mScriptObject);
|
|
}
|
|
*aScriptObject = mScriptObject;
|
|
return res;
|
|
}
|
|
|
|
nsresult
|
|
DOMAttribute::SetScriptObject(void *aScriptObject)
|
|
{
|
|
mScriptObject = aScriptObject;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
DOMAttribute::GetName(nsString& aName)
|
|
{
|
|
aName = mName;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
DOMAttribute::GetValue(nsString& aValue)
|
|
{
|
|
aValue = mValue;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
DOMAttribute::GetSpecified(PRBool* aSpecified)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
nsresult
|
|
DOMAttribute::SetSpecified(PRBool specified)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::GetNodeName(nsString& aNodeName)
|
|
{
|
|
return GetName(aNodeName);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::GetNodeValue(nsString& aNodeValue)
|
|
{
|
|
return GetValue(aNodeValue);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::SetNodeValue(const nsString& aNodeValue)
|
|
{
|
|
// You can't actually do this, but we'll fail silently
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::GetNodeType(PRInt32* aNodeType)
|
|
{
|
|
*aNodeType = (PRInt32)nsIDOMNode::ATTRIBUTE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::GetParentNode(nsIDOMNode** aParentNode)
|
|
{
|
|
*aParentNode = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::GetChildNodes(nsIDOMNodeList** aChildNodes)
|
|
{
|
|
*aChildNodes = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::GetHasChildNodes(PRBool* aHasChildNodes)
|
|
{
|
|
*aHasChildNodes = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::GetFirstChild(nsIDOMNode** aFirstChild)
|
|
{
|
|
*aFirstChild = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::GetLastChild(nsIDOMNode** aLastChild)
|
|
{
|
|
*aLastChild = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::GetPreviousSibling(nsIDOMNode** aPreviousSibling)
|
|
{
|
|
*aPreviousSibling = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::GetNextSibling(nsIDOMNode** aNextSibling)
|
|
{
|
|
*aNextSibling = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::GetAttributes(nsIDOMNamedNodeMap** aAttributes)
|
|
{
|
|
*aAttributes = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNode** aReturn)
|
|
{
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
|
|
{
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
|
|
{
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
|
|
{
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::CloneNode(nsIDOMNode** aReturn)
|
|
{
|
|
DOMAttribute* newAttr = new DOMAttribute(mName, mValue);
|
|
if (nsnull == newAttr) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
*aReturn = newAttr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttribute::Equals(nsIDOMNode* aNode, PRBool aDeep, PRBool* aReturn)
|
|
{
|
|
// XXX TBI
|
|
return NS_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
DOMAttributeMap::DOMAttributeMap(nsIHTMLContent* aContent)
|
|
: mContent(aContent)
|
|
{
|
|
mRefCnt = 1;
|
|
NS_ADDREF(mContent);
|
|
mScriptObject = nsnull;
|
|
}
|
|
|
|
DOMAttributeMap::~DOMAttributeMap()
|
|
{
|
|
NS_RELEASE(mContent);
|
|
}
|
|
|
|
nsresult
|
|
DOMAttributeMap::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|
{
|
|
if (NULL == aInstancePtr) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
if (aIID.Equals(kIDOMNamedNodeMapIID)) {
|
|
nsIDOMNamedNodeMap* 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)) {
|
|
nsIDOMNamedNodeMap* tmp1 = this;
|
|
nsISupports* tmp2 = tmp1;
|
|
*aInstancePtr = (void*)tmp2;
|
|
NS_ADDREF_THIS();
|
|
return NS_OK;
|
|
}
|
|
return NS_NOINTERFACE;
|
|
}
|
|
|
|
NS_IMPL_ADDREF(DOMAttributeMap)
|
|
|
|
NS_IMPL_RELEASE(DOMAttributeMap)
|
|
|
|
nsresult
|
|
DOMAttributeMap::GetScriptObject(nsIScriptContext *aContext,
|
|
void** aScriptObject)
|
|
{
|
|
nsresult res = NS_OK;
|
|
if (nsnull == mScriptObject) {
|
|
res = NS_NewScriptNamedNodeMap(aContext,
|
|
(nsISupports *)(nsIDOMNamedNodeMap *)this,
|
|
nsnull,
|
|
(void**)&mScriptObject);
|
|
}
|
|
*aScriptObject = mScriptObject;
|
|
return res;
|
|
}
|
|
|
|
nsresult
|
|
DOMAttributeMap::SetScriptObject(void *aScriptObject)
|
|
{
|
|
mScriptObject = aScriptObject;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
DOMAttributeMap::GetNamedItem(const nsString &aAttrName,
|
|
nsIDOMNode** aAttribute)
|
|
{
|
|
nsAutoString value;
|
|
mContent->GetAttribute(aAttrName, value);
|
|
*aAttribute = (nsIDOMNode *) new DOMAttribute(aAttrName, value);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
DOMAttributeMap::SetNamedItem(nsIDOMNode *aNode)
|
|
{
|
|
nsIDOMAttribute *attribute;
|
|
nsAutoString name, value;
|
|
nsresult err;
|
|
|
|
if (NS_OK != (err = aNode->QueryInterface(kIDOMAttributeIID,
|
|
(void **)&attribute))) {
|
|
return err;
|
|
}
|
|
|
|
attribute->GetName(name);
|
|
attribute->GetValue(value);
|
|
NS_RELEASE(attribute);
|
|
|
|
mContent->SetAttribute(name, value, PR_TRUE);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DOMAttributeMap::RemoveNamedItem(const nsString& aName, nsIDOMNode** aReturn)
|
|
{
|
|
nsresult res = GetNamedItem(aName, aReturn);
|
|
if (NS_OK == res) {
|
|
nsAutoString upper;
|
|
aName.ToUpperCase(upper);
|
|
nsIAtom* attr = NS_NewAtom(upper);
|
|
mContent->UnsetAttribute(attr, PR_TRUE);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
nsresult
|
|
DOMAttributeMap::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
|
|
{
|
|
nsresult res = NS_ERROR_FAILURE;
|
|
nsAutoString name, value;
|
|
nsISupportsArray *attributes = nsnull;
|
|
if (NS_OK == NS_NewISupportsArray(&attributes)) {
|
|
PRInt32 count;
|
|
mContent->GetAllAttributeNames(attributes, count);
|
|
if (count > 0) {
|
|
if ((PRInt32)aIndex < count) {
|
|
nsISupports *att = attributes->ElementAt(aIndex);
|
|
static NS_DEFINE_IID(kIAtom, NS_IATOM_IID);
|
|
nsIAtom *atName = nsnull;
|
|
if (nsnull != att && NS_OK == att->QueryInterface(kIAtom, (void**)&atName)) {
|
|
atName->ToString(name);
|
|
if (NS_CONTENT_ATTR_NOT_THERE != mContent->GetAttribute(name, value)) {
|
|
*aReturn = (nsIDOMNode *)new DOMAttribute(name, value);
|
|
res = NS_OK;
|
|
}
|
|
NS_RELEASE(atName);
|
|
}
|
|
}
|
|
}
|
|
NS_RELEASE(attributes);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
nsresult
|
|
DOMAttributeMap::GetLength(PRUint32 *aLength)
|
|
{
|
|
PRInt32 n;
|
|
nsresult rv = mContent->GetAttributeCount(n);
|
|
*aLength = PRUint32(n);
|
|
return rv;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
class nsDOMCSSAttributeDeclaration : public nsDOMCSSDeclaration
|
|
{
|
|
public:
|
|
nsDOMCSSAttributeDeclaration(nsIHTMLContent *aContent);
|
|
~nsDOMCSSAttributeDeclaration();
|
|
|
|
virtual void DropReference();
|
|
virtual nsresult GetCSSDeclaration(nsICSSDeclaration **aDecl,
|
|
PRBool aAllocate);
|
|
virtual nsresult StylePropertyChanged(const nsString& aPropertyName,
|
|
PRInt32 aHint);
|
|
virtual nsresult GetParent(nsISupports **aParent);
|
|
|
|
protected:
|
|
nsIHTMLContent *mContent;
|
|
};
|
|
|
|
nsDOMCSSAttributeDeclaration::nsDOMCSSAttributeDeclaration(nsIHTMLContent *aContent)
|
|
{
|
|
// This reference is not reference-counted. The content
|
|
// object tells us when its about to go away.
|
|
mContent = aContent;
|
|
}
|
|
|
|
nsDOMCSSAttributeDeclaration::~nsDOMCSSAttributeDeclaration()
|
|
{
|
|
}
|
|
|
|
void
|
|
nsDOMCSSAttributeDeclaration::DropReference()
|
|
{
|
|
mContent = nsnull;
|
|
}
|
|
|
|
nsresult
|
|
nsDOMCSSAttributeDeclaration::GetCSSDeclaration(nsICSSDeclaration **aDecl,
|
|
PRBool aAllocate)
|
|
{
|
|
nsHTMLValue val;
|
|
nsIStyleRule* rule;
|
|
nsICSSStyleRule* cssRule;
|
|
nsresult result = NS_OK;
|
|
|
|
*aDecl = nsnull;
|
|
if (nsnull != mContent) {
|
|
mContent->GetAttribute(nsHTMLAtoms::style, val);
|
|
if (eHTMLUnit_ISupports == val.GetUnit()) {
|
|
rule = (nsIStyleRule*) val.GetISupportsValue();
|
|
result = rule->QueryInterface(kICSSStyleRuleIID, (void**)&cssRule);
|
|
if (NS_OK == result) {
|
|
*aDecl = cssRule->GetDeclaration();
|
|
NS_RELEASE(cssRule);
|
|
}
|
|
NS_RELEASE(rule);
|
|
}
|
|
else if (PR_TRUE == aAllocate) {
|
|
result = NS_NewCSSDeclaration(aDecl);
|
|
if (NS_OK == result) {
|
|
result = NS_NewCSSStyleRule(&cssRule, nsCSSSelector());
|
|
if (NS_OK == result) {
|
|
cssRule->SetDeclaration(*aDecl);
|
|
cssRule->SetWeight(0x7fffffff);
|
|
rule = (nsIStyleRule *)cssRule;
|
|
result = mContent->SetAttribute(nsHTMLAtoms::style,
|
|
nsHTMLValue(cssRule),
|
|
PR_FALSE);
|
|
NS_RELEASE(cssRule);
|
|
}
|
|
else {
|
|
NS_RELEASE(*aDecl);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
nsresult
|
|
nsDOMCSSAttributeDeclaration::StylePropertyChanged(const nsString& aPropertyName,
|
|
PRInt32 aHint)
|
|
{
|
|
nsresult result = NS_OK;
|
|
if (nsnull != mContent) {
|
|
nsIDocument *doc;
|
|
result = mContent->GetDocument(doc);
|
|
if (NS_OK == result) {
|
|
result = doc->AttributeChanged(mContent, nsHTMLAtoms::style, aHint);
|
|
NS_RELEASE(doc);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
nsresult
|
|
nsDOMCSSAttributeDeclaration::GetParent(nsISupports **aParent)
|
|
{
|
|
if (nsnull != mContent) {
|
|
return mContent->QueryInterface(kISupportsIID, (void **)aParent);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
static nsresult EnsureWritableAttributes(nsIHTMLContent* aContent,
|
|
nsIHTMLAttributes*& aAttributes, PRBool aCreate)
|
|
{
|
|
nsresult result = NS_OK;
|
|
|
|
if (nsnull == aAttributes) {
|
|
if (PR_TRUE == aCreate) {
|
|
nsMapAttributesFunc mapFunc;
|
|
result = aContent->GetAttributeMappingFunction(mapFunc);
|
|
if (NS_OK == result) {
|
|
result = NS_NewHTMLAttributes(&aAttributes, mapFunc);
|
|
if (NS_OK == result) {
|
|
aAttributes->AddContentRef();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
PRInt32 contentRefCount;
|
|
aAttributes->GetContentRefCount(contentRefCount);
|
|
if (1 < contentRefCount) {
|
|
nsIHTMLAttributes* attrs;
|
|
result = aAttributes->Clone(&attrs);
|
|
if (NS_OK == result) {
|
|
aAttributes->ReleaseContentRef();
|
|
NS_RELEASE(aAttributes);
|
|
aAttributes = attrs;
|
|
aAttributes->AddContentRef();
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static void ReleaseAttributes(nsIHTMLAttributes*& aAttributes)
|
|
{
|
|
aAttributes->ReleaseContentRef();
|
|
NS_RELEASE(aAttributes);
|
|
}
|
|
|
|
// XXX Currently, the script object factory is global. The way we
|
|
// obtain it should, at least, be made thread-safe later. Ideally,
|
|
// we'd find a better way.
|
|
nsIDOMScriptObjectFactory* nsGenericHTMLElement::gScriptObjectFactory = nsnull;
|
|
|
|
static NS_DEFINE_IID(kIDOMScriptObjectFactoryIID, NS_IDOM_SCRIPT_OBJECT_FACTORY_IID);
|
|
static NS_DEFINE_IID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetScriptObjectFactory(nsIDOMScriptObjectFactory **aResult)
|
|
{
|
|
nsresult result = NS_OK;
|
|
|
|
if (nsnull == gScriptObjectFactory) {
|
|
result = nsServiceManager::GetService(kDOMScriptObjectFactoryCID,
|
|
kIDOMScriptObjectFactoryIID,
|
|
(nsISupports **)&gScriptObjectFactory);
|
|
if (result != NS_OK) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
*aResult = gScriptObjectFactory;
|
|
NS_ADDREF(gScriptObjectFactory);
|
|
return result;
|
|
}
|
|
|
|
nsGenericHTMLElement::nsGenericHTMLElement()
|
|
{
|
|
mDocument = nsnull;
|
|
mParent = nsnull;
|
|
mAttributes = nsnull;
|
|
mTag = nsnull;
|
|
mContent = nsnull;
|
|
mDOMSlots = nsnull;
|
|
mListenerManager = nsnull;
|
|
}
|
|
|
|
nsGenericHTMLElement::~nsGenericHTMLElement()
|
|
{
|
|
if (nsnull != mAttributes) {
|
|
ReleaseAttributes(mAttributes);
|
|
}
|
|
NS_IF_RELEASE(mTag);
|
|
NS_IF_RELEASE(mListenerManager);
|
|
if (nsnull != mDOMSlots) {
|
|
if (nsnull != mDOMSlots->mChildNodes) {
|
|
mDOMSlots->mChildNodes->DropReference();
|
|
NS_RELEASE(mDOMSlots->mChildNodes);
|
|
}
|
|
if (nsnull != mDOMSlots->mStyle) {
|
|
mDOMSlots->mStyle->DropReference();
|
|
NS_RELEASE(mDOMSlots->mStyle);
|
|
}
|
|
// XXX Should really be arena managed
|
|
PR_DELETE(mDOMSlots);
|
|
}
|
|
}
|
|
|
|
nsDOMSlots *
|
|
nsGenericHTMLElement::GetDOMSlots()
|
|
{
|
|
if (nsnull == mDOMSlots) {
|
|
mDOMSlots = PR_NEW(nsDOMSlots);
|
|
mDOMSlots->mScriptObject = nsnull;
|
|
mDOMSlots->mChildNodes = nsnull;
|
|
mDOMSlots->mStyle = nsnull;
|
|
}
|
|
|
|
return mDOMSlots;
|
|
}
|
|
|
|
void
|
|
nsGenericHTMLElement::Init(nsIHTMLContent* aOuterContentObject,
|
|
nsIAtom* aTag)
|
|
{
|
|
NS_ASSERTION((nsnull == mContent) && (nsnull != aOuterContentObject),
|
|
"null ptr");
|
|
mContent = aOuterContentObject;
|
|
mTag = aTag;
|
|
NS_IF_ADDREF(aTag);
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetNodeName(nsString& aNodeName)
|
|
{
|
|
return GetTagName(aNodeName);
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetNodeValue(nsString& aNodeValue)
|
|
{
|
|
aNodeValue.Truncate();
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetNodeValue(const nsString& aNodeValue)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetNodeType(PRInt32* aNodeType)
|
|
{
|
|
*aNodeType = nsIDOMNode::ELEMENT;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetParentNode(nsIDOMNode** aParentNode)
|
|
{
|
|
if (nsnull != mParent) {
|
|
nsresult res = mParent->QueryInterface(kIDOMNodeIID, (void**)aParentNode);
|
|
NS_ASSERTION(NS_OK == res, "Must be a DOM Node");
|
|
return res;
|
|
}
|
|
else {
|
|
*aParentNode = nsnull;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetPreviousSibling(nsIDOMNode** aNode)
|
|
{
|
|
if (nsnull != mParent) {
|
|
PRInt32 pos;
|
|
mParent->IndexOf(mContent, pos);
|
|
if (pos > -1) {
|
|
nsIContent* prev;
|
|
mParent->ChildAt(--pos, prev);
|
|
if (nsnull != prev) {
|
|
nsresult res = prev->QueryInterface(kIDOMNodeIID, (void**)aNode);
|
|
NS_ASSERTION(NS_OK == res, "Must be a DOM Node");
|
|
NS_RELEASE(prev); // balance the AddRef in ChildAt()
|
|
return res;
|
|
}
|
|
}
|
|
}
|
|
*aNode = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetNextSibling(nsIDOMNode** aNextSibling)
|
|
{
|
|
if (nsnull != mParent) {
|
|
PRInt32 pos;
|
|
mParent->IndexOf(mContent, pos);
|
|
if (pos > -1 ) {
|
|
nsIContent* prev;
|
|
mParent->ChildAt(++pos, prev);
|
|
if (nsnull != prev) {
|
|
nsresult res = prev->QueryInterface(kIDOMNodeIID,(void**)aNextSibling);
|
|
NS_ASSERTION(NS_OK == res, "Must be a DOM Node");
|
|
NS_RELEASE(prev); // balance the AddRef in ChildAt()
|
|
return res;
|
|
}
|
|
}
|
|
}
|
|
*aNextSibling = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetAttributes(nsIDOMNamedNodeMap** aAttributes)
|
|
{
|
|
NS_PRECONDITION(nsnull != aAttributes, "null pointer argument");
|
|
if (nsnull != mAttributes) {
|
|
// XXX Should we create a new one every time or should we
|
|
// cache one after we create it? If we find that this is
|
|
// something that's called often, we might need to do the
|
|
// latter.
|
|
*aAttributes = new DOMAttributeMap(mContent);
|
|
}
|
|
else {
|
|
*aAttributes = nsnull;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetTagName(nsString& aTagName)
|
|
{
|
|
aTagName.Truncate();
|
|
if (nsnull != mTag) {
|
|
mTag->ToString(aTagName);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetDOMAttribute(const nsString& aName, nsString& aReturn)
|
|
{
|
|
GetAttribute(aName, aReturn);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetDOMAttribute(const nsString& aName,
|
|
const nsString& aValue)
|
|
{
|
|
SetAttribute(aName, aValue, PR_TRUE);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::RemoveAttribute(const nsString& aName)
|
|
{
|
|
nsAutoString upper;
|
|
aName.ToUpperCase(upper);
|
|
nsIAtom* attr = NS_NewAtom(upper);
|
|
UnsetAttribute(attr, PR_TRUE);
|
|
NS_RELEASE(attr);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetAttributeNode(const nsString& aName,
|
|
nsIDOMAttribute** aReturn)
|
|
{
|
|
nsAutoString value;
|
|
if (NS_CONTENT_ATTR_NOT_THERE != GetAttribute(aName, value)) {
|
|
*aReturn = new DOMAttribute(aName, value);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetAttributeNode(nsIDOMAttribute* aAttribute)
|
|
{
|
|
NS_PRECONDITION(nsnull != aAttribute, "null attribute");
|
|
|
|
nsresult res = NS_ERROR_FAILURE;
|
|
|
|
if (nsnull != aAttribute) {
|
|
nsAutoString name, value;
|
|
res = aAttribute->GetName(name);
|
|
if (NS_OK == res) {
|
|
res = aAttribute->GetValue(value);
|
|
if (NS_OK == res) {
|
|
SetAttribute(name, value, PR_TRUE);
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::RemoveAttributeNode(nsIDOMAttribute* aAttribute)
|
|
{
|
|
NS_PRECONDITION(nsnull != aAttribute, "null attribute");
|
|
|
|
nsresult res = NS_ERROR_FAILURE;
|
|
|
|
if (nsnull != aAttribute) {
|
|
nsAutoString name;
|
|
res = aAttribute->GetName(name);
|
|
if (NS_OK == res) {
|
|
nsAutoString upper;
|
|
name.ToUpperCase(upper);
|
|
nsIAtom* attr = NS_NewAtom(upper);
|
|
UnsetAttribute(attr, PR_TRUE);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetElementsByTagName(const nsString& aTagname,
|
|
nsIDOMNodeList** aReturn)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;/* XXX */
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::Normalize()
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;/* XXX */
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetId(nsString& aId)
|
|
{
|
|
GetAttribute(nsHTMLAtoms::id, aId);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetId(const nsString& aId)
|
|
{
|
|
SetAttribute(nsHTMLAtoms::id, aId, PR_TRUE);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetTitle(nsString& aTitle)
|
|
{
|
|
GetAttribute(nsHTMLAtoms::title, aTitle);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetTitle(const nsString& aTitle)
|
|
{
|
|
SetAttribute(nsHTMLAtoms::title, aTitle, PR_TRUE);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetLang(nsString& aLang)
|
|
{
|
|
GetAttribute(nsHTMLAtoms::lang, aLang);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetLang(const nsString& aLang)
|
|
{
|
|
SetAttribute(nsHTMLAtoms::lang, aLang, PR_TRUE);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetDir(nsString& aDir)
|
|
{
|
|
GetAttribute(nsHTMLAtoms::dir, aDir);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetDir(const nsString& aDir)
|
|
{
|
|
SetAttribute(nsHTMLAtoms::dir, aDir, PR_TRUE);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetClassName(nsString& aClassName)
|
|
{
|
|
GetAttribute(nsHTMLAtoms::kClass, aClassName);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetClassName(const nsString& aClassName)
|
|
{
|
|
SetAttribute(nsHTMLAtoms::kClass, aClassName, PR_TRUE);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
|
|
{
|
|
nsresult res = NS_OK;
|
|
nsDOMSlots *slots = GetDOMSlots();
|
|
|
|
if (nsnull == slots->mStyle) {
|
|
slots->mStyle = new nsDOMCSSAttributeDeclaration(mContent);
|
|
if (nsnull == slots->mStyle) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
NS_ADDREF(slots->mStyle);
|
|
}
|
|
|
|
res = slots->mStyle->QueryInterface(kIDOMCSSStyleDeclarationIID,
|
|
(void **)aStyle);
|
|
|
|
return res;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetDocument(nsIDocument*& aResult) const
|
|
{
|
|
NS_IF_ADDREF(mDocument);
|
|
aResult = mDocument;
|
|
return NS_OK;
|
|
}
|
|
|
|
static nsIHTMLStyleSheet* GetAttrStyleSheet(nsIDocument* aDocument)
|
|
{
|
|
nsIHTMLStyleSheet* sheet = nsnull;
|
|
nsIHTMLDocument* htmlDoc;
|
|
|
|
if (nsnull != aDocument) {
|
|
if (NS_OK == aDocument->QueryInterface(kIHTMLDocumentIID, (void**)&htmlDoc)) {
|
|
htmlDoc->GetAttributeStyleSheet(&sheet);
|
|
NS_RELEASE(htmlDoc);
|
|
}
|
|
}
|
|
NS_ASSERTION(nsnull != sheet, "can't get attribute style sheet");
|
|
return sheet;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetDocument(nsIDocument* aDocument)
|
|
{
|
|
mDocument = aDocument;
|
|
|
|
if ((nsnull != mDocument) && (nsnull != mAttributes)) {
|
|
nsIHTMLStyleSheet* sheet = GetAttrStyleSheet(mDocument);
|
|
if (nsnull != sheet) {
|
|
sheet->SetAttributesFor(mContent, mAttributes); // sync attributes with sheet
|
|
NS_RELEASE(sheet);
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetParent(nsIContent*& aResult) const
|
|
{
|
|
NS_IF_ADDREF(mParent);
|
|
aResult = mParent;
|
|
return NS_OK;;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetParent(nsIContent* aParent)
|
|
{
|
|
mParent = aParent;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetTag(nsIAtom*& aResult) const
|
|
{
|
|
NS_IF_ADDREF(mTag);
|
|
aResult = mTag;
|
|
return NS_OK;
|
|
}
|
|
|
|
//void
|
|
//nsHTMLTagContent::SizeOfWithoutThis(nsISizeOfHandler* aHandler) const
|
|
//{
|
|
// if (!aHandler->HaveSeen(mTag)) {
|
|
// mTag->SizeOf(aHandler);
|
|
// }
|
|
// if (!aHandler->HaveSeen(mAttributes)) {
|
|
// mAttributes->SizeOf(aHandler);
|
|
// }
|
|
//}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::HandleDOMEvent(nsIPresContext& aPresContext,
|
|
nsEvent* aEvent,
|
|
nsIDOMEvent** aDOMEvent,
|
|
PRUint32 aFlags,
|
|
nsEventStatus& aEventStatus)
|
|
{
|
|
nsresult ret = NS_OK;
|
|
|
|
nsIDOMEvent* domEvent = nsnull;
|
|
if (DOM_EVENT_INIT == aFlags) {
|
|
nsIEventStateManager *manager;
|
|
if (NS_OK == aPresContext.GetEventStateManager(&manager)) {
|
|
manager->SetEventTarget(mContent);
|
|
NS_RELEASE(manager);
|
|
}
|
|
aDOMEvent = &domEvent;
|
|
}
|
|
|
|
//Capturing stage
|
|
|
|
//Local handling stage
|
|
if (nsnull != mListenerManager) {
|
|
mListenerManager->HandleEvent(aPresContext, aEvent, aDOMEvent, aEventStatus);
|
|
}
|
|
|
|
//Bubbling stage
|
|
if (DOM_EVENT_CAPTURE != aFlags && mParent != nsnull) {
|
|
ret = mParent->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
|
|
DOM_EVENT_BUBBLE, aEventStatus);
|
|
}
|
|
|
|
if (DOM_EVENT_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 *privateEvent;
|
|
if (NS_OK == (*aDOMEvent)->QueryInterface(kIPrivateDOMEventIID, (void**)&privateEvent)) {
|
|
privateEvent->DuplicatePrivateData();
|
|
NS_RELEASE(privateEvent);
|
|
}
|
|
}
|
|
}
|
|
aDOMEvent = nsnull;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetAttribute(const nsString& aName,
|
|
const nsString& aValue,
|
|
PRBool aNotify)
|
|
{
|
|
nsAutoString upper;
|
|
aName.ToUpperCase(upper);
|
|
nsIAtom* attr = NS_NewAtom(upper);
|
|
nsresult rv = SetAttribute(attr, aValue, aNotify);
|
|
NS_RELEASE(attr);
|
|
return rv;
|
|
}
|
|
|
|
#if 0
|
|
static nsGenericHTMLElement::EnumTable kDirTable[] = {
|
|
{ "ltr", NS_STYLE_DIRECTION_LTR },
|
|
{ "rtl", NS_STYLE_DIRECTION_RTL },
|
|
{ 0 }
|
|
};
|
|
#endif
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetAttribute(nsIAtom* aAttribute,
|
|
const nsString& aValue,
|
|
PRBool aNotify)
|
|
{
|
|
nsresult result = NS_OK;
|
|
#if 0
|
|
if (nsHTMLAtoms::dir == aAttribute) {
|
|
nsHTMLValue val;
|
|
if (ParseEnumValue(aValue, kDirTable, val)) {
|
|
result = SetAttribute(aAttribute, val, aNotify);
|
|
}
|
|
else {
|
|
result = SetStringAttribute(aAttribute, aValue, aNotify);
|
|
}
|
|
}
|
|
else if (nsHTMLAtoms::lang == aAttribute) {
|
|
result = SetStringAttribute(aAttribute, aValue, aNotify);
|
|
}
|
|
else if (nsHTMLAtoms::title == aAttribute) {
|
|
result = SetStringAttribute(aAttribute, aValue, aNotify);
|
|
}
|
|
else
|
|
#endif
|
|
if (nsHTMLAtoms::style == aAttribute) {
|
|
// XXX the style sheet language is a document property that
|
|
// should be used to lookup the style sheet parser to parse the
|
|
// attribute.
|
|
nsICSSParser* css;
|
|
result = NS_NewCSSParser(&css);
|
|
if (NS_OK != result) {
|
|
return result;
|
|
}
|
|
nsIStyleRule* rule;
|
|
result = css->ParseDeclarations(aValue, nsnull, rule);
|
|
if ((NS_OK == result) && (nsnull != rule)) {
|
|
result = SetAttribute(aAttribute, nsHTMLValue(rule), aNotify);
|
|
NS_RELEASE(rule);
|
|
}
|
|
NS_RELEASE(css);
|
|
}
|
|
else {
|
|
// Check for event handlers
|
|
if (nsHTMLAtoms::onclick == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::onclick, aValue, kIDOMMouseListenerIID);
|
|
else if (nsHTMLAtoms::ondblclick == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::ondblclick, aValue, kIDOMMouseListenerIID);
|
|
else if (nsHTMLAtoms::onmousedown == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::onmousedown, aValue, kIDOMMouseListenerIID);
|
|
else if (nsHTMLAtoms::onmouseup == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::onmouseup, aValue, kIDOMMouseListenerIID);
|
|
else if (nsHTMLAtoms::onmouseover == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::onmouseover, aValue, kIDOMMouseListenerIID);
|
|
else if (nsHTMLAtoms::onmouseout == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::onmouseout, aValue, kIDOMMouseListenerIID);
|
|
else if (nsHTMLAtoms::onkeydown == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::onkeydown, aValue, kIDOMKeyListenerIID);
|
|
else if (nsHTMLAtoms::onkeyup == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::onkeyup, aValue, kIDOMKeyListenerIID);
|
|
else if (nsHTMLAtoms::onkeypress == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::onkeypress, aValue, kIDOMKeyListenerIID);
|
|
else if (nsHTMLAtoms::onmousemove == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::onmousemove, aValue, kIDOMMouseMotionListenerIID);
|
|
else if (nsHTMLAtoms::onload == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::onload, aValue, kIDOMLoadListenerIID);
|
|
else if (nsHTMLAtoms::onunload == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::onunload, aValue, kIDOMLoadListenerIID);
|
|
else if (nsHTMLAtoms::onabort == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::onabort, aValue, kIDOMLoadListenerIID);
|
|
else if (nsHTMLAtoms::onerror == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::onerror, aValue, kIDOMLoadListenerIID);
|
|
else if (nsHTMLAtoms::onfocus == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::onfocus, aValue, kIDOMFocusListenerIID);
|
|
else if (nsHTMLAtoms::onblur == aAttribute)
|
|
AddScriptEventListener(nsHTMLAtoms::onblur, aValue, kIDOMFocusListenerIID);
|
|
else if (nsHTMLAtoms::onpaint == aAttribute)
|
|
AddScriptEventListener(aAttribute, aValue, kIDOMPaintListenerIID);
|
|
|
|
nsHTMLValue val;
|
|
if (NS_CONTENT_ATTR_NOT_THERE !=
|
|
mContent->StringToAttribute(aAttribute, aValue, val)) {
|
|
// string value was mapped to nsHTMLValue, set it that way
|
|
result = SetAttribute(aAttribute, val, aNotify);
|
|
return result;
|
|
}
|
|
else {
|
|
// set as string value to avoid another string copy
|
|
if (nsnull != mDocument) { // set attr via style sheet
|
|
nsIHTMLStyleSheet* sheet = GetAttrStyleSheet(mDocument);
|
|
if (nsnull != sheet) {
|
|
result = sheet->SetAttributeFor(aAttribute, aValue, mContent, mAttributes);
|
|
NS_RELEASE(sheet);
|
|
}
|
|
}
|
|
else { // manage this ourselves and re-sync when we connect to doc
|
|
result = EnsureWritableAttributes(mContent, mAttributes, PR_TRUE);
|
|
if (nsnull != mAttributes) {
|
|
PRInt32 count;
|
|
result = mAttributes->SetAttribute(aAttribute, aValue, count);
|
|
if (0 == count) {
|
|
ReleaseAttributes(mAttributes);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (aNotify && (nsnull != mDocument)) {
|
|
mDocument->AttributeChanged(mContent, aAttribute, NS_STYLE_HINT_UNKNOWN);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetAttribute(nsIAtom* aAttribute,
|
|
const nsHTMLValue& aValue,
|
|
PRBool aNotify)
|
|
{
|
|
nsresult result = NS_OK;
|
|
if (nsnull != mDocument) { // set attr via style sheet
|
|
nsIHTMLStyleSheet* sheet = GetAttrStyleSheet(mDocument);
|
|
if (nsnull != sheet) {
|
|
result = sheet->SetAttributeFor(aAttribute, aValue, mContent,
|
|
mAttributes);
|
|
NS_RELEASE(sheet);
|
|
}
|
|
if (aNotify) {
|
|
mDocument->AttributeChanged(mContent, aAttribute, NS_STYLE_HINT_UNKNOWN);
|
|
}
|
|
}
|
|
else { // manage this ourselves and re-sync when we connect to doc
|
|
result = EnsureWritableAttributes(mContent, mAttributes, PR_TRUE);
|
|
if (nsnull != mAttributes) {
|
|
PRInt32 count;
|
|
result = mAttributes->SetAttribute(aAttribute, aValue, count);
|
|
if (0 == count) {
|
|
ReleaseAttributes(mAttributes);
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Handle attributes common to all html elements
|
|
*/
|
|
void
|
|
nsGenericHTMLElement::MapCommonAttributesInto(nsIHTMLAttributes* aAttributes,
|
|
nsIStyleContext* aStyleContext,
|
|
nsIPresContext* aPresContext)
|
|
{
|
|
if (nsnull != aAttributes) {
|
|
nsHTMLValue value;
|
|
aAttributes->GetAttribute(nsHTMLAtoms::dir, value);
|
|
if (value.GetUnit() == eHTMLUnit_Enumerated) {
|
|
nsStyleDisplay* display = (nsStyleDisplay*)
|
|
aStyleContext->GetMutableStyleData(eStyleStruct_Display);
|
|
display->mDirection = value.GetIntValue();
|
|
}
|
|
}
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::UnsetAttribute(nsIAtom* aAttribute, PRBool aNotify)
|
|
{
|
|
nsresult result = NS_OK;
|
|
if (nsnull != mDocument) { // set attr via style sheet
|
|
nsIHTMLStyleSheet* sheet = GetAttrStyleSheet(mDocument);
|
|
if (nsnull != sheet) {
|
|
result = sheet->UnsetAttributeFor(aAttribute, mContent, mAttributes);
|
|
NS_RELEASE(sheet);
|
|
}
|
|
if (aNotify) {
|
|
mDocument->AttributeChanged(mContent, aAttribute, NS_STYLE_HINT_UNKNOWN);
|
|
}
|
|
}
|
|
else { // manage this ourselves and re-sync when we connect to doc
|
|
result = EnsureWritableAttributes(mContent, mAttributes, PR_FALSE);
|
|
if (nsnull != mAttributes) {
|
|
PRInt32 count;
|
|
result = mAttributes->UnsetAttribute(aAttribute, count);
|
|
if (0 == count) {
|
|
ReleaseAttributes(mAttributes);
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetAttribute(const nsString& aName,
|
|
nsString& aResult) const
|
|
{
|
|
nsAutoString upper;
|
|
aName.ToUpperCase(upper);
|
|
nsIAtom* attr = NS_NewAtom(upper);
|
|
nsresult result = GetAttribute(attr, aResult);
|
|
NS_RELEASE(attr);
|
|
return result;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetAttribute(nsIAtom *aAttribute,
|
|
nsString &aResult) const
|
|
{
|
|
nsHTMLValue value;
|
|
nsresult result = GetAttribute(aAttribute, value);
|
|
|
|
char cbuf[20];
|
|
nscolor color;
|
|
if (NS_CONTENT_ATTR_HAS_VALUE == result) {
|
|
// Try subclass conversion routine first
|
|
if (NS_CONTENT_ATTR_HAS_VALUE ==
|
|
mContent->AttributeToString(aAttribute, value, aResult)) {
|
|
return result;
|
|
}
|
|
|
|
// Provide default conversions for most everything
|
|
switch (value.GetUnit()) {
|
|
case eHTMLUnit_Empty:
|
|
aResult.Truncate();
|
|
break;
|
|
|
|
case eHTMLUnit_String:
|
|
case eHTMLUnit_Null:
|
|
value.GetStringValue(aResult);
|
|
break;
|
|
|
|
case eHTMLUnit_Integer:
|
|
aResult.Truncate();
|
|
aResult.Append(value.GetIntValue(), 10);
|
|
break;
|
|
|
|
case eHTMLUnit_Pixel:
|
|
aResult.Truncate();
|
|
aResult.Append(value.GetPixelValue(), 10);
|
|
break;
|
|
|
|
case eHTMLUnit_Percent:
|
|
aResult.Truncate(0);
|
|
aResult.Append(PRInt32(value.GetPercentValue() * 100.0f), 10);
|
|
aResult.Append('%');
|
|
break;
|
|
|
|
case eHTMLUnit_Color:
|
|
color = nscolor(value.GetColorValue());
|
|
PR_snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
|
|
NS_GET_R(color), NS_GET_G(color), NS_GET_B(color));
|
|
aResult.Truncate(0);
|
|
aResult.Append(cbuf);
|
|
break;
|
|
|
|
default:
|
|
case eHTMLUnit_Enumerated:
|
|
NS_NOTREACHED("no default enumerated value to string conversion");
|
|
result = NS_CONTENT_ATTR_NOT_THERE;
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetAttribute(nsIAtom* aAttribute,
|
|
nsHTMLValue& aValue) const
|
|
{
|
|
if (nsnull != mAttributes) {
|
|
return mAttributes->GetAttribute(aAttribute, aValue);
|
|
}
|
|
aValue.Reset();
|
|
return NS_CONTENT_ATTR_NOT_THERE;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetAllAttributeNames(nsISupportsArray* aArray,
|
|
PRInt32& aCount) const
|
|
{
|
|
if (nsnull != mAttributes) {
|
|
return mAttributes->GetAllAttributeNames(aArray, aCount);
|
|
}
|
|
aCount = 0;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetAttributeCount(PRInt32& aCount) const
|
|
{
|
|
if (nsnull != mAttributes) {
|
|
return mAttributes->Count(aCount);
|
|
}
|
|
aCount = 0;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetID(nsIAtom* aID)
|
|
{
|
|
nsresult result = NS_OK;
|
|
if (nsnull != mDocument) { // set attr via style sheet
|
|
nsIHTMLStyleSheet* sheet = GetAttrStyleSheet(mDocument);
|
|
if (nsnull != sheet) {
|
|
result = sheet->SetIDFor(aID, mContent, mAttributes);
|
|
NS_RELEASE(sheet);
|
|
}
|
|
}
|
|
else { // manage this ourselves and re-sync when we connect to doc
|
|
EnsureWritableAttributes(mContent, mAttributes, PRBool(nsnull != aID));
|
|
if (nsnull != mAttributes) {
|
|
PRInt32 count;
|
|
result = mAttributes->SetID(aID, count);
|
|
if (0 == count) {
|
|
ReleaseAttributes(mAttributes);
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetID(nsIAtom*& aResult) const
|
|
{
|
|
if (nsnull != mAttributes) {
|
|
return mAttributes->GetID(aResult);
|
|
}
|
|
aResult = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetClass(nsIAtom* aClass)
|
|
{
|
|
nsresult result = NS_OK;
|
|
if (nsnull != mDocument) { // set attr via style sheet
|
|
nsIHTMLStyleSheet* sheet = GetAttrStyleSheet(mDocument);
|
|
if (nsnull != sheet) {
|
|
result = sheet->SetClassFor(aClass, mContent, mAttributes);
|
|
NS_RELEASE(sheet);
|
|
}
|
|
}
|
|
else { // manage this ourselves and re-sync when we connect to doc
|
|
EnsureWritableAttributes(mContent, mAttributes, PRBool(nsnull != aClass));
|
|
if (nsnull != mAttributes) {
|
|
PRInt32 count;
|
|
result = mAttributes->SetClass(aClass, count);
|
|
if (0 == count) {
|
|
ReleaseAttributes(mAttributes);
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetClass(nsIAtom*& aResult) const
|
|
{
|
|
if (nsnull != mAttributes) {
|
|
return mAttributes->GetClass(aResult);
|
|
}
|
|
aResult = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetStyleRule(nsIStyleRule*& aResult)
|
|
{
|
|
nsIStyleRule* result = nsnull;
|
|
|
|
if (nsnull != mAttributes) {
|
|
mAttributes->QueryInterface(kIStyleRuleIID, (void**)&result);
|
|
}
|
|
aResult = result;
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsGenericHTMLElement::ListAttributes(FILE* out) const
|
|
{
|
|
nsISupportsArray* attrs;
|
|
if (NS_OK == NS_NewISupportsArray(&attrs)) {
|
|
PRInt32 index, count;
|
|
GetAllAttributeNames(attrs, count);
|
|
for (index = 0; index < count; index++) {
|
|
// name
|
|
nsIAtom* attr = (nsIAtom*)attrs->ElementAt(index);
|
|
nsAutoString buffer;
|
|
attr->ToString(buffer);
|
|
|
|
// value
|
|
nsAutoString value;
|
|
GetAttribute(buffer, value);
|
|
buffer.Append("=");
|
|
buffer.Append(value);
|
|
|
|
fputs(" ", out);
|
|
fputs(buffer, out);
|
|
NS_RELEASE(attr);
|
|
}
|
|
NS_RELEASE(attrs);
|
|
}
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::List(FILE* out, PRInt32 aIndent) const
|
|
{
|
|
NS_PRECONDITION(nsnull != mDocument, "bad content");
|
|
|
|
PRInt32 index;
|
|
for (index = aIndent; --index >= 0; ) fputs(" ", out);
|
|
|
|
nsIAtom* tag;
|
|
GetTag(tag);
|
|
if (tag != nsnull) {
|
|
nsAutoString buf;
|
|
tag->ToString(buf);
|
|
fputs(buf, out);
|
|
NS_RELEASE(tag);
|
|
}
|
|
|
|
ListAttributes(out);
|
|
|
|
nsIHTMLContent* hc = mContent;
|
|
nsrefcnt r = NS_ADDREF(hc) - 1;
|
|
NS_RELEASE(hc);
|
|
fprintf(out, " refcount=%d<", r);
|
|
|
|
PRBool canHaveKids;
|
|
mContent->CanContainChildren(canHaveKids);
|
|
if (canHaveKids) {
|
|
fputs("\n", out);
|
|
PRInt32 kids;
|
|
mContent->ChildCount(kids);
|
|
for (index = 0; index < kids; index++) {
|
|
nsIContent* kid;
|
|
mContent->ChildAt(index, kid);
|
|
kid->List(out, aIndent + 1);
|
|
NS_RELEASE(kid);
|
|
}
|
|
for (index = aIndent; --index >= 0; ) fputs(" ", out);
|
|
}
|
|
fputs(">\n", out);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::ToHTML(FILE* out) const
|
|
{
|
|
nsAutoString tmp;
|
|
nsresult rv = ToHTMLString(tmp);
|
|
fputs(tmp, out);
|
|
return rv;
|
|
}
|
|
|
|
// XXX i18n: this is wrong (?) because we need to know the outgoing
|
|
// character set (I think)
|
|
void
|
|
NS_QuoteForHTML(const nsString& aValue, nsString& aResult)
|
|
{
|
|
aResult.Truncate();
|
|
const PRUnichar* cp = aValue.GetUnicode();
|
|
const PRUnichar* end = aValue.GetUnicode() + aValue.Length();
|
|
aResult.Append('"');
|
|
while (cp < end) {
|
|
PRUnichar ch = *cp++;
|
|
if ((ch >= 0x20) && (ch <= 0x7f)) {
|
|
if (ch == '\"') {
|
|
aResult.Append(""");
|
|
}
|
|
else {
|
|
aResult.Append(ch);
|
|
}
|
|
}
|
|
else {
|
|
aResult.Append("&#");
|
|
aResult.Append((PRInt32) ch, 10);
|
|
aResult.Append(';');
|
|
}
|
|
}
|
|
aResult.Append('"');
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::ToHTMLString(nsString& aBuf) const
|
|
{
|
|
aBuf.Truncate(0);
|
|
aBuf.Append('<');
|
|
|
|
if (nsnull != mTag) {
|
|
nsAutoString tmp;
|
|
mTag->ToString(tmp);
|
|
aBuf.Append(tmp);
|
|
} else {
|
|
aBuf.Append("?NULL");
|
|
}
|
|
|
|
if (nsnull != mAttributes) {
|
|
nsISupportsArray* attrs;
|
|
nsresult rv = NS_NewISupportsArray(&attrs);
|
|
if (NS_OK == rv) {
|
|
PRInt32 i, n;
|
|
mAttributes->GetAllAttributeNames(attrs, n);
|
|
nsAutoString name, value, quotedValue;
|
|
for (i = 0; i < n; i++) {
|
|
nsIAtom* atom = (nsIAtom*) attrs->ElementAt(i);
|
|
atom->ToString(name);
|
|
aBuf.Append(' ');
|
|
aBuf.Append(name);
|
|
value.Truncate();
|
|
GetAttribute(name, value);
|
|
if (value.Length() > 0) {
|
|
aBuf.Append('=');
|
|
NS_QuoteForHTML(value, quotedValue);
|
|
aBuf.Append(quotedValue);
|
|
}
|
|
}
|
|
NS_RELEASE(attrs);
|
|
}
|
|
}
|
|
|
|
aBuf.Append('>');
|
|
return NS_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::RenderFrame()
|
|
{
|
|
nsPoint offset;
|
|
nsRect bounds;
|
|
|
|
// Trigger damage repairs for each frame that maps the given content
|
|
PRInt32 i, n;
|
|
n = mDocument->GetNumberOfShells();
|
|
for (i = 0; i < n; i++) {
|
|
nsIPresShell* shell;
|
|
shell = mDocument->GetShellAt(i);
|
|
nsIFrame* frame;
|
|
frame = shell->FindFrameWithContent(mContent);
|
|
while (nsnull != frame) {
|
|
nsIViewManager* vm;
|
|
nsIView* view;
|
|
|
|
// Determine damaged area and tell view manager to redraw it
|
|
frame->GetRect(bounds);
|
|
bounds.x = bounds.y = 0;
|
|
|
|
// XXX We should tell the frame the damage area and let it invalidate
|
|
// itself. Add some API calls to nsIFrame to allow a caller to invalidate
|
|
// parts of the frame...
|
|
frame->GetOffsetFromView(offset, view);
|
|
view->GetViewManager(vm);
|
|
bounds.x += offset.x;
|
|
bounds.y += offset.y;
|
|
|
|
vm->UpdateView(view, bounds, NS_VMREFRESH_IMMEDIATE);
|
|
NS_RELEASE(vm);
|
|
|
|
// If frame has a next-in-flow, repaint it too
|
|
frame->GetNextInFlow(frame);
|
|
}
|
|
NS_RELEASE(shell);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// nsIScriptObjectOwner implementation
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetScriptObject(nsIScriptContext* aContext,
|
|
void** aScriptObject)
|
|
{
|
|
nsresult res = NS_OK;
|
|
nsDOMSlots *slots = GetDOMSlots();
|
|
|
|
if (nsnull == slots->mScriptObject) {
|
|
nsIDOMScriptObjectFactory *factory;
|
|
|
|
res = GetScriptObjectFactory(&factory);
|
|
if (NS_OK != res) {
|
|
return res;
|
|
}
|
|
|
|
nsAutoString tag;
|
|
mTag->ToString(tag);
|
|
res = factory->NewScriptElement(tag, aContext, mContent,
|
|
mParent, (void**)&slots->mScriptObject);
|
|
NS_RELEASE(factory);
|
|
}
|
|
*aScriptObject = slots->mScriptObject;
|
|
return res;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::SetScriptObject(void *aScriptObject)
|
|
{
|
|
nsDOMSlots *slots = GetDOMSlots();
|
|
|
|
slots->mScriptObject = aScriptObject;
|
|
return NS_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// nsIDOMEventReceiver implementation
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetListenerManager(nsIEventListenerManager** aResult)
|
|
{
|
|
if (nsnull != mListenerManager) {
|
|
NS_ADDREF(mListenerManager);
|
|
*aResult = mListenerManager;
|
|
return NS_OK;
|
|
}
|
|
nsresult rv = NS_NewEventListenerManager(aResult);
|
|
if (NS_OK == rv) {
|
|
mListenerManager = *aResult;
|
|
NS_ADDREF(mListenerManager);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::GetNewListenerManager(nsIEventListenerManager** aResult)
|
|
{
|
|
return NS_NewEventListenerManager(aResult);
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::AddEventListener(nsIDOMEventListener* aListener,
|
|
const nsIID& aIID)
|
|
{
|
|
nsIEventListenerManager *manager;
|
|
|
|
if (NS_OK == GetListenerManager(&manager)) {
|
|
manager->AddEventListener(aListener, aIID);
|
|
NS_RELEASE(manager);
|
|
return NS_OK;
|
|
}
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::RemoveEventListener(nsIDOMEventListener* aListener,
|
|
const nsIID& aIID)
|
|
{
|
|
if (nsnull != mListenerManager) {
|
|
mListenerManager->RemoveEventListener(aListener, aIID);
|
|
return NS_OK;
|
|
}
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// nsIJSScriptObject implementation
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::AddProperty(JSContext *aContext, jsval aID, jsval *aVp)
|
|
{
|
|
return PR_TRUE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::DeleteProperty(JSContext *aContext, jsval aID, jsval *aVp)
|
|
{
|
|
return PR_TRUE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::GetProperty(JSContext *aContext, jsval aID, jsval *aVp)
|
|
{
|
|
return PR_TRUE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::SetProperty(JSContext *aContext, jsval aID, jsval *aVp)
|
|
{
|
|
nsIScriptObjectOwner *owner;
|
|
|
|
if (NS_OK != mContent->QueryInterface(kIScriptObjectOwnerIID, (void **)&owner)) {
|
|
return PR_FALSE;
|
|
}
|
|
|
|
if (JS_TypeOfValue(aContext, *aVp) == JSTYPE_FUNCTION && JSVAL_IS_STRING(aID)) {
|
|
nsAutoString propName, prefix;
|
|
propName.SetString(JS_GetStringChars(JS_ValueToString(aContext, aID)));
|
|
prefix.SetString(propName, 2);
|
|
if (prefix == "on") {
|
|
nsIEventListenerManager *manager = nsnull;
|
|
|
|
if (propName == "onmousedown" || propName == "onmouseup" || propName == "onclick" ||
|
|
propName == "onmouseover" || propName == "onmouseout") {
|
|
if (NS_OK == GetListenerManager(&manager)) {
|
|
nsIScriptContext *mScriptCX = (nsIScriptContext *)JS_GetContextPrivate(aContext);
|
|
if (NS_OK != manager->RegisterScriptEventListener(mScriptCX, owner, kIDOMMouseListenerIID)) {
|
|
NS_RELEASE(manager);
|
|
return PR_FALSE;
|
|
}
|
|
}
|
|
}
|
|
else if (propName == "onkeydown" || propName == "onkeyup" || propName == "onkeypress") {
|
|
if (NS_OK == GetListenerManager(&manager)) {
|
|
nsIScriptContext *mScriptCX = (nsIScriptContext *)JS_GetContextPrivate(aContext);
|
|
if (NS_OK != manager->RegisterScriptEventListener(mScriptCX, owner, kIDOMKeyListenerIID)) {
|
|
NS_RELEASE(manager);
|
|
return PR_FALSE;
|
|
}
|
|
}
|
|
}
|
|
else if (propName == "onmousemove") {
|
|
if (NS_OK == GetListenerManager(&manager)) {
|
|
nsIScriptContext *mScriptCX = (nsIScriptContext *)JS_GetContextPrivate(aContext);
|
|
if (NS_OK != manager->RegisterScriptEventListener(mScriptCX, owner, kIDOMMouseMotionListenerIID)) {
|
|
NS_RELEASE(manager);
|
|
return PR_FALSE;
|
|
}
|
|
}
|
|
}
|
|
else if (propName == "onfocus" || propName == "onblur") {
|
|
if (NS_OK == GetListenerManager(&manager)) {
|
|
nsIScriptContext *mScriptCX = (nsIScriptContext *)JS_GetContextPrivate(aContext);
|
|
if (NS_OK != manager->RegisterScriptEventListener(mScriptCX, owner, kIDOMFocusListenerIID)) {
|
|
NS_RELEASE(manager);
|
|
return PR_FALSE;
|
|
}
|
|
}
|
|
}
|
|
else if (propName == "onsubmit" || propName == "onreset") {
|
|
if (NS_OK == GetListenerManager(&manager)) {
|
|
nsIScriptContext *mScriptCX = (nsIScriptContext *)JS_GetContextPrivate(aContext);
|
|
if (NS_OK != manager->RegisterScriptEventListener(mScriptCX, owner, kIDOMFormListenerIID)) {
|
|
NS_RELEASE(manager);
|
|
return PR_FALSE;
|
|
}
|
|
}
|
|
}
|
|
else if (propName == "onload" || propName == "onunload" || propName == "onabort" ||
|
|
propName == "onerror") {
|
|
if (NS_OK == GetListenerManager(&manager)) {
|
|
nsIScriptContext *mScriptCX = (nsIScriptContext *)JS_GetContextPrivate(aContext);
|
|
if (NS_OK != manager->RegisterScriptEventListener(mScriptCX, owner, kIDOMLoadListenerIID)) {
|
|
NS_RELEASE(manager);
|
|
return PR_FALSE;
|
|
}
|
|
}
|
|
}
|
|
else if (propName == "onpaint") {
|
|
if (NS_OK == GetListenerManager(&manager)) {
|
|
nsIScriptContext *mScriptCX = (nsIScriptContext *)
|
|
JS_GetContextPrivate(aContext);
|
|
if (NS_OK != manager->RegisterScriptEventListener(mScriptCX, owner,
|
|
kIDOMPaintListenerIID)) {
|
|
NS_RELEASE(manager);
|
|
return PR_FALSE;
|
|
}
|
|
}
|
|
}
|
|
NS_IF_RELEASE(manager);
|
|
}
|
|
}
|
|
|
|
NS_IF_RELEASE(owner);
|
|
|
|
return PR_TRUE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::EnumerateProperty(JSContext *aContext)
|
|
{
|
|
return PR_TRUE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::Resolve(JSContext *aContext, jsval aID)
|
|
{
|
|
return PR_TRUE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::Convert(JSContext *aContext, jsval aID)
|
|
{
|
|
return PR_TRUE;
|
|
}
|
|
|
|
void
|
|
nsGenericHTMLElement::Finalize(JSContext *aContext)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// nsISupports implementation
|
|
|
|
NS_IMETHODIMP
|
|
nsGenericHTMLElement::QueryInterface(REFNSIID aIID,void** aInstancePtr)
|
|
{
|
|
return mContent->QueryInterface(aIID, aInstancePtr);
|
|
}
|
|
|
|
NS_IMETHODIMP_(nsrefcnt)
|
|
nsGenericHTMLElement::AddRef()
|
|
{
|
|
return NS_ADDREF(mContent);
|
|
}
|
|
|
|
NS_IMETHODIMP_(nsrefcnt)
|
|
nsGenericHTMLElement::Release()
|
|
{
|
|
nsIHTMLContent* content = mContent;
|
|
|
|
// Release the copy since the macro will null the pointer.
|
|
return NS_RELEASE(content);
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::AddScriptEventListener(nsIAtom* aAttribute,
|
|
const nsString& aValue,
|
|
REFNSIID aIID)
|
|
{
|
|
nsresult ret = NS_OK;
|
|
nsIScriptContext* context;
|
|
nsIScriptContextOwner* owner;
|
|
|
|
if (nsnull != mDocument) {
|
|
owner = mDocument->GetScriptContextOwner();
|
|
if (NS_OK == owner->GetScriptContext(&context)) {
|
|
if (nsHTMLAtoms::body == mTag || nsHTMLAtoms::frameset == mTag) {
|
|
nsIDOMEventReceiver *receiver;
|
|
nsIScriptGlobalObject *global = context->GetGlobalObject();
|
|
|
|
if (nsnull != global && NS_OK == global->QueryInterface(kIDOMEventReceiverIID, (void**)&receiver)) {
|
|
nsIEventListenerManager *manager;
|
|
if (NS_OK == receiver->GetListenerManager(&manager)) {
|
|
nsIScriptObjectOwner *mObjectOwner;
|
|
if (NS_OK == global->QueryInterface(kIScriptObjectOwnerIID, (void**)&mObjectOwner)) {
|
|
ret = manager->AddScriptEventListener(context, mObjectOwner, aAttribute, aValue, aIID);
|
|
NS_RELEASE(mObjectOwner);
|
|
}
|
|
NS_RELEASE(manager);
|
|
}
|
|
NS_RELEASE(receiver);
|
|
}
|
|
NS_IF_RELEASE(global);
|
|
}
|
|
else {
|
|
nsIEventListenerManager *manager;
|
|
if (NS_OK == GetListenerManager(&manager)) {
|
|
nsIScriptObjectOwner* owner;
|
|
if (NS_OK == mContent->QueryInterface(kIScriptObjectOwnerIID,
|
|
(void**) &owner)) {
|
|
ret = manager->AddScriptEventListener(context, owner,
|
|
aAttribute, aValue, aIID);
|
|
NS_RELEASE(owner);
|
|
}
|
|
NS_RELEASE(manager);
|
|
}
|
|
}
|
|
NS_RELEASE(context);
|
|
}
|
|
NS_RELEASE(owner);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLElement::AttributeToString(nsIAtom* aAttribute,
|
|
nsHTMLValue& aValue,
|
|
nsString& aResult) const
|
|
{
|
|
if (nsHTMLAtoms::style == aAttribute) {
|
|
if (eHTMLUnit_ISupports == aValue.GetUnit()) {
|
|
nsIStyleRule* rule = (nsIStyleRule*) aValue.GetISupportsValue();
|
|
nsICSSStyleRule* cssRule;
|
|
if (NS_OK == rule->QueryInterface(kICSSStyleRuleIID, (void**)&cssRule)) {
|
|
nsICSSDeclaration* decl = cssRule->GetDeclaration();
|
|
if (nsnull != decl) {
|
|
decl->ToString(aResult);
|
|
}
|
|
NS_RELEASE(cssRule);
|
|
}
|
|
else {
|
|
aResult = "Unknown rule type";
|
|
}
|
|
return NS_CONTENT_ATTR_HAS_VALUE;
|
|
}
|
|
}
|
|
aResult.Truncate();
|
|
return NS_CONTENT_ATTR_NOT_THERE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ParseEnumValue(const nsString& aValue,
|
|
EnumTable* aTable,
|
|
nsHTMLValue& aResult)
|
|
{
|
|
while (nsnull != aTable->tag) {
|
|
if (aValue.EqualsIgnoreCase(aTable->tag)) {
|
|
aResult.SetIntValue(aTable->value, eHTMLUnit_Enumerated);
|
|
return PR_TRUE;
|
|
}
|
|
aTable++;
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ParseCaseSensitiveEnumValue(const nsString& aValue,
|
|
EnumTable* aTable,
|
|
nsHTMLValue& aResult)
|
|
{
|
|
while (nsnull != aTable->tag) {
|
|
if (aValue.Equals(aTable->tag)) {
|
|
aResult.SetIntValue(aTable->value, eHTMLUnit_Enumerated);
|
|
return PR_TRUE;
|
|
}
|
|
aTable++;
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::EnumValueToString(const nsHTMLValue& aValue,
|
|
EnumTable* aTable,
|
|
nsString& aResult)
|
|
{
|
|
aResult.Truncate(0);
|
|
if (aValue.GetUnit() == eHTMLUnit_Enumerated) {
|
|
PRInt32 v = aValue.GetIntValue();
|
|
while (nsnull != aTable->tag) {
|
|
if (aTable->value == v) {
|
|
aResult.Append(aTable->tag);
|
|
return PR_TRUE;
|
|
}
|
|
aTable++;
|
|
}
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ParseValueOrPercent(const nsString& aString,
|
|
nsHTMLValue& aResult,
|
|
nsHTMLUnit aValueUnit)
|
|
{
|
|
nsAutoString tmp(aString);
|
|
tmp.CompressWhitespace(PR_TRUE, PR_TRUE);
|
|
PRInt32 ec, val = tmp.ToInteger(&ec);
|
|
if (NS_OK == ec) {
|
|
if (val < 0) val = 0;
|
|
if (tmp.Last() == '%') {/* XXX not 100% compatible with ebina's code */
|
|
if (val > 100) val = 100;
|
|
aResult.SetPercentValue(float(val)/100.0f);
|
|
} else {
|
|
if (eHTMLUnit_Pixel == aValueUnit) {
|
|
aResult.SetPixelValue(val);
|
|
}
|
|
else {
|
|
aResult.SetIntValue(val, aValueUnit);
|
|
}
|
|
}
|
|
return PR_TRUE;
|
|
}
|
|
|
|
// Illegal values are mapped to empty
|
|
aResult.SetEmptyValue();
|
|
return PR_FALSE;
|
|
}
|
|
|
|
/* used to parse attribute values that could be either:
|
|
* integer (n),
|
|
* percent (n%),
|
|
* or proportional (n*)
|
|
*/
|
|
void
|
|
nsGenericHTMLElement::ParseValueOrPercentOrProportional(const nsString& aString,
|
|
nsHTMLValue& aResult,
|
|
nsHTMLUnit aValueUnit)
|
|
{
|
|
nsAutoString tmp(aString);
|
|
tmp.CompressWhitespace(PR_TRUE, PR_TRUE);
|
|
PRInt32 ec, val = tmp.ToInteger(&ec);
|
|
if (NS_OK == ec) {
|
|
if (val < 0) val = 0;
|
|
if (tmp.Last() == '%') {/* XXX not 100% compatible with ebina's code */
|
|
if (val > 100) val = 100;
|
|
aResult.SetPercentValue(float(val)/100.0f);
|
|
} else if (tmp.Last() == '*') {
|
|
aResult.SetIntValue(val, eHTMLUnit_Proportional); // proportional values are integers
|
|
} else {
|
|
if (eHTMLUnit_Pixel == aValueUnit) {
|
|
aResult.SetPixelValue(val);
|
|
}
|
|
else {
|
|
aResult.SetIntValue(val, aValueUnit);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ValueOrPercentToString(const nsHTMLValue& aValue,
|
|
nsString& aResult)
|
|
{
|
|
aResult.Truncate(0);
|
|
switch (aValue.GetUnit()) {
|
|
case eHTMLUnit_Integer:
|
|
aResult.Append(aValue.GetIntValue(), 10);
|
|
return PR_TRUE;
|
|
case eHTMLUnit_Pixel:
|
|
aResult.Append(aValue.GetPixelValue(), 10);
|
|
return PR_TRUE;
|
|
case eHTMLUnit_Percent:
|
|
aResult.Append(PRInt32(aValue.GetPercentValue() * 100.0f), 10);
|
|
aResult.Append('%');
|
|
return PR_TRUE;
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ParseValue(const nsString& aString, PRInt32 aMin,
|
|
nsHTMLValue& aResult, nsHTMLUnit aValueUnit)
|
|
{
|
|
PRInt32 ec, val = aString.ToInteger(&ec);
|
|
if (NS_OK == ec) {
|
|
if (val < aMin) val = aMin;
|
|
if (eHTMLUnit_Pixel == aValueUnit) {
|
|
aResult.SetPixelValue(val);
|
|
}
|
|
else {
|
|
aResult.SetIntValue(val, aValueUnit);
|
|
}
|
|
return PR_TRUE;
|
|
}
|
|
|
|
// Illegal values are mapped to empty
|
|
aResult.SetEmptyValue();
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ParseValue(const nsString& aString, PRInt32 aMin,
|
|
PRInt32 aMax,
|
|
nsHTMLValue& aResult, nsHTMLUnit aValueUnit)
|
|
{
|
|
PRInt32 ec, val = aString.ToInteger(&ec);
|
|
if (NS_OK == ec) {
|
|
if (val < aMin) val = aMin;
|
|
if (val > aMax) val = aMax;
|
|
if (eHTMLUnit_Pixel == aValueUnit) {
|
|
aResult.SetPixelValue(val);
|
|
}
|
|
else {
|
|
aResult.SetIntValue(val, aValueUnit);
|
|
}
|
|
return PR_TRUE;
|
|
}
|
|
|
|
// Illegal values are mapped to empty
|
|
aResult.SetEmptyValue();
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ParseColor(const nsString& aString,
|
|
nsHTMLValue& aResult)
|
|
{
|
|
if (aString.Length() > 0) {
|
|
nsAutoString colorStr (aString);
|
|
colorStr.CompressWhitespace();
|
|
char cbuf[40];
|
|
colorStr.ToCString(cbuf, sizeof(cbuf));
|
|
nscolor color;
|
|
if (NS_ColorNameToRGB(cbuf, &color)) {
|
|
aResult.SetStringValue(colorStr);
|
|
return PR_TRUE;
|
|
}
|
|
if (NS_LooseHexToRGB(cbuf, &color)) {
|
|
aResult.SetColorValue(color);
|
|
return PR_TRUE;
|
|
}
|
|
}
|
|
|
|
// Illegal values are mapped to empty
|
|
aResult.SetEmptyValue();
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ColorToString(const nsHTMLValue& aValue,
|
|
nsString& aResult)
|
|
{
|
|
if (aValue.GetUnit() == eHTMLUnit_Color) {
|
|
nscolor v = aValue.GetColorValue();
|
|
char buf[10];
|
|
PR_snprintf(buf, sizeof(buf), "#%02x%02x%02x",
|
|
NS_GET_R(v), NS_GET_G(v), NS_GET_B(v));
|
|
aResult.Truncate(0);
|
|
aResult.Append(buf);
|
|
return PR_TRUE;
|
|
}
|
|
if (aValue.GetUnit() == eHTMLUnit_String) {
|
|
aValue.GetStringValue(aResult);
|
|
return PR_TRUE;
|
|
}
|
|
if (aValue.GetUnit() == eHTMLUnit_Empty) { // was illegal
|
|
aResult.Truncate();
|
|
return PR_TRUE;
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
|
|
// XXX check all mappings against ebina's usage
|
|
static nsGenericHTMLElement::EnumTable kAlignTable[] = {
|
|
{ "left", NS_STYLE_TEXT_ALIGN_LEFT },
|
|
{ "right", NS_STYLE_TEXT_ALIGN_RIGHT },
|
|
{ "texttop", NS_STYLE_VERTICAL_ALIGN_TEXT_TOP },
|
|
{ "baseline", NS_STYLE_VERTICAL_ALIGN_BASELINE },
|
|
{ "center", NS_STYLE_TEXT_ALIGN_CENTER },
|
|
{ "bottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM },
|
|
{ "top", NS_STYLE_VERTICAL_ALIGN_TOP },
|
|
{ "middle", NS_STYLE_VERTICAL_ALIGN_MIDDLE },
|
|
{ "absbottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM },
|
|
{ "abscenter", NS_STYLE_VERTICAL_ALIGN_MIDDLE },
|
|
{ "absmiddle", NS_STYLE_VERTICAL_ALIGN_MIDDLE },
|
|
{ 0 }
|
|
};
|
|
|
|
static nsGenericHTMLElement::EnumTable kDivAlignTable[] = {
|
|
{ "left", NS_STYLE_TEXT_ALIGN_LEFT },
|
|
{ "right", NS_STYLE_TEXT_ALIGN_RIGHT },
|
|
{ "center", NS_STYLE_TEXT_ALIGN_CENTER },
|
|
{ "middle", NS_STYLE_TEXT_ALIGN_CENTER },
|
|
{ "justify", NS_STYLE_TEXT_ALIGN_JUSTIFY },
|
|
{ 0 }
|
|
};
|
|
|
|
static nsGenericHTMLElement::EnumTable kFormAlignTable[] = {
|
|
{ "left", NS_STYLE_TEXT_ALIGN_LEFT },
|
|
{ "right", NS_STYLE_TEXT_ALIGN_RIGHT },
|
|
{ "bottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM },
|
|
{ "top", NS_STYLE_VERTICAL_ALIGN_TOP },
|
|
{ "middle", NS_STYLE_VERTICAL_ALIGN_MIDDLE },
|
|
{ 0 }
|
|
};
|
|
|
|
static nsGenericHTMLElement::EnumTable kFrameborderQuirksTable[] = {
|
|
{ "yes", NS_STYLE_FRAME_YES },
|
|
{ "no", NS_STYLE_FRAME_NO },
|
|
{ "1", NS_STYLE_FRAME_1 },
|
|
{ "0", NS_STYLE_FRAME_0 },
|
|
{ 0 }
|
|
};
|
|
|
|
static nsGenericHTMLElement::EnumTable kFrameborderStandardTable[] = {
|
|
{ "1", NS_STYLE_FRAME_1 },
|
|
{ "0", NS_STYLE_FRAME_0 },
|
|
{ 0 }
|
|
};
|
|
|
|
static nsGenericHTMLElement::EnumTable kScrollingQuirksTable[] = {
|
|
{ "yes", NS_STYLE_FRAME_YES },
|
|
{ "no", NS_STYLE_FRAME_NO },
|
|
{ "on", NS_STYLE_FRAME_ON },
|
|
{ "off", NS_STYLE_FRAME_OFF },
|
|
{ "scroll", NS_STYLE_FRAME_SCROLL },
|
|
{ "noscroll", NS_STYLE_FRAME_NOSCROLL },
|
|
{ "auto", NS_STYLE_FRAME_AUTO },
|
|
{ 0 }
|
|
};
|
|
|
|
static nsGenericHTMLElement::EnumTable kScrollingStandardTable[] = {
|
|
{ "yes", NS_STYLE_FRAME_YES },
|
|
{ "no", NS_STYLE_FRAME_NO },
|
|
{ "auto", NS_STYLE_FRAME_AUTO },
|
|
{ 0 }
|
|
};
|
|
|
|
static nsGenericHTMLElement::EnumTable kTableHAlignTable[] = {
|
|
{ "left", NS_STYLE_TEXT_ALIGN_LEFT },
|
|
{ "right", NS_STYLE_TEXT_ALIGN_RIGHT },
|
|
{ "center", NS_STYLE_TEXT_ALIGN_CENTER },
|
|
{ "middle", NS_STYLE_TEXT_ALIGN_CENTER }, // non-standard but necessary for Nav4 compatibility
|
|
{ "char", NS_STYLE_TEXT_ALIGN_CHAR },
|
|
{ "justify",NS_STYLE_TEXT_ALIGN_JUSTIFY },
|
|
{ 0 }
|
|
};
|
|
|
|
static nsGenericHTMLElement::EnumTable kTableVAlignTable[] = {
|
|
{ "top", NS_STYLE_VERTICAL_ALIGN_TOP },
|
|
{ "middle", NS_STYLE_VERTICAL_ALIGN_MIDDLE },
|
|
{ "bottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM },
|
|
{ "baseline",NS_STYLE_VERTICAL_ALIGN_BASELINE },
|
|
{ 0 }
|
|
};
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ParseAlignValue(const nsString& aString,
|
|
nsHTMLValue& aResult)
|
|
{
|
|
return ParseEnumValue(aString, kAlignTable, aResult);
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ParseTableHAlignValue(const nsString& aString,
|
|
nsHTMLValue& aResult)
|
|
{
|
|
return ParseEnumValue(aString, kTableHAlignTable, aResult);
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ParseTableVAlignValue(const nsString& aString,
|
|
nsHTMLValue& aResult)
|
|
{
|
|
return ParseEnumValue(aString, kTableVAlignTable, aResult);
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::AlignValueToString(const nsHTMLValue& aValue,
|
|
nsString& aResult)
|
|
{
|
|
return EnumValueToString(aValue, kAlignTable, aResult);
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ParseFormAlignValue(const nsString& aString,
|
|
nsHTMLValue& aResult)
|
|
{
|
|
return ParseEnumValue(aString, kFormAlignTable, aResult);
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::FormAlignValueToString(const nsHTMLValue& aValue,
|
|
nsString& aResult)
|
|
{
|
|
return EnumValueToString(aValue, kFormAlignTable, aResult);
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::TableHAlignValueToString(const nsHTMLValue& aValue,
|
|
nsString& aResult)
|
|
{
|
|
return EnumValueToString(aValue, kTableHAlignTable, aResult);
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::TableVAlignValueToString(const nsHTMLValue& aValue,
|
|
nsString& aResult)
|
|
{
|
|
return EnumValueToString(aValue, kTableVAlignTable, aResult);
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ParseDivAlignValue(const nsString& aString,
|
|
nsHTMLValue& aResult)
|
|
{
|
|
return ParseEnumValue(aString, kDivAlignTable, aResult);
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::DivAlignValueToString(const nsHTMLValue& aValue,
|
|
nsString& aResult)
|
|
{
|
|
return EnumValueToString(aValue, kDivAlignTable, aResult);
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ParseImageAttribute(nsIAtom* aAttribute,
|
|
const nsString& aString,
|
|
nsHTMLValue& aResult)
|
|
{
|
|
if ((aAttribute == nsHTMLAtoms::width) ||
|
|
(aAttribute == nsHTMLAtoms::height)) {
|
|
ParseValueOrPercent(aString, aResult, eHTMLUnit_Pixel);
|
|
return PR_TRUE;
|
|
}
|
|
else if ((aAttribute == nsHTMLAtoms::hspace) ||
|
|
(aAttribute == nsHTMLAtoms::vspace) ||
|
|
(aAttribute == nsHTMLAtoms::border)) {
|
|
ParseValue(aString, 0, aResult, eHTMLUnit_Pixel);
|
|
return PR_TRUE;
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ImageAttributeToString(nsIAtom* aAttribute,
|
|
const nsHTMLValue& aValue,
|
|
nsString& aResult)
|
|
{
|
|
if ((aAttribute == nsHTMLAtoms::width) ||
|
|
(aAttribute == nsHTMLAtoms::height) ||
|
|
(aAttribute == nsHTMLAtoms::border) ||
|
|
(aAttribute == nsHTMLAtoms::hspace) ||
|
|
(aAttribute == nsHTMLAtoms::vspace)) {
|
|
return ValueOrPercentToString(aValue, aResult);
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ParseFrameborderValue(PRBool aStandardMode,
|
|
const nsString& aString,
|
|
nsHTMLValue& aResult)
|
|
{
|
|
if (aStandardMode) {
|
|
return ParseEnumValue(aString, kFrameborderStandardTable, aResult);
|
|
} else {
|
|
return ParseEnumValue(aString, kFrameborderQuirksTable, aResult);
|
|
}
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::FrameborderValueToString(PRBool aStandardMode,
|
|
const nsHTMLValue& aValue,
|
|
nsString& aResult)
|
|
{
|
|
if (aStandardMode) {
|
|
return EnumValueToString(aValue, kFrameborderStandardTable, aResult);
|
|
} else {
|
|
return EnumValueToString(aValue, kFrameborderQuirksTable, aResult);
|
|
}
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ParseScrollingValue(PRBool aStandardMode,
|
|
const nsString& aString,
|
|
nsHTMLValue& aResult)
|
|
{
|
|
if (aStandardMode) {
|
|
return ParseEnumValue(aString, kScrollingStandardTable, aResult);
|
|
} else {
|
|
return ParseEnumValue(aString, kScrollingQuirksTable, aResult);
|
|
}
|
|
}
|
|
|
|
PRBool
|
|
nsGenericHTMLElement::ScrollingValueToString(PRBool aStandardMode,
|
|
const nsHTMLValue& aValue,
|
|
nsString& aResult)
|
|
{
|
|
if (aStandardMode) {
|
|
return EnumValueToString(aValue, kScrollingStandardTable, aResult);
|
|
} else {
|
|
return EnumValueToString(aValue, kScrollingQuirksTable, aResult);
|
|
}
|
|
}
|
|
|
|
void
|
|
nsGenericHTMLElement::MapImageAttributesInto(nsIHTMLAttributes* aAttributes,
|
|
nsIStyleContext* aContext,
|
|
nsIPresContext* aPresContext)
|
|
{
|
|
if (nsnull != aAttributes) {
|
|
nsHTMLValue value;
|
|
|
|
float p2t = aPresContext->GetPixelsToTwips();
|
|
nsStylePosition* pos = (nsStylePosition*)
|
|
aContext->GetMutableStyleData(eStyleStruct_Position);
|
|
nsStyleSpacing* spacing = (nsStyleSpacing*)
|
|
aContext->GetMutableStyleData(eStyleStruct_Spacing);
|
|
|
|
// width: value
|
|
aAttributes->GetAttribute(nsHTMLAtoms::width, value);
|
|
if (value.GetUnit() == eHTMLUnit_Pixel) {
|
|
nscoord twips = NSIntPixelsToTwips(value.GetPixelValue(), p2t);
|
|
pos->mWidth.SetCoordValue(twips);
|
|
}
|
|
else if (value.GetUnit() == eHTMLUnit_Percent) {
|
|
pos->mWidth.SetPercentValue(value.GetPercentValue());
|
|
}
|
|
|
|
// height: value
|
|
aAttributes->GetAttribute(nsHTMLAtoms::height, value);
|
|
if (value.GetUnit() == eHTMLUnit_Pixel) {
|
|
nscoord twips = NSIntPixelsToTwips(value.GetPixelValue(), p2t);
|
|
pos->mHeight.SetCoordValue(twips);
|
|
}
|
|
else if (value.GetUnit() == eHTMLUnit_Percent) {
|
|
pos->mHeight.SetPercentValue(value.GetPercentValue());
|
|
}
|
|
|
|
// hspace: value
|
|
aAttributes->GetAttribute(nsHTMLAtoms::hspace, value);
|
|
if (value.GetUnit() == eHTMLUnit_Pixel) {
|
|
nscoord twips = NSIntPixelsToTwips(value.GetPixelValue(), p2t);
|
|
spacing->mMargin.SetRight(nsStyleCoord(twips));
|
|
}
|
|
else if (value.GetUnit() == eHTMLUnit_Percent) {
|
|
spacing->mMargin.SetRight(nsStyleCoord(value.GetPercentValue(),
|
|
eStyleUnit_Coord));
|
|
}
|
|
|
|
// vspace: value
|
|
aAttributes->GetAttribute(nsHTMLAtoms::vspace, value);
|
|
if (value.GetUnit() == eHTMLUnit_Pixel) {
|
|
nscoord twips = NSIntPixelsToTwips(value.GetPixelValue(), p2t);
|
|
spacing->mMargin.SetBottom(nsStyleCoord(twips));
|
|
}
|
|
else if (value.GetUnit() == eHTMLUnit_Percent) {
|
|
spacing->mMargin.SetBottom(nsStyleCoord(value.GetPercentValue(),
|
|
eStyleUnit_Coord));
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
nsGenericHTMLElement::MapImageAlignAttributeInto(nsIHTMLAttributes* aAttributes,
|
|
nsIStyleContext* aContext,
|
|
nsIPresContext* aPresContext)
|
|
{
|
|
if (nsnull != aAttributes) {
|
|
nsHTMLValue value;
|
|
aAttributes->GetAttribute(nsHTMLAtoms::align, value);
|
|
if (value.GetUnit() == eHTMLUnit_Enumerated) {
|
|
PRUint8 align = value.GetIntValue();
|
|
nsStyleDisplay* display = (nsStyleDisplay*)
|
|
aContext->GetMutableStyleData(eStyleStruct_Display);
|
|
nsStyleText* text = (nsStyleText*)
|
|
aContext->GetMutableStyleData(eStyleStruct_Text);
|
|
nsStyleSpacing* spacing = (nsStyleSpacing*)
|
|
aContext->GetMutableStyleData(eStyleStruct_Spacing);
|
|
float p2t = aPresContext->GetPixelsToTwips();
|
|
nsStyleCoord three(NSIntPixelsToTwips(3, p2t));
|
|
switch (align) {
|
|
case NS_STYLE_TEXT_ALIGN_LEFT:
|
|
display->mFloats = NS_STYLE_FLOAT_LEFT;
|
|
spacing->mMargin.SetLeft(three);
|
|
spacing->mMargin.SetRight(three);
|
|
break;
|
|
case NS_STYLE_TEXT_ALIGN_RIGHT:
|
|
display->mFloats = NS_STYLE_FLOAT_RIGHT;
|
|
spacing->mMargin.SetLeft(three);
|
|
spacing->mMargin.SetRight(three);
|
|
break;
|
|
default:
|
|
text->mVerticalAlign.SetIntValue(align, eStyleUnit_Enumerated);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
nsGenericHTMLElement::MapImageBorderAttributesInto(nsIHTMLAttributes* aAttributes,
|
|
nsIStyleContext* aContext,
|
|
nsIPresContext* aPresContext,
|
|
nscolor aBorderColors[4])
|
|
{
|
|
if (nsnull != aAttributes) {
|
|
nsHTMLValue value;
|
|
|
|
// border: pixels
|
|
aAttributes->GetAttribute(nsHTMLAtoms::border, value);
|
|
if (value.GetUnit() != eHTMLUnit_Pixel) {
|
|
if (nsnull == aBorderColors) {
|
|
return;
|
|
}
|
|
// If no border is defined and we are forcing a border, force
|
|
// the size to 2 pixels.
|
|
value.SetPixelValue(2);
|
|
}
|
|
|
|
float p2t = aPresContext->GetPixelsToTwips();
|
|
nscoord twips = NSIntPixelsToTwips(value.GetPixelValue(), p2t);
|
|
|
|
// Fixup border-padding sums: subtract out the old size and then
|
|
// add in the new size.
|
|
nsStyleSpacing* spacing = (nsStyleSpacing*)
|
|
aContext->GetMutableStyleData(eStyleStruct_Spacing);
|
|
nsStyleCoord coord;
|
|
coord.SetCoordValue(twips);
|
|
spacing->mBorder.SetTop(coord);
|
|
spacing->mBorder.SetRight(coord);
|
|
spacing->mBorder.SetBottom(coord);
|
|
spacing->mBorder.SetLeft(coord);
|
|
spacing->mBorderStyle[0] = NS_STYLE_BORDER_STYLE_SOLID;
|
|
spacing->mBorderStyle[1] = NS_STYLE_BORDER_STYLE_SOLID;
|
|
spacing->mBorderStyle[2] = NS_STYLE_BORDER_STYLE_SOLID;
|
|
spacing->mBorderStyle[3] = NS_STYLE_BORDER_STYLE_SOLID;
|
|
|
|
// Use supplied colors if provided, otherwise use color for border
|
|
// color
|
|
if (nsnull != aBorderColors) {
|
|
spacing->mBorderColor[0] = aBorderColors[0];
|
|
spacing->mBorderColor[1] = aBorderColors[1];
|
|
spacing->mBorderColor[2] = aBorderColors[2];
|
|
spacing->mBorderColor[3] = aBorderColors[3];
|
|
}
|
|
else {
|
|
// Color is inherited from "color"
|
|
const nsStyleColor* styleColor = (const nsStyleColor*)
|
|
aContext->GetStyleData(eStyleStruct_Color);
|
|
nscolor color = styleColor->mColor;
|
|
spacing->mBorderColor[0] = color;
|
|
spacing->mBorderColor[1] = color;
|
|
spacing->mBorderColor[2] = color;
|
|
spacing->mBorderColor[3] = color;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
nsGenericHTMLElement::MapBackgroundAttributesInto(nsIHTMLAttributes* aAttributes,
|
|
nsIStyleContext* aContext,
|
|
nsIPresContext* aPresContext)
|
|
{
|
|
nsHTMLValue value;
|
|
|
|
// background
|
|
if (NS_CONTENT_ATTR_HAS_VALUE ==
|
|
aAttributes->GetAttribute(nsHTMLAtoms::background, value)) {
|
|
if (eHTMLUnit_String == value.GetUnit()) {
|
|
nsAutoString absURLSpec;
|
|
nsAutoString spec;
|
|
value.GetStringValue(spec);
|
|
if (spec.Length() > 0) {
|
|
// Resolve url to an absolute url
|
|
nsIURL* docURL = nsnull;
|
|
aPresContext->GetBaseURL(docURL);
|
|
|
|
nsresult rv = NS_MakeAbsoluteURL(docURL, "", spec, absURLSpec);
|
|
NS_IF_RELEASE(docURL);
|
|
|
|
nsStyleColor* color = (nsStyleColor*)
|
|
aContext->GetMutableStyleData(eStyleStruct_Color);
|
|
color->mBackgroundImage = absURLSpec;
|
|
color->mBackgroundFlags &= ~NS_STYLE_BG_IMAGE_NONE;
|
|
color->mBackgroundRepeat = NS_STYLE_BG_REPEAT_XY;
|
|
}
|
|
}
|
|
}
|
|
|
|
// bgcolor
|
|
if (NS_CONTENT_ATTR_HAS_VALUE == aAttributes->GetAttribute(nsHTMLAtoms::bgcolor, value)) {
|
|
if (eHTMLUnit_Color == value.GetUnit()) {
|
|
nsStyleColor* color = (nsStyleColor*)
|
|
aContext->GetMutableStyleData(eStyleStruct_Color);
|
|
color->mBackgroundColor = value.GetColorValue();
|
|
color->mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT;
|
|
}
|
|
else if (eHTMLUnit_String == value.GetUnit()) {
|
|
nsAutoString buffer;
|
|
value.GetStringValue(buffer);
|
|
char cbuf[40];
|
|
buffer.ToCString(cbuf, sizeof(cbuf));
|
|
|
|
nsStyleColor* color = (nsStyleColor*)
|
|
aContext->GetMutableStyleData(eStyleStruct_Color);
|
|
NS_ColorNameToRGB(cbuf, &(color->mBackgroundColor));
|
|
color->mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
nsGenericHTMLElement::TriggerLink(nsIPresContext& aPresContext,
|
|
const nsString& aBase,
|
|
const nsString& aURLSpec,
|
|
const nsString& aTargetSpec,
|
|
PRBool aClick)
|
|
{
|
|
nsILinkHandler* handler;
|
|
if (NS_OK == aPresContext.GetLinkHandler(&handler) && (nsnull != handler)) {
|
|
// Resolve url to an absolute url
|
|
nsIURL* docURL = nsnull;
|
|
nsIDocument* doc;
|
|
if (NS_OK == GetDocument(doc)) {
|
|
docURL = doc->GetDocumentURL();
|
|
NS_RELEASE(doc);
|
|
}
|
|
|
|
nsAutoString absURLSpec;
|
|
if (aURLSpec.Length() > 0) {
|
|
nsresult rv = NS_MakeAbsoluteURL(docURL, aBase, aURLSpec, absURLSpec);
|
|
}
|
|
else {
|
|
absURLSpec = aURLSpec;
|
|
}
|
|
|
|
if (nsnull != docURL) {
|
|
NS_RELEASE(docURL);
|
|
}
|
|
|
|
// Now pass on absolute url to the click handler
|
|
if (aClick) {
|
|
handler->OnLinkClick(nsnull, absURLSpec, aTargetSpec);
|
|
}
|
|
else {
|
|
handler->OnOverLink(nsnull, absURLSpec, aTargetSpec);
|
|
}
|
|
NS_RELEASE(handler);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
nsGenericHTMLLeafElement::nsGenericHTMLLeafElement()
|
|
{
|
|
}
|
|
|
|
nsGenericHTMLLeafElement::~nsGenericHTMLLeafElement()
|
|
{
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLLeafElement::CopyInnerTo(nsIHTMLContent* aSrcContent,
|
|
nsGenericHTMLLeafElement* aDst)
|
|
{
|
|
aDst->mContent = aSrcContent;
|
|
// XXX should the node's document be set?
|
|
// XXX copy attributes not yet impelemented
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLLeafElement::Equals(nsIDOMNode* aNode, PRBool aDeep,
|
|
PRBool* aReturn)
|
|
{
|
|
// XXX not yet implemented
|
|
*aReturn = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLLeafElement::GetChildNodes(nsIDOMNodeList** aChildNodes)
|
|
{
|
|
nsDOMSlots *slots = GetDOMSlots();
|
|
|
|
if (nsnull == slots->mChildNodes) {
|
|
slots->mChildNodes = new nsChildContentList(nsnull);
|
|
NS_ADDREF(slots->mChildNodes);
|
|
}
|
|
|
|
return slots->mChildNodes->QueryInterface(kIDOMNodeListIID, (void **)aChildNodes);
|
|
}
|
|
|
|
|
|
nsresult
|
|
nsGenericHTMLLeafElement::BeginConvertToXIF(nsXIFConverter& aConverter) const
|
|
{
|
|
nsresult rv = NS_OK;
|
|
if (nsnull != mTag)
|
|
{
|
|
nsAutoString name;
|
|
mTag->ToString(name);
|
|
aConverter.BeginLeaf(name);
|
|
}
|
|
|
|
// Add all attributes to the convert
|
|
if (nsnull != mAttributes)
|
|
{
|
|
nsISupportsArray* attrs;
|
|
rv = NS_NewISupportsArray(&attrs);
|
|
if (NS_OK == rv)
|
|
{
|
|
PRInt32 i, n;
|
|
mAttributes->GetAllAttributeNames(attrs, n);
|
|
nsAutoString name, value;
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
nsIAtom* atom = (nsIAtom*) attrs->ElementAt(i);
|
|
atom->ToString(name);
|
|
|
|
value.Truncate();
|
|
GetAttribute(name, value);
|
|
|
|
aConverter.AddHTMLAttribute(name,value);
|
|
}
|
|
NS_RELEASE(attrs);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLLeafElement::ConvertContentToXIF(nsXIFConverter& aConverter) const
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLLeafElement::FinishConvertToXIF(nsXIFConverter& aConverter) const
|
|
{
|
|
if (nsnull != mTag)
|
|
{
|
|
nsAutoString name;
|
|
mTag->ToString(name);
|
|
aConverter.EndLeaf(name);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
// XXX not really implemented (yet)
|
|
nsresult
|
|
nsGenericHTMLLeafElement::SizeOf(nsISizeOfHandler* aHandler) const
|
|
{
|
|
aHandler->Add(sizeof(*this));
|
|
return NS_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
nsChildContentList::nsChildContentList(nsGenericHTMLContainerElement *aContent)
|
|
{
|
|
NS_INIT_REFCNT();
|
|
// This reference is not reference-counted. The content
|
|
// object tells us when its about to go away.
|
|
mContent = aContent;
|
|
mScriptObject = nsnull;
|
|
}
|
|
|
|
NS_IMPL_ADDREF(nsChildContentList);
|
|
NS_IMPL_RELEASE(nsChildContentList);
|
|
|
|
nsresult
|
|
nsChildContentList::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|
{
|
|
if (NULL == aInstancePtr) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
if (aIID.Equals(kIDOMNodeListIID)) {
|
|
nsIDOMNodeList* 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)) {
|
|
nsIDOMNodeList* tmp1 = this;
|
|
nsISupports* tmp2 = tmp1;
|
|
*aInstancePtr = (void*)tmp2;
|
|
NS_ADDREF_THIS();
|
|
return NS_OK;
|
|
}
|
|
return NS_NOINTERFACE;
|
|
}
|
|
|
|
nsresult
|
|
nsChildContentList::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject)
|
|
{
|
|
nsresult res = NS_OK;
|
|
if (nsnull == mScriptObject) {
|
|
res = NS_NewScriptNodeList(aContext, (nsISupports *)(nsIDOMNodeList *)this, mContent, (void**)&mScriptObject);
|
|
}
|
|
*aScriptObject = mScriptObject;
|
|
return res;
|
|
}
|
|
|
|
nsresult
|
|
nsChildContentList::SetScriptObject(void *aScriptObject)
|
|
{
|
|
mScriptObject = aScriptObject;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChildContentList::GetLength(PRUint32* aLength)
|
|
{
|
|
if (nsnull != mContent) {
|
|
PRInt32 length;
|
|
mContent->ChildCount(length);
|
|
*aLength = (PRUint32)length;
|
|
}
|
|
else {
|
|
*aLength = 0;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChildContentList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
|
|
{
|
|
nsIContent *content;
|
|
nsresult res = NS_OK;
|
|
|
|
if (nsnull != mContent) {
|
|
mContent->ChildAt(aIndex, content);
|
|
if (nsnull != content) {
|
|
res = content->QueryInterface(kIDOMNodeIID, (void**)aReturn);
|
|
NS_RELEASE(content);
|
|
}
|
|
else {
|
|
*aReturn = nsnull;
|
|
}
|
|
}
|
|
else {
|
|
*aReturn = nsnull;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
void
|
|
nsChildContentList::DropReference()
|
|
{
|
|
mContent = nsnull;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
nsGenericHTMLContainerElement::nsGenericHTMLContainerElement()
|
|
{
|
|
}
|
|
|
|
nsGenericHTMLContainerElement::~nsGenericHTMLContainerElement()
|
|
{
|
|
PRInt32 n = mChildren.Count();
|
|
for (PRInt32 i = 0; i < n; i++) {
|
|
nsIContent* kid = (nsIContent *)mChildren.ElementAt(i);
|
|
NS_RELEASE(kid);
|
|
}
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::CopyInnerTo(nsIHTMLContent* aSrcContent,
|
|
nsGenericHTMLContainerElement* aDst)
|
|
{
|
|
aDst->mContent = aSrcContent;
|
|
// XXX should the node's document be set?
|
|
// XXX copy attributes not yet impelemented
|
|
// XXX deep copy?
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::Equals(nsIDOMNode* aNode, PRBool aDeep,
|
|
PRBool* aReturn)
|
|
{
|
|
// XXX not yet implemented
|
|
*aReturn = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::GetChildNodes(nsIDOMNodeList** aChildNodes)
|
|
{
|
|
nsDOMSlots *slots = GetDOMSlots();
|
|
|
|
if (nsnull == slots->mChildNodes) {
|
|
slots->mChildNodes = new nsChildContentList(this);
|
|
NS_ADDREF(slots->mChildNodes);
|
|
}
|
|
|
|
return slots->mChildNodes->QueryInterface(kIDOMNodeListIID, (void **)aChildNodes);
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::GetHasChildNodes(PRBool* aReturn)
|
|
{
|
|
if (0 != mChildren.Count()) {
|
|
*aReturn = PR_TRUE;
|
|
}
|
|
else {
|
|
*aReturn = PR_FALSE;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::GetFirstChild(nsIDOMNode** aNode)
|
|
{
|
|
nsIContent *child = (nsIContent *)mChildren.ElementAt(0);
|
|
if (nsnull != child) {
|
|
nsresult res = child->QueryInterface(kIDOMNodeIID, (void**)aNode);
|
|
NS_ASSERTION(NS_OK == res, "Must be a DOM Node"); // must be a DOM Node
|
|
return res;
|
|
}
|
|
aNode = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::GetLastChild(nsIDOMNode** aNode)
|
|
{
|
|
nsIContent *child = (nsIContent *)mChildren.ElementAt(mChildren.Count()-1);
|
|
if (nsnull != child) {
|
|
nsresult res = child->QueryInterface(kIDOMNodeIID, (void**)aNode);
|
|
NS_ASSERTION(NS_OK == res, "Must be a DOM Node"); // must be a DOM Node
|
|
return res;
|
|
}
|
|
aNode = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
static void
|
|
SetDocumentInChildrenOf(nsIContent* aContent, nsIDocument* aDocument)
|
|
{
|
|
PRInt32 i, n;
|
|
aContent->ChildCount(n);
|
|
for (i = 0; i < n; i++) {
|
|
nsIContent* child;
|
|
aContent->ChildAt(i, child);
|
|
if (nsnull != child) {
|
|
child->SetDocument(aDocument);
|
|
SetDocumentInChildrenOf(child, aDocument);
|
|
}
|
|
}
|
|
}
|
|
|
|
// XXX It's possible that newChild has already been inserted in the
|
|
// tree; if this is the case then we need to remove it from where it
|
|
// was before placing it in it's new home
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::InsertBefore(nsIDOMNode* aNewChild,
|
|
nsIDOMNode* aRefChild,
|
|
nsIDOMNode** aReturn)
|
|
{
|
|
if (nsnull == aNewChild) {
|
|
*aReturn = nsnull;
|
|
return NS_OK;/* XXX wrong error value */
|
|
}
|
|
|
|
// Get the nsIContent interface for the new content
|
|
nsIContent* newContent = nsnull;
|
|
nsresult res = aNewChild->QueryInterface(kIContentIID, (void**)&newContent);
|
|
NS_ASSERTION(NS_OK == res, "New child must be an nsIContent");
|
|
if (NS_OK == res) {
|
|
if (nsnull == aRefChild) {
|
|
// Append the new child to the end
|
|
SetDocumentInChildrenOf(newContent, mDocument);
|
|
res = AppendChildTo(newContent, PR_TRUE);
|
|
}
|
|
else {
|
|
// Get the index of where to insert the new child
|
|
nsIContent* refContent = nsnull;
|
|
res = aRefChild->QueryInterface(kIContentIID, (void**)&refContent);
|
|
NS_ASSERTION(NS_OK == res, "Ref child must be an nsIContent");
|
|
if (NS_OK == res) {
|
|
PRInt32 pos;
|
|
IndexOf(refContent, pos);
|
|
if (pos >= 0) {
|
|
SetDocumentInChildrenOf(newContent, mDocument);
|
|
res = InsertChildAt(newContent, pos, PR_TRUE);
|
|
}
|
|
NS_RELEASE(refContent);
|
|
}
|
|
}
|
|
NS_RELEASE(newContent);
|
|
|
|
*aReturn = aNewChild;
|
|
NS_ADDREF(aNewChild);
|
|
}
|
|
else {
|
|
*aReturn = nsnull;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::ReplaceChild(nsIDOMNode* aNewChild,
|
|
nsIDOMNode* aOldChild,
|
|
nsIDOMNode** aReturn)
|
|
{
|
|
nsIContent* content = nsnull;
|
|
*aReturn = nsnull;
|
|
nsresult res = aOldChild->QueryInterface(kIContentIID, (void**)&content);
|
|
NS_ASSERTION(NS_OK == res, "Must be an nsIContent");
|
|
if (NS_OK == res) {
|
|
PRInt32 pos;
|
|
IndexOf(content, pos);
|
|
if (pos >= 0) {
|
|
nsIContent* newContent = nsnull;
|
|
nsresult res = aNewChild->QueryInterface(kIContentIID, (void**)&newContent);
|
|
NS_ASSERTION(NS_OK == res, "Must be an nsIContent");
|
|
if (NS_OK == res) {
|
|
res = ReplaceChildAt(newContent, pos, PR_TRUE);
|
|
NS_RELEASE(newContent);
|
|
}
|
|
*aReturn = aOldChild;
|
|
NS_ADDREF(aOldChild);
|
|
}
|
|
NS_RELEASE(content);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
|
|
{
|
|
nsIContent* content = nsnull;
|
|
*aReturn = nsnull;
|
|
nsresult res = aOldChild->QueryInterface(kIContentIID, (void**)&content);
|
|
NS_ASSERTION(NS_OK == res, "Must be an nsIContent");
|
|
if (NS_OK == res) {
|
|
PRInt32 pos;
|
|
IndexOf(content, pos);
|
|
if (pos >= 0) {
|
|
res = RemoveChildAt(pos, PR_TRUE);
|
|
*aReturn = aOldChild;
|
|
NS_ADDREF(aOldChild);
|
|
}
|
|
NS_RELEASE(content);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
|
|
{
|
|
return InsertBefore(aNewChild, nsnull, aReturn);
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::SizeOf(nsISizeOfHandler* aHandler) const
|
|
{
|
|
aHandler->Add(sizeof(*this));
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::BeginConvertToXIF(nsXIFConverter& aConverter) const
|
|
{
|
|
nsresult rv = NS_OK;
|
|
if (nsnull != mTag)
|
|
{
|
|
nsAutoString name;
|
|
mTag->ToString(name);
|
|
aConverter.BeginContainer(name);
|
|
}
|
|
|
|
// Add all attributes to the convert
|
|
if (nsnull != mAttributes)
|
|
{
|
|
nsISupportsArray* attrs;
|
|
rv = NS_NewISupportsArray(&attrs);
|
|
if (NS_OK == rv)
|
|
{
|
|
PRInt32 i, n;
|
|
mAttributes->GetAllAttributeNames(attrs, n);
|
|
nsAutoString name, value;
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
nsIAtom* atom = (nsIAtom*) attrs->ElementAt(i);
|
|
atom->ToString(name);
|
|
|
|
value.Truncate();
|
|
GetAttribute(name, value);
|
|
|
|
aConverter.AddHTMLAttribute(name,value);
|
|
}
|
|
NS_RELEASE(attrs);
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::ConvertContentToXIF(nsXIFConverter& aConverter) const
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::FinishConvertToXIF(nsXIFConverter& aConverter) const
|
|
{
|
|
if (nsnull != mTag)
|
|
{
|
|
nsAutoString name;
|
|
mTag->ToString(name);
|
|
aConverter.EndContainer(name);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::Compact()
|
|
{
|
|
mChildren.Compact();
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::CanContainChildren(PRBool& aResult) const
|
|
{
|
|
aResult = PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::ChildCount(PRInt32& aCount) const
|
|
{
|
|
aCount = mChildren.Count();
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::ChildAt(PRInt32 aIndex,
|
|
nsIContent*& aResult) const
|
|
{
|
|
nsIContent *child = (nsIContent *)mChildren.ElementAt(aIndex);
|
|
if (nsnull != child) {
|
|
NS_ADDREF(child);
|
|
}
|
|
aResult = child;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::IndexOf(nsIContent* aPossibleChild,
|
|
PRInt32& aIndex) const
|
|
{
|
|
NS_PRECONDITION(nsnull != aPossibleChild, "null ptr");
|
|
aIndex = mChildren.IndexOf(aPossibleChild);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::InsertChildAt(nsIContent* aKid,
|
|
PRInt32 aIndex,
|
|
PRBool aNotify)
|
|
{
|
|
NS_PRECONDITION(nsnull != aKid, "null ptr");
|
|
PRBool rv = mChildren.InsertElementAt(aKid, aIndex);/* XXX fix up void array api to use nsresult's*/
|
|
if (rv) {
|
|
NS_ADDREF(aKid);
|
|
aKid->SetParent(mContent);
|
|
nsIDocument* doc = mDocument;
|
|
if (nsnull != doc) {
|
|
aKid->SetDocument(doc);
|
|
if (aNotify) {
|
|
doc->ContentInserted(mContent, aKid, aIndex);
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::ReplaceChildAt(nsIContent* aKid,
|
|
PRInt32 aIndex,
|
|
PRBool aNotify)
|
|
{
|
|
NS_PRECONDITION(nsnull != aKid, "null ptr");
|
|
nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex);
|
|
PRBool rv = mChildren.ReplaceElementAt(aKid, aIndex);
|
|
if (rv) {
|
|
NS_ADDREF(aKid);
|
|
aKid->SetParent(mContent);
|
|
nsIDocument* doc = mDocument;
|
|
if (nsnull != doc) {
|
|
aKid->SetDocument(doc);
|
|
if (aNotify) {
|
|
doc->ContentReplaced(mContent, oldKid, aKid, aIndex);
|
|
}
|
|
}
|
|
oldKid->SetDocument(nsnull);
|
|
oldKid->SetParent(nsnull);
|
|
NS_RELEASE(oldKid);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
|
|
{
|
|
NS_PRECONDITION((nsnull != aKid) && (aKid != mContent), "null ptr");
|
|
PRBool rv = mChildren.AppendElement(aKid);
|
|
if (rv) {
|
|
NS_ADDREF(aKid);
|
|
aKid->SetParent(mContent);
|
|
nsIDocument* doc = mDocument;
|
|
if (nsnull != doc) {
|
|
aKid->SetDocument(doc);
|
|
if (aNotify) {
|
|
doc->ContentAppended(mContent, mChildren.Count() - 1);
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsGenericHTMLContainerElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
|
|
{
|
|
nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex);
|
|
if (nsnull != oldKid ) {
|
|
nsIDocument* doc = mDocument;
|
|
PRBool rv = mChildren.RemoveElementAt(aIndex);
|
|
if (aNotify) {
|
|
if (nsnull != doc) {
|
|
doc->ContentRemoved(mContent, oldKid, aIndex);
|
|
}
|
|
}
|
|
oldKid->SetDocument(nsnull);
|
|
oldKid->SetParent(nsnull);
|
|
NS_RELEASE(oldKid);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|