зеркало из https://github.com/mozilla/pjs.git
478 строки
15 KiB
C++
478 строки
15 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* ***** 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.org 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 ***** */
|
|
#ifndef nsHTMLValue_h___
|
|
#define nsHTMLValue_h___
|
|
|
|
#include "nscore.h"
|
|
#include "nsColor.h"
|
|
#include "nsString.h"
|
|
#include "nsISupports.h"
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsReadableUtils.h"
|
|
#include "nsCRT.h"
|
|
|
|
class nsIDocument;
|
|
|
|
class nsCheapStringBufferUtils {
|
|
public:
|
|
/**
|
|
* Get the string pointer
|
|
* @param aBuf the buffer
|
|
* @return a pointer to the string
|
|
*/
|
|
static const PRUnichar* StrPtr(const PRUnichar* aBuf) {
|
|
NS_ASSERTION(aBuf, "Cannot work on null buffer!");
|
|
return (const PRUnichar*)( ((const char*)aBuf) + sizeof(PRUint32) );
|
|
}
|
|
static PRUnichar* StrPtr(PRUnichar* aBuf) {
|
|
NS_ASSERTION(aBuf, "Cannot work on null buffer!");
|
|
return (PRUnichar*)( ((char*)aBuf) + sizeof(PRUint32) );
|
|
}
|
|
/**
|
|
* Get the string length
|
|
* @param aBuf the buffer
|
|
* @return the string length
|
|
*/
|
|
static PRUint32 Length(const PRUnichar* aBuf) {
|
|
NS_ASSERTION(aBuf, "Cannot work on null buffer!");
|
|
return *((PRUint32*)aBuf);
|
|
}
|
|
/**
|
|
* Get a DependentString from a buffer
|
|
*
|
|
* @param aBuf the buffer to get string from
|
|
* @return a DependentString representing this string
|
|
*/
|
|
static nsDependentSingleFragmentSubstring GetDependentString(const PRUnichar* aBuf) {
|
|
NS_ASSERTION(aBuf, "Cannot work on null buffer!");
|
|
const PRUnichar* buf = StrPtr(aBuf);
|
|
return Substring(buf, buf + Length(aBuf));
|
|
}
|
|
/**
|
|
* Construct from an AString
|
|
* @param aBuf the buffer to copy to
|
|
* @param aStr the string to construct from
|
|
*/
|
|
static void CopyToBuffer(PRUnichar*& aBuf, const nsAString& aStr) {
|
|
PRUint32 len = aStr.Length();
|
|
aBuf = (PRUnichar*)nsMemory::Alloc(sizeof(PRUint32) +
|
|
len * sizeof(PRUnichar));
|
|
*((PRUint32*)aBuf) = len;
|
|
CopyUnicodeTo(aStr, 0, StrPtr(aBuf), len);
|
|
}
|
|
/**
|
|
* Construct from another nsCheapStringBuffer
|
|
* @param aBuf the buffer to put into
|
|
* @param aSrc the buffer to construct from
|
|
*/
|
|
static void Clone(PRUnichar*& aBuf, const PRUnichar* aSrc) {
|
|
NS_ASSERTION(aSrc, "Cannot work on null buffer!");
|
|
aBuf = (PRUnichar*)nsMemory::Clone(aSrc, sizeof(PRUint32) +
|
|
Length(aSrc) * sizeof(PRUnichar));
|
|
}
|
|
/**
|
|
* Free the memory for the buf
|
|
* @param aBuf the buffer to free
|
|
*/
|
|
static void Free(PRUnichar* aBuf) {
|
|
NS_ASSERTION(aBuf, "Cannot work on null buffer!");
|
|
nsMemory::Free(aBuf);
|
|
}
|
|
/**
|
|
* Get a hashcode for the buffer
|
|
* @param aBuf the buffer
|
|
* @return the hashcode
|
|
*/
|
|
static PRUint32 HashCode(const PRUnichar* aBuf) {
|
|
NS_ASSERTION(aBuf, "Cannot work on null buffer!");
|
|
return nsCRT::BufferHashCode((char*)StrPtr(aBuf),
|
|
Length(aBuf)*sizeof(PRUnichar));
|
|
}
|
|
};
|
|
|
|
//
|
|
// nsHTMLUnit is two bytes: the class of type, and a specifier to distinguish
|
|
// 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_CLASS_MASK 0xff00
|
|
|
|
enum nsHTMLUnit {
|
|
// null, value is not specified: 0x0000
|
|
eHTMLUnit_Null = HTMLUNIT_NOSTORE,
|
|
// empty, value is not specified: 0x0001
|
|
eHTMLUnit_Empty = HTMLUNIT_NOSTORE | 1,
|
|
|
|
// a string value
|
|
eHTMLUnit_String = HTMLUNIT_STRING,
|
|
// a color name value
|
|
eHTMLUnit_ColorName = HTMLUNIT_STRING | 1,
|
|
|
|
// a simple int value
|
|
eHTMLUnit_Integer = HTMLUNIT_INTEGER,
|
|
// value has enumerated meaning
|
|
eHTMLUnit_Enumerated = HTMLUNIT_INTEGER | 1,
|
|
// value is a relative proportion of some whole
|
|
eHTMLUnit_Proportional = HTMLUNIT_INTEGER | 2,
|
|
|
|
// screen pixels (screen relative measure)
|
|
eHTMLUnit_Pixel = HTMLUNIT_PIXEL,
|
|
|
|
// an RGBA value
|
|
eHTMLUnit_Color = HTMLUNIT_COLOR,
|
|
|
|
// (nsISupports*) a ref counted interface
|
|
eHTMLUnit_ISupports = HTMLUNIT_ISUPPORTS,
|
|
|
|
// (1.0 == 100%) value is percentage of something
|
|
eHTMLUnit_Percent = HTMLUNIT_PERCENT
|
|
};
|
|
|
|
/**
|
|
* Class which is used to represent the value of an attribute of an
|
|
* HTML element. The value has a unit which is an nsHTMLUnit;
|
|
* checking the unit is a must before asking for the value in any
|
|
* particular form.
|
|
*/
|
|
class nsHTMLValue {
|
|
public:
|
|
nsHTMLValue(nsHTMLUnit aUnit = eHTMLUnit_Null);
|
|
nsHTMLValue(PRInt32 aValue, nsHTMLUnit aUnit);
|
|
nsHTMLValue(float aValue);
|
|
nsHTMLValue(const nsAString& aValue, nsHTMLUnit aUnit = eHTMLUnit_String);
|
|
nsHTMLValue(nsISupports* aValue);
|
|
nsHTMLValue(nscolor aValue);
|
|
nsHTMLValue(const nsHTMLValue& aCopy);
|
|
~nsHTMLValue(void);
|
|
|
|
nsHTMLValue& operator=(const nsHTMLValue& aCopy);
|
|
PRBool operator==(const nsHTMLValue& aOther) const;
|
|
PRBool operator!=(const nsHTMLValue& aOther) const;
|
|
PRUint32 HashValue(void) const;
|
|
|
|
/**
|
|
* Get the unit of this HTMLValue
|
|
* @return the unit of this HTMLValue
|
|
*/
|
|
nsHTMLUnit GetUnit(void) const { return (nsHTMLUnit)mUnit; }
|
|
|
|
PRInt32 GetIntValue(void) const;
|
|
PRInt32 GetPixelValue(void) const;
|
|
float GetPercentValue(void) const;
|
|
nsAString& GetStringValue(nsAString& aBuffer) const;
|
|
already_AddRefed<nsISupports> GetISupportsValue(void) const;
|
|
nscolor GetColorValue(void) const;
|
|
|
|
/**
|
|
* Reset the string to null type, freeing things in the process if necessary.
|
|
*/
|
|
void Reset(void);
|
|
void SetIntValue(PRInt32 aValue, nsHTMLUnit aUnit);
|
|
void SetPixelValue(PRInt32 aValue);
|
|
void SetPercentValue(float aValue);
|
|
void SetStringValue(const nsAString& aValue, nsHTMLUnit aUnit = eHTMLUnit_String);
|
|
void SetISupportsValue(nsISupports* aValue);
|
|
void SetColorValue(nscolor aValue);
|
|
void SetEmptyValue(void);
|
|
|
|
/**
|
|
* Get this HTML value as a string (depends on the type)
|
|
* @param aResult the resulting string
|
|
* @return whether the value was successfully turned to a string
|
|
*/
|
|
PRBool ToString(nsAString& aResult) const;
|
|
|
|
#ifdef DEBUG
|
|
void AppendToString(nsAString& aBuffer) const;
|
|
#endif
|
|
|
|
/**
|
|
* Structure for a mapping from int (enum) values to strings. When you use
|
|
* it you generally create an array of them.
|
|
* Instantiate like this:
|
|
* EnumTable myTable[] = {
|
|
* { "string1", 1 },
|
|
* { "string2", 2 },
|
|
* { 0 }
|
|
* }
|
|
*/
|
|
struct EnumTable {
|
|
/** The string the value maps to */
|
|
const char* tag;
|
|
/** The enum value that maps to this string */
|
|
PRInt32 value;
|
|
};
|
|
|
|
/**
|
|
* Parse and output this HTMLValue in a variety of ways
|
|
*/
|
|
// Attribute parsing utilities
|
|
|
|
/**
|
|
* Map a string to its enum value and return result as HTMLValue
|
|
* (case-insensitive matching)
|
|
*
|
|
* @param aValue the string to find the value for
|
|
* @param aTable the enumeration to map with
|
|
* @param aResult the enum mapping [OUT]
|
|
* @return whether the enum value was found or not
|
|
*/
|
|
PRBool ParseEnumValue(const nsAString& aValue,
|
|
const EnumTable* aTable,
|
|
PRBool aCaseSensitive = PR_FALSE);
|
|
|
|
/**
|
|
* Map an enum HTMLValue to its string
|
|
*
|
|
* @param aValue the HTMLValue with the int in it
|
|
* @param aTable the enumeration to map with
|
|
* @param aResult the string the value maps to [OUT]
|
|
* @return whether the enum value was found or not
|
|
*/
|
|
PRBool EnumValueToString(const EnumTable* aTable,
|
|
nsAString& aResult) const;
|
|
|
|
/**
|
|
* Parse a string value into an int or pixel HTMLValue.
|
|
*
|
|
* @param aString the string to parse
|
|
* @param aDefaultUnit the unit to use (eHTMLUnit_Pixel or Integer)
|
|
* @return whether the value could be parsed
|
|
*/
|
|
PRBool ParseIntValue(const nsAString& aString, nsHTMLUnit aDefaultUnit) {
|
|
return ParseIntWithBounds(aString, aDefaultUnit, PR_INT32_MIN, PR_INT32_MAX);
|
|
}
|
|
|
|
/**
|
|
* Parse a string value into an int or pixel HTMLValue with minimum
|
|
* value and maximum value (can optionally parse percent (n%) and
|
|
* proportional (n%). This method explicitly sets a lower bound of zero on
|
|
* the element, whether it be proportional or percent or raw integer.
|
|
*
|
|
* @param aString the string to parse
|
|
* @param aDefaultUnit the unit to use (eHTMLUnit_Pixel or Integer)
|
|
* @param aCanBePercent true if it can be a percent value (%)
|
|
* @param aCanBeProportional true if it can be a proportional value (*)
|
|
* @return whether the value could be parsed
|
|
*/
|
|
PRBool ParseSpecialIntValue(const nsAString& aString, nsHTMLUnit aDefaultUnit,
|
|
PRBool aCanBePercent,
|
|
PRBool aCanBeProportional);
|
|
|
|
/**
|
|
* Parse a string value into an int or pixel HTMLValue with minimum
|
|
* value and maximum value
|
|
*
|
|
* @param aString the string to parse
|
|
* @param aMin the minimum value (if value is less it will be bumped up)
|
|
* @param aMax the maximum value (if value is greater it will be chopped down)
|
|
* @param aValueUnit the unit to use (eHTMLUnit_Pixel or Integer)
|
|
* @return whether the value could be parsed
|
|
*/
|
|
PRBool ParseIntWithBounds(const nsAString& aString, nsHTMLUnit aValueUnit,
|
|
PRInt32 aMin, PRInt32 aMax = PR_INT32_MAX);
|
|
|
|
/**
|
|
* Parse a string into a color HTMLValue (with hexes or color names)
|
|
*
|
|
* @param aString the string to parse
|
|
* @param aDocument the document (to find out whether we're in quirks mode)
|
|
* @param aResult the resulting HTMLValue [OUT]
|
|
* @return whether the value could be parsed
|
|
*/
|
|
PRBool ParseColor(const nsAString& aString, nsIDocument* aDocument);
|
|
|
|
|
|
protected:
|
|
/**
|
|
* The unit of the value
|
|
* @see nsHTMLUnit
|
|
*/
|
|
PRUint32 mUnit;
|
|
|
|
/**
|
|
* The actual value. Please to not be adding more-than-4-byte things to this
|
|
* union.
|
|
*/
|
|
union {
|
|
/** Int. */
|
|
PRInt32 mInt;
|
|
/** Float. */
|
|
float mFloat;
|
|
/** String. First 4 bytes are the length, non-null-terminated. */
|
|
PRUnichar* mString;
|
|
/** ISupports. Strong reference. */
|
|
nsISupports* mISupports;
|
|
/** Color. */
|
|
nscolor mColor;
|
|
} mValue;
|
|
|
|
private:
|
|
/**
|
|
* Copy into this HTMLValue from aCopy. Please be aware that if this is an
|
|
* existing HTMLValue and you do not call Reset(), this will leak.
|
|
* @param aCopy the value to copy
|
|
*/
|
|
void InitializeFrom(const nsHTMLValue& aCopy);
|
|
/**
|
|
* Helper to set string value (checks for embedded nulls or length); verifies
|
|
* that aUnit is a string type as well.
|
|
* @param aValue the value to set
|
|
* @param aUnit the unit to set
|
|
*/
|
|
void SetStringValueInternal(const nsAString& aValue, nsHTMLUnit aUnit);
|
|
/**
|
|
* Get a DependentString from mValue.mString (if the string is stored with
|
|
* length, passes that information to the DependentString). Do not call this
|
|
* if mValue.mString is null.
|
|
*
|
|
* @return a DependentString representing this string
|
|
*/
|
|
nsDependentSingleFragmentSubstring GetDependentString() const;
|
|
/**
|
|
* Get the unit class (HTMLUNIT_*)
|
|
* @return the unit class
|
|
*/
|
|
PRUint32 GetUnitClass() const { return mUnit & HTMLUNIT_CLASS_MASK; }
|
|
};
|
|
|
|
inline nsDependentSingleFragmentSubstring nsHTMLValue::GetDependentString() const
|
|
{
|
|
NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING,
|
|
"Some dork called GetDependentString() on a non-string!");
|
|
static const PRUnichar blankStr[] = { '\0' };
|
|
return mValue.mString
|
|
? nsCheapStringBufferUtils::GetDependentString(mValue.mString)
|
|
: Substring(blankStr, blankStr);
|
|
}
|
|
|
|
inline PRInt32 nsHTMLValue::GetIntValue(void) const
|
|
{
|
|
NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING ||
|
|
GetUnitClass() == HTMLUNIT_INTEGER,
|
|
"not an int value");
|
|
PRUint32 unitClass = GetUnitClass();
|
|
if (unitClass == HTMLUNIT_INTEGER) {
|
|
return mValue.mInt;
|
|
}
|
|
|
|
if (unitClass == HTMLUNIT_STRING) {
|
|
if (mValue.mString) {
|
|
PRInt32 err=0;
|
|
// XXX this copies. new string APIs will make this better, right?
|
|
nsAutoString str(GetDependentString());
|
|
return str.ToInteger(&err);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
inline PRInt32 nsHTMLValue::GetPixelValue(void) const
|
|
{
|
|
NS_ASSERTION((mUnit == eHTMLUnit_Pixel), "not a pixel value");
|
|
if (mUnit == eHTMLUnit_Pixel) {
|
|
return mValue.mInt;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
inline float nsHTMLValue::GetPercentValue(void) const
|
|
{
|
|
NS_ASSERTION(mUnit == eHTMLUnit_Percent, "not a percent value");
|
|
if (mUnit == eHTMLUnit_Percent) {
|
|
return mValue.mFloat;
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
inline nsAString& nsHTMLValue::GetStringValue(nsAString& aBuffer) const
|
|
{
|
|
NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING || mUnit == eHTMLUnit_Null,
|
|
"not a string value");
|
|
if (GetUnitClass() == HTMLUNIT_STRING && mValue.mString) {
|
|
aBuffer = GetDependentString();
|
|
} else {
|
|
aBuffer.Truncate();
|
|
}
|
|
return aBuffer;
|
|
}
|
|
|
|
inline already_AddRefed<nsISupports> nsHTMLValue::GetISupportsValue(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;
|
|
}
|
|
return nsnull;
|
|
}
|
|
|
|
inline nscolor nsHTMLValue::GetColorValue(void) const
|
|
{
|
|
NS_ASSERTION((mUnit == eHTMLUnit_Color) || (mUnit == eHTMLUnit_ColorName),
|
|
"not a color value");
|
|
if (mUnit == eHTMLUnit_Color) {
|
|
return mValue.mColor;
|
|
}
|
|
if (mUnit == eHTMLUnit_ColorName) {
|
|
nscolor color;
|
|
if (NS_ColorNameToRGB(GetDependentString(), &color)) {
|
|
return color;
|
|
}
|
|
}
|
|
return NS_RGB(0,0,0);
|
|
}
|
|
|
|
inline PRBool nsHTMLValue::operator!=(const nsHTMLValue& aOther) const
|
|
{
|
|
return PRBool(! ((*this) == aOther));
|
|
}
|
|
|
|
#endif /* nsHTMLValue_h___ */
|
|
|