#pragma once #include "LiteHTMLCommon.h" #include "LiteHTMLEntityResolver.h" #pragma warning(push, 4) #pragma warning (disable : 4290) // C++ Exception Specification ignored class CLiteHTMLAttributes; // forward declaration class CLiteHTMLElemAttr { // Friends friend class CLiteHTMLAttributes; // Constructors public: CLiteHTMLElemAttr(LPCWSTR lpszAttribName = NULL, LPCWSTR lpszAttribValue = NULL) { Init(); m_strAttrName = lpszAttribName; m_strAttrValue = lpszAttribValue; } CLiteHTMLElemAttr(const CLiteHTMLElemAttr &rSource) { Init(); m_strAttrName = rSource.m_strAttrName; m_strAttrValue = rSource.m_strAttrValue; } // Initialization Helpers private: static void Init(void) { if(_namedColors.size()) return; /** 28 system colors */ _namedColors[L"activeborder"] = (COLORREF)0x8000000A; _namedColors[L"activecaption"] = (COLORREF)0x80000002; _namedColors[L"appworkspace"] = (COLORREF)0x8000000C; _namedColors[L"background"] = (COLORREF)0x80000001; _namedColors[L"buttonface"] = (COLORREF)0x8000000F; _namedColors[L"buttonhighlight"] = (COLORREF)0x80000014; _namedColors[L"buttonshadow"] = (COLORREF)0x80000010; _namedColors[L"buttontext"] = (COLORREF)0x80000012; _namedColors[L"captiontext"] = (COLORREF)0x80000009; _namedColors[L"graytext"] = (COLORREF)0x80000011; _namedColors[L"highlight"] = (COLORREF)0x8000000D; _namedColors[L"highlighttext"] = (COLORREF)0x8000000E; _namedColors[L"inactiveborder"] = (COLORREF)0x8000000B; _namedColors[L"inactivecaption"] = (COLORREF)0x80000003; _namedColors[L"inactivecaptiontext"] = (COLORREF)0x80000013; _namedColors[L"infobackground"] = (COLORREF)0x80000018; _namedColors[L"infotext"] = (COLORREF)0x80000017; _namedColors[L"menu"] = (COLORREF)0x80000004; _namedColors[L"menutext"] = (COLORREF)0x80000007; _namedColors[L"scrollbar"] = (COLORREF)0x80000000; _namedColors[L"threeddarkshadow"] = (COLORREF)0x80000015; _namedColors[L"threedface"] = (COLORREF)0x8000000F; _namedColors[L"threedhighlight"] = (COLORREF)0x80000014; _namedColors[L"threedlightshadow"] = (COLORREF)0x80000016; _namedColors[L"threedshadow"] = (COLORREF)0x80000010; _namedColors[L"window"] = (COLORREF)0x80000005; _namedColors[L"windowframe"] = (COLORREF)0x80000006; _namedColors[L"windowtext"] = (COLORREF)0x80000008; /** 16 basic colors */ _namedColors[L"black"] = LITEHTML_ARGB(0xFF, 0x00, 0x00, 0x00); _namedColors[L"gray"] = LITEHTML_ARGB(0xFF, 0x80, 0x80, 0x80); _namedColors[L"silver"] = LITEHTML_ARGB(0xFF, 0xC0, 0xC0, 0xC0); _namedColors[L"white"] = LITEHTML_ARGB(0xFF, 0xFF, 0xFF, 0xFF); _namedColors[L"yellow"] = LITEHTML_ARGB(0xFF, 0xFF, 0xFF, 0x00); _namedColors[L"olive"] = LITEHTML_ARGB(0xFF, 0x80, 0x80, 0x00); _namedColors[L"red"] = LITEHTML_ARGB(0xFF, 0xFF, 0x00, 0x00); _namedColors[L"maroon"] = LITEHTML_ARGB(0xFF, 0x80, 0x00, 0x00); _namedColors[L"fuchsia"] = LITEHTML_ARGB(0xFF, 0xFF, 0x00, 0xFF); _namedColors[L"purple"] = LITEHTML_ARGB(0xFF, 0x80, 0x00, 0x80); _namedColors[L"blue"] = LITEHTML_ARGB(0xFF, 0x00, 0x00, 0xFF); _namedColors[L"navy"] = LITEHTML_ARGB(0xFF, 0x00, 0x00, 0x80); _namedColors[L"aqua"] = LITEHTML_ARGB(0xFF, 0x00, 0xFF, 0xFF); _namedColors[L"teal"] = LITEHTML_ARGB(0xFF, 0x00, 0x80, 0x80); _namedColors[L"lime"] = LITEHTML_ARGB(0xFF, 0x00, 0x80, 0xFF); _namedColors[L"green"] = LITEHTML_ARGB(0xFF, 0x00, 0xFF, 0x00); /** additional named colors */ _namedColors[L"darkolivegreen"] = LITEHTML_ARGB(0xFF, 0x55, 0x6B, 0x2F); _namedColors[L"olivedrab"] = LITEHTML_ARGB(0xFF, 0x6B, 0x8E, 0x23); _namedColors[L"yellowgreen"] = LITEHTML_ARGB(0xFF, 0x9A, 0xCD, 0x32); _namedColors[L"lawngreen"] = LITEHTML_ARGB(0xFF, 0x7C, 0xFC, 0x00); _namedColors[L"chartreuse"] = LITEHTML_ARGB(0xFF, 0x7F, 0xFF, 0x00); _namedColors[L"greenyellow"] = LITEHTML_ARGB(0xFF, 0xAD, 0xFF, 0x2F); _namedColors[L"palegreen"] = LITEHTML_ARGB(0xFF, 0x98, 0xFB, 0x98); _namedColors[L"lightgreen"] = LITEHTML_ARGB(0xFF, 0x90, 0xEE, 0x90); _namedColors[L"darkgreen"] = LITEHTML_ARGB(0xFF, 0x00, 0x64, 0x00); _namedColors[L"forestgreen"] = LITEHTML_ARGB(0xFF, 0x22, 0x8B, 0x22); _namedColors[L"seagreen"] = LITEHTML_ARGB(0xFF, 0x2E, 0x8B, 0x57); _namedColors[L"mediumseagreen"] = LITEHTML_ARGB(0xFF, 0x3C, 0xB3, 0x71); _namedColors[L"limegreen"] = LITEHTML_ARGB(0xFF, 0x32, 0xCD, 0x32); _namedColors[L"darkseagreen"] = LITEHTML_ARGB(0xFF, 0x8F, 0xBC, 0x8B); _namedColors[L"springgreen"] = LITEHTML_ARGB(0xFF, 0x00, 0xFF, 0x7F); _namedColors[L"mediumspringgreen"] = LITEHTML_ARGB(0xFF, 0x00, 0xFA, 0x99); _namedColors[L"darkslategray"] = LITEHTML_ARGB(0xFF, 0x2F, 0x4F, 0x4F); _namedColors[L"darkcyan"] = LITEHTML_ARGB(0xFF, 0x00, 0x8B, 0x8B); _namedColors[L"cadetblue"] = LITEHTML_ARGB(0xFF, 0x5F, 0x9E, 0xA0); _namedColors[L"lightseagreen"] = LITEHTML_ARGB(0xFF, 0x20, 0xB2, 0xAA); _namedColors[L"mediumaquamarine"] = LITEHTML_ARGB(0xFF, 0x66, 0xCD, 0xAA); _namedColors[L"turquoise"] = LITEHTML_ARGB(0xFF, 0x40, 0xE0, 0xD0); _namedColors[L"aquamarine"] = LITEHTML_ARGB(0xFF, 0x7F, 0xFF, 0xD4); _namedColors[L"paleturquoise"] = LITEHTML_ARGB(0xFF, 0xAF, 0xEE, 0xEE); _namedColors[L"slategray"] = LITEHTML_ARGB(0xFF, 0x70, 0x80, 0x90); _namedColors[L"lightslategray"] = LITEHTML_ARGB(0xFF, 0x77, 0x88, 0x99); _namedColors[L"steelblue"] = LITEHTML_ARGB(0xFF, 0x46, 0x82, 0xB4); _namedColors[L"deepskyblue"] = LITEHTML_ARGB(0xFF, 0x00, 0xBF, 0xFF); _namedColors[L"darkturquoise"] = LITEHTML_ARGB(0xFF, 0x00, 0xCE, 0xD1); _namedColors[L"mediumturquoise"] = LITEHTML_ARGB(0xFF, 0x48, 0xD1, 0xCC); _namedColors[L"powderblue"] = LITEHTML_ARGB(0xFF, 0xB0, 0xE0, 0xE6); _namedColors[L"lightcyan"] = LITEHTML_ARGB(0xFF, 0xE0, 0xFF, 0xFF); _namedColors[L"darkblue"] = LITEHTML_ARGB(0xFF, 0x00, 0x00, 0x8B); _namedColors[L"mediumblue"] = LITEHTML_ARGB(0xFF, 0x00, 0x00, 0xCD); _namedColors[L"royalblue"] = LITEHTML_ARGB(0xFF, 0x41, 0x69, 0xe1); _namedColors[L"dodgerblue"] = LITEHTML_ARGB(0xFF, 0x1E, 0x90, 0xFF); _namedColors[L"cornflowerblue"] = LITEHTML_ARGB(0xFF, 0x64, 0x95, 0xED); _namedColors[L"skyblue"] = LITEHTML_ARGB(0xFF, 0x87, 0xCE, 0xEB); _namedColors[L"lightskyblue"] = LITEHTML_ARGB(0xFF, 0x87, 0xCE, 0xFA); _namedColors[L"lightblue"] = LITEHTML_ARGB(0xFF, 0xAD, 0xD8, 0xE6); _namedColors[L"midnightblue"] = LITEHTML_ARGB(0xFF, 0x19, 0x19, 0x70); _namedColors[L"darkslateblue"] = LITEHTML_ARGB(0xFF, 0x48, 0x3D, 0x8B); _namedColors[L"blueviolet"] = LITEHTML_ARGB(0xFF, 0x8A, 0x2B, 0xE2); _namedColors[L"slateblue"] = LITEHTML_ARGB(0xFF, 0x6A, 0x5A, 0xCD); _namedColors[L"mediumslateblue"] = LITEHTML_ARGB(0xFF, 0x7B, 0x68, 0xEE); _namedColors[L"mediumpurple"] = LITEHTML_ARGB(0xFF, 0x93, 0x70, 0xDB); _namedColors[L"lightsteelblue"] = LITEHTML_ARGB(0xFF, 0xB0, 0xC4, 0xDE); _namedColors[L"lavender"] = LITEHTML_ARGB(0xFF, 0xE6, 0xE6, 0xFA); _namedColors[L"indigo"] = LITEHTML_ARGB(0xFF, 0x4B, 0x00, 0x82); _namedColors[L"darkviolet"] = LITEHTML_ARGB(0xFF, 0x94, 0x00, 0xD3); _namedColors[L"darkorchid"] = LITEHTML_ARGB(0xFF, 0x99, 0x32, 0xCC); _namedColors[L"mediumorchid"] = LITEHTML_ARGB(0xFF, 0xBA, 0x55, 0xD3); _namedColors[L"orchid"] = LITEHTML_ARGB(0xFF, 0xDA, 0x70, 0xD6); _namedColors[L"violet"] = LITEHTML_ARGB(0xFF, 0xEE, 0x82, 0xEE); _namedColors[L"plum"] = LITEHTML_ARGB(0xFF, 0xDD, 0xA0, 0xDD); _namedColors[L"thistle"] = LITEHTML_ARGB(0xFF, 0xD8, 0xDF, 0xD8); _namedColors[L"darkmagenta"] = LITEHTML_ARGB(0xFF, 0x8B, 0x00, 0x8B); _namedColors[L"mediumvioletred"] = LITEHTML_ARGB(0xFF, 0xC7, 0x15, 0x85); _namedColors[L"deeppink"] = LITEHTML_ARGB(0xFF, 0xFF, 0x14, 0x93); _namedColors[L"palmvioletred"] = LITEHTML_ARGB(0xFF, 0xDB, 0x70, 0x93); _namedColors[L"hotpink"] = LITEHTML_ARGB(0xFF, 0xFF, 0x69, 0xB4); _namedColors[L"lightpink"] = LITEHTML_ARGB(0xFF, 0xFF, 0xB6, 0xC1); _namedColors[L"pink"] = LITEHTML_ARGB(0xFF, 0xFF, 0xC0, 0xCB); _namedColors[L"mistyrose"] = LITEHTML_ARGB(0xFF, 0xFF, 0xE4, 0xE1); _namedColors[L"brown"] = LITEHTML_ARGB(0xFF, 0xA5, 0x2A, 0x2A); _namedColors[L"indianred"] = LITEHTML_ARGB(0xFF, 0xCD, 0x5C, 0x5C); _namedColors[L"rosybrown"] = LITEHTML_ARGB(0xFF, 0xBC, 0x8F, 0x8F); _namedColors[L"salmon"] = LITEHTML_ARGB(0xFF, 0xFA, 0x80, 0x72); _namedColors[L"lightcoral"] = LITEHTML_ARGB(0xFF, 0xF0, 0x80, 0x80); _namedColors[L"darksalmon"] = LITEHTML_ARGB(0xFF, 0xE9, 0x96, 0x7A); _namedColors[L"lightsalmon"] = LITEHTML_ARGB(0xFF, 0xFF, 0xA0, 0x7A); _namedColors[L"peachpuff"] = LITEHTML_ARGB(0xFF, 0xFF, 0xDA, 0xB9); _namedColors[L"darkred"] = LITEHTML_ARGB(0xFF, 0x8B, 0x00, 0x00); _namedColors[L"firebrick"] = LITEHTML_ARGB(0xFF, 0xB2, 0x22, 0x22); _namedColors[L"crimson"] = LITEHTML_ARGB(0xFF, 0xDC, 0x14, 0x3C); _namedColors[L"orangered"] = LITEHTML_ARGB(0xFF, 0xFF, 0x45, 0x00); _namedColors[L"tomato"] = LITEHTML_ARGB(0xFF, 0xFF, 0x63, 0x47); _namedColors[L"coral"] = LITEHTML_ARGB(0xFF, 0xFF, 0x7F, 0x50); _namedColors[L"wheat"] = LITEHTML_ARGB(0xFF, 0xF5, 0xDE, 0xB3); _namedColors[L"papayawhip"] = LITEHTML_ARGB(0xFF, 0xFF, 0xEF, 0xD5); _namedColors[L"sienna"] = LITEHTML_ARGB(0xFF, 0xA0, 0x52, 0x2D); _namedColors[L"chocolate"] = LITEHTML_ARGB(0xFF, 0xD2, 0x69, 0x1E); _namedColors[L"darkorange"] = LITEHTML_ARGB(0xFF, 0xFF, 0x8C, 0x00); _namedColors[L"sandybrown"] = LITEHTML_ARGB(0xFF, 0xF4, 0xA4, 0x60); _namedColors[L"orange"] = LITEHTML_ARGB(0xFF, 0xFF, 0xA5, 0x00); _namedColors[L"navajowhite"] = LITEHTML_ARGB(0xFF, 0xFF, 0xDE, 0xAD); _namedColors[L"moccasin"] = LITEHTML_ARGB(0xFF, 0xFF, 0xE4, 0xB5); _namedColors[L"saddlebrown"] = LITEHTML_ARGB(0xFF, 0x8B, 0x45, 0x13); _namedColors[L"peru"] = LITEHTML_ARGB(0xFF, 0xCD, 0x85, 0x3F); _namedColors[L"burlywood"] = LITEHTML_ARGB(0xFF, 0xDE, 0xB8, 0x87); _namedColors[L"tan"] = LITEHTML_ARGB(0xFF, 0xD2, 0xB4, 0x8C); _namedColors[L"bisque"] = LITEHTML_ARGB(0xFF, 0xFF, 0xE4, 0xC4); _namedColors[L"blanchedalmond"] = LITEHTML_ARGB(0xFF, 0xFF, 0xEB, 0xCD); _namedColors[L"antiquewhite"] = LITEHTML_ARGB(0xFF, 0xFA, 0xEB, 0xD7); _namedColors[L"darkgoldenrod"] = LITEHTML_ARGB(0xFF, 0xB8, 0x86, 0x0B); _namedColors[L"goldenrod"] = LITEHTML_ARGB(0xFF, 0xDA, 0xA5, 0x20); _namedColors[L"darkkhaki"] = LITEHTML_ARGB(0xFF, 0xBD, 0xB7, 0x6B); _namedColors[L"gold"] = LITEHTML_ARGB(0xFF, 0xFF, 0xD7, 0x00); _namedColors[L"khaki"] = LITEHTML_ARGB(0xFF, 0xF0, 0xE6, 0x8C); _namedColors[L"palegoldenrod"] = LITEHTML_ARGB(0xFF, 0xEE, 0xE8, 0xAA); _namedColors[L"lemonchiffon"] = LITEHTML_ARGB(0xFF, 0xFF, 0xFA, 0xCD); _namedColors[L"beige"] = LITEHTML_ARGB(0xFF, 0xF5, 0xF5, 0xDC); _namedColors[L"lightgoldenrodyellow"] = LITEHTML_ARGB(0xFF, 0xFA, 0xFA, 0xD2); _namedColors[L"lightyellow"] = LITEHTML_ARGB(0xFF, 0xFF, 0xFF, 0xE0); _namedColors[L"ivory"] = LITEHTML_ARGB(0xFF, 0xFF, 0xFF, 0x00); _namedColors[L"cornsilk"] = LITEHTML_ARGB(0xFF, 0xFF, 0xF8, 0xDC); _namedColors[L"oldlace"] = LITEHTML_ARGB(0xFF, 0xFD, 0xF5, 0xE6); _namedColors[L"florawhite"] = LITEHTML_ARGB(0xFF, 0xFF, 0xFA, 0xF0); _namedColors[L"honeydew"] = LITEHTML_ARGB(0xFF, 0xF0, 0xFF, 0xF0); _namedColors[L"mintcream"] = LITEHTML_ARGB(0xFF, 0xF5, 0xFF, 0xFA); _namedColors[L"azure"] = LITEHTML_ARGB(0xFF, 0xF0, 0xFF, 0xFF); _namedColors[L"ghostwhite"] = LITEHTML_ARGB(0xFF, 0xF8, 0xF8, 0xFF); _namedColors[L"linen"] = LITEHTML_ARGB(0xFF, 0xFA, 0xF0, 0xE6); _namedColors[L"seashell"] = LITEHTML_ARGB(0xFF, 0xFF, 0xF5, 0xEE); _namedColors[L"snow"] = LITEHTML_ARGB(0xFF, 0xFF, 0xFA, 0xFA); _namedColors[L"dimgray"] = LITEHTML_ARGB(0xFF, 0x69, 0x69, 0x69); _namedColors[L"darkgray"] = LITEHTML_ARGB(0xFF, 0xA9, 0xA9, 0xA9); _namedColors[L"lightgray"] = LITEHTML_ARGB(0xFF, 0xD3, 0xD3, 0xD3); _namedColors[L"gainsboro"] = LITEHTML_ARGB(0xFF, 0xDC, 0xDC, 0xDC); _namedColors[L"whitesmoke"] = LITEHTML_ARGB(0xFF, 0xF5, 0xF5, 0xF5); _namedColors[L"ghostwhite"] = LITEHTML_ARGB(0xFF, 0xF8, 0xF8, 0xFF); _namedColors[L"aliceblue"] = LITEHTML_ARGB(0xFF, 0xF0, 0xF8, 0xFF); } // Attributes public: CStringW getName(void) const { return (m_strAttrName); } CStringW getValue(void) const { return (m_strAttrValue); } bool isNamedColorValue(void) const { if ( (m_strAttrValue.GetLength()) && (::iswalnum(m_strAttrValue[0])) ) { COLORREF crTemp = _clrInvalid; CStringW strKey(m_strAttrValue); strKey.MakeLower(); NAMEDCOLOR_MAP_ITER iter = _namedColors.find(m_strAttrValue); if( iter != _namedColors.end() ) { crTemp = iter->second; return true; } } return (false); } bool isSysColorValue(void) const { if ( (m_strAttrValue.GetLength()) && (::iswalnum(m_strAttrValue[0])) ) { COLORREF crTemp = _clrInvalid; CStringW strKey(m_strAttrValue); strKey.MakeLower(); NAMEDCOLOR_MAP_ITER iter = _namedColors.find(strKey); if( iter != _namedColors.end() ) { crTemp = iter->second; return (crTemp >= 0x80000000 && crTemp <= 0x80000018); } } return (false); } bool isHexColorValue(void) const { // zero-length attribute value? if (m_strAttrValue.IsEmpty()) return (false); if (m_strAttrValue[0] == L'#') { if (m_strAttrValue.GetLength() > 1) { for (int i = 1; i < m_strAttrValue.GetLength(); i++) { if (!::iswxdigit(m_strAttrValue[i])) return (false); } return (true); } } return (false); } bool isColorValue(void) const { return (isNamedColorValue() || isHexColorValue()); } COLORREF getColorValue(void) const { COLORREF crTemp = _clrInvalid; if (isNamedColorValue()) { CStringW strKey(m_strAttrValue); strKey.MakeLower(); NAMEDCOLOR_MAP_ITER iter = _namedColors.find(strKey); if( iter != _namedColors.end() ) { crTemp = iter->second; // is this a system named color value? if (crTemp >= 0x80000000 && crTemp <= 0x80000018) crTemp = ::GetSysColor(crTemp & 0x7FFFFFFF); } } else if (isHexColorValue()) { crTemp = ::wcstoul(m_strAttrValue.Mid(1), NULL, 16); } return (crTemp); } CStringW getColorHexValue(void) const { CStringW strColorHex; if (isHexColorValue()) strColorHex = m_strAttrValue.Mid(1); else { COLORREF crTemp = getColorValue(); if (crTemp != _clrInvalid) strColorHex.Format(L"#%06x", crTemp); } return (strColorHex); } bool isPercentValue(void) const { return (m_strAttrValue.Right(1) == L"%" ? true : false); } unsigned short getPercentValue(unsigned short max = _percentMax) const { ASSERT(max > 0); if (!isPercentValue()) return (0); unsigned short percentVal = (unsigned short)((short)*this); return ((percentVal > max ? max : percentVal)); } enum LengthUnitsEnum { em, ex, px, per, in, cm, mm, pt, pc }; short getLengthValue(LengthUnitsEnum &rUnit) const { static const wchar_t _szUnits[][4] = { /** relative length units */ L"em", L"ex", L"px", L"%", /** absolute length units */ L"in", L"cm", L"mm", L"pt", L"pc" }; if (m_strAttrValue.IsEmpty()) return (0); int i; for (i = 0; i < sizeof(_szUnits)/sizeof(_szUnits[0]); i++) { if (m_strAttrValue.Right(::lstrlenW(_szUnits[i])). \ CompareNoCase(_szUnits[i]) == 0) { rUnit = (LengthUnitsEnum)i; break; } } if (i == sizeof(_szUnits)/sizeof(_szUnits[0])) return (0); return (*this); } // Operators public: operator bool() const { if (!m_strAttrValue.CompareNoCase(L"true")) return (true); if (!m_strAttrValue.CompareNoCase(L"false")) return (false); return (((short)*this ? true : false)); } operator BYTE() const { return ((BYTE)(m_strAttrValue.GetLength() ? m_strAttrValue[0] : 0)); } operator double() const { return (::wcstod(m_strAttrValue, NULL)); } operator short() const { return ((short)::_wtoi(m_strAttrValue)); } operator LPCWSTR() const { return (m_strAttrValue); } // Private Operations private: void putValue(LPCWSTR lpszValue) { ASSERT(lpszValue); //ASSERT(AfxIsValidString(lpszValue)); m_strAttrValue = lpszValue; // ignore leading white-spaces m_strAttrValue.TrimLeft(); // ignore trailing white-spaces m_strAttrValue.TrimRight(); // ignore line feeds m_strAttrValue.Remove(L'\n'); // replace tab and carriage-return with a single space m_strAttrValue.Replace(L'\r', L' '); m_strAttrValue.Replace(L'\t', L' '); /** resolve entity reference(s) */ int iCurPos = -1, iParseLen = 0; wchar_t chSubst = 0; do { if ((iCurPos = m_strAttrValue.Find(L'&', ++iCurPos)) == -1) break; iParseLen = CLiteHTMLEntityResolver::resolveEntity(m_strAttrValue.Mid(iCurPos), chSubst); if (iParseLen) { m_strAttrValue.Replace ( m_strAttrValue.Mid(iCurPos, iParseLen), CStringW(chSubst) ); } } while (true); } // Parsing Helpers public: // parses an attribute/value pair from the given string UINT parseFromStr(LPCWSTR lpszString); // Data Members public: static const COLORREF _clrInvalid; // an invalid color static const unsigned short _percentMax; // maximum allowable percentage value private: static NAMEDCOLOR_MAP _namedColors; // collection of named colors CStringW m_strAttrName, // attribute name m_strAttrValue; // attribute value }; inline UINT CLiteHTMLElemAttr::parseFromStr(LPCWSTR lpszString) { ASSERT(lpszString); //ASSERT(AfxIsValidString(lpszString)); LPCWSTR lpszBegin = lpszString; LPCWSTR lpszEnd; wchar_t ch = 0; // skip leading white-space characters while (::iswspace(*lpszBegin)) //lpszBegin = ::_tcsinc(lpszBegin); lpszBegin++; // name doesn't begin with an alphabet? if (!::iswalnum(*lpszBegin)) return (0U); lpszEnd = lpszBegin; do { // attribute name may contain letters (a-z, A-Z), digits (0-9), // underscores '_', hyphen '-', colons ':', and periods '.' if ( (!::iswalnum(*lpszEnd)) && (*lpszEnd != L'-') && (*lpszEnd != L':') && (*lpszEnd != L'_') && (*lpszEnd != L'.') ) { ASSERT(lpszEnd != lpszBegin); // only white-space characters, a null-character, an // equal-sign, a greater-than symbol, or a forward-slash // can act as the separator between an attribute and its // value if (*lpszEnd == NULL || ::iswspace(*lpszEnd) || *lpszEnd == L'=' || *lpszEnd == L'>' || *lpszEnd == L'/') { break; } return (0U); // any other character will fail parsing process } //lpszEnd = ::_tcsinc(lpszEnd); lpszEnd++; } while (true); // extract attribute name CStringW strAttrName(lpszBegin, UINT(lpszEnd - lpszBegin)); // Note : ¼Ó¼º À̸§°ú '=' »çÀÌ¿¡ ½ºÆäÀ̽º°¡ ÀÖ´Ù¸é Skip ÇØÁà¾ß ÇÑ´Ù. // while (::iswspace(*lpszEnd)) //lpszEnd = ::_tcsinc(lpszEnd); lpszEnd++; if (*lpszEnd != L'=') { m_strAttrName = strAttrName; m_strAttrValue.Empty(); return UINT(lpszEnd - lpszString); } else { // skip white-space characters after equal-sign // and the equal-sign itself do { //lpszEnd = ::_tcsinc(lpszEnd); lpszEnd++; } while (::iswspace(*lpszEnd)); lpszBegin = lpszEnd; ch = *lpszEnd; // is attribute value wrapped in quotes? if (ch == L'\'' || ch == L'\"') { //lpszBegin = ::_tcsinc(lpszBegin); // skip quote symbol lpszBegin++; do { //lpszEnd = ::_tcsinc(lpszEnd); lpszEnd++; } // Loop until we find the same quote character that // was used at the starting of the attribute value. // Anything within these quotes is considered valid! // NOTE that the entity references are resolved later. while (*lpszEnd != NULL && *lpszEnd != ch); } // open attribute value i.e. not wrapped in quotes? else { do { //lpszEnd = ::_tcsinc(lpszEnd); lpszEnd++; } // loop until we find a tag ending delimeter or any // white-space character, or until we reach at the // end of the string buffer while (*lpszEnd != NULL && !::iswspace(*lpszEnd) && *lpszEnd != L'/' && *lpszEnd != L'>'); } m_strAttrName = strAttrName; if (lpszEnd == lpszBegin) // empty attribute value? { m_strAttrValue.Empty(); } else { // use putValue() instead of direct assignment; // this will automatically normalize data before // assigning according to the specs and will // also resolve entity references!!! putValue(CStringW(lpszBegin, UINT(lpszEnd - lpszBegin))); } // calculate and return the count of characters successfully parsed // Note : ¸¶Áö¸·¿¡ ºÙÀº ''' or '"'´Â Skip // while( *lpszEnd == L'\'' || *lpszEnd == L'\"' ) //lpszEnd = ::_tcsinc(lpszEnd); lpszEnd++; return UINT(lpszEnd - lpszString); } return (0U); } class CLiteHTMLAttributes { // Construction/Destruction public: CLiteHTMLAttributes() { } CLiteHTMLAttributes(CLiteHTMLAttributes &rSource, bool bCopy = false)// throw(CMemoryException) { if (!bCopy) { for( int i=0; i<(int)rSource.m_parrAttrib.size(); i++ ) { m_parrAttrib.push_back( rSource.m_parrAttrib[i] ); rSource.m_parrAttrib[i] = NULL; } rSource.m_parrAttrib.clear(); } else { for( int i=0; i<(int)rSource.m_parrAttrib.size(); i++ ) { CLiteHTMLElemAttr *pAttr = new CLiteHTMLElemAttr((*rSource.m_parrAttrib[i])); m_parrAttrib.push_back( pAttr ); } } } virtual ~CLiteHTMLAttributes() { removeAll(); } // Initialization public: // parses attribute/value pairs from the given string UINT parseFromStr(LPCWSTR lpszString); // Attributes public: int getCount(void) const { return (int)m_parrAttrib.size(); } int getIndexFromName(LPCWSTR lpszAttributeName) const { //ASSERT(AfxIsValidString(lpszAttributeName)); CLiteHTMLElemAttr *pItem = NULL; for (int iElem = 0; iElem < getCount(); iElem++) { if ((pItem = m_parrAttrib[iElem]) == NULL) // just in case continue; // perform a CASE-INSENSITIVE search if (pItem->m_strAttrName.CompareNoCase(lpszAttributeName) == 0) return (iElem); } return (-1); } CLiteHTMLElemAttr operator[](int nIndex) const { if (!(nIndex >= 0 && nIndex < getCount())) { ASSERT(FALSE); return (CLiteHTMLElemAttr()); } return (*(m_parrAttrib[nIndex])); } CLiteHTMLElemAttr operator[](LPCWSTR lpszIndex) const { ASSERT(lpszIndex); //ASSERT(AfxIsValidString(lpszIndex)); return ((*this)[getIndexFromName(lpszIndex)]); } CLiteHTMLElemAttr getAttribute(int nIndex) const { return ((*this)[nIndex]); } CLiteHTMLElemAttr getAttribute(LPCWSTR lpszIndex) const { ASSERT(lpszIndex); //ASSERT(AfxIsValidString(lpszIndex)); return ((*this)[getIndexFromName(lpszIndex)]); } CStringW getName(int nIndex) const { return ((*this)[nIndex].m_strAttrName); } CStringW getValue(int nIndex) const { return ((*this)[nIndex].m_strAttrValue); } CStringW getValueFromName(LPCWSTR lpszAttributeName) const { return ((*this)[lpszAttributeName].m_strAttrValue); } // Operations public: CLiteHTMLElemAttr* addAttribute(LPCWSTR lpszName, LPCWSTR lpszValue) { ASSERT(lpszName); ASSERT(lpszValue); //ASSERT(AfxIsValidString(lpszName)); //ASSERT(AfxIsValidString(lpszValue)); CLiteHTMLElemAttr *pItem = new CLiteHTMLElemAttr(lpszName, lpszValue); if (pItem != NULL) { m_parrAttrib.push_back(pItem); } return (pItem); } bool removeAttribute(int nIndex) { if (!(nIndex >= 0 && nIndex < (int)m_parrAttrib.size())) return (false); SAFE_DELETE_POINTER(m_parrAttrib[nIndex]); return (true); } bool removeAll(void) { for (int iElem = 0; iElem < (int)m_parrAttrib.size(); iElem++) { SAFE_DELETE_POINTER(m_parrAttrib[iElem]); } m_parrAttrib.clear(); return (true); } // Data Members private: typedef std::vector HTMLElemAttr_VEC; HTMLElemAttr_VEC m_parrAttrib; // array of attributes/value pairs }; inline UINT CLiteHTMLAttributes::parseFromStr(LPCWSTR lpszString) { ASSERT(lpszString); //ASSERT(AfxIsValidString(lpszString)); HTMLElemAttr_VEC pcoll; CLiteHTMLElemAttr oElemAttr; const UINT nStrLen = (UINT)::wcslen(lpszString); UINT nRetVal = 0U, nTemp = 0U; do { // try to parse an attribute/value // pair from the rest of the string if (!(nTemp = oElemAttr.parseFromStr(&lpszString[nRetVal]))) { if (!nRetVal) goto LError; break; } // add attribute/value pair to collection pcoll.push_back(new CLiteHTMLElemAttr(oElemAttr)); // advance seek pointer nRetVal += nTemp; } while (nRetVal < nStrLen); // do we still have something in the buffer to parse? // collection is empty? if(pcoll.empty()) goto LError; // current collection could not be emptied? if(!removeAll()) goto LError; for( int i=0; i<(int)pcoll.size(); i++ ) { m_parrAttrib.push_back( pcoll[i] ); pcoll[i] = NULL; } pcoll.clear(); goto LCleanExit; // success! LError: for( int i=0; i<(int)pcoll.size(); i++ ) { SAFE_DELETE_POINTER(pcoll[i]); } pcoll.clear(); nRetVal = 0U; LCleanExit: return (nRetVal); } #pragma warning(default : 4290) #pragma warning(pop)