Final patch for bug 195350. Make XUL use new nsAttrAndChildren class. Kill nsXULAttributeValue and nsXULAttributes in favour of nsAttrValue resp. nsDOMAttributeMap. Should fix a few bugs, improve performance and reduce bloat.

r=bz sr=jst
This commit is contained in:
sicking%bigfoot.com 2004-02-10 09:08:06 +00:00
parent e16b0d28c8
commit 4cedcd531b
30 changed files with 1234 additions and 2559 deletions

View File

@ -144,12 +144,6 @@ public:
*/
virtual nsresult SetDocumentPrincipal(nsIPrincipal* aPrincipal) = 0;
/**
* Populate the given nsCOMArray with all of the nsINodeInfos
* managed by this manager.
*/
virtual nsresult GetNodeInfos(nsCOMArray<nsINodeInfo> *aArray) = 0;
protected:
nsIDocument *mDocument; // WEAK
};

View File

@ -379,18 +379,17 @@ nsAttrAndChildArray::GetSafeAttrNameAt(PRUint32 aPos) const
}
const nsAttrName*
nsAttrAndChildArray::GetExistingAttrNameFromQName(const nsAString& aName) const
nsAttrAndChildArray::GetExistingAttrNameFromQName(const nsACString& aName) const
{
NS_ConvertUTF16toUTF8 name(aName);
PRUint32 i, slotCount = AttrSlotCount();
for (i = 0; i < slotCount && mImpl->mBuffer[i * ATTRSIZE]; ++i) {
if (ATTRS(mImpl)[i].mName.QualifiedNameEquals(name)) {
if (ATTRS(mImpl)[i].mName.QualifiedNameEquals(aName)) {
return &ATTRS(mImpl)[i].mName;
}
}
if (mImpl && mImpl->mMappedAttrs) {
return mImpl->mMappedAttrs->GetExistingAttrNameFromQName(name);
return mImpl->mMappedAttrs->GetExistingAttrNameFromQName(aName);
}
return nsnull;

View File

@ -99,7 +99,8 @@ public:
nsresult SetAndTakeAttr(nsINodeInfo* aName, nsAttrValue& aValue);
nsresult RemoveAttrAt(PRUint32 aPos);
const nsAttrName* GetSafeAttrNameAt(PRUint32 aPos) const;
const nsAttrName* GetExistingAttrNameFromQName(const nsAString& aName) const;
// aName is UTF-8 encoded
const nsAttrName* GetExistingAttrNameFromQName(const nsACString& aName) const;
PRInt32 IndexOfAttr(nsIAtom* aLocalName, PRInt32 aNamespaceID = kNameSpaceID_None) const;
nsresult SetAndTakeMappedAttr(nsIAtom* aLocalName, nsAttrValue& aValue,

View File

@ -96,6 +96,15 @@ public:
}
}
void SetTo(nsIAtom* aAtom)
{
NS_ASSERTION(aAtom, "null atom-name in nsAttrName");
ReleaseInternalName();
mBits = NS_REINTERPRET_CAST(PtrBits, aAtom);
NS_ADDREF(aAtom);
}
PRBool IsAtom() const
{
return !(mBits & NS_ATTRNAME_NODEINFO_BIT);

View File

@ -58,7 +58,7 @@ nsAttrValue::nsAttrValue(const nsAString& aValue)
SetTo(aValue);
}
nsAttrValue::nsAttrValue(nsHTMLValue* aValue)
nsAttrValue::nsAttrValue(const nsHTMLValue& aValue)
: mBits(0)
{
SetTo(aValue);
@ -115,11 +115,7 @@ nsAttrValue::SetTo(const nsAttrValue& aOther)
}
case eHTMLValue:
{
nsHTMLValue* newVal =
new nsHTMLValue(*aOther.GetHTMLValue());
if (newVal) {
SetTo(newVal);
}
SetTo(*aOther.GetHTMLValue());
break;
}
case eAtom:
@ -155,11 +151,13 @@ nsAttrValue::SetTo(const nsAString& aValue)
}
void
nsAttrValue::SetTo(nsHTMLValue* aValue)
nsAttrValue::SetTo(const nsHTMLValue& aValue)
{
NS_ASSERTION(aValue, "null value in nsAttrValue::SetTo");
Reset();
SetValueAndType(aValue, eHTMLValue);
nsHTMLValue* htmlValue = new nsHTMLValue(aValue);
if (htmlValue) {
SetValueAndType(htmlValue, eHTMLValue);
}
}
void
@ -168,7 +166,24 @@ nsAttrValue::SetTo(nsIAtom* aValue)
NS_ASSERTION(aValue, "null value in nsAttrValue::SetTo");
Reset();
NS_ADDREF(aValue);
mBits = NS_REINTERPRET_CAST(PtrBits, aValue) | eAtom;
SetValueAndType(aValue, eAtom);
}
void
nsAttrValue::SetToStringOrAtom(const nsAString& aValue)
{
PRUint32 len = aValue.Length();
// Don't bother with atoms if it's an empty string since
// we can store those efficently anyway.
if (len && len <= NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM) {
nsCOMPtr<nsIAtom> atom = do_GetAtom(aValue);
if (atom) {
SetTo(atom);
}
}
else {
SetTo(aValue);
}
}
void

View File

@ -47,6 +47,7 @@ class nsHTMLValue;
class nsAString;
class nsIAtom;
#define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12
#define NS_ATTRVALUE_TYPE_MASK (PtrBits(3))
#define NS_ATTRVALUE_VALUE_MASK (~NS_ATTRVALUE_TYPE_MASK)
@ -55,15 +56,16 @@ public:
nsAttrValue();
nsAttrValue(const nsAttrValue& aOther);
explicit nsAttrValue(const nsAString& aValue);
explicit nsAttrValue(nsHTMLValue* aValue);
explicit nsAttrValue(const nsHTMLValue& aValue);
explicit nsAttrValue(nsIAtom* aValue);
~nsAttrValue();
void Reset();
void SetTo(const nsAttrValue& aOther);
void SetTo(const nsAString& aValue);
void SetTo(nsHTMLValue* aValue);
void SetTo(const nsHTMLValue& aValue);
void SetTo(nsIAtom* aValue);
void SetToStringOrAtom(const nsAString& aValue);
void SwapValueWith(nsAttrValue& aOther);

View File

@ -1281,6 +1281,11 @@ nsGenericElement::RemoveAttribute(const nsAString& aName)
return NS_OK;
}
// Hold a strong reference here so that the atom or nodeinfo doesn't go
// away during UnsetAttr. If it did UnsetAttr would be left with a
// dangling pointer as argument without knowing it.
nsAttrName tmp(*name);
return UnsetAttr(name->NamespaceID(), name->LocalName(), PR_TRUE);
}
@ -3174,7 +3179,8 @@ nsGenericElement::AddScriptEventListener(nsIAtom* aAttribute,
const nsAttrName*
nsGenericContainerElement::InternalGetExistingAttrNameFromQName(const nsAString& aStr) const
{
return mAttrsAndChildren.GetExistingAttrNameFromQName(aStr);
return mAttrsAndChildren.GetExistingAttrNameFromQName(
NS_ConvertUTF16toUTF8(aStr));
}
nsresult

View File

@ -47,6 +47,8 @@
#include "nsIHTMLDocument.h"
#include "nsUnitConversion.h"
#include "prprf.h"
#include "nsICSSStyleRule.h"
#include "nsCSSDeclaration.h"
nsHTMLValue::nsHTMLValue(nsHTMLUnit aUnit)
: mUnit(aUnit)
@ -84,11 +86,11 @@ nsHTMLValue::nsHTMLValue(const nsAString& aValue, nsHTMLUnit aUnit)
SetStringValueInternal(aValue, aUnit);
}
nsHTMLValue::nsHTMLValue(nsISupports* aValue)
: mUnit(eHTMLUnit_ISupports)
nsHTMLValue::nsHTMLValue(nsICSSStyleRule* aValue)
: mUnit(eHTMLUnit_CSSStyleRule)
{
mValue.mISupports = aValue;
NS_IF_ADDREF(mValue.mISupports);
mValue.mCSSStyleRule = aValue;
NS_IF_ADDREF(mValue.mCSSStyleRule);
}
nsHTMLValue::nsHTMLValue(nscolor aValue)
@ -145,8 +147,8 @@ PRBool nsHTMLValue::operator==(const nsHTMLValue& aOther) const
case HTMLUNIT_COLOR:
return mValue.mColor == aOther.mValue.mColor;
case HTMLUNIT_ISUPPORTS:
return mValue.mISupports == aOther.mValue.mISupports;
case HTMLUNIT_CSSSTYLERULE:
return mValue.mCSSStyleRule == aOther.mValue.mCSSStyleRule;
case HTMLUNIT_PERCENT:
return mValue.mFloat == aOther.mValue.mFloat;
@ -203,8 +205,8 @@ void nsHTMLValue::Reset(void)
nsCheapStringBufferUtils::Free(mValue.mString);
}
}
else if (mUnit == eHTMLUnit_ISupports) {
NS_IF_RELEASE(mValue.mISupports);
else if (mUnit == eHTMLUnit_CSSStyleRule) {
NS_IF_RELEASE(mValue.mCSSStyleRule);
}
else if (mUnit == eHTMLUnit_AtomArray) {
delete mValue.mAtomArray;
@ -265,12 +267,12 @@ void nsHTMLValue::SetStringValue(const nsAString& aValue,
SetStringValueInternal(aValue, aUnit);
}
void nsHTMLValue::SetISupportsValue(nsISupports* aValue)
void nsHTMLValue::SetCSSStyleRuleValue(nsICSSStyleRule* aValue)
{
Reset();
mUnit = eHTMLUnit_ISupports;
mValue.mISupports = aValue;
NS_IF_ADDREF(mValue.mISupports);
mUnit = eHTMLUnit_CSSStyleRule;
mValue.mCSSStyleRule = aValue;
NS_IF_ADDREF(mValue.mCSSStyleRule);
}
void nsHTMLValue::SetColorValue(nscolor aValue)
@ -312,9 +314,9 @@ nsHTMLValue::InitializeFrom(const nsHTMLValue& aCopy)
mValue.mColor = aCopy.mValue.mColor;
break;
case HTMLUNIT_ISUPPORTS:
mValue.mISupports = aCopy.mValue.mISupports;
NS_IF_ADDREF(mValue.mISupports);
case HTMLUNIT_CSSSTYLERULE:
mValue.mCSSStyleRule = aCopy.mValue.mCSSStyleRule;
NS_IF_ADDREF(mValue.mCSSStyleRule);
break;
case HTMLUNIT_PERCENT:
@ -486,6 +488,18 @@ nsHTMLValue::ToString(nsAString& aResult) const
}
return PR_TRUE;
}
case eHTMLUnit_CSSStyleRule:
{
if (mValue.mCSSStyleRule) {
nsCSSDeclaration* decl = mValue.mCSSStyleRule->GetDeclaration();
if (decl) {
decl->ToString(aResult);
}
}
return PR_TRUE;
}
default:
return PR_FALSE;
}

