Index: xfa/src/fdp/src/css/fde_cssstylesheet.cpp |
diff --git a/xfa/src/fdp/src/css/fde_cssstylesheet.cpp b/xfa/src/fdp/src/css/fde_cssstylesheet.cpp |
index 4e9567fa334e4f04a7bac86f86a302471cad38e5..b9da5b6b8b048d7391d2e78cbd5cdc676bbf16c0 100644 |
--- a/xfa/src/fdp/src/css/fde_cssstylesheet.cpp |
+++ b/xfa/src/fdp/src/css/fde_cssstylesheet.cpp |
@@ -1,505 +1,505 @@ |
-// Copyright 2014 PDFium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
- |
-#include "xfa/src/foxitlib.h" |
-#include "fde_csssyntax.h" |
-#include "fde_cssdatatable.h" |
-#include "fde_cssstylesheet.h" |
-IFDE_CSSStyleSheet* IFDE_CSSStyleSheet::LoadHTMLStandardStyleSheet() { |
- static const FX_WCHAR* s_pStyle = |
- L"html,address,blockquote,body,dd,div,dl,dt,fieldset,form,frame,frameset," |
- L"h1,h2,h3,h4,h5,h6,noframes,ol,p,ul,center,dir,hr,menu,pre{display:" |
- L"block}" |
- L"li{display:list-item}head{display:none}table{display:table}tr{display:" |
- L"table-row}thead{display:table-header-group}tbody{display:table-row-" |
- L"group}tfoot{display:table-footer-group}" |
- L"col{display:table-column}colgroup{display:table-column-group}td,th{" |
- L"display:table-cell}caption{display:table-caption}th{font-weight:bolder;" |
- L"text-align:center}caption{text-align:center}" |
- L"body{margin:0}h1{font-size:2em;margin:.67em " |
- L"0}h2{font-size:1.5em;margin:.75em 0}h3{font-size:1.17em;margin:.83em " |
- L"0}h4,p,blockquote,ul,fieldset,form,ol,dl,dir,menu{margin:1.12em 0}" |
- L"h5{font-size:.83em;margin:1.5em 0}h6{font-size:.75em;margin:1.67em " |
- L"0}h1,h2,h3,h4,h5,h6,b,strong{font-weight:bolder}blockquote{margin-left:" |
- L"40px;margin-right:40px}i,cite,em,var,address{font-style:italic}" |
- L"pre,tt,code,kbd,samp{font-family:monospace}pre{white-space:pre}button," |
- L"textarea,input,select{display:inline-block}big{font-size:1.17em}small," |
- L"sub,sup{font-size:.83em}sub{vertical-align:sub}" |
- L"sup{vertical-align:super}table{border-spacing:2px}thead,tbody,tfoot{" |
- L"vertical-align:middle}td,th,tr{vertical-align:inherit}s,strike,del{" |
- L"text-decoration:line-through}hr{border:1px inset silver}" |
- L"ol,ul,dir,menu,dd{margin-left:40px}ol{list-style-type:decimal}ol ul,ul " |
- L"ol,ul ul,ol " |
- L"ol{margin-top:0;margin-bottom:0}u,ins{text-decoration:underline}center{" |
- L"text-align:center}" |
- L"ruby{display:ruby}rt{display:ruby-text;font-size:.5em}rb{display:ruby-" |
- L"base}rbc{display:ruby-base-group}rtc{display:ruby-text-group}" |
- L"q:before{content:open-quote}q:after{content:close-quote}" |
- L"rp{display:none}"; |
- return IFDE_CSSStyleSheet::LoadFromBuffer( |
- CFX_WideString(), s_pStyle, FXSYS_wcslen(s_pStyle), FX_CODEPAGE_UTF8); |
-} |
-IFDE_CSSStyleSheet* IFDE_CSSStyleSheet::LoadFromStream( |
- const CFX_WideString& szUrl, |
- IFX_Stream* pStream, |
- FX_WORD wCodePage, |
- FX_DWORD dwMediaList) { |
- CFDE_CSSStyleSheet* pStyleSheet = new CFDE_CSSStyleSheet(dwMediaList); |
- if (!pStyleSheet->LoadFromStream(szUrl, pStream, wCodePage)) { |
- pStyleSheet->Release(); |
- pStyleSheet = NULL; |
- } |
- return pStyleSheet; |
-} |
-IFDE_CSSStyleSheet* IFDE_CSSStyleSheet::LoadFromBuffer( |
- const CFX_WideString& szUrl, |
- const FX_WCHAR* pBuffer, |
- int32_t iBufSize, |
- FX_WORD wCodePage, |
- FX_DWORD dwMediaList) { |
- CFDE_CSSStyleSheet* pStyleSheet = new CFDE_CSSStyleSheet(dwMediaList); |
- if (!pStyleSheet->LoadFromBuffer(szUrl, pBuffer, iBufSize, wCodePage)) { |
- pStyleSheet->Release(); |
- pStyleSheet = NULL; |
- } |
- return pStyleSheet; |
-} |
-CFDE_CSSStyleSheet::CFDE_CSSStyleSheet(FX_DWORD dwMediaList) |
- : m_wCodePage(FX_CODEPAGE_UTF8), |
- m_wRefCount(1), |
- m_dwMediaList(dwMediaList), |
- m_pAllocator(NULL) { |
- FXSYS_assert(m_dwMediaList > 0); |
-} |
-CFDE_CSSStyleSheet::~CFDE_CSSStyleSheet() { |
- Reset(); |
-} |
-void CFDE_CSSStyleSheet::Reset() { |
- for (int32_t i = m_RuleArray.GetSize() - 1; i >= 0; --i) { |
- IFDE_CSSRule* pRule = m_RuleArray.GetAt(i); |
- switch (pRule->GetType()) { |
- case FDE_CSSRULETYPE_Style: |
- ((CFDE_CSSStyleRule*)pRule)->~CFDE_CSSStyleRule(); |
- break; |
- case FDE_CSSRULETYPE_Media: |
- ((CFDE_CSSMediaRule*)pRule)->~CFDE_CSSMediaRule(); |
- break; |
- case FDE_CSSRULETYPE_FontFace: |
- ((CFDE_CSSFontFaceRule*)pRule)->~CFDE_CSSFontFaceRule(); |
- break; |
- default: |
- FXSYS_assert(FALSE); |
- break; |
- } |
- } |
- m_RuleArray.RemoveAll(); |
- m_Selectors.RemoveAll(); |
- m_StringCache.RemoveAll(); |
- if (m_pAllocator) { |
- m_pAllocator->Release(); |
- m_pAllocator = NULL; |
- } |
-} |
-FX_DWORD CFDE_CSSStyleSheet::AddRef() { |
- return ++m_wRefCount; |
-} |
-FX_DWORD CFDE_CSSStyleSheet::Release() { |
- FX_DWORD dwRefCount = --m_wRefCount; |
- if (dwRefCount == 0) { |
- delete this; |
- } |
- return dwRefCount; |
-} |
-int32_t CFDE_CSSStyleSheet::CountRules() const { |
- return m_RuleArray.GetSize(); |
-} |
-IFDE_CSSRule* CFDE_CSSStyleSheet::GetRule(int32_t index) { |
- return m_RuleArray.GetAt(index); |
-} |
-FX_BOOL CFDE_CSSStyleSheet::LoadFromStream(const CFX_WideString& szUrl, |
- IFX_Stream* pStream, |
- FX_WORD wCodePage) { |
- FXSYS_assert(pStream != NULL); |
- IFDE_CSSSyntaxParser* pSyntax = IFDE_CSSSyntaxParser::Create(); |
- if (pSyntax == NULL) { |
- return FALSE; |
- } |
- if (pStream->GetCodePage() != wCodePage) { |
- pStream->SetCodePage(wCodePage); |
- } |
- FX_BOOL bRet = pSyntax->Init(pStream, 4096) && LoadFromSyntax(pSyntax); |
- pSyntax->Release(); |
- m_wCodePage = wCodePage; |
- m_szUrl = szUrl; |
- return bRet; |
-} |
-FX_BOOL CFDE_CSSStyleSheet::LoadFromBuffer(const CFX_WideString& szUrl, |
- const FX_WCHAR* pBuffer, |
- int32_t iBufSize, |
- FX_WORD wCodePage) { |
- FXSYS_assert(pBuffer != NULL && iBufSize > 0); |
- IFDE_CSSSyntaxParser* pSyntax = IFDE_CSSSyntaxParser::Create(); |
- if (pSyntax == NULL) { |
- return FALSE; |
- } |
- FX_BOOL bRet = pSyntax->Init(pBuffer, iBufSize) && LoadFromSyntax(pSyntax); |
- pSyntax->Release(); |
- m_wCodePage = wCodePage; |
- m_szUrl = szUrl; |
- return bRet; |
-} |
-FX_BOOL CFDE_CSSStyleSheet::LoadFromSyntax(IFDE_CSSSyntaxParser* pSyntax) { |
- Reset(); |
- m_pAllocator = FX_CreateAllocator(FX_ALLOCTYPE_Static, 1024, 0); |
- if (m_pAllocator == NULL) { |
- return FALSE; |
- } |
- FDE_CSSSYNTAXSTATUS eStatus; |
- do { |
- switch (eStatus = pSyntax->DoSyntaxParse()) { |
- case FDE_CSSSYNTAXSTATUS_StyleRule: |
- eStatus = LoadStyleRule(pSyntax, m_RuleArray); |
- break; |
- case FDE_CSSSYNTAXSTATUS_MediaRule: |
- eStatus = LoadMediaRule(pSyntax); |
- break; |
- case FDE_CSSSYNTAXSTATUS_FontFaceRule: |
- eStatus = LoadFontFaceRule(pSyntax, m_RuleArray); |
- break; |
- case FDE_CSSSYNTAXSTATUS_ImportRule: |
- eStatus = LoadImportRule(pSyntax); |
- break; |
- case FDE_CSSSYNTAXSTATUS_PageRule: |
- eStatus = LoadPageRule(pSyntax); |
- break; |
- default: |
- break; |
- } |
- } while (eStatus >= FDE_CSSSYNTAXSTATUS_None); |
- m_Selectors.RemoveAll(); |
- m_StringCache.RemoveAll(); |
- return eStatus != FDE_CSSSYNTAXSTATUS_Error; |
-} |
-FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::LoadMediaRule( |
- IFDE_CSSSyntaxParser* pSyntax) { |
- FX_DWORD dwMediaList = 0; |
- CFDE_CSSMediaRule* pMediaRule = NULL; |
- for (;;) { |
- switch (pSyntax->DoSyntaxParse()) { |
- case FDE_CSSSYNTAXSTATUS_MediaType: { |
- int32_t iLen; |
- const FX_WCHAR* psz = pSyntax->GetCurrentString(iLen); |
- FDE_LPCCSSMEDIATYPETABLE pMediaType = |
- FDE_GetCSSMediaTypeByName(psz, iLen); |
- if (pMediaType != NULL) { |
- dwMediaList |= pMediaType->wValue; |
- } |
- } break; |
- case FDE_CSSSYNTAXSTATUS_StyleRule: |
- if (pMediaRule == NULL) { |
- SkipRuleSet(pSyntax); |
- } else { |
- FDE_CSSSYNTAXSTATUS eStatus = |
- LoadStyleRule(pSyntax, pMediaRule->GetArray()); |
- if (eStatus < FDE_CSSSYNTAXSTATUS_None) { |
- return eStatus; |
- } |
- } |
- break; |
- case FDE_CSSSYNTAXSTATUS_DeclOpen: |
- if ((dwMediaList & m_dwMediaList) > 0 && pMediaRule == NULL) { |
- pMediaRule = FDE_NewWith(m_pAllocator) CFDE_CSSMediaRule(dwMediaList); |
- m_RuleArray.Add(pMediaRule); |
- } |
- break; |
- case FDE_CSSSYNTAXSTATUS_DeclClose: |
- return FDE_CSSSYNTAXSTATUS_None; |
- FDE_CSSSWITCHDEFAULTS(); |
- } |
- } |
-} |
-FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::LoadStyleRule( |
- IFDE_CSSSyntaxParser* pSyntax, |
- CFDE_CSSRuleArray& ruleArray) { |
- m_Selectors.RemoveAt(0, m_Selectors.GetSize()); |
- CFDE_CSSStyleRule* pStyleRule = NULL; |
- const FX_WCHAR* pszValue = NULL; |
- int32_t iValueLen = 0; |
- FDE_CSSPROPERTYARGS propertyArgs; |
- propertyArgs.pStaticStore = m_pAllocator; |
- propertyArgs.pStringCache = &m_StringCache; |
- propertyArgs.pProperty = NULL; |
- CFX_WideString wsName; |
- for (;;) { |
- switch (pSyntax->DoSyntaxParse()) { |
- case FDE_CSSSYNTAXSTATUS_Selector: { |
- pszValue = pSyntax->GetCurrentString(iValueLen); |
- IFDE_CSSSelector* pSelector = |
- CFDE_CSSSelector::FromString(m_pAllocator, pszValue, iValueLen); |
- if (pSelector != NULL) { |
- m_Selectors.Add(pSelector); |
- } |
- } break; |
- case FDE_CSSSYNTAXSTATUS_PropertyName: |
- pszValue = pSyntax->GetCurrentString(iValueLen); |
- propertyArgs.pProperty = FDE_GetCSSPropertyByName(pszValue, iValueLen); |
- if (propertyArgs.pProperty == NULL) { |
- wsName = CFX_WideStringC(pszValue, iValueLen); |
- } |
- break; |
- case FDE_CSSSYNTAXSTATUS_PropertyValue: |
- if (propertyArgs.pProperty != NULL) { |
- pszValue = pSyntax->GetCurrentString(iValueLen); |
- if (iValueLen > 0) { |
- pStyleRule->GetDeclImp().AddProperty(&propertyArgs, pszValue, |
- iValueLen); |
- } |
- } else if (iValueLen > 0) { |
- pszValue = pSyntax->GetCurrentString(iValueLen); |
- if (iValueLen > 0) { |
- pStyleRule->GetDeclImp().AddProperty( |
- &propertyArgs, wsName, wsName.GetLength(), pszValue, iValueLen); |
- } |
- } |
- break; |
- case FDE_CSSSYNTAXSTATUS_DeclOpen: |
- if (pStyleRule == NULL && m_Selectors.GetSize() > 0) { |
- pStyleRule = FDE_NewWith(m_pAllocator) CFDE_CSSStyleRule; |
- pStyleRule->SetSelector(m_pAllocator, m_Selectors); |
- ruleArray.Add(pStyleRule); |
- } else { |
- SkipRuleSet(pSyntax); |
- return FDE_CSSSYNTAXSTATUS_None; |
- } |
- break; |
- case FDE_CSSSYNTAXSTATUS_DeclClose: |
- if (pStyleRule != NULL && |
- pStyleRule->GetDeclImp().GetStartPosition() == NULL) { |
- pStyleRule->~CFDE_CSSStyleRule(); |
- ruleArray.RemoveLast(1); |
- } |
- return FDE_CSSSYNTAXSTATUS_None; |
- FDE_CSSSWITCHDEFAULTS(); |
- } |
- } |
-} |
-FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::LoadFontFaceRule( |
- IFDE_CSSSyntaxParser* pSyntax, |
- CFDE_CSSRuleArray& ruleArray) { |
- CFDE_CSSFontFaceRule* pFontFaceRule = NULL; |
- const FX_WCHAR* pszValue = NULL; |
- int32_t iValueLen = 0; |
- FDE_CSSPROPERTYARGS propertyArgs; |
- propertyArgs.pStaticStore = m_pAllocator; |
- propertyArgs.pStringCache = &m_StringCache; |
- propertyArgs.pProperty = NULL; |
- for (;;) { |
- switch (pSyntax->DoSyntaxParse()) { |
- case FDE_CSSSYNTAXSTATUS_PropertyName: |
- pszValue = pSyntax->GetCurrentString(iValueLen); |
- propertyArgs.pProperty = FDE_GetCSSPropertyByName(pszValue, iValueLen); |
- break; |
- case FDE_CSSSYNTAXSTATUS_PropertyValue: |
- if (propertyArgs.pProperty != NULL) { |
- pszValue = pSyntax->GetCurrentString(iValueLen); |
- if (iValueLen > 0) { |
- pFontFaceRule->GetDeclImp().AddProperty(&propertyArgs, pszValue, |
- iValueLen); |
- } |
- } |
- break; |
- case FDE_CSSSYNTAXSTATUS_DeclOpen: |
- if (pFontFaceRule == NULL) { |
- pFontFaceRule = FDE_NewWith(m_pAllocator) CFDE_CSSFontFaceRule; |
- ruleArray.Add(pFontFaceRule); |
- } |
- break; |
- case FDE_CSSSYNTAXSTATUS_DeclClose: |
- return FDE_CSSSYNTAXSTATUS_None; |
- FDE_CSSSWITCHDEFAULTS(); |
- } |
- } |
- return FDE_CSSSYNTAXSTATUS_None; |
-} |
-FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::LoadImportRule( |
- IFDE_CSSSyntaxParser* pSyntax) { |
- for (;;) { |
- switch (pSyntax->DoSyntaxParse()) { |
- case FDE_CSSSYNTAXSTATUS_ImportClose: |
- return FDE_CSSSYNTAXSTATUS_None; |
- case FDE_CSSSYNTAXSTATUS_URI: |
- break; |
- FDE_CSSSWITCHDEFAULTS(); |
- } |
- } |
-} |
-FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::LoadPageRule( |
- IFDE_CSSSyntaxParser* pSyntax) { |
- return SkipRuleSet(pSyntax); |
-} |
-FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::SkipRuleSet( |
- IFDE_CSSSyntaxParser* pSyntax) { |
- for (;;) { |
- switch (pSyntax->DoSyntaxParse()) { |
- case FDE_CSSSYNTAXSTATUS_Selector: |
- case FDE_CSSSYNTAXSTATUS_DeclOpen: |
- case FDE_CSSSYNTAXSTATUS_PropertyName: |
- case FDE_CSSSYNTAXSTATUS_PropertyValue: |
- break; |
- case FDE_CSSSYNTAXSTATUS_DeclClose: |
- return FDE_CSSSYNTAXSTATUS_None; |
- FDE_CSSSWITCHDEFAULTS(); |
- } |
- } |
- return FDE_CSSSYNTAXSTATUS_None; |
-} |
-void CFDE_CSSStyleRule::SetSelector(IFX_MEMAllocator* pStaticStore, |
- const CFDE_CSSSelectorArray& list) { |
- FXSYS_assert(m_ppSelector == NULL); |
- m_iSelectors = list.GetSize(); |
- m_ppSelector = (IFDE_CSSSelector**)pStaticStore->Alloc( |
- m_iSelectors * sizeof(IFDE_CSSSelector*)); |
- for (int32_t i = 0; i < m_iSelectors; ++i) { |
- m_ppSelector[i] = list.GetAt(i); |
- } |
-} |
-CFDE_CSSMediaRule::~CFDE_CSSMediaRule() { |
- for (int32_t i = m_RuleArray.GetSize() - 1; i >= 0; --i) { |
- IFDE_CSSRule* pRule = m_RuleArray.GetAt(i); |
- switch (pRule->GetType()) { |
- case FDE_CSSRULETYPE_Style: |
- ((CFDE_CSSStyleRule*)pRule)->~CFDE_CSSStyleRule(); |
- break; |
- default: |
- FXSYS_assert(FALSE); |
- break; |
- } |
- } |
-} |
-inline FX_BOOL FDE_IsCSSChar(FX_WCHAR wch) { |
- return (wch >= 'a' && wch <= 'z') || (wch >= 'A' && wch <= 'Z'); |
-} |
-int32_t FDE_GetCSSPersudoLen(const FX_WCHAR* psz, const FX_WCHAR* pEnd) { |
- FXSYS_assert(*psz == ':'); |
- const FX_WCHAR* pStart = psz; |
- while (psz < pEnd) { |
- FX_WCHAR wch = *psz; |
- if (FDE_IsCSSChar(wch) || wch == ':') { |
- ++psz; |
- } else { |
- break; |
- } |
- } |
- return psz - pStart; |
-} |
-int32_t FDE_GetCSSNameLen(const FX_WCHAR* psz, const FX_WCHAR* pEnd) { |
- const FX_WCHAR* pStart = psz; |
- while (psz < pEnd) { |
- FX_WCHAR wch = *psz; |
- if (FDE_IsCSSChar(wch) || (wch >= '0' && wch <= '9') || wch == '_' || |
- wch == '-') { |
- ++psz; |
- } else { |
- break; |
- } |
- } |
- return psz - pStart; |
-} |
-IFDE_CSSSelector* CFDE_CSSSelector::FromString(IFX_MEMAllocator* pStaticStore, |
- const FX_WCHAR* psz, |
- int32_t iLen) { |
- FXSYS_assert(pStaticStore != NULL && psz != NULL && iLen > 0); |
- const FX_WCHAR* pStart = psz; |
- const FX_WCHAR* pEnd = psz + iLen; |
- for (; psz < pEnd; ++psz) { |
- switch (*psz) { |
- case '>': |
- case '[': |
- case '+': |
- return NULL; |
- } |
- } |
- CFDE_CSSSelector *pFirst = NULL, *pLast = NULL; |
- CFDE_CSSSelector *pPersudoFirst = NULL, *pPersudoLast = NULL; |
- for (psz = pStart; psz < pEnd;) { |
- FX_WCHAR wch = *psz; |
- if (wch == '.' || wch == '#') { |
- if (psz == pStart || psz[-1] == ' ') { |
- CFDE_CSSSelector* p = FDE_NewWith(pStaticStore) |
- CFDE_CSSSelector(FDE_CSSSELECTORTYPE_Element, L"*", 1, TRUE); |
- if (p == NULL) { |
- return NULL; |
- } |
- if (pFirst != NULL) { |
- pFirst->SetType(FDE_CSSSELECTORTYPE_Descendant); |
- p->SetNext(pFirst); |
- } |
- pFirst = pLast = p; |
- } |
- FXSYS_assert(pLast != NULL); |
- int32_t iNameLen = FDE_GetCSSNameLen(++psz, pEnd); |
- if (iNameLen == 0) { |
- return NULL; |
- } |
- FDE_CSSSELECTORTYPE eType = |
- wch == '.' ? FDE_CSSSELECTORTYPE_Class : FDE_CSSSELECTORTYPE_ID; |
- CFDE_CSSSelector* p = FDE_NewWith(pStaticStore) |
- CFDE_CSSSelector(eType, psz, iNameLen, FALSE); |
- if (p == NULL) { |
- return NULL; |
- } |
- p->SetNext(pLast->GetNextSelector()); |
- pLast->SetNext(p); |
- pLast = p; |
- psz += iNameLen; |
- } else if (FDE_IsCSSChar(wch) || wch == '*') { |
- int32_t iNameLen = wch == '*' ? 1 : FDE_GetCSSNameLen(psz, pEnd); |
- if (iNameLen == 0) { |
- return NULL; |
- } |
- CFDE_CSSSelector* p = FDE_NewWith(pStaticStore) |
- CFDE_CSSSelector(FDE_CSSSELECTORTYPE_Element, psz, iNameLen, TRUE); |
- if (p == NULL) { |
- return NULL; |
- } |
- if (pFirst == NULL) { |
- pFirst = pLast = p; |
- } else { |
- pFirst->SetType(FDE_CSSSELECTORTYPE_Descendant); |
- p->SetNext(pFirst); |
- pFirst = pLast = p; |
- } |
- psz += iNameLen; |
- } else if (wch == ':') { |
- int32_t iNameLen = FDE_GetCSSPersudoLen(psz, pEnd); |
- if (iNameLen == 0) { |
- return NULL; |
- } |
- CFDE_CSSSelector* p = FDE_NewWith(pStaticStore) |
- CFDE_CSSSelector(FDE_CSSSELECTORTYPE_Persudo, psz, iNameLen, TRUE); |
- if (p == NULL) { |
- return NULL; |
- } |
- if (pPersudoFirst == NULL) { |
- pPersudoFirst = pPersudoLast = p; |
- } else { |
- pPersudoLast->SetNext(p); |
- pPersudoLast = p; |
- } |
- psz += iNameLen; |
- } else if (wch == ' ') { |
- psz++; |
- } else { |
- return NULL; |
- } |
- } |
- if (pPersudoFirst == NULL) { |
- return pFirst; |
- } else { |
- pPersudoLast->SetNext(pFirst); |
- return pPersudoFirst; |
- } |
-} |
+// Copyright 2014 PDFium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
+ |
+#include "xfa/src/foxitlib.h" |
+#include "fde_csssyntax.h" |
+#include "fde_cssdatatable.h" |
+#include "fde_cssstylesheet.h" |
+IFDE_CSSStyleSheet* IFDE_CSSStyleSheet::LoadHTMLStandardStyleSheet() { |
+ static const FX_WCHAR* s_pStyle = |
+ L"html,address,blockquote,body,dd,div,dl,dt,fieldset,form,frame,frameset," |
+ L"h1,h2,h3,h4,h5,h6,noframes,ol,p,ul,center,dir,hr,menu,pre{display:" |
+ L"block}" |
+ L"li{display:list-item}head{display:none}table{display:table}tr{display:" |
+ L"table-row}thead{display:table-header-group}tbody{display:table-row-" |
+ L"group}tfoot{display:table-footer-group}" |
+ L"col{display:table-column}colgroup{display:table-column-group}td,th{" |
+ L"display:table-cell}caption{display:table-caption}th{font-weight:bolder;" |
+ L"text-align:center}caption{text-align:center}" |
+ L"body{margin:0}h1{font-size:2em;margin:.67em " |
+ L"0}h2{font-size:1.5em;margin:.75em 0}h3{font-size:1.17em;margin:.83em " |
+ L"0}h4,p,blockquote,ul,fieldset,form,ol,dl,dir,menu{margin:1.12em 0}" |
+ L"h5{font-size:.83em;margin:1.5em 0}h6{font-size:.75em;margin:1.67em " |
+ L"0}h1,h2,h3,h4,h5,h6,b,strong{font-weight:bolder}blockquote{margin-left:" |
+ L"40px;margin-right:40px}i,cite,em,var,address{font-style:italic}" |
+ L"pre,tt,code,kbd,samp{font-family:monospace}pre{white-space:pre}button," |
+ L"textarea,input,select{display:inline-block}big{font-size:1.17em}small," |
+ L"sub,sup{font-size:.83em}sub{vertical-align:sub}" |
+ L"sup{vertical-align:super}table{border-spacing:2px}thead,tbody,tfoot{" |
+ L"vertical-align:middle}td,th,tr{vertical-align:inherit}s,strike,del{" |
+ L"text-decoration:line-through}hr{border:1px inset silver}" |
+ L"ol,ul,dir,menu,dd{margin-left:40px}ol{list-style-type:decimal}ol ul,ul " |
+ L"ol,ul ul,ol " |
+ L"ol{margin-top:0;margin-bottom:0}u,ins{text-decoration:underline}center{" |
+ L"text-align:center}" |
+ L"ruby{display:ruby}rt{display:ruby-text;font-size:.5em}rb{display:ruby-" |
+ L"base}rbc{display:ruby-base-group}rtc{display:ruby-text-group}" |
+ L"q:before{content:open-quote}q:after{content:close-quote}" |
+ L"rp{display:none}"; |
+ return IFDE_CSSStyleSheet::LoadFromBuffer( |
+ CFX_WideString(), s_pStyle, FXSYS_wcslen(s_pStyle), FX_CODEPAGE_UTF8); |
+} |
+IFDE_CSSStyleSheet* IFDE_CSSStyleSheet::LoadFromStream( |
+ const CFX_WideString& szUrl, |
+ IFX_Stream* pStream, |
+ FX_WORD wCodePage, |
+ FX_DWORD dwMediaList) { |
+ CFDE_CSSStyleSheet* pStyleSheet = new CFDE_CSSStyleSheet(dwMediaList); |
+ if (!pStyleSheet->LoadFromStream(szUrl, pStream, wCodePage)) { |
+ pStyleSheet->Release(); |
+ pStyleSheet = NULL; |
+ } |
+ return pStyleSheet; |
+} |
+IFDE_CSSStyleSheet* IFDE_CSSStyleSheet::LoadFromBuffer( |
+ const CFX_WideString& szUrl, |
+ const FX_WCHAR* pBuffer, |
+ int32_t iBufSize, |
+ FX_WORD wCodePage, |
+ FX_DWORD dwMediaList) { |
+ CFDE_CSSStyleSheet* pStyleSheet = new CFDE_CSSStyleSheet(dwMediaList); |
+ if (!pStyleSheet->LoadFromBuffer(szUrl, pBuffer, iBufSize, wCodePage)) { |
+ pStyleSheet->Release(); |
+ pStyleSheet = NULL; |
+ } |
+ return pStyleSheet; |
+} |
+CFDE_CSSStyleSheet::CFDE_CSSStyleSheet(FX_DWORD dwMediaList) |
+ : m_wCodePage(FX_CODEPAGE_UTF8), |
+ m_wRefCount(1), |
+ m_dwMediaList(dwMediaList), |
+ m_pAllocator(NULL) { |
+ FXSYS_assert(m_dwMediaList > 0); |
+} |
+CFDE_CSSStyleSheet::~CFDE_CSSStyleSheet() { |
+ Reset(); |
+} |
+void CFDE_CSSStyleSheet::Reset() { |
+ for (int32_t i = m_RuleArray.GetSize() - 1; i >= 0; --i) { |
+ IFDE_CSSRule* pRule = m_RuleArray.GetAt(i); |
+ switch (pRule->GetType()) { |
+ case FDE_CSSRULETYPE_Style: |
+ ((CFDE_CSSStyleRule*)pRule)->~CFDE_CSSStyleRule(); |
+ break; |
+ case FDE_CSSRULETYPE_Media: |
+ ((CFDE_CSSMediaRule*)pRule)->~CFDE_CSSMediaRule(); |
+ break; |
+ case FDE_CSSRULETYPE_FontFace: |
+ ((CFDE_CSSFontFaceRule*)pRule)->~CFDE_CSSFontFaceRule(); |
+ break; |
+ default: |
+ FXSYS_assert(FALSE); |
+ break; |
+ } |
+ } |
+ m_RuleArray.RemoveAll(); |
+ m_Selectors.RemoveAll(); |
+ m_StringCache.RemoveAll(); |
+ if (m_pAllocator) { |
+ m_pAllocator->Release(); |
+ m_pAllocator = NULL; |
+ } |
+} |
+FX_DWORD CFDE_CSSStyleSheet::AddRef() { |
+ return ++m_wRefCount; |
+} |
+FX_DWORD CFDE_CSSStyleSheet::Release() { |
+ FX_DWORD dwRefCount = --m_wRefCount; |
+ if (dwRefCount == 0) { |
+ delete this; |
+ } |
+ return dwRefCount; |
+} |
+int32_t CFDE_CSSStyleSheet::CountRules() const { |
+ return m_RuleArray.GetSize(); |
+} |
+IFDE_CSSRule* CFDE_CSSStyleSheet::GetRule(int32_t index) { |
+ return m_RuleArray.GetAt(index); |
+} |
+FX_BOOL CFDE_CSSStyleSheet::LoadFromStream(const CFX_WideString& szUrl, |
+ IFX_Stream* pStream, |
+ FX_WORD wCodePage) { |
+ FXSYS_assert(pStream != NULL); |
+ IFDE_CSSSyntaxParser* pSyntax = IFDE_CSSSyntaxParser::Create(); |
+ if (pSyntax == NULL) { |
+ return FALSE; |
+ } |
+ if (pStream->GetCodePage() != wCodePage) { |
+ pStream->SetCodePage(wCodePage); |
+ } |
+ FX_BOOL bRet = pSyntax->Init(pStream, 4096) && LoadFromSyntax(pSyntax); |
+ pSyntax->Release(); |
+ m_wCodePage = wCodePage; |
+ m_szUrl = szUrl; |
+ return bRet; |
+} |
+FX_BOOL CFDE_CSSStyleSheet::LoadFromBuffer(const CFX_WideString& szUrl, |
+ const FX_WCHAR* pBuffer, |
+ int32_t iBufSize, |
+ FX_WORD wCodePage) { |
+ FXSYS_assert(pBuffer != NULL && iBufSize > 0); |
+ IFDE_CSSSyntaxParser* pSyntax = IFDE_CSSSyntaxParser::Create(); |
+ if (pSyntax == NULL) { |
+ return FALSE; |
+ } |
+ FX_BOOL bRet = pSyntax->Init(pBuffer, iBufSize) && LoadFromSyntax(pSyntax); |
+ pSyntax->Release(); |
+ m_wCodePage = wCodePage; |
+ m_szUrl = szUrl; |
+ return bRet; |
+} |
+FX_BOOL CFDE_CSSStyleSheet::LoadFromSyntax(IFDE_CSSSyntaxParser* pSyntax) { |
+ Reset(); |
+ m_pAllocator = FX_CreateAllocator(FX_ALLOCTYPE_Static, 1024, 0); |
+ if (m_pAllocator == NULL) { |
+ return FALSE; |
+ } |
+ FDE_CSSSYNTAXSTATUS eStatus; |
+ do { |
+ switch (eStatus = pSyntax->DoSyntaxParse()) { |
+ case FDE_CSSSYNTAXSTATUS_StyleRule: |
+ eStatus = LoadStyleRule(pSyntax, m_RuleArray); |
+ break; |
+ case FDE_CSSSYNTAXSTATUS_MediaRule: |
+ eStatus = LoadMediaRule(pSyntax); |
+ break; |
+ case FDE_CSSSYNTAXSTATUS_FontFaceRule: |
+ eStatus = LoadFontFaceRule(pSyntax, m_RuleArray); |
+ break; |
+ case FDE_CSSSYNTAXSTATUS_ImportRule: |
+ eStatus = LoadImportRule(pSyntax); |
+ break; |
+ case FDE_CSSSYNTAXSTATUS_PageRule: |
+ eStatus = LoadPageRule(pSyntax); |
+ break; |
+ default: |
+ break; |
+ } |
+ } while (eStatus >= FDE_CSSSYNTAXSTATUS_None); |
+ m_Selectors.RemoveAll(); |
+ m_StringCache.RemoveAll(); |
+ return eStatus != FDE_CSSSYNTAXSTATUS_Error; |
+} |
+FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::LoadMediaRule( |
+ IFDE_CSSSyntaxParser* pSyntax) { |
+ FX_DWORD dwMediaList = 0; |
+ CFDE_CSSMediaRule* pMediaRule = NULL; |
+ for (;;) { |
+ switch (pSyntax->DoSyntaxParse()) { |
+ case FDE_CSSSYNTAXSTATUS_MediaType: { |
+ int32_t iLen; |
+ const FX_WCHAR* psz = pSyntax->GetCurrentString(iLen); |
+ FDE_LPCCSSMEDIATYPETABLE pMediaType = |
+ FDE_GetCSSMediaTypeByName(psz, iLen); |
+ if (pMediaType != NULL) { |
+ dwMediaList |= pMediaType->wValue; |
+ } |
+ } break; |
+ case FDE_CSSSYNTAXSTATUS_StyleRule: |
+ if (pMediaRule == NULL) { |
+ SkipRuleSet(pSyntax); |
+ } else { |
+ FDE_CSSSYNTAXSTATUS eStatus = |
+ LoadStyleRule(pSyntax, pMediaRule->GetArray()); |
+ if (eStatus < FDE_CSSSYNTAXSTATUS_None) { |
+ return eStatus; |
+ } |
+ } |
+ break; |
+ case FDE_CSSSYNTAXSTATUS_DeclOpen: |
+ if ((dwMediaList & m_dwMediaList) > 0 && pMediaRule == NULL) { |
+ pMediaRule = FDE_NewWith(m_pAllocator) CFDE_CSSMediaRule(dwMediaList); |
+ m_RuleArray.Add(pMediaRule); |
+ } |
+ break; |
+ case FDE_CSSSYNTAXSTATUS_DeclClose: |
+ return FDE_CSSSYNTAXSTATUS_None; |
+ FDE_CSSSWITCHDEFAULTS(); |
+ } |
+ } |
+} |
+FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::LoadStyleRule( |
+ IFDE_CSSSyntaxParser* pSyntax, |
+ CFDE_CSSRuleArray& ruleArray) { |
+ m_Selectors.RemoveAt(0, m_Selectors.GetSize()); |
+ CFDE_CSSStyleRule* pStyleRule = NULL; |
+ const FX_WCHAR* pszValue = NULL; |
+ int32_t iValueLen = 0; |
+ FDE_CSSPROPERTYARGS propertyArgs; |
+ propertyArgs.pStaticStore = m_pAllocator; |
+ propertyArgs.pStringCache = &m_StringCache; |
+ propertyArgs.pProperty = NULL; |
+ CFX_WideString wsName; |
+ for (;;) { |
+ switch (pSyntax->DoSyntaxParse()) { |
+ case FDE_CSSSYNTAXSTATUS_Selector: { |
+ pszValue = pSyntax->GetCurrentString(iValueLen); |
+ IFDE_CSSSelector* pSelector = |
+ CFDE_CSSSelector::FromString(m_pAllocator, pszValue, iValueLen); |
+ if (pSelector != NULL) { |
+ m_Selectors.Add(pSelector); |
+ } |
+ } break; |
+ case FDE_CSSSYNTAXSTATUS_PropertyName: |
+ pszValue = pSyntax->GetCurrentString(iValueLen); |
+ propertyArgs.pProperty = FDE_GetCSSPropertyByName(pszValue, iValueLen); |
+ if (propertyArgs.pProperty == NULL) { |
+ wsName = CFX_WideStringC(pszValue, iValueLen); |
+ } |
+ break; |
+ case FDE_CSSSYNTAXSTATUS_PropertyValue: |
+ if (propertyArgs.pProperty != NULL) { |
+ pszValue = pSyntax->GetCurrentString(iValueLen); |
+ if (iValueLen > 0) { |
+ pStyleRule->GetDeclImp().AddProperty(&propertyArgs, pszValue, |
+ iValueLen); |
+ } |
+ } else if (iValueLen > 0) { |
+ pszValue = pSyntax->GetCurrentString(iValueLen); |
+ if (iValueLen > 0) { |
+ pStyleRule->GetDeclImp().AddProperty( |
+ &propertyArgs, wsName, wsName.GetLength(), pszValue, iValueLen); |
+ } |
+ } |
+ break; |
+ case FDE_CSSSYNTAXSTATUS_DeclOpen: |
+ if (pStyleRule == NULL && m_Selectors.GetSize() > 0) { |
+ pStyleRule = FDE_NewWith(m_pAllocator) CFDE_CSSStyleRule; |
+ pStyleRule->SetSelector(m_pAllocator, m_Selectors); |
+ ruleArray.Add(pStyleRule); |
+ } else { |
+ SkipRuleSet(pSyntax); |
+ return FDE_CSSSYNTAXSTATUS_None; |
+ } |
+ break; |
+ case FDE_CSSSYNTAXSTATUS_DeclClose: |
+ if (pStyleRule != NULL && |
+ pStyleRule->GetDeclImp().GetStartPosition() == NULL) { |
+ pStyleRule->~CFDE_CSSStyleRule(); |
+ ruleArray.RemoveLast(1); |
+ } |
+ return FDE_CSSSYNTAXSTATUS_None; |
+ FDE_CSSSWITCHDEFAULTS(); |
+ } |
+ } |
+} |
+FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::LoadFontFaceRule( |
+ IFDE_CSSSyntaxParser* pSyntax, |
+ CFDE_CSSRuleArray& ruleArray) { |
+ CFDE_CSSFontFaceRule* pFontFaceRule = NULL; |
+ const FX_WCHAR* pszValue = NULL; |
+ int32_t iValueLen = 0; |
+ FDE_CSSPROPERTYARGS propertyArgs; |
+ propertyArgs.pStaticStore = m_pAllocator; |
+ propertyArgs.pStringCache = &m_StringCache; |
+ propertyArgs.pProperty = NULL; |
+ for (;;) { |
+ switch (pSyntax->DoSyntaxParse()) { |
+ case FDE_CSSSYNTAXSTATUS_PropertyName: |
+ pszValue = pSyntax->GetCurrentString(iValueLen); |
+ propertyArgs.pProperty = FDE_GetCSSPropertyByName(pszValue, iValueLen); |
+ break; |
+ case FDE_CSSSYNTAXSTATUS_PropertyValue: |
+ if (propertyArgs.pProperty != NULL) { |
+ pszValue = pSyntax->GetCurrentString(iValueLen); |
+ if (iValueLen > 0) { |
+ pFontFaceRule->GetDeclImp().AddProperty(&propertyArgs, pszValue, |
+ iValueLen); |
+ } |
+ } |
+ break; |
+ case FDE_CSSSYNTAXSTATUS_DeclOpen: |
+ if (pFontFaceRule == NULL) { |
+ pFontFaceRule = FDE_NewWith(m_pAllocator) CFDE_CSSFontFaceRule; |
+ ruleArray.Add(pFontFaceRule); |
+ } |
+ break; |
+ case FDE_CSSSYNTAXSTATUS_DeclClose: |
+ return FDE_CSSSYNTAXSTATUS_None; |
+ FDE_CSSSWITCHDEFAULTS(); |
+ } |
+ } |
+ return FDE_CSSSYNTAXSTATUS_None; |
+} |
+FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::LoadImportRule( |
+ IFDE_CSSSyntaxParser* pSyntax) { |
+ for (;;) { |
+ switch (pSyntax->DoSyntaxParse()) { |
+ case FDE_CSSSYNTAXSTATUS_ImportClose: |
+ return FDE_CSSSYNTAXSTATUS_None; |
+ case FDE_CSSSYNTAXSTATUS_URI: |
+ break; |
+ FDE_CSSSWITCHDEFAULTS(); |
+ } |
+ } |
+} |
+FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::LoadPageRule( |
+ IFDE_CSSSyntaxParser* pSyntax) { |
+ return SkipRuleSet(pSyntax); |
+} |
+FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::SkipRuleSet( |
+ IFDE_CSSSyntaxParser* pSyntax) { |
+ for (;;) { |
+ switch (pSyntax->DoSyntaxParse()) { |
+ case FDE_CSSSYNTAXSTATUS_Selector: |
+ case FDE_CSSSYNTAXSTATUS_DeclOpen: |
+ case FDE_CSSSYNTAXSTATUS_PropertyName: |
+ case FDE_CSSSYNTAXSTATUS_PropertyValue: |
+ break; |
+ case FDE_CSSSYNTAXSTATUS_DeclClose: |
+ return FDE_CSSSYNTAXSTATUS_None; |
+ FDE_CSSSWITCHDEFAULTS(); |
+ } |
+ } |
+ return FDE_CSSSYNTAXSTATUS_None; |
+} |
+void CFDE_CSSStyleRule::SetSelector(IFX_MEMAllocator* pStaticStore, |
+ const CFDE_CSSSelectorArray& list) { |
+ FXSYS_assert(m_ppSelector == NULL); |
+ m_iSelectors = list.GetSize(); |
+ m_ppSelector = (IFDE_CSSSelector**)pStaticStore->Alloc( |
+ m_iSelectors * sizeof(IFDE_CSSSelector*)); |
+ for (int32_t i = 0; i < m_iSelectors; ++i) { |
+ m_ppSelector[i] = list.GetAt(i); |
+ } |
+} |
+CFDE_CSSMediaRule::~CFDE_CSSMediaRule() { |
+ for (int32_t i = m_RuleArray.GetSize() - 1; i >= 0; --i) { |
+ IFDE_CSSRule* pRule = m_RuleArray.GetAt(i); |
+ switch (pRule->GetType()) { |
+ case FDE_CSSRULETYPE_Style: |
+ ((CFDE_CSSStyleRule*)pRule)->~CFDE_CSSStyleRule(); |
+ break; |
+ default: |
+ FXSYS_assert(FALSE); |
+ break; |
+ } |
+ } |
+} |
+inline FX_BOOL FDE_IsCSSChar(FX_WCHAR wch) { |
+ return (wch >= 'a' && wch <= 'z') || (wch >= 'A' && wch <= 'Z'); |
+} |
+int32_t FDE_GetCSSPersudoLen(const FX_WCHAR* psz, const FX_WCHAR* pEnd) { |
+ FXSYS_assert(*psz == ':'); |
+ const FX_WCHAR* pStart = psz; |
+ while (psz < pEnd) { |
+ FX_WCHAR wch = *psz; |
+ if (FDE_IsCSSChar(wch) || wch == ':') { |
+ ++psz; |
+ } else { |
+ break; |
+ } |
+ } |
+ return psz - pStart; |
+} |
+int32_t FDE_GetCSSNameLen(const FX_WCHAR* psz, const FX_WCHAR* pEnd) { |
+ const FX_WCHAR* pStart = psz; |
+ while (psz < pEnd) { |
+ FX_WCHAR wch = *psz; |
+ if (FDE_IsCSSChar(wch) || (wch >= '0' && wch <= '9') || wch == '_' || |
+ wch == '-') { |
+ ++psz; |
+ } else { |
+ break; |
+ } |
+ } |
+ return psz - pStart; |
+} |
+IFDE_CSSSelector* CFDE_CSSSelector::FromString(IFX_MEMAllocator* pStaticStore, |
+ const FX_WCHAR* psz, |
+ int32_t iLen) { |
+ FXSYS_assert(pStaticStore != NULL && psz != NULL && iLen > 0); |
+ const FX_WCHAR* pStart = psz; |
+ const FX_WCHAR* pEnd = psz + iLen; |
+ for (; psz < pEnd; ++psz) { |
+ switch (*psz) { |
+ case '>': |
+ case '[': |
+ case '+': |
+ return NULL; |
+ } |
+ } |
+ CFDE_CSSSelector *pFirst = NULL, *pLast = NULL; |
+ CFDE_CSSSelector *pPersudoFirst = NULL, *pPersudoLast = NULL; |
+ for (psz = pStart; psz < pEnd;) { |
+ FX_WCHAR wch = *psz; |
+ if (wch == '.' || wch == '#') { |
+ if (psz == pStart || psz[-1] == ' ') { |
+ CFDE_CSSSelector* p = FDE_NewWith(pStaticStore) |
+ CFDE_CSSSelector(FDE_CSSSELECTORTYPE_Element, L"*", 1, TRUE); |
+ if (p == NULL) { |
+ return NULL; |
+ } |
+ if (pFirst != NULL) { |
+ pFirst->SetType(FDE_CSSSELECTORTYPE_Descendant); |
+ p->SetNext(pFirst); |
+ } |
+ pFirst = pLast = p; |
+ } |
+ FXSYS_assert(pLast != NULL); |
+ int32_t iNameLen = FDE_GetCSSNameLen(++psz, pEnd); |
+ if (iNameLen == 0) { |
+ return NULL; |
+ } |
+ FDE_CSSSELECTORTYPE eType = |
+ wch == '.' ? FDE_CSSSELECTORTYPE_Class : FDE_CSSSELECTORTYPE_ID; |
+ CFDE_CSSSelector* p = FDE_NewWith(pStaticStore) |
+ CFDE_CSSSelector(eType, psz, iNameLen, FALSE); |
+ if (p == NULL) { |
+ return NULL; |
+ } |
+ p->SetNext(pLast->GetNextSelector()); |
+ pLast->SetNext(p); |
+ pLast = p; |
+ psz += iNameLen; |
+ } else if (FDE_IsCSSChar(wch) || wch == '*') { |
+ int32_t iNameLen = wch == '*' ? 1 : FDE_GetCSSNameLen(psz, pEnd); |
+ if (iNameLen == 0) { |
+ return NULL; |
+ } |
+ CFDE_CSSSelector* p = FDE_NewWith(pStaticStore) |
+ CFDE_CSSSelector(FDE_CSSSELECTORTYPE_Element, psz, iNameLen, TRUE); |
+ if (p == NULL) { |
+ return NULL; |
+ } |
+ if (pFirst == NULL) { |
+ pFirst = pLast = p; |
+ } else { |
+ pFirst->SetType(FDE_CSSSELECTORTYPE_Descendant); |
+ p->SetNext(pFirst); |
+ pFirst = pLast = p; |
+ } |
+ psz += iNameLen; |
+ } else if (wch == ':') { |
+ int32_t iNameLen = FDE_GetCSSPersudoLen(psz, pEnd); |
+ if (iNameLen == 0) { |
+ return NULL; |
+ } |
+ CFDE_CSSSelector* p = FDE_NewWith(pStaticStore) |
+ CFDE_CSSSelector(FDE_CSSSELECTORTYPE_Persudo, psz, iNameLen, TRUE); |
+ if (p == NULL) { |
+ return NULL; |
+ } |
+ if (pPersudoFirst == NULL) { |
+ pPersudoFirst = pPersudoLast = p; |
+ } else { |
+ pPersudoLast->SetNext(p); |
+ pPersudoLast = p; |
+ } |
+ psz += iNameLen; |
+ } else if (wch == ' ') { |
+ psz++; |
+ } else { |
+ return NULL; |
+ } |
+ } |
+ if (pPersudoFirst == NULL) { |
+ return pFirst; |
+ } else { |
+ pPersudoLast->SetNext(pFirst); |
+ return pPersudoFirst; |
+ } |
+} |