Mozilla/mozilla/content/html/style/src/nsHTMLAttributes.cpp
peterl 738c42eb75 cleaned up list output
git-svn-id: svn://10.0.0.236/trunk@1848 18797224-902f-48f8-a5cc-f745e15eee43
1998-05-18 21:10:44 +00:00

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