| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| 6 | |
| 7 #include "xfa/src/fde/css/fde_cssstylesheet.h" | |
| 8 | |
| 9 #include "xfa/src/fde/css/fde_cssdatatable.h" | |
| 10 #include "xfa/src/fde/css/fde_csssyntax.h" | |
| 11 #include "xfa/src/fgas/crt/fgas_codepage.h" | |
| 12 | |
| 13 IFDE_CSSStyleSheet* IFDE_CSSStyleSheet::LoadHTMLStandardStyleSheet() { | |
| 14 static const FX_WCHAR* s_pStyle = | |
| 15 L"html,address,blockquote,body,dd,div,dl,dt,fieldset,form,frame,frameset," | |
| 16 L"h1,h2,h3,h4,h5,h6,noframes,ol,p,ul,center,dir,hr,menu,pre{display:" | |
| 17 L"block}" | |
| 18 L"li{display:list-item}head{display:none}table{display:table}tr{display:" | |
| 19 L"table-row}thead{display:table-header-group}tbody{display:table-row-" | |
| 20 L"group}tfoot{display:table-footer-group}" | |
| 21 L"col{display:table-column}colgroup{display:table-column-group}td,th{" | |
| 22 L"display:table-cell}caption{display:table-caption}th{font-weight:bolder;" | |
| 23 L"text-align:center}caption{text-align:center}" | |
| 24 L"body{margin:0}h1{font-size:2em;margin:.67em " | |
| 25 L"0}h2{font-size:1.5em;margin:.75em 0}h3{font-size:1.17em;margin:.83em " | |
| 26 L"0}h4,p,blockquote,ul,fieldset,form,ol,dl,dir,menu{margin:1.12em 0}" | |
| 27 L"h5{font-size:.83em;margin:1.5em 0}h6{font-size:.75em;margin:1.67em " | |
| 28 L"0}h1,h2,h3,h4,h5,h6,b,strong{font-weight:bolder}blockquote{margin-left:" | |
| 29 L"40px;margin-right:40px}i,cite,em,var,address{font-style:italic}" | |
| 30 L"pre,tt,code,kbd,samp{font-family:monospace}pre{white-space:pre}button," | |
| 31 L"textarea,input,select{display:inline-block}big{font-size:1.17em}small," | |
| 32 L"sub,sup{font-size:.83em}sub{vertical-align:sub}" | |
| 33 L"sup{vertical-align:super}table{border-spacing:2px}thead,tbody,tfoot{" | |
| 34 L"vertical-align:middle}td,th,tr{vertical-align:inherit}s,strike,del{" | |
| 35 L"text-decoration:line-through}hr{border:1px inset silver}" | |
| 36 L"ol,ul,dir,menu,dd{margin-left:40px}ol{list-style-type:decimal}ol ul,ul " | |
| 37 L"ol,ul ul,ol " | |
| 38 L"ol{margin-top:0;margin-bottom:0}u,ins{text-decoration:underline}center{" | |
| 39 L"text-align:center}" | |
| 40 L"ruby{display:ruby}rt{display:ruby-text;font-size:.5em}rb{display:ruby-" | |
| 41 L"base}rbc{display:ruby-base-group}rtc{display:ruby-text-group}" | |
| 42 L"q:before{content:open-quote}q:after{content:close-quote}" | |
| 43 L"rp{display:none}"; | |
| 44 return IFDE_CSSStyleSheet::LoadFromBuffer( | |
| 45 CFX_WideString(), s_pStyle, FXSYS_wcslen(s_pStyle), FX_CODEPAGE_UTF8); | |
| 46 } | |
| 47 | |
| 48 IFDE_CSSStyleSheet* IFDE_CSSStyleSheet::LoadFromStream( | |
| 49 const CFX_WideString& szUrl, | |
| 50 IFX_Stream* pStream, | |
| 51 FX_WORD wCodePage, | |
| 52 FX_DWORD dwMediaList) { | |
| 53 CFDE_CSSStyleSheet* pStyleSheet = new CFDE_CSSStyleSheet(dwMediaList); | |
| 54 if (!pStyleSheet->LoadFromStream(szUrl, pStream, wCodePage)) { | |
| 55 pStyleSheet->Release(); | |
| 56 pStyleSheet = NULL; | |
| 57 } | |
| 58 return pStyleSheet; | |
| 59 } | |
| 60 IFDE_CSSStyleSheet* IFDE_CSSStyleSheet::LoadFromBuffer( | |
| 61 const CFX_WideString& szUrl, | |
| 62 const FX_WCHAR* pBuffer, | |
| 63 int32_t iBufSize, | |
| 64 FX_WORD wCodePage, | |
| 65 FX_DWORD dwMediaList) { | |
| 66 CFDE_CSSStyleSheet* pStyleSheet = new CFDE_CSSStyleSheet(dwMediaList); | |
| 67 if (!pStyleSheet->LoadFromBuffer(szUrl, pBuffer, iBufSize, wCodePage)) { | |
| 68 pStyleSheet->Release(); | |
| 69 pStyleSheet = NULL; | |
| 70 } | |
| 71 return pStyleSheet; | |
| 72 } | |
| 73 CFDE_CSSStyleSheet::CFDE_CSSStyleSheet(FX_DWORD dwMediaList) | |
| 74 : m_wCodePage(FX_CODEPAGE_UTF8), | |
| 75 m_wRefCount(1), | |
| 76 m_dwMediaList(dwMediaList), | |
| 77 m_pAllocator(NULL) { | |
| 78 FXSYS_assert(m_dwMediaList > 0); | |
| 79 } | |
| 80 CFDE_CSSStyleSheet::~CFDE_CSSStyleSheet() { | |
| 81 Reset(); | |
| 82 } | |
| 83 void CFDE_CSSStyleSheet::Reset() { | |
| 84 for (int32_t i = m_RuleArray.GetSize() - 1; i >= 0; --i) { | |
| 85 IFDE_CSSRule* pRule = m_RuleArray.GetAt(i); | |
| 86 switch (pRule->GetType()) { | |
| 87 case FDE_CSSRULETYPE_Style: | |
| 88 ((CFDE_CSSStyleRule*)pRule)->~CFDE_CSSStyleRule(); | |
| 89 break; | |
| 90 case FDE_CSSRULETYPE_Media: | |
| 91 ((CFDE_CSSMediaRule*)pRule)->~CFDE_CSSMediaRule(); | |
| 92 break; | |
| 93 case FDE_CSSRULETYPE_FontFace: | |
| 94 ((CFDE_CSSFontFaceRule*)pRule)->~CFDE_CSSFontFaceRule(); | |
| 95 break; | |
| 96 default: | |
| 97 FXSYS_assert(FALSE); | |
| 98 break; | |
| 99 } | |
| 100 } | |
| 101 m_RuleArray.RemoveAll(); | |
| 102 m_Selectors.RemoveAll(); | |
| 103 m_StringCache.RemoveAll(); | |
| 104 if (m_pAllocator) { | |
| 105 m_pAllocator->Release(); | |
| 106 m_pAllocator = NULL; | |
| 107 } | |
| 108 } | |
| 109 FX_DWORD CFDE_CSSStyleSheet::AddRef() { | |
| 110 return ++m_wRefCount; | |
| 111 } | |
| 112 FX_DWORD CFDE_CSSStyleSheet::Release() { | |
| 113 FX_DWORD dwRefCount = --m_wRefCount; | |
| 114 if (dwRefCount == 0) { | |
| 115 delete this; | |
| 116 } | |
| 117 return dwRefCount; | |
| 118 } | |
| 119 int32_t CFDE_CSSStyleSheet::CountRules() const { | |
| 120 return m_RuleArray.GetSize(); | |
| 121 } | |
| 122 IFDE_CSSRule* CFDE_CSSStyleSheet::GetRule(int32_t index) { | |
| 123 return m_RuleArray.GetAt(index); | |
| 124 } | |
| 125 FX_BOOL CFDE_CSSStyleSheet::LoadFromStream(const CFX_WideString& szUrl, | |
| 126 IFX_Stream* pStream, | |
| 127 FX_WORD wCodePage) { | |
| 128 FXSYS_assert(pStream != NULL); | |
| 129 IFDE_CSSSyntaxParser* pSyntax = IFDE_CSSSyntaxParser::Create(); | |
| 130 if (pSyntax == NULL) { | |
| 131 return FALSE; | |
| 132 } | |
| 133 if (pStream->GetCodePage() != wCodePage) { | |
| 134 pStream->SetCodePage(wCodePage); | |
| 135 } | |
| 136 FX_BOOL bRet = pSyntax->Init(pStream, 4096) && LoadFromSyntax(pSyntax); | |
| 137 pSyntax->Release(); | |
| 138 m_wCodePage = wCodePage; | |
| 139 m_szUrl = szUrl; | |
| 140 return bRet; | |
| 141 } | |
| 142 FX_BOOL CFDE_CSSStyleSheet::LoadFromBuffer(const CFX_WideString& szUrl, | |
| 143 const FX_WCHAR* pBuffer, | |
| 144 int32_t iBufSize, | |
| 145 FX_WORD wCodePage) { | |
| 146 FXSYS_assert(pBuffer != NULL && iBufSize > 0); | |
| 147 IFDE_CSSSyntaxParser* pSyntax = IFDE_CSSSyntaxParser::Create(); | |
| 148 if (pSyntax == NULL) { | |
| 149 return FALSE; | |
| 150 } | |
| 151 FX_BOOL bRet = pSyntax->Init(pBuffer, iBufSize) && LoadFromSyntax(pSyntax); | |
| 152 pSyntax->Release(); | |
| 153 m_wCodePage = wCodePage; | |
| 154 m_szUrl = szUrl; | |
| 155 return bRet; | |
| 156 } | |
| 157 FX_BOOL CFDE_CSSStyleSheet::LoadFromSyntax(IFDE_CSSSyntaxParser* pSyntax) { | |
| 158 Reset(); | |
| 159 m_pAllocator = FX_CreateAllocator(FX_ALLOCTYPE_Static, 1024, 0); | |
| 160 if (m_pAllocator == NULL) { | |
| 161 return FALSE; | |
| 162 } | |
| 163 FDE_CSSSYNTAXSTATUS eStatus; | |
| 164 do { | |
| 165 switch (eStatus = pSyntax->DoSyntaxParse()) { | |
| 166 case FDE_CSSSYNTAXSTATUS_StyleRule: | |
| 167 eStatus = LoadStyleRule(pSyntax, m_RuleArray); | |
| 168 break; | |
| 169 case FDE_CSSSYNTAXSTATUS_MediaRule: | |
| 170 eStatus = LoadMediaRule(pSyntax); | |
| 171 break; | |
| 172 case FDE_CSSSYNTAXSTATUS_FontFaceRule: | |
| 173 eStatus = LoadFontFaceRule(pSyntax, m_RuleArray); | |
| 174 break; | |
| 175 case FDE_CSSSYNTAXSTATUS_ImportRule: | |
| 176 eStatus = LoadImportRule(pSyntax); | |
| 177 break; | |
| 178 case FDE_CSSSYNTAXSTATUS_PageRule: | |
| 179 eStatus = LoadPageRule(pSyntax); | |
| 180 break; | |
| 181 default: | |
| 182 break; | |
| 183 } | |
| 184 } while (eStatus >= FDE_CSSSYNTAXSTATUS_None); | |
| 185 m_Selectors.RemoveAll(); | |
| 186 m_StringCache.RemoveAll(); | |
| 187 return eStatus != FDE_CSSSYNTAXSTATUS_Error; | |
| 188 } | |
| 189 FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::LoadMediaRule( | |
| 190 IFDE_CSSSyntaxParser* pSyntax) { | |
| 191 FX_DWORD dwMediaList = 0; | |
| 192 CFDE_CSSMediaRule* pMediaRule = NULL; | |
| 193 for (;;) { | |
| 194 switch (pSyntax->DoSyntaxParse()) { | |
| 195 case FDE_CSSSYNTAXSTATUS_MediaType: { | |
| 196 int32_t iLen; | |
| 197 const FX_WCHAR* psz = pSyntax->GetCurrentString(iLen); | |
| 198 FDE_LPCCSSMEDIATYPETABLE pMediaType = | |
| 199 FDE_GetCSSMediaTypeByName(psz, iLen); | |
| 200 if (pMediaType != NULL) { | |
| 201 dwMediaList |= pMediaType->wValue; | |
| 202 } | |
| 203 } break; | |
| 204 case FDE_CSSSYNTAXSTATUS_StyleRule: | |
| 205 if (pMediaRule == NULL) { | |
| 206 SkipRuleSet(pSyntax); | |
| 207 } else { | |
| 208 FDE_CSSSYNTAXSTATUS eStatus = | |
| 209 LoadStyleRule(pSyntax, pMediaRule->GetArray()); | |
| 210 if (eStatus < FDE_CSSSYNTAXSTATUS_None) { | |
| 211 return eStatus; | |
| 212 } | |
| 213 } | |
| 214 break; | |
| 215 case FDE_CSSSYNTAXSTATUS_DeclOpen: | |
| 216 if ((dwMediaList & m_dwMediaList) > 0 && pMediaRule == NULL) { | |
| 217 pMediaRule = | |
| 218 FXTARGET_NewWith(m_pAllocator) CFDE_CSSMediaRule(dwMediaList); | |
| 219 m_RuleArray.Add(pMediaRule); | |
| 220 } | |
| 221 break; | |
| 222 case FDE_CSSSYNTAXSTATUS_DeclClose: | |
| 223 return FDE_CSSSYNTAXSTATUS_None; | |
| 224 FDE_CSSSWITCHDEFAULTS(); | |
| 225 } | |
| 226 } | |
| 227 } | |
| 228 FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::LoadStyleRule( | |
| 229 IFDE_CSSSyntaxParser* pSyntax, | |
| 230 CFDE_CSSRuleArray& ruleArray) { | |
| 231 m_Selectors.RemoveAt(0, m_Selectors.GetSize()); | |
| 232 CFDE_CSSStyleRule* pStyleRule = NULL; | |
| 233 const FX_WCHAR* pszValue = NULL; | |
| 234 int32_t iValueLen = 0; | |
| 235 FDE_CSSPROPERTYARGS propertyArgs; | |
| 236 propertyArgs.pStaticStore = m_pAllocator; | |
| 237 propertyArgs.pStringCache = &m_StringCache; | |
| 238 propertyArgs.pProperty = NULL; | |
| 239 CFX_WideString wsName; | |
| 240 for (;;) { | |
| 241 switch (pSyntax->DoSyntaxParse()) { | |
| 242 case FDE_CSSSYNTAXSTATUS_Selector: { | |
| 243 pszValue = pSyntax->GetCurrentString(iValueLen); | |
| 244 IFDE_CSSSelector* pSelector = | |
| 245 CFDE_CSSSelector::FromString(m_pAllocator, pszValue, iValueLen); | |
| 246 if (pSelector != NULL) { | |
| 247 m_Selectors.Add(pSelector); | |
| 248 } | |
| 249 } break; | |
| 250 case FDE_CSSSYNTAXSTATUS_PropertyName: | |
| 251 pszValue = pSyntax->GetCurrentString(iValueLen); | |
| 252 propertyArgs.pProperty = FDE_GetCSSPropertyByName(pszValue, iValueLen); | |
| 253 if (propertyArgs.pProperty == NULL) { | |
| 254 wsName = CFX_WideStringC(pszValue, iValueLen); | |
| 255 } | |
| 256 break; | |
| 257 case FDE_CSSSYNTAXSTATUS_PropertyValue: | |
| 258 if (propertyArgs.pProperty != NULL) { | |
| 259 pszValue = pSyntax->GetCurrentString(iValueLen); | |
| 260 if (iValueLen > 0) { | |
| 261 pStyleRule->GetDeclImp().AddProperty(&propertyArgs, pszValue, | |
| 262 iValueLen); | |
| 263 } | |
| 264 } else if (iValueLen > 0) { | |
| 265 pszValue = pSyntax->GetCurrentString(iValueLen); | |
| 266 if (iValueLen > 0) { | |
| 267 pStyleRule->GetDeclImp().AddProperty( | |
| 268 &propertyArgs, wsName, wsName.GetLength(), pszValue, iValueLen); | |
| 269 } | |
| 270 } | |
| 271 break; | |
| 272 case FDE_CSSSYNTAXSTATUS_DeclOpen: | |
| 273 if (pStyleRule == NULL && m_Selectors.GetSize() > 0) { | |
| 274 pStyleRule = FXTARGET_NewWith(m_pAllocator) CFDE_CSSStyleRule; | |
| 275 pStyleRule->SetSelector(m_pAllocator, m_Selectors); | |
| 276 ruleArray.Add(pStyleRule); | |
| 277 } else { | |
| 278 SkipRuleSet(pSyntax); | |
| 279 return FDE_CSSSYNTAXSTATUS_None; | |
| 280 } | |
| 281 break; | |
| 282 case FDE_CSSSYNTAXSTATUS_DeclClose: | |
| 283 if (pStyleRule != NULL && | |
| 284 pStyleRule->GetDeclImp().GetStartPosition() == NULL) { | |
| 285 pStyleRule->~CFDE_CSSStyleRule(); | |
| 286 ruleArray.RemoveLast(1); | |
| 287 } | |
| 288 return FDE_CSSSYNTAXSTATUS_None; | |
| 289 FDE_CSSSWITCHDEFAULTS(); | |
| 290 } | |
| 291 } | |
| 292 } | |
| 293 FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::LoadFontFaceRule( | |
| 294 IFDE_CSSSyntaxParser* pSyntax, | |
| 295 CFDE_CSSRuleArray& ruleArray) { | |
| 296 CFDE_CSSFontFaceRule* pFontFaceRule = NULL; | |
| 297 const FX_WCHAR* pszValue = NULL; | |
| 298 int32_t iValueLen = 0; | |
| 299 FDE_CSSPROPERTYARGS propertyArgs; | |
| 300 propertyArgs.pStaticStore = m_pAllocator; | |
| 301 propertyArgs.pStringCache = &m_StringCache; | |
| 302 propertyArgs.pProperty = NULL; | |
| 303 for (;;) { | |
| 304 switch (pSyntax->DoSyntaxParse()) { | |
| 305 case FDE_CSSSYNTAXSTATUS_PropertyName: | |
| 306 pszValue = pSyntax->GetCurrentString(iValueLen); | |
| 307 propertyArgs.pProperty = FDE_GetCSSPropertyByName(pszValue, iValueLen); | |
| 308 break; | |
| 309 case FDE_CSSSYNTAXSTATUS_PropertyValue: | |
| 310 if (propertyArgs.pProperty != NULL) { | |
| 311 pszValue = pSyntax->GetCurrentString(iValueLen); | |
| 312 if (iValueLen > 0) { | |
| 313 pFontFaceRule->GetDeclImp().AddProperty(&propertyArgs, pszValue, | |
| 314 iValueLen); | |
| 315 } | |
| 316 } | |
| 317 break; | |
| 318 case FDE_CSSSYNTAXSTATUS_DeclOpen: | |
| 319 if (pFontFaceRule == NULL) { | |
| 320 pFontFaceRule = FXTARGET_NewWith(m_pAllocator) CFDE_CSSFontFaceRule; | |
| 321 ruleArray.Add(pFontFaceRule); | |
| 322 } | |
| 323 break; | |
| 324 case FDE_CSSSYNTAXSTATUS_DeclClose: | |
| 325 return FDE_CSSSYNTAXSTATUS_None; | |
| 326 FDE_CSSSWITCHDEFAULTS(); | |
| 327 } | |
| 328 } | |
| 329 return FDE_CSSSYNTAXSTATUS_None; | |
| 330 } | |
| 331 FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::LoadImportRule( | |
| 332 IFDE_CSSSyntaxParser* pSyntax) { | |
| 333 for (;;) { | |
| 334 switch (pSyntax->DoSyntaxParse()) { | |
| 335 case FDE_CSSSYNTAXSTATUS_ImportClose: | |
| 336 return FDE_CSSSYNTAXSTATUS_None; | |
| 337 case FDE_CSSSYNTAXSTATUS_URI: | |
| 338 break; | |
| 339 FDE_CSSSWITCHDEFAULTS(); | |
| 340 } | |
| 341 } | |
| 342 } | |
| 343 FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::LoadPageRule( | |
| 344 IFDE_CSSSyntaxParser* pSyntax) { | |
| 345 return SkipRuleSet(pSyntax); | |
| 346 } | |
| 347 FDE_CSSSYNTAXSTATUS CFDE_CSSStyleSheet::SkipRuleSet( | |
| 348 IFDE_CSSSyntaxParser* pSyntax) { | |
| 349 for (;;) { | |
| 350 switch (pSyntax->DoSyntaxParse()) { | |
| 351 case FDE_CSSSYNTAXSTATUS_Selector: | |
| 352 case FDE_CSSSYNTAXSTATUS_DeclOpen: | |
| 353 case FDE_CSSSYNTAXSTATUS_PropertyName: | |
| 354 case FDE_CSSSYNTAXSTATUS_PropertyValue: | |
| 355 break; | |
| 356 case FDE_CSSSYNTAXSTATUS_DeclClose: | |
| 357 return FDE_CSSSYNTAXSTATUS_None; | |
| 358 FDE_CSSSWITCHDEFAULTS(); | |
| 359 } | |
| 360 } | |
| 361 return FDE_CSSSYNTAXSTATUS_None; | |
| 362 } | |
| 363 void CFDE_CSSStyleRule::SetSelector(IFX_MEMAllocator* pStaticStore, | |
| 364 const CFDE_CSSSelectorArray& list) { | |
| 365 FXSYS_assert(m_ppSelector == NULL); | |
| 366 m_iSelectors = list.GetSize(); | |
| 367 m_ppSelector = (IFDE_CSSSelector**)pStaticStore->Alloc( | |
| 368 m_iSelectors * sizeof(IFDE_CSSSelector*)); | |
| 369 for (int32_t i = 0; i < m_iSelectors; ++i) { | |
| 370 m_ppSelector[i] = list.GetAt(i); | |
| 371 } | |
| 372 } | |
| 373 CFDE_CSSMediaRule::~CFDE_CSSMediaRule() { | |
| 374 for (int32_t i = m_RuleArray.GetSize() - 1; i >= 0; --i) { | |
| 375 IFDE_CSSRule* pRule = m_RuleArray.GetAt(i); | |
| 376 switch (pRule->GetType()) { | |
| 377 case FDE_CSSRULETYPE_Style: | |
| 378 ((CFDE_CSSStyleRule*)pRule)->~CFDE_CSSStyleRule(); | |
| 379 break; | |
| 380 default: | |
| 381 FXSYS_assert(FALSE); | |
| 382 break; | |
| 383 } | |
| 384 } | |
| 385 } | |
| 386 inline FX_BOOL FDE_IsCSSChar(FX_WCHAR wch) { | |
| 387 return (wch >= 'a' && wch <= 'z') || (wch >= 'A' && wch <= 'Z'); | |
| 388 } | |
| 389 int32_t FDE_GetCSSPersudoLen(const FX_WCHAR* psz, const FX_WCHAR* pEnd) { | |
| 390 FXSYS_assert(*psz == ':'); | |
| 391 const FX_WCHAR* pStart = psz; | |
| 392 while (psz < pEnd) { | |
| 393 FX_WCHAR wch = *psz; | |
| 394 if (FDE_IsCSSChar(wch) || wch == ':') { | |
| 395 ++psz; | |
| 396 } else { | |
| 397 break; | |
| 398 } | |
| 399 } | |
| 400 return psz - pStart; | |
| 401 } | |
| 402 int32_t FDE_GetCSSNameLen(const FX_WCHAR* psz, const FX_WCHAR* pEnd) { | |
| 403 const FX_WCHAR* pStart = psz; | |
| 404 while (psz < pEnd) { | |
| 405 FX_WCHAR wch = *psz; | |
| 406 if (FDE_IsCSSChar(wch) || (wch >= '0' && wch <= '9') || wch == '_' || | |
| 407 wch == '-') { | |
| 408 ++psz; | |
| 409 } else { | |
| 410 break; | |
| 411 } | |
| 412 } | |
| 413 return psz - pStart; | |
| 414 } | |
| 415 IFDE_CSSSelector* CFDE_CSSSelector::FromString(IFX_MEMAllocator* pStaticStore, | |
| 416 const FX_WCHAR* psz, | |
| 417 int32_t iLen) { | |
| 418 FXSYS_assert(pStaticStore != NULL && psz != NULL && iLen > 0); | |
| 419 const FX_WCHAR* pStart = psz; | |
| 420 const FX_WCHAR* pEnd = psz + iLen; | |
| 421 for (; psz < pEnd; ++psz) { | |
| 422 switch (*psz) { | |
| 423 case '>': | |
| 424 case '[': | |
| 425 case '+': | |
| 426 return NULL; | |
| 427 } | |
| 428 } | |
| 429 CFDE_CSSSelector *pFirst = NULL, *pLast = NULL; | |
| 430 CFDE_CSSSelector *pPersudoFirst = NULL, *pPersudoLast = NULL; | |
| 431 for (psz = pStart; psz < pEnd;) { | |
| 432 FX_WCHAR wch = *psz; | |
| 433 if (wch == '.' || wch == '#') { | |
| 434 if (psz == pStart || psz[-1] == ' ') { | |
| 435 CFDE_CSSSelector* p = FXTARGET_NewWith(pStaticStore) | |
| 436 CFDE_CSSSelector(FDE_CSSSELECTORTYPE_Element, L"*", 1, TRUE); | |
| 437 if (p == NULL) { | |
| 438 return NULL; | |
| 439 } | |
| 440 if (pFirst != NULL) { | |
| 441 pFirst->SetType(FDE_CSSSELECTORTYPE_Descendant); | |
| 442 p->SetNext(pFirst); | |
| 443 } | |
| 444 pFirst = pLast = p; | |
| 445 } | |
| 446 FXSYS_assert(pLast != NULL); | |
| 447 int32_t iNameLen = FDE_GetCSSNameLen(++psz, pEnd); | |
| 448 if (iNameLen == 0) { | |
| 449 return NULL; | |
| 450 } | |
| 451 FDE_CSSSELECTORTYPE eType = | |
| 452 wch == '.' ? FDE_CSSSELECTORTYPE_Class : FDE_CSSSELECTORTYPE_ID; | |
| 453 CFDE_CSSSelector* p = FXTARGET_NewWith(pStaticStore) | |
| 454 CFDE_CSSSelector(eType, psz, iNameLen, FALSE); | |
| 455 if (p == NULL) { | |
| 456 return NULL; | |
| 457 } | |
| 458 p->SetNext(pLast->GetNextSelector()); | |
| 459 pLast->SetNext(p); | |
| 460 pLast = p; | |
| 461 psz += iNameLen; | |
| 462 } else if (FDE_IsCSSChar(wch) || wch == '*') { | |
| 463 int32_t iNameLen = wch == '*' ? 1 : FDE_GetCSSNameLen(psz, pEnd); | |
| 464 if (iNameLen == 0) { | |
| 465 return NULL; | |
| 466 } | |
| 467 CFDE_CSSSelector* p = FXTARGET_NewWith(pStaticStore) | |
| 468 CFDE_CSSSelector(FDE_CSSSELECTORTYPE_Element, psz, iNameLen, TRUE); | |
| 469 if (p == NULL) { | |
| 470 return NULL; | |
| 471 } | |
| 472 if (pFirst == NULL) { | |
| 473 pFirst = pLast = p; | |
| 474 } else { | |
| 475 pFirst->SetType(FDE_CSSSELECTORTYPE_Descendant); | |
| 476 p->SetNext(pFirst); | |
| 477 pFirst = pLast = p; | |
| 478 } | |
| 479 psz += iNameLen; | |
| 480 } else if (wch == ':') { | |
| 481 int32_t iNameLen = FDE_GetCSSPersudoLen(psz, pEnd); | |
| 482 if (iNameLen == 0) { | |
| 483 return NULL; | |
| 484 } | |
| 485 CFDE_CSSSelector* p = FXTARGET_NewWith(pStaticStore) | |
| 486 CFDE_CSSSelector(FDE_CSSSELECTORTYPE_Persudo, psz, iNameLen, TRUE); | |
| 487 if (p == NULL) { | |
| 488 return NULL; | |
| 489 } | |
| 490 if (pPersudoFirst == NULL) { | |
| 491 pPersudoFirst = pPersudoLast = p; | |
| 492 } else { | |
| 493 pPersudoLast->SetNext(p); | |
| 494 pPersudoLast = p; | |
| 495 } | |
| 496 psz += iNameLen; | |
| 497 } else if (wch == ' ') { | |
| 498 psz++; | |
| 499 } else { | |
| 500 return NULL; | |
| 501 } | |
| 502 } | |
| 503 if (pPersudoFirst == NULL) { | |
| 504 return pFirst; | |
| 505 } else { | |
| 506 pPersudoLast->SetNext(pFirst); | |
| 507 return pPersudoFirst; | |
| 508 } | |
| 509 } | |
| OLD | NEW |