View File

@ -41,7 +41,6 @@
#include "nscore.h"
#include "nsColor.h"
#include "nsString.h"
#include "nsISupports.h"
#include "nsCOMPtr.h"
#include "nsReadableUtils.h"
@ -50,6 +49,7 @@
#include "nsIAtom.h"
class nsIDocument;
class nsICSSStyleRule;
class nsCheapStringBufferUtils {
public:
@ -148,15 +148,15 @@ public:
// between different things stored as the same type. Doing
// mUnit & HTMLUNIT_CLASS_MASK should give you the class of type.
//
#define HTMLUNIT_NOSTORE 0x0000
#define HTMLUNIT_STRING 0x0100
#define HTMLUNIT_INTEGER 0x0200
#define HTMLUNIT_PIXEL 0x0400
#define HTMLUNIT_COLOR 0x0800
#define HTMLUNIT_ISUPPORTS 0x1000
#define HTMLUNIT_PERCENT 0x2000
#define HTMLUNIT_ATOMARRAY 0x4000
#define HTMLUNIT_CLASS_MASK 0xff00
#define HTMLUNIT_NOSTORE 0x0000
#define HTMLUNIT_STRING 0x0100
#define HTMLUNIT_INTEGER 0x0200
#define HTMLUNIT_PIXEL 0x0400
#define HTMLUNIT_COLOR 0x0800
#define HTMLUNIT_CSSSTYLERULE 0x1000
#define HTMLUNIT_PERCENT 0x2000
#define HTMLUNIT_ATOMARRAY 0x4000
#define HTMLUNIT_CLASS_MASK 0xff00
enum nsHTMLUnit {
// null, value is not specified: 0x0000
@ -182,8 +182,8 @@ enum nsHTMLUnit {
// an RGBA value
eHTMLUnit_Color = HTMLUNIT_COLOR,
// (nsISupports*) a ref counted interface
eHTMLUnit_ISupports = HTMLUNIT_ISUPPORTS,
// a nsICSSStyleRule
eHTMLUnit_CSSStyleRule = HTMLUNIT_CSSSTYLERULE,
// (1.0 == 100%) value is percentage of something
eHTMLUnit_Percent = HTMLUNIT_PERCENT,
@ -204,7 +204,7 @@ public:
nsHTMLValue(PRInt32 aValue, nsHTMLUnit aUnit);
nsHTMLValue(float aValue);
nsHTMLValue(const nsAString& aValue, nsHTMLUnit aUnit = eHTMLUnit_String);
nsHTMLValue(nsISupports* aValue);
nsHTMLValue(nsICSSStyleRule* aValue);
nsHTMLValue(nscolor aValue);
nsHTMLValue(nsCOMArray<nsIAtom>* aArray);
nsHTMLValue(const nsHTMLValue& aCopy);
@ -225,7 +225,7 @@ public:
PRInt32 GetPixelValue(void) const;
float GetPercentValue(void) const;
nsAString& GetStringValue(nsAString& aBuffer) const;
already_AddRefed<nsISupports> GetISupportsValue(void) const;
nsICSSStyleRule* GetCSSStyleRuleValue(void) const;
nscolor GetColorValue(void) const;
nsCOMArray<nsIAtom>* AtomArrayValue() const;
@ -237,7 +237,7 @@ public:
void SetPixelValue(PRInt32 aValue);
void SetPercentValue(float aValue);
void SetStringValue(const nsAString& aValue, nsHTMLUnit aUnit = eHTMLUnit_String);
void SetISupportsValue(nsISupports* aValue);
void SetCSSStyleRuleValue(nsICSSStyleRule* aValue);
void SetColorValue(nscolor aValue);
void SetEmptyValue(void);
@ -363,8 +363,8 @@ protected:
float mFloat;
/** String. First 4 bytes are the length, non-null-terminated. */
PRUnichar* mString;
/** ISupports. Strong reference. */
nsISupports* mISupports;
/** nsICSSStyleRule. Strong reference. */
nsICSSStyleRule* mCSSStyleRule;
/** Color. */
nscolor mColor;
/** Array if atoms */
@ -462,13 +462,11 @@ inline nsAString& nsHTMLValue::GetStringValue(nsAString& aBuffer) const
return aBuffer;
}
inline already_AddRefed<nsISupports> nsHTMLValue::GetISupportsValue(void) const
inline nsICSSStyleRule* nsHTMLValue::GetCSSStyleRuleValue(void) const
{
NS_ASSERTION(mUnit == eHTMLUnit_ISupports, "not an ISupports value");
if (mUnit == eHTMLUnit_ISupports) {
nsISupports *result = mValue.mISupports;
NS_IF_ADDREF(result);
return result;
NS_ASSERTION(mUnit == eHTMLUnit_CSSStyleRule, "not an CSSStyleRule value");
if (mUnit == eHTMLUnit_CSSStyleRule) {
return mValue.mCSSStyleRule;
}
return nsnull;
}

View File

@ -295,33 +295,6 @@ nsNodeInfoManager::SetDocumentPrincipal(nsIPrincipal* aPrincipal)
return NS_OK;
}
nsresult
nsNodeInfoManager::GetNodeInfos(nsCOMArray<nsINodeInfo> *aArray)
{
PL_HashTableEnumerateEntries(mNodeInfoHash,
GetNodeInfoArrayEnumerator,
aArray);
PRInt32 n = aArray->Count();
NS_ENSURE_TRUE((PRUint32)n == mNodeInfoHash->nentries, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
}
//static
PRIntn
nsNodeInfoManager::GetNodeInfoArrayEnumerator(PLHashEntry* he, PRIntn i,
void* arg)
{
NS_ASSERTION(arg, "missing array");
nsCOMArray<nsINodeInfo> *array = (nsCOMArray<nsINodeInfo> *) arg;
if (!array->AppendObject((nsINodeInfo*)he->value)) {
return HT_ENUMERATE_STOP;
}
return HT_ENUMERATE_NEXT;
}
void
nsNodeInfoManager::RemoveNodeInfo(nsNodeInfo *aNodeInfo)
{

View File

@ -69,7 +69,6 @@ public:
virtual nsresult GetDocumentPrincipal(nsIPrincipal** aPrincipal);
virtual nsresult SetDocumentPrincipal(nsIPrincipal* aPrincipal);
virtual nsresult GetNodeInfos(nsCOMArray<nsINodeInfo> *aArray);
// nsNodeInfoManager
nsNodeInfoManager();
@ -82,10 +81,6 @@ private:
const void *key2);
static PLHashNumber PR_CALLBACK GetNodeInfoInnerHashValue(const void *key);
PR_STATIC_CALLBACK(PRIntn) GetNodeInfoArrayEnumerator(PLHashEntry* he,
PRIntn i,
void* arg);
PLHashTable *mNodeInfoHash;
nsCOMPtr<nsIPrincipal> mPrincipal;

View File

@ -294,16 +294,18 @@ nsGenericHTMLElement::CopyInnerTo(nsIContent* aSrcContent,
nsHTMLValue val;
rv = GetHTMLAttribute(nsHTMLAtoms::style, val);
if (rv == NS_CONTENT_ATTR_HAS_VALUE &&
val.GetUnit() == eHTMLUnit_ISupports) {
nsCOMPtr<nsISupports> supports(val.GetISupportsValue());
nsCOMPtr<nsICSSStyleRule> rule(do_QueryInterface(supports));
val.GetUnit() == eHTMLUnit_CSSStyleRule) {
nsICSSStyleRule* rule = val.GetCSSStyleRuleValue();
if (rule) {
nsCOMPtr<nsICSSRule> ruleClone;
rv = rule->Clone(*getter_AddRefs(ruleClone));
NS_ENSURE_SUCCESS(rv, rv);
val.SetISupportsValue(ruleClone);
nsCOMPtr<nsICSSStyleRule> styleRule = do_QueryInterface(ruleClone);
NS_ENSURE_TRUE(styleRule, NS_ERROR_UNEXPECTED);
val.SetCSSStyleRuleValue(styleRule);
rv = aDst->SetHTMLAttribute(nsHTMLAtoms::style, val, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
@ -1540,8 +1542,9 @@ nsGenericHTMLElement::GetNameSpaceID(PRInt32* aID) const
*aID = kNameSpaceID_XHTML;
}
static nsresult
ParseClassAttribute(const nsAString& aStr, nsAttrValue& aValue)
// static
nsresult
nsGenericHTMLElement::ParseClassAttribute(const nsAString& aStr, nsAttrValue& aValue)
{
nsAString::const_iterator iter, end;
aStr.BeginReading(iter);
@ -1607,11 +1610,7 @@ ParseClassAttribute(const nsAString& aStr, nsAttrValue& aValue)
}
} while (iter != end);
nsHTMLValue* htmlVal = new nsHTMLValue(array);
NS_ENSURE_TRUE(htmlVal, NS_ERROR_OUT_OF_MEMORY);
array.forget();
aValue.SetTo(htmlVal);
aValue.SetTo(nsHTMLValue(array.forget()));
return NS_OK;
}
@ -1658,16 +1657,15 @@ nsGenericHTMLElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aAttribute,
nsAttrValue attrValue;
if (aNamespaceID == kNameSpaceID_None) {
nsHTMLValue htmlValue;
if ((aAttribute == nsHTMLAtoms::style &&
NS_SUCCEEDED(ParseStyleAttribute(aValue, htmlValue))) ||
(StringToAttribute(aAttribute, aValue, htmlValue) !=
if ((StringToAttribute(aAttribute, aValue, htmlValue) !=
NS_CONTENT_ATTR_NOT_THERE) ||
ParseCommonAttribute(aAttribute, aValue, htmlValue)) {
// string value was mapped to nsHTMLValue, set it that way
nsHTMLValue* tmp = new nsHTMLValue(htmlValue);
NS_ENSURE_TRUE(tmp, NS_ERROR_OUT_OF_MEMORY);
attrValue.SetTo(tmp);
attrValue.SetTo(htmlValue);
}
else if (aAttribute == nsHTMLAtoms::style) {
ParseStyleAttribute(this, mNodeInfo->NamespaceEquals(kNameSpaceID_XHTML),
aValue, attrValue);
}
else if (aAttribute == nsHTMLAtoms::id) {
nsCOMPtr<nsIAtom> idAtom = do_GetAtom(aValue);
@ -1682,10 +1680,7 @@ nsGenericHTMLElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aAttribute,
else if (aValue.IsEmpty()) {
// This is a bit evil but there's code out there that only looks for
// this datatype and not for empty-string.
nsHTMLValue* tmp = new nsHTMLValue(eHTMLUnit_Empty);
NS_ENSURE_TRUE(tmp, NS_ERROR_OUT_OF_MEMORY);
attrValue.SetTo(tmp);
attrValue.SetTo(nsHTMLValue(eHTMLUnit_Empty));
}
else {
attrValue.SetTo(aValue);
@ -1879,11 +1874,7 @@ nsGenericHTMLElement::SetHTMLAttribute(nsIAtom* aAttribute,
}
}
nsHTMLValue* htmlVal = new nsHTMLValue(aValue);
NS_ENSURE_TRUE(htmlVal, NS_ERROR_OUT_OF_MEMORY);
nsAttrValue attrValue(htmlVal);
nsAttrValue attrValue(aValue);
return SetAttrAndNotify(kNameSpaceID_None, aAttribute, nsnull, oldValueStr,
attrValue, modification, hasListeners, aNotify);
@ -1998,6 +1989,7 @@ nsGenericHTMLElement::GetAttr(PRInt32 aNameSpaceID, nsIAtom *aAttribute,
case eHTMLUnit_Pixel:
case eHTMLUnit_Color:
case eHTMLUnit_Percent:
case eHTMLUnit_CSSStyleRule:
case eHTMLUnit_AtomArray:
value->ToString(aResult);
break;
@ -2191,19 +2183,16 @@ nsGenericHTMLElement::GetInlineStyleRule(nsICSSStyleRule** aStyleRule)
if (attrVal) {
if (attrVal->GetType() != nsAttrValue::eHTMLValue ||
attrVal->GetHTMLValue()->GetUnit() != eHTMLUnit_ISupports) {
attrVal->GetHTMLValue()->GetUnit() != eHTMLUnit_CSSStyleRule) {
ReparseStyleAttribute();
attrVal = mAttrsAndChildren.GetAttr(nsHTMLAtoms::style);
// hopefully value.GetUnit() is now eHTMLUnit_ISupports
// hopefully value.GetUnit() is now eHTMLUnit_CSSStyleRule
}
if (attrVal->GetType() == nsAttrValue::eHTMLValue &&
attrVal->GetHTMLValue()->GetUnit() == eHTMLUnit_ISupports) {
nsCOMPtr<nsISupports> supports =
attrVal->GetHTMLValue()->GetISupportsValue();
if (supports) {
return CallQueryInterface(supports, aStyleRule);
}
attrVal->GetHTMLValue()->GetUnit() == eHTMLUnit_CSSStyleRule) {
NS_IF_ADDREF(*aStyleRule =
attrVal->GetHTMLValue()->GetCSSStyleRuleValue());
}
}
@ -2389,24 +2378,7 @@ nsGenericHTMLElement::AttributeToString(nsIAtom* aAttribute,
const nsHTMLValue& aValue,
nsAString& aResult) const
{
if (nsHTMLAtoms::style == aAttribute) {
if (eHTMLUnit_ISupports == aValue.GetUnit()) {
nsCOMPtr<nsISupports> rule = aValue.GetISupportsValue();
nsCOMPtr<nsICSSStyleRule> cssRule = do_QueryInterface(rule);
if (cssRule) {
nsCSSDeclaration* decl = cssRule->GetDeclaration();
if (decl) {
decl->ToString(aResult);
} else {
aResult.Truncate();
}
}
else {
aResult.Assign(NS_LITERAL_STRING("Unknown rule type"));
}
return NS_CONTENT_ATTR_HAS_VALUE;
}
} else if (nsHTMLAtoms::dir == aAttribute) {
if (nsHTMLAtoms::dir == aAttribute) {
nsHTMLValue value;
nsresult result = GetHTMLAttribute(nsHTMLAtoms::dir, value);
@ -2957,37 +2929,38 @@ nsGenericHTMLElement::AttrToURI(nsIAtom* aAttrName, nsAString& aAbsoluteURI)
nsresult
nsGenericHTMLElement::ReparseStyleAttribute()
{
const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(nsHTMLAtoms::style);
const nsAttrValue* oldVal = mAttrsAndChildren.GetAttr(nsHTMLAtoms::style);
if (attrVal &&
(attrVal->GetType() != nsAttrValue::eHTMLValue ||
attrVal->GetHTMLValue()->GetUnit() == eHTMLUnit_String)) {
nsHTMLValue parsedValue;
if (oldVal &&
(oldVal->GetType() != nsAttrValue::eHTMLValue ||
oldVal->GetHTMLValue()->GetUnit() != eHTMLUnit_CSSStyleRule)) {
nsAttrValue attrValue;
nsAutoString stringValue;
attrVal->ToString(stringValue);
nsresult rv = ParseStyleAttribute(stringValue, parsedValue);
if (NS_SUCCEEDED(rv) && parsedValue.GetUnit() == eHTMLUnit_ISupports) {
nsHTMLValue* tmp = new nsHTMLValue(parsedValue);
NS_ENSURE_TRUE(tmp, NS_ERROR_OUT_OF_MEMORY);
// Don't bother going through SetHTMLAttribute, we don't want to fire off
// mutation events or document notifications anyway
nsAttrValue attrValue(tmp);
rv = mAttrsAndChildren.SetAndTakeAttr(nsHTMLAtoms::style, attrValue);
NS_ENSURE_SUCCESS(rv, rv);
}
oldVal->ToString(stringValue);
ParseStyleAttribute(this, mNodeInfo->NamespaceEquals(kNameSpaceID_XHTML),
stringValue, attrValue);
// Don't bother going through SetHTMLAttribute, we don't want to fire off
// mutation events or document notifications anyway
nsresult rv = mAttrsAndChildren.SetAndTakeAttr(nsHTMLAtoms::style, attrValue);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
nsresult
nsGenericHTMLElement::ParseStyleAttribute(const nsAString& aValue, nsHTMLValue& aResult)
void
nsGenericHTMLElement::ParseStyleAttribute(nsIContent* aContent,
PRBool aCaseSensitive,
const nsAString& aValue,
nsAttrValue& aResult)
{
nsresult result = NS_OK;
NS_ASSERTION(mNodeInfo, "If we don't have a nodeinfo, we are very screwed");
NS_ASSERTION(aContent->GetNodeInfo(), "If we don't have a nodeinfo, we are very screwed");
nsIDocument* doc = GetOwnerDocument();
nsIDocument* doc = aContent->GetDocument();
if (!doc) {
doc = aContent->GetNodeInfo()->GetDocument();
}
if (doc) {
PRBool isCSS = PR_TRUE; // assume CSS until proven otherwise
@ -3010,11 +2983,11 @@ nsGenericHTMLElement::ParseStyleAttribute(const nsAString& aValue, nsHTMLValue&
if (cssParser) {
// look up our namespace. If we're XHTML, we need to be case-sensitive
// Otherwise, we should not be.
cssParser->SetCaseSensitive(mNodeInfo->NamespaceEquals(kNameSpaceID_XHTML));
cssParser->SetCaseSensitive(aCaseSensitive);
}
}
if (cssParser) {
nsCOMPtr<nsIURI> baseURI = GetBaseURI();
nsCOMPtr<nsIURI> baseURI = aContent->GetBaseURI();
nsCOMPtr<nsICSSStyleRule> rule;
result = cssParser->ParseStyleAttribute(aValue, baseURI,
@ -3024,14 +2997,15 @@ nsGenericHTMLElement::ParseStyleAttribute(const nsAString& aValue, nsHTMLValue&
}
if (rule) {
aResult.SetISupportsValue(rule);
return NS_OK;
aResult.SetTo(nsHTMLValue(rule));
return;
}
}
}
}
return NS_ERROR_FAILURE;
aResult.SetTo(aValue);
}
/**
@ -4418,7 +4392,10 @@ nsGenericHTMLElement::InternalGetExistingAttrNameFromQName(const nsAString& aStr
if (mNodeInfo->NamespaceEquals(kNameSpaceID_None)) {
nsAutoString lower;
ToLowerCase(aStr, lower);
return mAttrsAndChildren.GetExistingAttrNameFromQName(lower);
return mAttrsAndChildren.GetExistingAttrNameFromQName(
NS_ConvertUTF16toUTF8(lower));
}
return mAttrsAndChildren.GetExistingAttrNameFromQName(aStr);
return mAttrsAndChildren.GetExistingAttrNameFromQName(
NS_ConvertUTF16toUTF8(aStr));
}

View File

@ -490,13 +490,28 @@ public:
nsresult ReparseStyleAttribute(void);
/**
* Parse a style attr value into a CSS rulestruct (or, if there is no
* document, leave it as a string) and return as HTMLValue.
* document, leave it as a string) and return as nsAttrValue.
* Note: this function is used by other classes than nsGenericHTMLElement
*
* @param aValue the value to parse
* @param aResult the resulting HTMLValue [OUT]
*/
nsresult ParseStyleAttribute(const nsAString& aValue,
nsHTMLValue& aResult);
static void ParseStyleAttribute(nsIContent* aContent,
PRBool aCaseSensitive,
const nsAString& aValue,
nsAttrValue& aResult);
/**
* Parse a class attr value into a nsAttrValue. If there is only one class
* the resulting type will be an atom. If there are more then one the result
* will be an atom-array.
* Note: this function is used by other classes than nsGenericHTMLElement
*
* @param aStr The attributes string-value to parse.
* @param aValue The resulting nsAttrValue [OUT]
*/
static nsresult ParseClassAttribute(const nsAString& aStr,
nsAttrValue& aValue);
/*
* Attribute Mapping Helpers

View File

@ -41,7 +41,6 @@
#include "nscore.h"
#include "nsColor.h"
#include "nsString.h"
#include "nsISupports.h"
#include "nsCOMPtr.h"
#include "nsReadableUtils.h"
@ -50,6 +49,7 @@
#include "nsIAtom.h"
class nsIDocument;
class nsICSSStyleRule;
class nsCheapStringBufferUtils {
public:
@ -148,15 +148,15 @@ public:
// between different things stored as the same type. Doing
// mUnit & HTMLUNIT_CLASS_MASK should give you the class of type.
//
#define HTMLUNIT_NOSTORE 0x0000
#define HTMLUNIT_STRING 0x0100
#define HTMLUNIT_INTEGER 0x0200
#define HTMLUNIT_PIXEL 0x0400
#define HTMLUNIT_COLOR 0x0800
#define HTMLUNIT_ISUPPORTS 0x1000
#define HTMLUNIT_PERCENT 0x2000
#define HTMLUNIT_ATOMARRAY 0x4000
#define HTMLUNIT_CLASS_MASK 0xff00
#define HTMLUNIT_NOSTORE 0x0000
#define HTMLUNIT_STRING 0x0100
#define HTMLUNIT_INTEGER 0x0200
#define HTMLUNIT_PIXEL 0x0400
#define HTMLUNIT_COLOR 0x0800
#define HTMLUNIT_CSSSTYLERULE 0x1000
#define HTMLUNIT_PERCENT 0x2000
#define HTMLUNIT_ATOMARRAY 0x4000
#define HTMLUNIT_CLASS_MASK 0xff00
enum nsHTMLUnit {
// null, value is not specified: 0x0000
@ -182,8 +182,8 @@ enum nsHTMLUnit {
// an RGBA value
eHTMLUnit_Color = HTMLUNIT_COLOR,
// (nsISupports*) a ref counted interface
eHTMLUnit_ISupports = HTMLUNIT_ISUPPORTS,
// a nsICSSStyleRule
eHTMLUnit_CSSStyleRule = HTMLUNIT_CSSSTYLERULE,
// (1.0 == 100%) value is percentage of something
eHTMLUnit_Percent = HTMLUNIT_PERCENT,
@ -204,7 +204,7 @@ public:
nsHTMLValue(PRInt32 aValue, nsHTMLUnit aUnit);
nsHTMLValue(float aValue);
nsHTMLValue(const nsAString& aValue, nsHTMLUnit aUnit = eHTMLUnit_String);
nsHTMLValue(nsISupports* aValue);
nsHTMLValue(nsICSSStyleRule* aValue);
nsHTMLValue(nscolor aValue);
nsHTMLValue(nsCOMArray<nsIAtom>* aArray);
nsHTMLValue(const nsHTMLValue& aCopy);
@ -225,7 +225,7 @@ public:
PRInt32 GetPixelValue(void) const;
float GetPercentValue(void) const;
nsAString& GetStringValue(nsAString& aBuffer) const;
already_AddRefed<nsISupports> GetISupportsValue(void) const;
nsICSSStyleRule* GetCSSStyleRuleValue(void) const;
nscolor GetColorValue(void) const;
nsCOMArray<nsIAtom>* AtomArrayValue() const;
@ -237,7 +237,7 @@ public:
void SetPixelValue(PRInt32 aValue);
void SetPercentValue(float aValue);
void SetStringValue(const nsAString& aValue, nsHTMLUnit aUnit = eHTMLUnit_String);
void SetISupportsValue(nsISupports* aValue);
void SetCSSStyleRuleValue(nsICSSStyleRule* aValue);
void SetColorValue(nscolor aValue);
void SetEmptyValue(void);
@ -363,8 +363,8 @@ protected:
float mFloat;
/** String. First 4 bytes are the length, non-null-terminated. */
PRUnichar* mString;
/** ISupports. Strong reference. */
nsISupports* mISupports;
/** nsICSSStyleRule. Strong reference. */
nsICSSStyleRule* mCSSStyleRule;
/** Color. */
nscolor mColor;
/** Array if atoms */
@ -462,13 +462,11 @@ inline nsAString& nsHTMLValue::GetStringValue(nsAString& aBuffer) const
return aBuffer;
}
inline already_AddRefed<nsISupports> nsHTMLValue::GetISupportsValue(void) const
inline nsICSSStyleRule* nsHTMLValue::GetCSSStyleRuleValue(void) const
{
NS_ASSERTION(mUnit == eHTMLUnit_ISupports, "not an ISupports value");
if (mUnit == eHTMLUnit_ISupports) {
nsISupports *result = mValue.mISupports;
NS_IF_ADDREF(result);
return result;
NS_ASSERTION(mUnit == eHTMLUnit_CSSStyleRule, "not an CSSStyleRule value");
if (mUnit == eHTMLUnit_CSSStyleRule) {
return mValue.mCSSStyleRule;
}
return nsnull;
}

View File

@ -67,4 +67,8 @@ FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk
INCLUDES += \
-I$(srcdir)/../../html/style/src \
$(NULL)
DEFINES += -D_IMPL_NS_LAYOUT

View File

@ -47,6 +47,8 @@
#include "nsIHTMLDocument.h"
#include "nsUnitConversion.h"
#include "prprf.h"
#include "nsICSSStyleRule.h"
#include "nsCSSDeclaration.h"
nsHTMLValue::nsHTMLValue(nsHTMLUnit aUnit)
: mUnit(aUnit)
@ -84,11 +86,11 @@ nsHTMLValue::nsHTMLValue(const nsAString& aValue, nsHTMLUnit aUnit)
SetStringValueInternal(aValue, aUnit);
}
nsHTMLValue::nsHTMLValue(nsISupports* aValue)
: mUnit(eHTMLUnit_ISupports)
nsHTMLValue::nsHTMLValue(nsICSSStyleRule* aValue)
: mUnit(eHTMLUnit_CSSStyleRule)
{
mValue.mISupports = aValue;
NS_IF_ADDREF(mValue.mISupports);
mValue.mCSSStyleRule = aValue;
NS_IF_ADDREF(mValue.mCSSStyleRule);
}
nsHTMLValue::nsHTMLValue(nscolor aValue)
@ -145,8 +147,8 @@ PRBool nsHTMLValue::operator==(const nsHTMLValue& aOther) const
case HTMLUNIT_COLOR:
return mValue.mColor == aOther.mValue.mColor;
case HTMLUNIT_ISUPPORTS:
return mValue.mISupports == aOther.mValue.mISupports;
case HTMLUNIT_CSSSTYLERULE:
return mValue.mCSSStyleRule == aOther.mValue.mCSSStyleRule;
case HTMLUNIT_PERCENT:
return mValue.mFloat == aOther.mValue.mFloat;
@ -203,8 +205,8 @@ void nsHTMLValue::Reset(void)
nsCheapStringBufferUtils::Free(mValue.mString);
}
}
else if (mUnit == eHTMLUnit_ISupports) {
NS_IF_RELEASE(mValue.mISupports);
else if (mUnit == eHTMLUnit_CSSStyleRule) {
NS_IF_RELEASE(mValue.mCSSStyleRule);
}
else if (mUnit == eHTMLUnit_AtomArray) {
delete mValue.mAtomArray;
@ -265,12 +267,12 @@ void nsHTMLValue::SetStringValue(const nsAString& aValue,
SetStringValueInternal(aValue, aUnit);
}
void nsHTMLValue::SetISupportsValue(nsISupports* aValue)
void nsHTMLValue::SetCSSStyleRuleValue(nsICSSStyleRule* aValue)
{
Reset();
mUnit = eHTMLUnit_ISupports;
mValue.mISupports = aValue;
NS_IF_ADDREF(mValue.mISupports);
mUnit = eHTMLUnit_CSSStyleRule;
mValue.mCSSStyleRule = aValue;
NS_IF_ADDREF(mValue.mCSSStyleRule);
}
void nsHTMLValue::SetColorValue(nscolor aValue)
@ -312,9 +314,9 @@ nsHTMLValue::InitializeFrom(const nsHTMLValue& aCopy)
mValue.mColor = aCopy.mValue.mColor;
break;
case HTMLUNIT_ISUPPORTS:
mValue.mISupports = aCopy.mValue.mISupports;
NS_IF_ADDREF(mValue.mISupports);
case HTMLUNIT_CSSSTYLERULE:
mValue.mCSSStyleRule = aCopy.mValue.mCSSStyleRule;
NS_IF_ADDREF(mValue.mCSSStyleRule);
break;
case HTMLUNIT_PERCENT:
@ -486,6 +488,18 @@ nsHTMLValue::ToString(nsAString& aResult) const
}
return PR_TRUE;
}
case eHTMLUnit_CSSStyleRule:
{
if (mValue.mCSSStyleRule) {
nsCSSDeclaration* decl = mValue.mCSSStyleRule->GetDeclaration();
if (decl) {
decl->ToString(aResult);
}
}
return PR_TRUE;
}
default:
return PR_FALSE;
}

View File

@ -915,9 +915,10 @@ nsXBLContentSink::AddAttributesToXULPrototype(const PRUnichar **aAtts,
// Copy the attributes into the prototype
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
for (; *aAtts; aAtts += 2) {
const nsDependentString key(aAtts[0]);
PRUint32 i;
for (i = 0; i < aAttsCount; ++i) {
const nsDependentString key(aAtts[i * 2]);
SplitXMLName(key, getter_AddRefs(nameSpacePrefix),
getter_AddRefs(nameAtom));
@ -939,43 +940,19 @@ nsXBLContentSink::AddAttributesToXULPrototype(const PRUnichar **aAtts,
nameSpacePrefix = nsnull;
}
mNodeInfoManager->GetNodeInfo(nameAtom, nameSpacePrefix, nameSpaceID,
getter_AddRefs(attrs->mNodeInfo));
if (nameSpaceID == kNameSpaceID_None) {
attrs[i].mName.SetTo(nameAtom);
}
else {
nsCOMPtr<nsINodeInfo> ni;
mNodeInfoManager->GetNodeInfo(nameAtom, nameSpacePrefix, nameSpaceID,
getter_AddRefs(ni));
attrs[i].mName.SetTo(ni);
}
attrs->mValue.SetValue(nsDependentString(aAtts[1]));
++attrs;
}
// XUL elements may require some additional work to compute
// derived information.
if (aElement->mNodeInfo->NamespaceEquals(kNameSpaceID_XUL)) {
nsAutoString value;
// Compute the element's class list if the element has a 'class' attribute.
rv = aElement->GetAttr(kNameSpaceID_None, nsXULAtoms::clazz, value);
if (NS_FAILED(rv)) return rv;
if (rv == NS_CONTENT_ATTR_HAS_VALUE) {
rv = nsClassList::ParseClasses(&aElement->mClassList, value);
if (NS_FAILED(rv)) return rv;
}
// Parse the element's 'style' attribute
rv = aElement->GetAttr(kNameSpaceID_None, nsHTMLAtoms::style, value);
if (NS_FAILED(rv)) return rv;
if (rv == NS_CONTENT_ATTR_HAS_VALUE) {
if (!mCSSParser) {
mCSSParser = do_CreateInstance(kCSSParserCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = mCSSParser->ParseStyleAttribute(value, mDocumentURI,
getter_AddRefs(aElement->mInlineStyleRule));
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to parse style rule");
if (NS_FAILED(rv)) return rv;
}
rv = aElement->SetAttrAt(i, nsDependentString(aAtts[i * 2 + 1]),
mDocumentURI);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;

View File

@ -156,8 +156,6 @@ protected:
nsIXBLDocumentInfo* mDocInfo;
PRBool mIsChromeOrResource; // For bug #45989
nsCOMPtr<nsICSSParser> mCSSParser; // [OWNER]
nsXBLPrototypeBinding* mBinding;
nsXBLPrototypeHandler* mHandler; // current handler, owned by its PrototypeBinding
nsXBLProtoImpl* mImplementation;

View File

@ -51,8 +51,6 @@ REQUIRES = xpcom \
CPPSRCS = \
nsRDFDOMNodeList.cpp \
nsXULAttributeValue.cpp \
nsXULAttributes.cpp \
nsXULElement.cpp \
nsXULPopupListener.cpp \
$(NULL)
@ -70,6 +68,7 @@ LOCAL_INCLUDES = \
-I$(srcdir)/../../../base/src \
-I$(srcdir)/../../../xml/document/src \
-I$(srcdir)/../../../html/style/src \
-I$(srcdir)/../../../html/content/src \
$(NULL)
DEFINES += -D_IMPL_NS_LAYOUT

View File

@ -1,154 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (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 the Initial Developer are Copyright (C) 2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Edward Kandrot <kandrot@netscape.com>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsReadableUtils.h"
#include "nsXULAttributeValue.h"
const PRUint32 nsXULAttributeValue::kMaxAtomValueLength = 12;
nsXULAttributeValue::nsXULAttributeValue()
{
mValue = nsnull;
}
nsXULAttributeValue::~nsXULAttributeValue()
{
if (mValue)
{
ReleaseValue();
}
}
nsresult nsXULAttributeValue::GetValue( nsAString& aResult )
{
nsresult rv = NS_OK;
if (! mValue) {
aResult.Truncate();
}
else if (IsStringValue())
{
aResult.Assign((const PRUnichar*) mValue);
}
else
{
nsIAtom* atom = (nsIAtom*)(PRWord(mValue) & ~PRWord(kTypeMask));
rv = atom->ToString(aResult);
}
return rv;
}
nsresult nsXULAttributeValue::SetValue(const nsAString& aValue,
PRBool forceAtom)
{
nsCOMPtr<nsIAtom> newAtom;
// Atomize the value if it is short, or if it is the 'id'
// attribute. We atomize the 'id' attribute to "prime" the global
// atom table: the style system frequently asks for it, and if the
// table is "unprimed" we see quite a bit of thrashing as the 'id'
// value is repeatedly added and then removed from the atom table.
PRUint32 len = aValue.Length();
if (len && ((len <= kMaxAtomValueLength) || forceAtom))
{
newAtom = do_GetAtom(aValue);
}
// Release the old value
if (mValue)
ReleaseValue();
// ...and set the new value
if (newAtom) {
NS_ADDREF((nsIAtom*)newAtom.get());
mValue = (void*)(PRWord(newAtom.get()) | kAtomType);
}
else {
PRUnichar* str = nsnull;
if (len) {
str = ToNewUnicode(aValue);
if (! str)
return NS_ERROR_OUT_OF_MEMORY;
}
mValue = str;
}
return NS_OK;
}
void nsXULAttributeValue::ReleaseValue( void ) {
if (IsStringValue())
{
nsMemory::Free(mValue);
}
else
{
nsIAtom* atom = (nsIAtom*)(PRWord(mValue) & ~PRWord(kTypeMask));
NS_RELEASE(atom);
}
mValue = nsnull;
}
nsresult nsXULAttributeValue::GetValueAsAtom(nsIAtom** aResult)
{
if (! mValue) {
*aResult = nsnull;
}
else if (IsStringValue()) {
*aResult = NS_NewAtom((const PRUnichar*) mValue);
}
else {
*aResult = (nsIAtom*)(PRWord(mValue) & ~PRWord(kTypeMask));
NS_ADDREF(*aResult);
}
return NS_OK;
}

View File

@ -1,74 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (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 the Initial Developer are Copyright (C) 2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Edward Kandrot <kandrot@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsXULAttributeValue_h__
#define nsXULAttributeValue_h__
#include "nsString.h"
#include "nsIAtom.h"
class nsXULAttributeValue
{
void *mValue;
static const PRUint32 kMaxAtomValueLength;
enum {
kTypeMask = 0x1,
kStringType = 0x0,
kAtomType = 0x1
};
PRBool IsStringValue() {
return (PRWord(mValue) & kTypeMask) == kStringType;
}
public:
nsXULAttributeValue();
~nsXULAttributeValue();
void ReleaseValue();
nsresult GetValue(nsAString& aResult);
nsresult SetValue(const nsAString& aValue, PRBool forceAtom=PR_FALSE);
nsresult GetValueAsAtom(nsIAtom** aResult);
};
#endif // nsXULAttributeValue_h__

View File

@ -1,781 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (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 the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
A helper class used to implement attributes.
*/
/*
* Notes
*
* A lot of these methods delegate back to the original content node
* that created them. This is so that we can lazily produce attribute
* values from the RDF graph as they're asked for.
*
*/
#include "nsCOMPtr.h"
#include "nsDOMCID.h"
#include "nsFixedSizeAllocator.h"
#include "nsIContent.h"
#include "nsINodeInfo.h"
#include "nsIDocument.h"
#include "nsICSSLoader.h"
#include "nsICSSParser.h"
#include "nsICSSStyleRule.h"
#include "nsIDOMElement.h"
#include "nsINameSpaceManager.h"
#include "nsIServiceManager.h"
#include "nsIURL.h"
#include "nsXULAttributes.h"
#include "nsLayoutCID.h"
#include "nsReadableUtils.h"
#include "nsContentUtils.h"
#include "nsXULAtoms.h"
#include "nsCRT.h"
static NS_DEFINE_CID(kCSSParserCID, NS_CSSPARSER_CID);
//----------------------------------------------------------------------
//
// nsClassList
//
PRBool
nsClassList::HasClass(nsClassList* aList, nsIAtom* aClass)
{
const nsClassList* classList = aList;
while (nsnull != classList) {
if (classList->mAtom.get() == aClass) {
return PR_TRUE;
}
classList = classList->mNext;
}
return PR_FALSE;
}
nsresult
nsClassList::GetClasses(nsClassList* aList, nsVoidArray& aArray)
{
aArray.Clear();
const nsClassList* classList = aList;
while (nsnull != classList) {
aArray.AppendElement(classList->mAtom); // NOTE atom is not addrefed
classList = classList->mNext;
}
return NS_OK;
}
nsresult
nsClassList::ParseClasses(nsClassList** aList, const nsAString& aClassString)
{
static const PRUnichar kNullCh = PRUnichar('\0');
if (*aList != nsnull) {
delete *aList;
*aList = nsnull;
}
if (!aClassString.IsEmpty()) {
nsAutoString classStr(aClassString); // copy to work buffer
classStr.Append(kNullCh); // put an extra null at the end
PRUnichar* start = (PRUnichar*)(const PRUnichar*)classStr.get();
PRUnichar* end = start;
while (kNullCh != *start) {
while ((kNullCh != *start) && nsCRT::IsAsciiSpace(*start)) { // skip leading space
start++;
}
end = start;
while ((kNullCh != *end) && (PR_FALSE == nsCRT::IsAsciiSpace(*end))) { // look for space or end
end++;
}
*end = kNullCh; // end string here
if (start < end) {
*aList = new nsClassList(NS_NewAtom(start));
aList = &((*aList)->mNext);
}
start = ++end;
}
}
return NS_OK;
}
//----------------------------------------------------------------------
//
// nsXULAttribute
//
nsXULAttribute::nsXULAttribute(nsIContent* aContent,
nsINodeInfo* aNodeInfo,
const nsAString& aValue)
: mContent(aContent),
mNodeInfo(aNodeInfo)
{
NS_IF_ADDREF(aNodeInfo);
SetValueInternal(aValue);
}
nsXULAttribute::~nsXULAttribute()
{
NS_IF_RELEASE(mNodeInfo);
mValue.ReleaseValue();
}
nsresult
nsXULAttribute::Create(nsIContent* aContent,
nsINodeInfo* aNodeInfo,
const nsAString& aValue,
nsXULAttribute** aResult)
{
NS_ENSURE_ARG_POINTER(aNodeInfo);
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (! (*aResult = new nsXULAttribute(aContent, aNodeInfo, aValue)))
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}
// nsISupports interface
// QueryInterface implementation for nsXULAttribute
NS_INTERFACE_MAP_BEGIN(nsXULAttribute)
NS_INTERFACE_MAP_ENTRY(nsIDOMAttr)
NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMAttr)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(XULAttr)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsXULAttribute)
NS_IMPL_RELEASE(nsXULAttribute)
// nsIDOMNode interface
NS_IMETHODIMP
nsXULAttribute::GetNodeName(nsAString& aNodeName)
{
GetQualifiedName(aNodeName);
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetNodeValue(nsAString& aNodeValue)
{
return mValue.GetValue(aNodeValue);
}
NS_IMETHODIMP
nsXULAttribute::SetNodeValue(const nsAString& aNodeValue)
{
return SetValue(aNodeValue);
}
NS_IMETHODIMP
nsXULAttribute::GetNodeType(PRUint16* aNodeType)
{
*aNodeType = (PRUint16)nsIDOMNode::ATTRIBUTE_NODE;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetParentNode(nsIDOMNode** aParentNode)
{
*aParentNode = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetChildNodes(nsIDOMNodeList** aChildNodes)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttribute::GetFirstChild(nsIDOMNode** aFirstChild)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttribute::GetLastChild(nsIDOMNode** aLastChild)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttribute::GetPreviousSibling(nsIDOMNode** aPreviousSibling)
{
*aPreviousSibling = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetNextSibling(nsIDOMNode** aNextSibling)
{
*aNextSibling = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetAttributes(nsIDOMNamedNodeMap** aAttributes)
{
*aAttributes = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttribute::GetNamespaceURI(nsAString& aNamespaceURI)
{
return mNodeInfo->GetNamespaceURI(aNamespaceURI);
}
NS_IMETHODIMP
nsXULAttribute::GetPrefix(nsAString& aPrefix)
{
mNodeInfo->GetPrefix(aPrefix);
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::SetPrefix(const nsAString& aPrefix)
{
// XXX: Validate the prefix string!
nsCOMPtr<nsINodeInfo> newNodeInfo;
nsCOMPtr<nsIAtom> prefix;
if (!aPrefix.IsEmpty()) {
prefix = do_GetAtom(aPrefix);
NS_ENSURE_TRUE(prefix, NS_ERROR_OUT_OF_MEMORY);
}
nsresult rv = mNodeInfo->PrefixChanged(prefix,
getter_AddRefs(newNodeInfo));
NS_ENSURE_SUCCESS(rv, rv);
NS_RELEASE(mNodeInfo);
mNodeInfo = newNodeInfo;
NS_ADDREF(mNodeInfo);
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetLocalName(nsAString& aLocalName)
{
mNodeInfo->GetLocalName(aLocalName);
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNode** aReturn)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXULAttribute::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXULAttribute::RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXULAttribute::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXULAttribute::HasChildNodes(PRBool* aReturn)
{
NS_ENSURE_ARG_POINTER(aReturn);
*aReturn = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::HasAttributes(PRBool* aReturn)
{
NS_ENSURE_ARG_POINTER(aReturn);
*aReturn = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttribute::Normalize()
{
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::IsSupported(const nsAString& aFeature,
const nsAString& aVersion,
PRBool* aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
// nsIDOMAttr interface
NS_IMETHODIMP
nsXULAttribute::GetName(nsAString& aName)
{
GetQualifiedName(aName);
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetSpecified(PRBool* aSpecified)
{
// XXX this'll break when we make Clone() work
*aSpecified = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetValue(nsAString& aValue)
{
return mValue.GetValue(aValue);
}
NS_IMETHODIMP
nsXULAttribute::SetValue(const nsAString& aValue)
{
// We call back to the content node's SetValue() method so we can
// share all of the work that it does.
return mContent->SetAttr(mNodeInfo->NamespaceID(), mNodeInfo->NameAtom(),
mNodeInfo->GetPrefixAtom(), aValue, PR_TRUE);
}
NS_IMETHODIMP
nsXULAttribute::GetOwnerElement(nsIDOMElement** aOwnerElement)
{
NS_ENSURE_ARG_POINTER(aOwnerElement);
return CallQueryInterface(mContent, aOwnerElement);
}
// Implementation methods
void
nsXULAttribute::GetQualifiedName(nsAString& aQualifiedName)
{
mNodeInfo->GetQualifiedName(aQualifiedName);
}
nsresult
nsXULAttribute::SetValueInternal(const nsAString& aValue)
{
return mValue.SetValue( aValue, mNodeInfo->Equals(nsXULAtoms::id) );
}
nsresult
nsXULAttribute::GetValueAsAtom(nsIAtom** aResult)
{
return mValue.GetValueAsAtom( aResult );
}
//----------------------------------------------------------------------
//
// nsXULAttributes
//
nsXULAttributes::nsXULAttributes(nsIContent* aContent)
: mContent(aContent),
mClassList(nsnull),
mStyleRule(nsnull)
{
}
nsXULAttributes::~nsXULAttributes()
{
PRInt32 count = mAttributes.Count();
for (PRInt32 indx = 0; indx < count; indx++) {
nsXULAttribute* attr = NS_REINTERPRET_CAST(nsXULAttribute*, mAttributes.ElementAt(indx));
NS_RELEASE(attr);
}
delete mClassList;
}
static nsFixedSizeAllocator *gAttrAllocator;
static PRUint32 gRefCnt;
static PRBool
CreateAttrAllocator()
{
gAttrAllocator = new nsFixedSizeAllocator();
if (!gAttrAllocator)
return PR_FALSE;
const size_t bucketSize = sizeof(nsXULAttributes);
const PRInt32 initalElements = 128; // XXX tune me
if (NS_FAILED(gAttrAllocator->Init("XUL Attributes", &bucketSize,
1, bucketSize * initalElements,
8))) {
delete gAttrAllocator;
gAttrAllocator = nsnull;
return PR_FALSE;
}
return PR_TRUE;
}
static void
DestroyAttrAllocator()
{
NS_ASSERTION(!gRefCnt, "Premature call to DestroyAttrAllocator!");
delete gAttrAllocator;
gAttrAllocator = nsnull;
}
nsresult
nsXULAttributes::Create(nsIContent* aContent, nsXULAttributes** aResult)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (!gRefCnt && !CreateAttrAllocator())
return NS_ERROR_OUT_OF_MEMORY;
// Increment here, because this controls the gAttrAllocator's destruction.
// Failure cases below must decrement gRefCnt, and then call
// DestroyAttrAllocator if gRefCnt == 0, to avoid leaking a ref that will
// not be balanced by a matching Destroy call. (|goto error;| works.)
gRefCnt++;
void *place = gAttrAllocator->Alloc(sizeof (nsXULAttributes));
if (!place)
goto error;
*aResult = ::new (place) nsXULAttributes(aContent);
if (!*aResult)
goto error;
NS_ADDREF(*aResult);
return NS_OK;
error:
if (!--gRefCnt)
DestroyAttrAllocator();
return NS_ERROR_OUT_OF_MEMORY;
}
/* static */ void
nsXULAttributes::Destroy(nsXULAttributes *aAttrs)
{
aAttrs->~nsXULAttributes();
NS_ASSERTION(gAttrAllocator,
"Allocator destroyed with live nsXULAttributes remaining!");
gAttrAllocator->Free(aAttrs, sizeof *aAttrs);
if (!--gRefCnt)
DestroyAttrAllocator();
}
// nsISupports interface
// QueryInterface implementation for nsXULAttributes
NS_INTERFACE_MAP_BEGIN(nsXULAttributes)
NS_INTERFACE_MAP_ENTRY(nsIDOMNamedNodeMap)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMNamedNodeMap)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(XULNamedNodeMap)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsXULAttributes)
// Custom release method to go through the fixed-size allocator
nsrefcnt
nsXULAttributes::Release()
{
--mRefCnt;
NS_LOG_RELEASE(this, mRefCnt, "nsXULAttributes");
if (mRefCnt == 0) {
mRefCnt = 1; // stabilize (necessary for this class?)
Destroy(this);
return 0;
}
return mRefCnt;
}
// nsIDOMNamedNodeMap interface
NS_IMETHODIMP
nsXULAttributes::GetLength(PRUint32* aLength)
{
NS_PRECONDITION(aLength != nsnull, "null ptr");
if (! aLength)
return NS_ERROR_NULL_POINTER;
*aLength = mAttributes.Count();
return NS_OK;
}
NS_IMETHODIMP
nsXULAttributes::GetNamedItem(const nsAString& aName,
nsIDOMNode** aReturn)
{
NS_PRECONDITION(aReturn != nsnull, "null ptr");
if (! aReturn)
return NS_ERROR_NULL_POINTER;
*aReturn = nsnull;
// XXX nameSpaceID only used in dead code (that was giving us a warning).
// XXX I'd remove it completely, but maybe it is a useful reminder???
// PRInt32 nameSpaceID;
nsCOMPtr<nsINodeInfo> inpNodeInfo =
mContent->GetExistingAttrNameFromQName(aName);
if (!inpNodeInfo) {
return NS_OK;
}
// if (kNameSpaceID_Unknown == nameSpaceID) {
// nameSpaceID = kNameSpaceID_None; // ignore unknown prefix XXX is this correct?
// }
// XXX doing this instead of calling mContent->GetAttr() will
// make it a lot harder to lazily instantiate properties from the
// graph. The problem is, how else do we get the named item?
for (PRInt32 i = mAttributes.Count() - 1; i >= 0; --i) {
nsXULAttribute* attr = (nsXULAttribute*) mAttributes[i];
nsINodeInfo *ni = attr->GetNodeInfo();
if (inpNodeInfo->Equals(ni)) {
NS_ADDREF(attr);
*aReturn = attr;
break;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsXULAttributes::SetNamedItem(nsIDOMNode* aArg, nsIDOMNode** aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttributes::RemoveNamedItem(const nsAString& aName,
nsIDOMNode** aReturn)
{
nsCOMPtr<nsIDOMElement> element( do_QueryInterface(mContent) );
*aReturn = nsnull;
if (element) {
// XXX should set aReturn to the element we are about to remove
return element->RemoveAttribute(aName);
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXULAttributes::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
{
*aReturn = (nsXULAttribute*) mAttributes[aIndex];
NS_IF_ADDREF(*aReturn);
return NS_OK;
}
nsresult
nsXULAttributes::GetNamedItemNS(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
nsIDOMNode** aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
nsXULAttributes::SetNamedItemNS(nsIDOMNode* aArg, nsIDOMNode** aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
nsXULAttributes::RemoveNamedItemNS(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
nsIDOMNode** aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
// Implementation methods
nsresult
nsXULAttributes::GetClasses(nsVoidArray& aArray) const
{
return nsClassList::GetClasses(mClassList, aArray);
}
PRBool
nsXULAttributes::HasClass(nsIAtom* aClass) const
{
return nsClassList::HasClass(mClassList, aClass);
}
nsresult nsXULAttributes::SetClassList(nsClassList* aClassList)
{
delete mClassList;
if (aClassList) {
mClassList = new nsClassList(*aClassList);
}
else {
mClassList = nsnull;
}
return NS_OK;
}
nsresult nsXULAttributes::UpdateClassList(const nsAString& aValue)
{
return nsClassList::ParseClasses(&mClassList, aValue);
}
nsresult nsXULAttributes::UpdateStyleRule(nsIURI* aDocURL, const nsAString& aValue)
{
if (aValue.IsEmpty())
{
// Just remove the rule; we'll be getting our style reresolved
mStyleRule = nsnull;
return NS_OK;
}
nsIDocument* doc = mContent->GetNodeInfo()->GetDocument();
nsICSSLoader* cssLoader = nsnull;
if (doc) {
cssLoader = doc->GetCSSLoader();
}
nsCOMPtr<nsICSSParser> css;
nsresult result = NS_OK;
if (cssLoader) {
result = cssLoader->GetParserFor(nsnull, getter_AddRefs(css));
} else {
css = do_CreateInstance(kCSSParserCID, &result);
}
NS_ENSURE_SUCCESS(result, result);
nsCOMPtr<nsICSSStyleRule> rule;
result = css->ParseStyleAttribute(aValue, aDocURL, getter_AddRefs(rule));
if ((NS_OK == result) && rule) {
mStyleRule = rule;
}
if (cssLoader) {
cssLoader->RecycleParser(css);
}
return NS_OK;
}
nsresult nsXULAttributes::SetInlineStyleRule(nsICSSStyleRule* aRule)
{
mStyleRule = aRule;
return NS_OK;
}
nsresult nsXULAttributes::GetInlineStyleRule(nsICSSStyleRule*& aRule)
{
nsresult result = NS_ERROR_NULL_POINTER;
if (mStyleRule != nsnull)
{
aRule = mStyleRule;
NS_ADDREF(aRule);
result = NS_OK;
}
return result;
}

View File

@ -1,214 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (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 the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
A set of helper classes used to implement attributes.
*/
#ifndef nsXULAttributes_h__
#define nsXULAttributes_h__
#include "nsIDOMAttr.h"
#include "nsIDOMNamedNodeMap.h"
#include "nsIStyleRule.h"
#include "nsString.h"
#include "nsIAtom.h"
#include "nsVoidArray.h"
#include "nsXULAttributeValue.h"
#include "nsDOMCSSDeclaration.h"
#include "nsAutoPtr.h"
class nsIURI;
class nsINodeInfo;
//----------------------------------------------------------------------
class nsClassList {
public:
nsClassList(nsIAtom* aAtom)
: mAtom(getter_AddRefs(aAtom)), mNext(nsnull)
{
MOZ_COUNT_CTOR(nsClassList);
}
nsClassList(const nsClassList& aCopy)
: mAtom(aCopy.mAtom), mNext(nsnull)
{
MOZ_COUNT_CTOR(nsClassList);
if (aCopy.mNext) mNext = new nsClassList(*(aCopy.mNext));
}
nsClassList& operator=(const nsClassList& aClassList)
{
if (this != &aClassList) {
delete mNext;
mNext = nsnull;
mAtom = aClassList.mAtom;
if (aClassList.mNext) {
mNext = new nsClassList(*(aClassList.mNext));
}
}
return *this;
}
~nsClassList(void)
{
MOZ_COUNT_DTOR(nsClassList);
delete mNext;
}
nsCOMPtr<nsIAtom> mAtom;
nsClassList* mNext;
static PRBool
HasClass(nsClassList* aList, nsIAtom* aClass);
static nsresult
GetClasses(nsClassList* aList, nsVoidArray& aArray);
static nsresult
ParseClasses(nsClassList** aList, const nsAString& aValue);
};
////////////////////////////////////////////////////////////////////////
class nsXULAttribute : public nsIDOMAttr
{
protected:
nsXULAttribute(nsIContent* aContent,
nsINodeInfo* aNodeInfo,
const nsAString& aValue);
virtual ~nsXULAttribute();
public:
static nsresult
Create(nsIContent* aContent,
nsINodeInfo* aNodeInfo,
const nsAString& aValue,
nsXULAttribute** aResult);
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIDOMNode interface
NS_DECL_NSIDOMNODE
// nsIDOMAttr interface
NS_DECL_NSIDOMATTR
// Implementation methods
void GetQualifiedName(nsAString& aAttributeName);
nsINodeInfo* GetNodeInfo() const { return mNodeInfo; }
nsresult SetValueInternal(const nsAString& aValue);
nsresult GetValueAsAtom(nsIAtom** aResult);
protected:
union {
nsIContent* mContent; // The content object that owns the attribute
nsXULAttribute* mNext; // For objects on the freelist
};
nsINodeInfo* mNodeInfo; // The attribute name
nsXULAttributeValue mValue; // The attribute value; either an nsIAtom* or PRUnichar*,
// with the low-order bit tagging its type
};
////////////////////////////////////////////////////////////////////////
class nsXULAttributes : public nsIDOMNamedNodeMap
{
public:
static nsresult
Create(nsIContent* aElement, nsXULAttributes** aResult);
static void
Destroy(nsXULAttributes *aAttrs);
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIDOMNamedNodeMap interface
NS_DECL_NSIDOMNAMEDNODEMAP
// Implementation methods
// VoidArray Helpers
PRUint32 Count() { return mAttributes.Count(); };
nsXULAttribute* ElementAt(PRInt32 i) { return (nsXULAttribute*)mAttributes.ElementAt(i); };
void AppendElement(nsXULAttribute* aElement) { mAttributes.AppendElement((void*)aElement); };
void RemoveElementAt(PRInt32 aIndex) { mAttributes.RemoveElementAt(aIndex); };
// Style Helpers
nsresult GetClasses(nsVoidArray& aArray) const;
PRBool HasClass(nsIAtom* aClass) const;
nsresult SetClassList(nsClassList* aClassList);
nsresult UpdateClassList(const nsAString& aValue);
nsresult UpdateStyleRule(nsIURI* aDocURL, const nsAString& aValue);
nsresult SetInlineStyleRule(nsICSSStyleRule* aRule);
nsresult GetInlineStyleRule(nsICSSStyleRule*& aRule);
void SetDOMStyle(nsDOMCSSDeclaration *aDOMDecl) { mDOMStyle = aDOMDecl; }
nsDOMCSSDeclaration* GetDOMStyle() { return mDOMStyle; }
protected:
nsXULAttributes(nsIContent* aContent);
virtual ~nsXULAttributes();
nsIContent* mContent;
nsClassList* mClassList;
nsCOMPtr<nsICSSStyleRule> mStyleRule;
nsRefPtr<nsDOMCSSDeclaration> mDOMStyle;
nsAutoVoidArray mAttributes;
private:
// Hide so that all construction and destruction use Create and Destroy.
static void *operator new(size_t) CPP_THROW_NEW { return 0; };
static void operator delete(void *, size_t) { };
};
#endif // nsXULAttributes_h__

File diff suppressed because it is too large Load Diff

View File

@ -75,14 +75,13 @@
#include "nsIXULPrototypeCache.h"
#include "nsIXULTemplateBuilder.h"
#include "nsIBoxObject.h"
#include "nsXULAttributes.h"
#include "nsIChromeEventHandler.h"
#include "nsXULAttributeValue.h"
#include "nsIXBLService.h"
#include "nsICSSOMFactory.h"
#include "nsLayoutCID.h"
#include "nsGenericElement.h" // for nsCheapVoidArray
#include "nsAttrAndChildArray.h"
#include "nsXULAtoms.h"
#include "nsAutoPtr.h"
class nsIDocument;
class nsIRDFService;
@ -91,9 +90,9 @@ class nsIXULContentUtils;
class nsIXULPrototypeDocument;
class nsRDFDOMNodeList;
class nsString;
class nsXULAttributes;
class nsVoidArray;
class nsIDocShell;
class nsDOMAttributeMap;
class nsIObjectInputStream;
class nsIObjectOutputStream;
@ -121,7 +120,8 @@ class nsXULPrototypeAttribute
{
public:
nsXULPrototypeAttribute()
: mEventHandler(nsnull)
: mEventHandler(nsnull),
mName(nsXULAtoms::id) // XXX this is a hack, but names have to have a value
{
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumAttributes);
MOZ_COUNT_CTOR(nsXULPrototypeAttribute);
@ -129,9 +129,9 @@ public:
~nsXULPrototypeAttribute();
nsCOMPtr<nsINodeInfo> mNodeInfo;
nsXULAttributeValue mValue;
void* mEventHandler;
nsAttrName mName;
nsAttrValue mValue;
void* mEventHandler;
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
/**
@ -241,8 +241,7 @@ public:
mNumChildren(0),
mChildren(nsnull),
mNumAttributes(0),
mAttributes(nsnull),
mClassList(nsnull)
mAttributes(nsnull)
{
NS_LOG_ADDREF(this, 1, ClassName(), ClassSize());
}
@ -250,7 +249,6 @@ public:
virtual ~nsXULPrototypeElement()
{
delete[] mAttributes;
delete mClassList;
delete[] mChildren;
}
@ -280,6 +278,8 @@ public:
nsIURI* aDocumentURI,
const nsCOMArray<nsINodeInfo> *aNodeInfos);
nsresult SetAttrAt(PRUint32 aPos, const nsAString& aValue, nsIURI* aDocumentURI);
PRUint32 mNumChildren;
nsXULPrototypeNode** mChildren; // [OWNER]
@ -288,12 +288,6 @@ public:
PRUint32 mNumAttributes;
nsXULPrototypeAttribute* mAttributes; // [OWNER]
nsCOMPtr<nsICSSStyleRule> mInlineStyleRule; // [OWNER]
nsClassList* mClassList;
nsresult GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsAString& aValue);
static void ReleaseGlobals()
{
NS_IF_RELEASE(sCSSParser);
@ -590,7 +584,7 @@ protected:
protected:
// Required fields
nsXULPrototypeElement* mPrototype;
nsSmallVoidArray mChildren; // [OWNER]
nsAttrAndChildArray mAttrsAndChildren; // [OWNER]
nsCOMPtr<nsIEventListenerManager> mListenerManager; // [OWNER]
/**
@ -604,33 +598,35 @@ protected:
* lazily copied from the prototype when changed.
*/
struct Slots {
Slots(nsXULElement* mElement);
Slots();
~Slots();
nsCOMPtr<nsINodeInfo> mNodeInfo; // [OWNER]
nsCOMPtr<nsIControllers> mControllers; // [OWNER]
nsRefPtr<nsDOMCSSDeclaration> mDOMStyle; // [OWNER]
/**
* Contains the mLazyState in the low two bits, and a pointer
* to the nsXULAttributes structure in the high bits.
* to the nsDOMAttributeMap structure in the high bits.
*/
PRWord mBits;
#define LAZYSTATE_MASK ((PRWord(1) << LAZYSTATE_BITS) - 1)
#define ATTRIBUTES_MASK (~LAZYSTATE_MASK)
nsXULAttributes *
GetAttributes() const {
return NS_REINTERPRET_CAST(nsXULAttributes *, mBits & ATTRIBUTES_MASK);
nsDOMAttributeMap *
GetAttributeMap() const {
return NS_REINTERPRET_CAST(nsDOMAttributeMap *, mBits & ATTRIBUTES_MASK);
}
void
SetAttributes(nsXULAttributes *aAttributes) {
NS_ASSERTION((NS_REINTERPRET_CAST(PRWord, aAttributes) & ~ATTRIBUTES_MASK) == 0,
"nsXULAttributes pointer is unaligned");
SetAttributeMap(nsDOMAttributeMap *aAttributeMap) {
NS_ASSERTION((NS_REINTERPRET_CAST(PRWord, aAttributeMap) &
~ATTRIBUTES_MASK) == 0,
"nsDOMAttributeMap pointer is unaligned");
mBits &= ~ATTRIBUTES_MASK;
mBits |= NS_REINTERPRET_CAST(PRWord, aAttributes);
mBits |= NS_REINTERPRET_CAST(PRWord, aAttributeMap);
}
LazyState
@ -657,34 +653,14 @@ protected:
*/
nsresult EnsureSlots();
/**
* Ensure that our mSlots has an mAttributes, creating an
* nsXULAttributes object if necessary.
*/
nsresult EnsureAttributes();
/**
* Abandon our prototype linkage, and copy all attributes locally
*/
nsresult MakeHeavyweight();
/**
* Return our private copy of the attribute, if one exists.
*/
nsXULAttribute *FindLocalAttribute(nsINodeInfo *info) const;
/**
* Return our private copy of the attribute, if one exists.
*/
nsXULAttribute *FindLocalAttribute(PRInt32 aNameSpaceID,
nsIAtom *aName,
PRInt32 *aIndex = nsnull) const;
/**
* Return our prototype's attribute, if one exists.
*/
nsXULPrototypeAttribute *FindPrototypeAttribute(nsINodeInfo *info) const;
const nsAttrValue* FindLocalOrProtoAttr(PRInt32 aNameSpaceID,
nsIAtom *aName) const;
/**
* Return our prototype's attribute, if one exists.
*/
@ -693,15 +669,24 @@ protected:
/**
* Add a listener for the specified attribute, if appropriate.
*/
nsresult AddListenerFor(nsINodeInfo *aNodeInfo,
PRBool aCompileEventHandlers);
void AddListenerFor(const nsAttrName& aName,
PRBool aCompileEventHandlers);
void MaybeAddPopupListener(nsIAtom* aLocalName);
nsresult HideWindowChrome(PRBool aShouldHide);
void FinishSetAttr(PRInt32 aAttrNS, nsIAtom* aAttrName,
const nsAString& aOldValue, const nsAString& aNewValue,
PRInt32 aModHint, PRBool aNotify);
nsresult SetAttrAndNotify(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
nsIAtom* aPrefix,
const nsAString& aOldValue,
nsAttrValue& aParsedValue,
PRBool aModification,
PRBool aFireMutation,
PRBool aNotify);
const nsAttrName* InternalGetExistingAttrNameFromQName(const nsAString& aStr) const;
protected:
// Internal accessors. These shadow the 'Slots', and return
@ -709,7 +694,6 @@ protected:
// delegate.
nsINodeInfo *NodeInfo() const { return mSlots ? mSlots->mNodeInfo : mPrototype->mNodeInfo; }
nsIControllers *Controllers() const { return mSlots ? mSlots->mControllers.get() : nsnull; }
nsXULAttributes *Attributes() const { return mSlots ? mSlots->GetAttributes() : nsnull; }
void UnregisterAccessKey(const nsAString& aOldValue);
};

View File

@ -104,6 +104,8 @@
#include "nsUnicharUtils.h"
#include "nsXULAtoms.h"
#include "nsHTMLAtoms.h"
#include "nsContentUtils.h"
#include "nsAttrName.h"
static const char kNameSpaceSeparator = ':';
@ -187,7 +189,7 @@ protected:
nsresult NormalizeAttributeString(const nsAFlatString& aText,
nsINodeInfo** aNodeInfo);
nsAttrName& aName);
nsresult CreateElement(nsINodeInfo *aNodeInfo, nsXULPrototypeElement** aResult);
// Style sheets
@ -689,7 +691,7 @@ XULContentSinkImpl::FlushText(PRBool aCreateTextNode)
nsresult
XULContentSinkImpl::NormalizeAttributeString(const nsAFlatString& aText,
nsINodeInfo** aNodeInfo)
nsAttrName& aName)
{
PRInt32 nameSpaceID = kNameSpaceID_None;
@ -702,8 +704,15 @@ XULContentSinkImpl::NormalizeAttributeString(const nsAFlatString& aText,
nsCOMPtr<nsIAtom> prefix;
if (!FindCharInReadable(kNameSpaceSeparator, colon, end)) {
colon = start; // No ':' found, reset colon
} else if (start != colon) {
nsCOMPtr<nsIAtom> atom = do_GetAtom(aText);
NS_ENSURE_TRUE(atom, NS_ERROR_OUT_OF_MEMORY);
aName.SetTo(atom);
return NS_OK;
}
if (start != colon) {
prefix = do_GetAtom(Substring(start, colon));
nsCOMPtr<nsINameSpace> ns;
@ -724,8 +733,15 @@ XULContentSinkImpl::NormalizeAttributeString(const nsAFlatString& aText,
++colon; // Skip over the ':'
}
return mNodeInfoManager->GetNodeInfo(Substring(colon, end), prefix,
nameSpaceID, aNodeInfo);
nsCOMPtr<nsINodeInfo> ni;
nsresult rv = mNodeInfoManager->GetNodeInfo(Substring(colon, end), prefix,
nameSpaceID,
getter_AddRefs(ni));
NS_ENSURE_SUCCESS(rv, rv);
aName.SetTo(ni);
return NS_OK;
}
nsresult
@ -1491,25 +1507,15 @@ XULContentSinkImpl::AddAttributes(const PRUnichar** aAttributes,
aElement->mNumAttributes = aAttrLen;
// Copy the attributes into the prototype
for (; *aAttributes; aAttributes += 2) {
rv = NormalizeAttributeString(nsDependentString(aAttributes[0]),
getter_AddRefs(attrs->mNodeInfo));
PRUint32 i;
for (i = 0; i < aAttrLen; ++i) {
rv = NormalizeAttributeString(nsDependentString(aAttributes[i * 2]),
attrs[i].mName);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(rv)) {
#ifdef PR_LOGGING
nsAutoString qnameC;
qnameC.Assign(aAttributes[0]);
PR_LOG(gLog, PR_LOG_ALWAYS,
("xul: unable to parse attribute '%s' at line %d",
NS_ConvertUCS2toUTF8(qnameC).get(), -1)); // XXX pass in line number
#endif
// Bring it. We'll just fail to copy an attribute that we
// can't parse. And that's one less attribute to worry
// about.
--(aElement->mNumAttributes);
continue;
}
attrs->mValue.SetValue(nsDependentString(aAttributes[1]));
rv = aElement->SetAttrAt(i, nsDependentString(aAttributes[i * 2 + 1]),
mDocumentURL);
NS_ENSURE_SUCCESS(rv, rv);
#ifdef PR_LOGGING
if (PR_LOG_TEST(gLog, PR_LOG_DEBUG)) {
@ -1528,40 +1534,6 @@ XULContentSinkImpl::AddAttributes(const PRUnichar** aAttributes,
NS_ConvertUCS2toUTF8(valueC).get()));
}
#endif
++attrs;
}
// XUL elements may require some additional work to compute
// derived information.
if (aElement->mNodeInfo->NamespaceEquals(kNameSpaceID_XUL)) {
nsAutoString value;
// Compute the element's class list if the element has a 'class' attribute.
rv = aElement->GetAttr(kNameSpaceID_None, nsXULAtoms::clazz, value);
if (NS_FAILED(rv)) return rv;
if (rv == NS_CONTENT_ATTR_HAS_VALUE) {
rv = nsClassList::ParseClasses(&aElement->mClassList, value);
if (NS_FAILED(rv)) return rv;
}
// Parse the element's 'style' attribute
rv = aElement->GetAttr(kNameSpaceID_None, nsXULAtoms::style, value);
if (NS_FAILED(rv)) return rv;
if (rv == NS_CONTENT_ATTR_HAS_VALUE) {
if (!mCSSParser) {
mCSSParser = do_CreateInstance(kCSSParserCID, &rv);
if (NS_FAILED(rv)) return rv;
}
rv = mCSSParser->ParseStyleAttribute(value, mDocumentURL,
getter_AddRefs(aElement->mInlineStyleRule));
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to parse style rule");
if (NS_FAILED(rv)) return rv;
}
}
return NS_OK;

View File

@ -115,6 +115,9 @@
#include "nsIScriptGlobalObject.h"
#include "nsIScriptGlobalObjectOwner.h"
#include "nsIScriptSecurityManager.h"
#include "nsContentUtils.h"
#include "nsIParser.h"
#include "nsICSSStyleSheet.h"
//----------------------------------------------------------------------
//
@ -3428,11 +3431,11 @@ nsXULDocument::AddAttributes(nsXULPrototypeElement* aPrototype,
for (PRUint32 i = 0; i < aPrototype->mNumAttributes; ++i) {
nsXULPrototypeAttribute* protoattr = &(aPrototype->mAttributes[i]);
nsAutoString valueStr;
protoattr->mValue.GetValue( valueStr );
protoattr->mValue.ToString(valueStr);
rv = aElement->SetAttr(protoattr->mNodeInfo->NamespaceID(),
protoattr->mNodeInfo->NameAtom(),
protoattr->mNodeInfo->GetPrefixAtom(),
rv = aElement->SetAttr(protoattr->mName.NamespaceID(),
protoattr->mName.LocalName(),
protoattr->mName.GetPrefix(),
valueStr,
PR_FALSE);
if (NS_FAILED(rv)) return rv;

View File

@ -55,6 +55,7 @@
#include "nsIXULDocument.h"
#include "nsIXULPrototypeDocument.h"
#include "nsScriptLoader.h"
#include "nsIStreamListener.h"
class nsIRDFResource;
class nsIRDFService;

View File

@ -69,6 +69,7 @@
#include "nsIDOMScriptObjectFactory.h"
#include "nsDOMCID.h"
#include "nsArray.h"
#include "nsContentUtils.h"
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
@ -438,6 +439,51 @@ nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream)
return rv;
}
static nsresult
GetNodeInfos(nsXULPrototypeElement* aPrototype,
nsCOMArray<nsINodeInfo>& aArray)
{
nsresult rv;
if (aArray.IndexOf(aPrototype->mNodeInfo) < 0) {
if (!aArray.AppendObject(aPrototype->mNodeInfo)) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
// Search attributes
PRUint32 i;
for (i = 0; i < aPrototype->mNumAttributes; ++i) {
nsCOMPtr<nsINodeInfo> ni;
nsAttrName* name = &aPrototype->mAttributes[i].mName;
if (name->IsAtom()) {
rv = aPrototype->mNodeInfo->NodeInfoManager()->
GetNodeInfo(name->Atom(), nsnull, kNameSpaceID_None,
getter_AddRefs(ni));
NS_ENSURE_SUCCESS(rv, rv);
}
else {
ni = name->NodeInfo();
}
if (aArray.IndexOf(ni) < 0) {
if (!aArray.AppendObject(ni)) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
}
// Search children
for (i = 0; i < aPrototype->mNumChildren; ++i) {
nsXULPrototypeNode* child = aPrototype->mChildren[i];
if (child->mType == nsXULPrototypeNode::eType_Element) {
rv = GetNodeInfos(NS_STATIC_CAST(nsXULPrototypeElement*, child),
aArray);
NS_ENSURE_SUCCESS(rv, rv);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsXULPrototypeDocument::Write(nsIObjectOutputStream* aStream)
@ -478,7 +524,7 @@ nsXULPrototypeDocument::Write(nsIObjectOutputStream* aStream)
// nsINodeInfo table
nsCOMArray<nsINodeInfo> nodeInfos;
rv |= mNodeInfoManager->GetNodeInfos(&nodeInfos);
rv |= GetNodeInfos(mRoot, nodeInfos);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 nodeInfoCount = nodeInfos.Count();

View File

@ -70,6 +70,7 @@
#include "nsXULElement.h"
#include "nsXULTemplateBuilder.h"
#include "nsSupportsArray.h"
#include "nsContentUtils.h"
#include "jsapi.h"
#include "pldhash.h"