673 lines
14 KiB
C++
673 lines
14 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#include "nsIHTMLAttributes.h"
|
|
#include "nsIStyleRule.h"
|
|
#include "nsString.h"
|
|
#include "nsISupportsArray.h"
|
|
#include "nsCRT.h"
|
|
#include "nsIArena.h"
|
|
#include "nsIStyleContext.h"
|
|
#include "nsHTMLAtoms.h"
|
|
#include "nsIHTMLContent.h"
|
|
|
|
static NS_DEFINE_IID(kIHTMLAttributesIID, NS_IHTML_ATTRIBUTES_IID);
|
|
static NS_DEFINE_IID(kIStyleRuleIID, NS_ISTYLE_RULE_IID);
|
|
|
|
|
|
struct HTMLAttribute {
|
|
HTMLAttribute(nsIAtom* aAttribute, const nsString& aValue)
|
|
: mAttribute(aAttribute),
|
|
mValue(aValue),
|
|
mNext(nsnull)
|
|
{
|
|
NS_IF_ADDREF(mAttribute);
|
|
}
|
|
|
|
HTMLAttribute(nsIAtom* aAttribute, const nsHTMLValue& aValue)
|
|
: mAttribute(aAttribute),
|
|
mValue(aValue),
|
|
mNext(nsnull)
|
|
{
|
|
NS_IF_ADDREF(mAttribute);
|
|
}
|
|
|
|
HTMLAttribute(const HTMLAttribute& aCopy)
|
|
: mAttribute(aCopy.mAttribute),
|
|
mValue(aCopy.mValue),
|
|
mNext(nsnull)
|
|
{
|
|
NS_IF_ADDREF(mAttribute);
|
|
}
|
|
|
|
~HTMLAttribute(void)
|
|
{
|
|
NS_IF_RELEASE(mAttribute);
|
|
}
|
|
|
|
HTMLAttribute& operator=(const HTMLAttribute& aCopy)
|
|
{
|
|
NS_IF_RELEASE(mAttribute);
|
|
mAttribute = aCopy.mAttribute;
|
|
NS_IF_ADDREF(mAttribute);
|
|
mValue = aCopy.mValue;
|
|
return *this;
|
|
}
|
|
|
|
PRBool operator==(const HTMLAttribute& aOther) const
|
|
{
|
|
return PRBool((mAttribute == aOther.mAttribute) &&
|
|
(mValue == aOther.mValue));
|
|
}
|
|
|
|
void Reset(void)
|
|
{
|
|
NS_IF_RELEASE(mAttribute);
|
|
mValue.Reset();
|
|
}
|
|
|
|
void AppendToString(nsString& aBuffer) const
|
|
{
|
|
if (nsnull != mAttribute) {
|
|
nsAutoString temp;
|
|
mAttribute->ToString(temp);
|
|
aBuffer.Append(temp);
|
|
if (eHTMLUnit_Null != mValue.GetUnit()) {
|
|
aBuffer.Append(" = ");
|
|
mValue.AppendToString(aBuffer);
|
|
}
|
|
}
|
|
else {
|
|
aBuffer.Append("null");
|
|
}
|
|
}
|
|
|
|
void ToString(nsString& aBuffer) const
|
|
{
|
|
if (nsnull != mAttribute) {
|
|
mAttribute->ToString(aBuffer);
|
|
if (eHTMLUnit_Null != mValue.GetUnit()) {
|
|
aBuffer.Append(" = ");
|
|
mValue.AppendToString(aBuffer);
|
|
}
|
|
}
|
|
else {
|
|
aBuffer.Truncate();
|
|
aBuffer.Append("null");
|
|
}
|
|
}
|
|
|
|
nsIAtom* mAttribute;
|
|
nsHTMLValue mValue;
|
|
HTMLAttribute* mNext;
|
|
};
|
|
|
|
// ----------------
|
|
|
|
|
|
class HTMLAttributesImpl: public nsIHTMLAttributes, public nsIStyleRule {
|
|
public:
|
|
void* operator new(size_t size);
|
|
void* operator new(size_t size, nsIArena* aArena);
|
|
void operator delete(void* ptr);
|
|
|
|
HTMLAttributesImpl(nsIHTMLContent* aContent);
|
|
~HTMLAttributesImpl(void);
|
|
|
|
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
|
NS_IMETHOD_(nsrefcnt) AddRef();
|
|
NS_IMETHOD_(nsrefcnt) Release();
|
|
|
|
virtual PRBool Equals(const nsIStyleRule* aRule) const;
|
|
virtual PRUint32 HashValue(void) const;
|
|
|
|
virtual PRInt32 SetAttribute(nsIAtom* aAttribute, const nsString& aValue);
|
|
virtual PRInt32 SetAttribute(nsIAtom* aAttribute,
|
|
const nsHTMLValue& aValue = nsHTMLValue::kNull);
|
|
virtual PRInt32 UnsetAttribute(nsIAtom* aAttribute);
|
|
virtual nsContentAttr GetAttribute(nsIAtom* aAttribute,
|
|
nsHTMLValue& aValue) const;
|
|
virtual PRInt32 GetAllAttributeNames(nsISupportsArray* aArray) const;
|
|
virtual PRInt32 Count(void) const;
|
|
|
|
virtual PRInt32 SetID(nsIAtom* aID);
|
|
virtual nsIAtom* GetID(void) const;
|
|
virtual PRInt32 SetClass(nsIAtom* aClass); // XXX this will have to change for CSS2
|
|
virtual nsIAtom* GetClass(void) const; // XXX this will have to change for CSS2
|
|
|
|
virtual void MapStyleInto(nsIStyleContext* aContext, nsIPresContext* aPresContext);
|
|
|
|
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
|
|
|
private:
|
|
HTMLAttributesImpl(const HTMLAttributesImpl& aCopy);
|
|
HTMLAttributesImpl& operator=(const HTMLAttributesImpl& aCopy);
|
|
PRBool operator==(const HTMLAttributesImpl& aCopy) const;
|
|
|
|
protected:
|
|
PRUint32 mInHeap : 1;
|
|
PRUint32 mRefCnt : 31;
|
|
|
|
nsIHTMLContent* mContent;
|
|
PRInt32 mCount;
|
|
HTMLAttribute* mFirst;
|
|
nsIAtom* mID;
|
|
nsIAtom* mClass;
|
|
};
|
|
|
|
void* HTMLAttributesImpl::operator new(size_t size)
|
|
{
|
|
HTMLAttributesImpl* rv = (HTMLAttributesImpl*) ::operator new(size);
|
|
#ifdef NS_DEBUG
|
|
if (nsnull != rv) {
|
|
nsCRT::memset(rv, 0xEE, size);
|
|
}
|
|
#endif
|
|
rv->mInHeap = 1;
|
|
return (void*) rv;
|
|
}
|
|
|
|
void* HTMLAttributesImpl::operator new(size_t size, nsIArena* aArena)
|
|
{
|
|
HTMLAttributesImpl* rv = (HTMLAttributesImpl*) aArena->Alloc(PRInt32(size));
|
|
#ifdef NS_DEBUG
|
|
if (nsnull != rv) {
|
|
nsCRT::memset(rv, 0xEE, size);
|
|
}
|
|
#endif
|
|
rv->mInHeap = 0;
|
|
return (void*) rv;
|
|
}
|
|
|
|
void HTMLAttributesImpl::operator delete(void* ptr)
|
|
{
|
|
HTMLAttributesImpl* attr = (HTMLAttributesImpl*) ptr;
|
|
if (nsnull != attr) {
|
|
if (attr->mInHeap) {
|
|
::delete ptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
HTMLAttributesImpl::HTMLAttributesImpl(nsIHTMLContent* aContent)
|
|
: mContent(aContent), // weak ref
|
|
mFirst(nsnull),
|
|
mCount(0),
|
|
mID(nsnull),
|
|
mClass(nsnull)
|
|
{
|
|
NS_INIT_REFCNT();
|
|
}
|
|
|
|
HTMLAttributesImpl::~HTMLAttributesImpl(void)
|
|
{
|
|
HTMLAttribute* next = mFirst;
|
|
while (nsnull != next) {
|
|
HTMLAttribute* attr = next;
|
|
next = next->mNext;
|
|
delete attr;
|
|
}
|
|
NS_IF_RELEASE(mID);
|
|
NS_IF_RELEASE(mClass);
|
|
}
|
|
|
|
NS_IMPL_ADDREF(HTMLAttributesImpl)
|
|
NS_IMPL_RELEASE(HTMLAttributesImpl)
|
|
|
|
nsresult HTMLAttributesImpl::QueryInterface(const nsIID& aIID,
|
|
void** aInstancePtrResult)
|
|
{
|
|
NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer");
|
|
if (nsnull == aInstancePtrResult) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|
if (aIID.Equals(kIHTMLAttributesIID)) {
|
|
*aInstancePtrResult = (void*) ((nsIHTMLAttributes*)this);
|
|
AddRef();
|
|
return NS_OK;
|
|
}
|
|
if (aIID.Equals(kIStyleRuleIID)) {
|
|
*aInstancePtrResult = (void*) ((nsIStyleRule*)this);
|
|
AddRef();
|
|
return NS_OK;
|
|
}
|
|
if (aIID.Equals(kISupportsIID)) {
|
|
*aInstancePtrResult = (void*) ((nsISupports*)(nsIHTMLAttributes*)this);
|
|
AddRef();
|
|
return NS_OK;
|
|
}
|
|
return NS_NOINTERFACE;
|
|
}
|
|
|
|
|
|
PRBool HTMLAttributesImpl::Equals(const nsIStyleRule* aRule) const
|
|
{
|
|
nsIHTMLAttributes* iHTMLAttr;
|
|
|
|
if (this == aRule) {
|
|
return PR_TRUE;
|
|
}
|
|
|
|
if ((nsnull != aRule) &&
|
|
(NS_OK == ((nsIStyleRule*)aRule)->QueryInterface(kIHTMLAttributesIID, (void**) &iHTMLAttr))) {
|
|
|
|
const HTMLAttributesImpl* other = (HTMLAttributesImpl*)iHTMLAttr;
|
|
PRBool result = PR_FALSE;
|
|
|
|
if (mCount == other->mCount) {
|
|
if ((mID == other->mID) && (mClass == other->mClass)) {
|
|
const HTMLAttribute* attr = mFirst;
|
|
const HTMLAttribute* otherAttr = other->mFirst;
|
|
|
|
result = PR_TRUE;
|
|
while (nsnull != attr) {
|
|
if (! ((*attr) == (*otherAttr))) {
|
|
result = PR_FALSE;
|
|
break;
|
|
}
|
|
attr = attr->mNext;
|
|
otherAttr = otherAttr->mNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
NS_RELEASE(iHTMLAttr);
|
|
return result;
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRUint32 HTMLAttributesImpl::HashValue(void) const
|
|
{
|
|
return (PRUint32)this;
|
|
}
|
|
|
|
PRInt32 HTMLAttributesImpl::SetAttribute(nsIAtom* aAttribute, const nsString& aValue)
|
|
{
|
|
if (nsHTMLAtoms::id == aAttribute) {
|
|
nsIAtom* id = NS_NewAtom(aValue);
|
|
PRInt32 result = SetID(id);
|
|
NS_RELEASE(id);
|
|
return result;
|
|
}
|
|
if (nsHTMLAtoms::kClass == aAttribute) {
|
|
nsIAtom* classA = NS_NewAtom(aValue);
|
|
PRInt32 result = SetClass(classA);
|
|
NS_RELEASE(classA);
|
|
return result;
|
|
}
|
|
|
|
HTMLAttribute* last = nsnull;
|
|
HTMLAttribute* attr = mFirst;
|
|
|
|
while (nsnull != attr) {
|
|
if (attr->mAttribute == aAttribute) {
|
|
attr->mValue.SetStringValue(aValue);
|
|
return mCount;
|
|
}
|
|
last = attr;
|
|
attr = attr->mNext;
|
|
}
|
|
|
|
attr = new HTMLAttribute(aAttribute, aValue);
|
|
if (nsnull == last) {
|
|
mFirst = attr;
|
|
}
|
|
else {
|
|
last->mNext = attr;
|
|
}
|
|
return ++mCount;
|
|
}
|
|
|
|
PRInt32 HTMLAttributesImpl::SetAttribute(nsIAtom* aAttribute, const nsHTMLValue& aValue)
|
|
{
|
|
if (nsHTMLAtoms::id == aAttribute) {
|
|
nsAutoString buffer;
|
|
nsIAtom* id = NS_NewAtom(aValue.GetStringValue(buffer));
|
|
PRInt32 result = SetID(id);
|
|
NS_RELEASE(id);
|
|
return result;
|
|
}
|
|
if (nsHTMLAtoms::kClass == aAttribute) {
|
|
nsAutoString buffer;
|
|
nsIAtom* classA = NS_NewAtom(aValue.GetStringValue(buffer));
|
|
PRInt32 result = SetClass(classA);
|
|
NS_RELEASE(classA);
|
|
return result;
|
|
}
|
|
|
|
HTMLAttribute* last = nsnull;
|
|
HTMLAttribute* attr = mFirst;
|
|
|
|
while (nsnull != attr) {
|
|
if (attr->mAttribute == aAttribute) {
|
|
attr->mValue = aValue;
|
|
return mCount;
|
|
}
|
|
last = attr;
|
|
attr = attr->mNext;
|
|
}
|
|
|
|
attr = new HTMLAttribute(aAttribute, aValue);
|
|
if (nsnull == last) {
|
|
mFirst = attr;
|
|
}
|
|
else {
|
|
last->mNext = attr;
|
|
}
|
|
return ++mCount;
|
|
}
|
|
|
|
PRInt32 HTMLAttributesImpl::UnsetAttribute(nsIAtom* aAttribute)
|
|
{
|
|
if (nsHTMLAtoms::id == aAttribute) {
|
|
return SetID (nsnull);
|
|
}
|
|
if (nsHTMLAtoms::kClass == aAttribute) {
|
|
return SetClass (nsnull);
|
|
}
|
|
|
|
HTMLAttribute* prev = nsnull;
|
|
HTMLAttribute* attr = mFirst;
|
|
|
|
while (nsnull != attr) {
|
|
if (attr->mAttribute == aAttribute) {
|
|
if (nsnull == prev) {
|
|
mFirst = attr->mNext;
|
|
}
|
|
else {
|
|
prev->mNext = attr->mNext;
|
|
}
|
|
delete attr;
|
|
mCount--;
|
|
break;
|
|
}
|
|
prev = attr;
|
|
attr = attr->mNext;
|
|
}
|
|
return mCount;
|
|
}
|
|
|
|
nsContentAttr HTMLAttributesImpl::GetAttribute(nsIAtom* aAttribute,
|
|
nsHTMLValue& aValue) const
|
|
{
|
|
aValue.Reset();
|
|
if (nsHTMLAtoms::id == aAttribute) {
|
|
nsIAtom* id = GetID();
|
|
if (nsnull != id) {
|
|
nsAutoString buffer;
|
|
id->ToString(buffer);
|
|
aValue.SetStringValue(buffer);
|
|
NS_RELEASE(id);
|
|
return eContentAttr_HasValue;
|
|
}
|
|
return eContentAttr_NotThere;
|
|
}
|
|
if (nsHTMLAtoms::kClass == aAttribute) {
|
|
nsIAtom* classA = GetClass();
|
|
if (nsnull != classA) {
|
|
nsAutoString buffer;
|
|
classA->ToString(buffer);
|
|
aValue.SetStringValue(buffer);
|
|
NS_RELEASE(classA);
|
|
return eContentAttr_HasValue;
|
|
}
|
|
return eContentAttr_NotThere;
|
|
}
|
|
|
|
HTMLAttribute* attr = mFirst;
|
|
|
|
while (nsnull != attr) {
|
|
if (attr->mAttribute == aAttribute) {
|
|
aValue = attr->mValue;
|
|
return ((attr->mValue.GetUnit() == eHTMLUnit_Null) ? eContentAttr_NoValue : eContentAttr_HasValue);
|
|
}
|
|
attr = attr->mNext;
|
|
}
|
|
return eContentAttr_NotThere;
|
|
}
|
|
|
|
PRInt32 HTMLAttributesImpl::GetAllAttributeNames(nsISupportsArray* aArray) const
|
|
{
|
|
NS_ASSERTION(nsnull != aArray, "null arg");
|
|
|
|
if (nsnull == aArray) {
|
|
return 0;
|
|
}
|
|
|
|
if (nsnull != mID) {
|
|
aArray->AppendElement((nsIAtom*)nsHTMLAtoms::id);
|
|
}
|
|
if (nsnull != mClass) {
|
|
aArray->AppendElement((nsIAtom*)nsHTMLAtoms::kClass);
|
|
}
|
|
|
|
HTMLAttribute* attr = mFirst;
|
|
|
|
while (nsnull != attr) {
|
|
aArray->AppendElement(attr->mAttribute);
|
|
attr = attr->mNext;
|
|
}
|
|
return mCount;
|
|
}
|
|
|
|
PRInt32 HTMLAttributesImpl::Count(void) const
|
|
{
|
|
return mCount;
|
|
}
|
|
|
|
PRInt32 HTMLAttributesImpl::SetID(nsIAtom* aID)
|
|
{
|
|
if (aID != mID) {
|
|
if (nsnull != mID) {
|
|
NS_RELEASE(mID);
|
|
mCount--;
|
|
}
|
|
mID = aID;
|
|
if (nsnull != mID) {
|
|
NS_ADDREF(mID);
|
|
mCount++;
|
|
}
|
|
}
|
|
return mCount;
|
|
}
|
|
|
|
nsIAtom* HTMLAttributesImpl::GetID(void) const
|
|
{
|
|
NS_IF_ADDREF(mID);
|
|
return mID;
|
|
}
|
|
|
|
PRInt32 HTMLAttributesImpl::SetClass(nsIAtom* aClass)
|
|
{
|
|
if (aClass != mClass) {
|
|
if (nsnull != mClass) {
|
|
NS_RELEASE(mClass);
|
|
mCount--;
|
|
}
|
|
mClass = aClass;
|
|
if (nsnull != mClass) {
|
|
NS_ADDREF(mClass);
|
|
mCount++;
|
|
}
|
|
}
|
|
return mCount;
|
|
}
|
|
|
|
nsIAtom* HTMLAttributesImpl::GetClass(void) const
|
|
{
|
|
NS_IF_ADDREF(mClass);
|
|
return mClass;
|
|
}
|
|
|
|
void HTMLAttributesImpl::MapStyleInto(nsIStyleContext* aContext, nsIPresContext* aPresContext)
|
|
{
|
|
if (nsnull != mContent) {
|
|
mContent->MapAttributesInto(aContext, aPresContext);
|
|
}
|
|
}
|
|
|
|
|
|
void HTMLAttributesImpl::List(FILE* out, PRInt32 aIndent) const
|
|
{
|
|
HTMLAttribute* attr = mFirst;
|
|
nsString buffer;
|
|
|
|
while (nsnull != attr) {
|
|
for (PRInt32 index = aIndent; --index >= 0; ) fputs(" ", out);
|
|
attr->ToString(buffer);
|
|
fputs(buffer, out);
|
|
fputs("\n", out);
|
|
attr = attr->mNext;
|
|
}
|
|
}
|
|
|
|
extern NS_HTML nsresult
|
|
NS_NewHTMLAttributes(nsIHTMLAttributes** aInstancePtrResult, nsIHTMLContent* aContent)
|
|
{
|
|
if (aInstancePtrResult == nsnull) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
|
|
HTMLAttributesImpl *it = new HTMLAttributesImpl(aContent);
|
|
|
|
if (nsnull == it) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
return it->QueryInterface(kIHTMLAttributesIID, (void **) aInstancePtrResult);
|
|
}
|
|
|
|
|
|
#if 0
|
|
|
|
|
|
marginwidth; marginheight: px
|
|
|
|
border: px
|
|
|
|
align(DIV): left, right, center, justify
|
|
align: left, right, center, abscenter
|
|
valign: baseline, top, bottom, middle, center
|
|
align(image): abscenter, left, right, texttop, absbottom, baseline, center, bottom, top, middle, absmiddle
|
|
|
|
dir: rtl, ltr
|
|
|
|
width: px, %
|
|
height: px, %
|
|
|
|
vspace; hspace: px
|
|
|
|
type(list): none, disc, (circle | round), square, decimal, lower-roman, upper-roman, lower-alpha, upper-alpha
|
|
|
|
href: url
|
|
target: string
|
|
src: url(string?)
|
|
color: color
|
|
face: string
|
|
suppress: bool
|
|
|
|
style: string
|
|
class: string (list)
|
|
id: string
|
|
name: string
|
|
|
|
//a
|
|
link; vlink; alink: color
|
|
|
|
//body
|
|
background: url
|
|
bgcolor: color
|
|
text: color
|
|
|
|
//frameset
|
|
bordercolor: color
|
|
|
|
//layer
|
|
background: url
|
|
bgcolor: color
|
|
|
|
//q
|
|
lang: string
|
|
|
|
//table
|
|
background: url
|
|
bgcolor: color
|
|
bordercolor: color
|
|
cellspacing: px
|
|
cellpadding: px
|
|
toppadding; leftpadding; bottompadding; rightpadding: px
|
|
cols: int
|
|
|
|
//td
|
|
background: url
|
|
bgcolor: color
|
|
nowrap: bool
|
|
colspan; rowspan: int
|
|
|
|
//tr
|
|
background: url
|
|
bgcolor: color
|
|
|
|
//colgroup
|
|
span: int
|
|
|
|
//col
|
|
repeat: int
|
|
|
|
//ul;ol
|
|
compact: bool
|
|
start: int
|
|
|
|
//li
|
|
value: int
|
|
|
|
//hr;spacer
|
|
size: px
|
|
|
|
//multicol
|
|
cols: int
|
|
gutter: px
|
|
|
|
//input
|
|
type: string
|
|
value: string
|
|
|
|
//factory methods:
|
|
GetStringData
|
|
GetBoolData
|
|
GetInvBoolData
|
|
GetPixelIntData
|
|
GetValueOrPctData
|
|
GetValueData
|
|
|
|
//tag methods
|
|
getAttribute
|
|
getIntAttribute
|
|
getKeywordAttribute
|
|
getSignedAttribute
|
|
getValueOrPctAttribute
|
|
|
|
|
|
//notes
|
|
nsIAtom->value table
|
|
|
|
#endif
|