From c4ca2d639c979cf07680445cbdbed5d9e48edfa5 Mon Sep 17 00:00:00 2001 From: Jim Mathies Date: Thu, 24 Jun 2010 21:01:07 -0500 Subject: [PATCH] Bug 513162 - Add 'top, right, bottom, left' margin support in nsAttrValue. r=smaug. --- content/base/public/nsContentUtils.h | 10 +++++ content/base/public/nsIContentUtils.h | 9 +++-- content/base/src/nsAttrValue.cpp | 55 +++++++++++++++++++++++++++ content/base/src/nsAttrValue.h | 26 +++++++++++++ content/base/src/nsContentUtils.cpp | 53 ++++++++++++++++++++++++++ 5 files changed, 150 insertions(+), 3 deletions(-) diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index b5faf23d7c89..7da4116c9828 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -401,6 +401,16 @@ public: */ static PRBool IsHTMLWhitespace(PRUnichar aChar); + /** + * Parse a margin string of format 'top, right, bottom, left' into + * an nsIntMargin. + * + * @param aString the string to parse + * @param aResult the resulting integer + * @return whether the value could be parsed + */ + static PRBool ParseIntMarginValue(const nsAString& aString, nsIntMargin& aResult); + static void Shutdown(); /** diff --git a/content/base/public/nsIContentUtils.h b/content/base/public/nsIContentUtils.h index d2c47f9b6d8a..196d6bbd6715 100644 --- a/content/base/public/nsIContentUtils.h +++ b/content/base/public/nsIContentUtils.h @@ -39,11 +39,13 @@ #include "nsIDocumentLoaderFactory.h" #include "nsCOMPtr.h" +#include "nsAString.h" +#include "nsMargin.h" -// C4EA618E-A3D9-4524-8EEA-E92F26FC44DB +// {3682DD99-8560-44f4-9B8F-CCCE9D7B96FB} #define NS_ICONTENTUTILS_IID \ -{ 0xC4EA618E, 0xA3D9, 0x4524, \ - { 0x8E, 0xEA, 0xE9, 0x2F, 0x26, 0xFC, 0x44, 0xDB } } +{ 0x3682dd99, 0x8560, 0x44f4, \ + { 0x9b, 0x8f, 0xcc, 0xce, 0x9d, 0x7b, 0x96, 0xfb } } class nsIContentUtils : public nsISupports { @@ -52,6 +54,7 @@ public: NS_DECL_ISUPPORTS virtual PRBool IsSafeToRunScript(); + virtual PRBool ParseIntMarginValue(const nsAString& aString, nsIntMargin& result); enum ContentViewerType { diff --git a/content/base/src/nsAttrValue.cpp b/content/base/src/nsAttrValue.cpp index c73209642898..5546dafa0d38 100644 --- a/content/base/src/nsAttrValue.cpp +++ b/content/base/src/nsAttrValue.cpp @@ -92,6 +92,12 @@ nsAttrValue::nsAttrValue(nsISVGValue* aValue) } #endif +nsAttrValue::nsAttrValue(const nsIntMargin& aValue) + : mBits(0) +{ + SetTo(aValue); +} + nsAttrValue::~nsAttrValue() { ResetIfSet(); @@ -259,6 +265,12 @@ nsAttrValue::SetTo(const nsAttrValue& aOther) cont->mFloatValue = otherCont->mFloatValue; break; } + case eIntMarginValue: + { + if (otherCont->mIntMargin) + cont->mIntMargin = new nsIntMargin(*otherCont->mIntMargin); + break; + } default: { NS_NOTREACHED("unknown type stored in MiscContainer"); @@ -320,6 +332,16 @@ nsAttrValue::SetTo(nsISVGValue* aValue) } #endif +void +nsAttrValue::SetTo(const nsIntMargin& aValue) +{ + if (EnsureEmptyMiscContainer()) { + MiscContainer* cont = GetMiscContainer(); + cont->mIntMargin = new nsIntMargin(aValue); + cont->mType = eIntMarginValue; + } +} + void nsAttrValue::SwapValueWith(nsAttrValue& aOther) { @@ -585,6 +607,10 @@ nsAttrValue::HashValue() const // XXX this is crappy, but oh well return cont->mFloatValue; } + case eIntMarginValue: + { + return NS_PTR_TO_INT32(cont->mIntMargin); + } default: { NS_NOTREACHED("unknown type stored in MiscContainer"); @@ -687,6 +713,10 @@ nsAttrValue::Equals(const nsAttrValue& aOther) const { return thisCont->mFloatValue == otherCont->mFloatValue; } + case eIntMarginValue: + { + return thisCont->mIntMargin == otherCont->mIntMargin; + } default: { NS_NOTREACHED("unknown type stored in MiscContainer"); @@ -1204,6 +1234,26 @@ PRBool nsAttrValue::ParseFloatValue(const nsAString& aString) return PR_FALSE; } +PRBool +nsAttrValue::ParseIntMarginValue(const nsAString& aString) +{ + ResetIfSet(); + + nsIntMargin margins; + if (!nsContentUtils::ParseIntMarginValue(aString, margins)) + return PR_FALSE; + + if (EnsureEmptyMiscContainer()) { + MiscContainer* cont = GetMiscContainer(); + cont->mIntMargin = new nsIntMargin(margins); + cont->mType = eIntMarginValue; + SetMiscAtomOrString(&aString); + return PR_TRUE; + } + + return PR_FALSE; +} + void nsAttrValue::SetMiscAtomOrString(const nsAString* aValue) { @@ -1269,6 +1319,11 @@ nsAttrValue::EnsureEmptyMiscContainer() break; } #endif + case eIntMarginValue: + { + delete cont->mIntMargin; + break; + } default: { break; diff --git a/content/base/src/nsAttrValue.h b/content/base/src/nsAttrValue.h index 1ee64aee1420..d08eacf89463 100644 --- a/content/base/src/nsAttrValue.h +++ b/content/base/src/nsAttrValue.h @@ -49,6 +49,7 @@ #include "nsStringBuffer.h" #include "nsColor.h" #include "nsCaseTreatment.h" +#include "nsMargin.h" typedef PRUptrdiff PtrBits; class nsAString; @@ -98,6 +99,7 @@ public: #ifdef MOZ_SVG explicit nsAttrValue(nsISVGValue* aValue); #endif + explicit nsAttrValue(const nsIntMargin& aValue); ~nsAttrValue(); static nsresult Init(); @@ -120,6 +122,7 @@ public: ,eSVGValue = 0x12 #endif ,eFloatValue = 0x13 + ,eIntMarginValue = 0x14 }; ValueType Type() const; @@ -133,6 +136,7 @@ public: #ifdef MOZ_SVG void SetTo(nsISVGValue* aValue); #endif + void SetTo(const nsIntMargin& aValue); void SwapValueWith(nsAttrValue& aOther); @@ -153,6 +157,7 @@ public: inline nsISVGValue* GetSVGValue() const; #endif inline float GetFloatValue() const; + PRBool GetIntMarginValue(nsIntMargin& aMargin) const; /** * Returns the string corresponding to the stored enum value. @@ -297,6 +302,15 @@ public: */ PRBool ParseLazyURIValue(const nsAString& aString); + /** + * Parse a margin string of format 'top, right, bottom, left' into + * an nsIntMargin. + * + * @param aString the string to parse + * @return whether the value could be parsed + */ + PRBool ParseIntMarginValue(const nsAString& aString); + private: // These have to be the same as in ValueType enum ValueBaseType { @@ -325,6 +339,7 @@ private: nsISVGValue* mSVGValue; #endif float mFloatValue; + nsIntMargin* mIntMargin; }; }; @@ -442,6 +457,17 @@ nsAttrValue::GetFloatValue() const return GetMiscContainer()->mFloatValue; } +inline PRBool +nsAttrValue::GetIntMarginValue(nsIntMargin& aMargin) const +{ + NS_PRECONDITION(Type() == eIntMarginValue, "wrong type"); + nsIntMargin* m = GetMiscContainer()->mIntMargin; + if (!m) + return PR_FALSE; + aMargin = *m; + return PR_TRUE; +} + inline nsAttrValue::ValueBaseType nsAttrValue::BaseType() const { diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index bb315efad4c4..0ab80be58ccb 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -924,6 +924,53 @@ nsContentUtils::IsHTMLWhitespace(PRUnichar aChar) aChar == PRUnichar(0x0020); } +/* static */ +PRBool +nsContentUtils::ParseIntMarginValue(const nsAString& aString, nsIntMargin& result) +{ + nsAutoString marginStr(aString); + marginStr.CompressWhitespace(PR_TRUE, PR_TRUE); + if (marginStr.IsEmpty()) { + return PR_FALSE; + } + + PRInt32 start = 0, end = 0; + for (int count = 0; count < 4; count++) { + if (end >= marginStr.Length()) + return PR_FALSE; + + // top, right, bottom, left + if (count < 3) + end = Substring(marginStr, start).FindChar(','); + else + end = Substring(marginStr, start).Length(); + + if (end <= 0) + return PR_FALSE; + + PRInt32 ec, val = + nsString(Substring(marginStr, start, end)).ToInteger(&ec); + if (NS_FAILED(ec)) + return PR_FALSE; + + switch(count) { + case 0: + result.top = val; + break; + case 1: + result.right = val; + break; + case 2: + result.bottom = val; + break; + case 3: + result.left = val; + break; + } + start += end + 1; + } + return PR_TRUE; +} /* static */ void @@ -6115,6 +6162,12 @@ nsIContentUtils::IsSafeToRunScript() return nsContentUtils::IsSafeToRunScript(); } +PRBool +nsIContentUtils::ParseIntMarginValue(const nsAString& aString, nsIntMargin& result) +{ + return nsContentUtils::ParseIntMarginValue(aString, result); +} + already_AddRefed nsIContentUtils::FindInternalContentViewer(const char* aType, ContentViewerType* aLoaderType)