blob: a24b4eee6698f0fe93a1b2c737eccc040f74d6e3 [file] [log] [blame]
Dan Sinclair1770c022016-03-14 14:14:16 -04001// 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
Dan Sinclair95bec802017-01-19 10:27:58 -05007#include "xfa/fde/css/cfde_csssyntaxparser.h"
Dan Sinclair1770c022016-03-14 14:14:16 -04008
npm23991522016-11-28 12:49:29 -08009#include <algorithm>
10
Dan Sinclair95bec802017-01-19 10:27:58 -050011#include "xfa/fde/css/cfde_cssdeclaration.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040012#include "xfa/fde/css/fde_cssdatatable.h"
13#include "xfa/fgas/crt/fgas_codepage.h"
14
thestigcfb77cc2016-06-10 12:21:53 -070015namespace {
Dan Sinclair1770c022016-03-14 14:14:16 -040016
Dan Sinclair95bec802017-01-19 10:27:58 -050017bool IsSelectorStart(FX_WCHAR wch) {
Dan Sinclair1770c022016-03-14 14:14:16 -040018 return wch == '.' || wch == '#' || wch == '*' || (wch >= 'a' && wch <= 'z') ||
19 (wch >= 'A' && wch <= 'Z');
20}
21
Dan Sinclair95bec802017-01-19 10:27:58 -050022bool ParseCSSURI(const FX_WCHAR* pszValue, int32_t* iOffset, int32_t* iLength) {
23 ASSERT(pszValue && *iLength > 0);
24 if (*iLength < 6 || pszValue[*iLength - 1] != ')' ||
25 FXSYS_wcsnicmp(L"url(", pszValue, 4)) {
26 return false;
27 }
28 if (CFDE_CSSDeclaration::ParseCSSString(pszValue + 4, *iLength - 5, iOffset,
29 iLength)) {
30 *iOffset += 4;
31 return true;
32 }
33 return false;
34}
35
thestigcfb77cc2016-06-10 12:21:53 -070036} // namespace
Dan Sinclair1770c022016-03-14 14:14:16 -040037
Dan Sinclair1770c022016-03-14 14:14:16 -040038CFDE_CSSSyntaxParser::CFDE_CSSSyntaxParser()
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050039 : m_iTextDatLen(0),
tsepez736f28a2016-03-25 14:19:51 -070040 m_dwCheck((uint32_t)-1),
Dan Sinclairbe591062017-01-18 08:58:25 -050041 m_eMode(FDE_CSSSyntaxMode::RuleSet),
42 m_eStatus(FDE_CSSSyntaxStatus::None) {}
dsinclair34965452016-07-18 13:14:49 -070043
Dan Sinclair1770c022016-03-14 14:14:16 -040044CFDE_CSSSyntaxParser::~CFDE_CSSSyntaxParser() {
45 m_TextData.Reset();
46 m_TextPlane.Reset();
47}
dsinclair34965452016-07-18 13:14:49 -070048
tsepezd19e9122016-11-02 15:43:18 -070049bool CFDE_CSSSyntaxParser::Init(const FX_WCHAR* pBuffer,
50 int32_t iBufferSize,
51 int32_t iTextDatSize,
52 bool bOnlyDeclaration) {
thestigcfb77cc2016-06-10 12:21:53 -070053 ASSERT(pBuffer && iBufferSize > 0 && iTextDatSize > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -040054 Reset(bOnlyDeclaration);
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050055 if (!m_TextData.EstimateSize(iTextDatSize))
tsepezd19e9122016-11-02 15:43:18 -070056 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -040057 return m_TextPlane.AttachBuffer(pBuffer, iBufferSize);
58}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050059
tsepezd19e9122016-11-02 15:43:18 -070060void CFDE_CSSSyntaxParser::Reset(bool bOnlyDeclaration) {
Dan Sinclair1770c022016-03-14 14:14:16 -040061 m_TextPlane.Reset();
62 m_TextData.Reset();
Dan Sinclair1770c022016-03-14 14:14:16 -040063 m_iTextDatLen = 0;
tsepez736f28a2016-03-25 14:19:51 -070064 m_dwCheck = (uint32_t)-1;
Dan Sinclair96f482c2017-01-11 16:31:27 -050065 m_eStatus = FDE_CSSSyntaxStatus::None;
Dan Sinclairbe591062017-01-18 08:58:25 -050066 m_eMode = bOnlyDeclaration ? FDE_CSSSyntaxMode::PropertyName
67 : FDE_CSSSyntaxMode::RuleSet;
Dan Sinclair1770c022016-03-14 14:14:16 -040068}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050069
Dan Sinclair96f482c2017-01-11 16:31:27 -050070FDE_CSSSyntaxStatus CFDE_CSSSyntaxParser::DoSyntaxParse() {
71 while (m_eStatus >= FDE_CSSSyntaxStatus::None) {
Dan Sinclair1770c022016-03-14 14:14:16 -040072 if (m_TextPlane.IsEOF()) {
Dan Sinclairbe591062017-01-18 08:58:25 -050073 if (m_eMode == FDE_CSSSyntaxMode::PropertyValue &&
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050074 m_TextData.GetLength() > 0) {
75 SaveTextData();
76 m_eStatus = FDE_CSSSyntaxStatus::PropertyValue;
Dan Sinclair96f482c2017-01-11 16:31:27 -050077 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -040078 }
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050079 m_eStatus = FDE_CSSSyntaxStatus::EOS;
80 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -040081 }
82 FX_WCHAR wch;
83 while (!m_TextPlane.IsEOF()) {
84 wch = m_TextPlane.GetChar();
85 switch (m_eMode) {
Dan Sinclairbe591062017-01-18 08:58:25 -050086 case FDE_CSSSyntaxMode::RuleSet:
Dan Sinclair1770c022016-03-14 14:14:16 -040087 switch (wch) {
88 case '@':
89 m_TextPlane.MoveNext();
Dan Sinclairbe591062017-01-18 08:58:25 -050090 SwitchMode(FDE_CSSSyntaxMode::AtRule);
Dan Sinclair1770c022016-03-14 14:14:16 -040091 break;
92 case '}':
93 m_TextPlane.MoveNext();
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050094 if (RestoreMode())
Dan Sinclair96f482c2017-01-11 16:31:27 -050095 return FDE_CSSSyntaxStatus::DeclClose;
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050096
97 m_eStatus = FDE_CSSSyntaxStatus::Error;
98 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -040099 case '/':
100 if (m_TextPlane.GetNextChar() == '*') {
Dan Sinclairbe591062017-01-18 08:58:25 -0500101 m_ModeStack.push(m_eMode);
102 SwitchMode(FDE_CSSSyntaxMode::Comment);
Dan Sinclair1770c022016-03-14 14:14:16 -0400103 break;
104 }
105 default:
106 if (wch <= ' ') {
107 m_TextPlane.MoveNext();
Dan Sinclair95bec802017-01-19 10:27:58 -0500108 } else if (IsSelectorStart(wch)) {
Dan Sinclairbe591062017-01-18 08:58:25 -0500109 SwitchMode(FDE_CSSSyntaxMode::Selector);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500110 return FDE_CSSSyntaxStatus::StyleRule;
Dan Sinclair1770c022016-03-14 14:14:16 -0400111 } else {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500112 m_eStatus = FDE_CSSSyntaxStatus::Error;
113 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400114 }
115 break;
116 }
117 break;
Dan Sinclairbe591062017-01-18 08:58:25 -0500118 case FDE_CSSSyntaxMode::Selector:
Dan Sinclair1770c022016-03-14 14:14:16 -0400119 switch (wch) {
120 case ',':
121 m_TextPlane.MoveNext();
Dan Sinclairbe591062017-01-18 08:58:25 -0500122 SwitchMode(FDE_CSSSyntaxMode::Selector);
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500123 if (m_iTextDatLen > 0)
Dan Sinclair96f482c2017-01-11 16:31:27 -0500124 return FDE_CSSSyntaxStatus::Selector;
Dan Sinclair1770c022016-03-14 14:14:16 -0400125 break;
126 case '{':
127 if (m_TextData.GetLength() > 0) {
128 SaveTextData();
Dan Sinclair96f482c2017-01-11 16:31:27 -0500129 return FDE_CSSSyntaxStatus::Selector;
Dan Sinclair1770c022016-03-14 14:14:16 -0400130 }
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500131 m_TextPlane.MoveNext();
Dan Sinclairbe591062017-01-18 08:58:25 -0500132 m_ModeStack.push(FDE_CSSSyntaxMode::RuleSet);
133 SwitchMode(FDE_CSSSyntaxMode::PropertyName);
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500134 return FDE_CSSSyntaxStatus::DeclOpen;
Dan Sinclair1770c022016-03-14 14:14:16 -0400135 case '/':
136 if (m_TextPlane.GetNextChar() == '*') {
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500137 if (SwitchToComment() > 0)
Dan Sinclair96f482c2017-01-11 16:31:27 -0500138 return FDE_CSSSyntaxStatus::Selector;
Dan Sinclair1770c022016-03-14 14:14:16 -0400139 break;
140 }
141 default:
142 AppendChar(wch);
143 break;
144 }
145 break;
Dan Sinclairbe591062017-01-18 08:58:25 -0500146 case FDE_CSSSyntaxMode::PropertyName:
Dan Sinclair1770c022016-03-14 14:14:16 -0400147 switch (wch) {
148 case ':':
149 m_TextPlane.MoveNext();
Dan Sinclairbe591062017-01-18 08:58:25 -0500150 SwitchMode(FDE_CSSSyntaxMode::PropertyValue);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500151 return FDE_CSSSyntaxStatus::PropertyName;
Dan Sinclair1770c022016-03-14 14:14:16 -0400152 case '}':
153 m_TextPlane.MoveNext();
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500154 if (RestoreMode())
Dan Sinclair96f482c2017-01-11 16:31:27 -0500155 return FDE_CSSSyntaxStatus::DeclClose;
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500156
157 m_eStatus = FDE_CSSSyntaxStatus::Error;
158 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400159 case '/':
160 if (m_TextPlane.GetNextChar() == '*') {
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500161 if (SwitchToComment() > 0)
Dan Sinclair96f482c2017-01-11 16:31:27 -0500162 return FDE_CSSSyntaxStatus::PropertyName;
Dan Sinclair1770c022016-03-14 14:14:16 -0400163 break;
164 }
165 default:
166 AppendChar(wch);
167 break;
168 }
169 break;
Dan Sinclairbe591062017-01-18 08:58:25 -0500170 case FDE_CSSSyntaxMode::PropertyValue:
Dan Sinclair1770c022016-03-14 14:14:16 -0400171 switch (wch) {
172 case ';':
173 m_TextPlane.MoveNext();
174 case '}':
Dan Sinclairbe591062017-01-18 08:58:25 -0500175 SwitchMode(FDE_CSSSyntaxMode::PropertyName);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500176 return FDE_CSSSyntaxStatus::PropertyValue;
Dan Sinclair1770c022016-03-14 14:14:16 -0400177 case '/':
178 if (m_TextPlane.GetNextChar() == '*') {
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500179 if (SwitchToComment() > 0)
Dan Sinclair96f482c2017-01-11 16:31:27 -0500180 return FDE_CSSSyntaxStatus::PropertyValue;
Dan Sinclair1770c022016-03-14 14:14:16 -0400181 break;
182 }
183 default:
184 AppendChar(wch);
185 break;
186 }
187 break;
Dan Sinclairbe591062017-01-18 08:58:25 -0500188 case FDE_CSSSyntaxMode::Comment:
Dan Sinclair1770c022016-03-14 14:14:16 -0400189 if (wch == '/' && m_TextData.GetLength() > 0 &&
190 m_TextData.GetAt(m_TextData.GetLength() - 1) == '*') {
191 RestoreMode();
192 } else {
193 m_TextData.AppendChar(wch);
194 }
195 m_TextPlane.MoveNext();
196 break;
Dan Sinclairbe591062017-01-18 08:58:25 -0500197 case FDE_CSSSyntaxMode::MediaType:
Dan Sinclair1770c022016-03-14 14:14:16 -0400198 switch (wch) {
199 case ',':
200 m_TextPlane.MoveNext();
Dan Sinclairbe591062017-01-18 08:58:25 -0500201 SwitchMode(FDE_CSSSyntaxMode::MediaType);
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500202 if (m_iTextDatLen > 0)
Dan Sinclair96f482c2017-01-11 16:31:27 -0500203 return FDE_CSSSyntaxStatus::MediaType;
Dan Sinclair1770c022016-03-14 14:14:16 -0400204 break;
205 case '{': {
Dan Sinclairbe591062017-01-18 08:58:25 -0500206 if (m_ModeStack.empty() ||
207 m_ModeStack.top() != FDE_CSSSyntaxMode::MediaRule) {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500208 m_eStatus = FDE_CSSSyntaxStatus::Error;
209 return m_eStatus;
210 }
thestigcfb77cc2016-06-10 12:21:53 -0700211
Dan Sinclair1770c022016-03-14 14:14:16 -0400212 if (m_TextData.GetLength() > 0) {
213 SaveTextData();
Dan Sinclair96f482c2017-01-11 16:31:27 -0500214 return FDE_CSSSyntaxStatus::MediaType;
Dan Sinclair1770c022016-03-14 14:14:16 -0400215 }
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500216 m_TextPlane.MoveNext();
Dan Sinclairbe591062017-01-18 08:58:25 -0500217
218 // Replace the MediaRule with a RuleSet rule.
219 m_ModeStack.top() = FDE_CSSSyntaxMode::RuleSet;
220
221 SwitchMode(FDE_CSSSyntaxMode::RuleSet);
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500222 return FDE_CSSSyntaxStatus::DeclOpen;
223 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400224 case ';': {
Dan Sinclairbe591062017-01-18 08:58:25 -0500225 if (m_ModeStack.empty() ||
226 m_ModeStack.top() != FDE_CSSSyntaxMode::Import) {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500227 m_eStatus = FDE_CSSSyntaxStatus::Error;
228 return m_eStatus;
229 }
thestigcfb77cc2016-06-10 12:21:53 -0700230
Dan Sinclair1770c022016-03-14 14:14:16 -0400231 if (m_TextData.GetLength() > 0) {
232 SaveTextData();
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500233 if (IsImportEnabled())
Dan Sinclair96f482c2017-01-11 16:31:27 -0500234 return FDE_CSSSyntaxStatus::MediaType;
Dan Sinclair1770c022016-03-14 14:14:16 -0400235 } else {
tsepezd19e9122016-11-02 15:43:18 -0700236 bool bEnabled = IsImportEnabled();
Dan Sinclair1770c022016-03-14 14:14:16 -0400237 m_TextPlane.MoveNext();
Dan Sinclairbe591062017-01-18 08:58:25 -0500238 m_ModeStack.pop();
239 SwitchMode(FDE_CSSSyntaxMode::RuleSet);
Dan Sinclair1770c022016-03-14 14:14:16 -0400240 if (bEnabled) {
241 DisableImport();
Dan Sinclair96f482c2017-01-11 16:31:27 -0500242 return FDE_CSSSyntaxStatus::ImportClose;
Dan Sinclair1770c022016-03-14 14:14:16 -0400243 }
244 }
245 } break;
246 case '/':
247 if (m_TextPlane.GetNextChar() == '*') {
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500248 if (SwitchToComment() > 0)
Dan Sinclair96f482c2017-01-11 16:31:27 -0500249 return FDE_CSSSyntaxStatus::MediaType;
Dan Sinclair1770c022016-03-14 14:14:16 -0400250 break;
251 }
252 default:
253 AppendChar(wch);
254 break;
255 }
256 break;
Dan Sinclairbe591062017-01-18 08:58:25 -0500257 case FDE_CSSSyntaxMode::URI: {
258 if (m_ModeStack.empty() ||
259 m_ModeStack.top() != FDE_CSSSyntaxMode::Import) {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500260 m_eStatus = FDE_CSSSyntaxStatus::Error;
261 return m_eStatus;
262 }
thestigcfb77cc2016-06-10 12:21:53 -0700263
Dan Sinclair1770c022016-03-14 14:14:16 -0400264 if (wch <= ' ' || wch == ';') {
265 int32_t iURIStart, iURILength = m_TextData.GetLength();
Dan Sinclair95bec802017-01-19 10:27:58 -0500266 if (iURILength > 0 &&
267 ParseCSSURI(m_TextData.GetBuffer(), &iURIStart, &iURILength)) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400268 m_TextData.Subtract(iURIStart, iURILength);
Dan Sinclairbe591062017-01-18 08:58:25 -0500269 SwitchMode(FDE_CSSSyntaxMode::MediaType);
npm23991522016-11-28 12:49:29 -0800270 if (IsImportEnabled())
Dan Sinclair96f482c2017-01-11 16:31:27 -0500271 return FDE_CSSSyntaxStatus::URI;
npm23991522016-11-28 12:49:29 -0800272 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400273 }
274 }
275 AppendChar(wch);
276 } break;
Dan Sinclairbe591062017-01-18 08:58:25 -0500277 case FDE_CSSSyntaxMode::AtRule:
Dan Sinclair1770c022016-03-14 14:14:16 -0400278 if (wch > ' ') {
279 AppendChar(wch);
280 } else {
281 int32_t iLen = m_TextData.GetLength();
282 const FX_WCHAR* psz = m_TextData.GetBuffer();
283 if (FXSYS_wcsncmp(L"charset", psz, iLen) == 0) {
Dan Sinclairbe591062017-01-18 08:58:25 -0500284 SwitchMode(FDE_CSSSyntaxMode::Charset);
Dan Sinclair1770c022016-03-14 14:14:16 -0400285 } else if (FXSYS_wcsncmp(L"import", psz, iLen) == 0) {
Dan Sinclairbe591062017-01-18 08:58:25 -0500286 m_ModeStack.push(FDE_CSSSyntaxMode::Import);
287 SwitchMode(FDE_CSSSyntaxMode::URI);
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500288 if (IsImportEnabled())
Dan Sinclair96f482c2017-01-11 16:31:27 -0500289 return FDE_CSSSyntaxStatus::ImportRule;
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500290 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400291 } else if (FXSYS_wcsncmp(L"media", psz, iLen) == 0) {
Dan Sinclairbe591062017-01-18 08:58:25 -0500292 m_ModeStack.push(FDE_CSSSyntaxMode::MediaRule);
293 SwitchMode(FDE_CSSSyntaxMode::MediaType);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500294 return FDE_CSSSyntaxStatus::MediaRule;
Dan Sinclair1770c022016-03-14 14:14:16 -0400295 } else if (FXSYS_wcsncmp(L"font-face", psz, iLen) == 0) {
Dan Sinclairbe591062017-01-18 08:58:25 -0500296 SwitchMode(FDE_CSSSyntaxMode::Selector);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500297 return FDE_CSSSyntaxStatus::FontFaceRule;
Dan Sinclair1770c022016-03-14 14:14:16 -0400298 } else if (FXSYS_wcsncmp(L"page", psz, iLen) == 0) {
Dan Sinclairbe591062017-01-18 08:58:25 -0500299 SwitchMode(FDE_CSSSyntaxMode::Selector);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500300 return FDE_CSSSyntaxStatus::PageRule;
Dan Sinclair1770c022016-03-14 14:14:16 -0400301 } else {
Dan Sinclairbe591062017-01-18 08:58:25 -0500302 SwitchMode(FDE_CSSSyntaxMode::UnknownRule);
Dan Sinclair1770c022016-03-14 14:14:16 -0400303 }
304 }
305 break;
Dan Sinclairbe591062017-01-18 08:58:25 -0500306 case FDE_CSSSyntaxMode::Charset:
Dan Sinclair1770c022016-03-14 14:14:16 -0400307 if (wch == ';') {
308 m_TextPlane.MoveNext();
Dan Sinclairbe591062017-01-18 08:58:25 -0500309 SwitchMode(FDE_CSSSyntaxMode::RuleSet);
Dan Sinclair1770c022016-03-14 14:14:16 -0400310 if (IsCharsetEnabled()) {
311 DisableCharset();
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500312 if (m_iTextDatLen > 0)
Dan Sinclair96f482c2017-01-11 16:31:27 -0500313 return FDE_CSSSyntaxStatus::Charset;
Dan Sinclair1770c022016-03-14 14:14:16 -0400314 }
315 } else {
316 AppendChar(wch);
317 }
318 break;
Dan Sinclairbe591062017-01-18 08:58:25 -0500319 case FDE_CSSSyntaxMode::UnknownRule:
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500320 if (wch == ';')
Dan Sinclairbe591062017-01-18 08:58:25 -0500321 SwitchMode(FDE_CSSSyntaxMode::RuleSet);
Dan Sinclair1770c022016-03-14 14:14:16 -0400322 m_TextPlane.MoveNext();
323 break;
324 default:
tsepezd19e9122016-11-02 15:43:18 -0700325 ASSERT(false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400326 break;
327 }
328 }
329 }
330 return m_eStatus;
331}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500332
tsepezd19e9122016-11-02 15:43:18 -0700333bool CFDE_CSSSyntaxParser::IsImportEnabled() const {
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500334 if ((m_dwCheck & FDE_CSSSYNTAXCHECK_AllowImport) == 0)
tsepezd19e9122016-11-02 15:43:18 -0700335 return false;
Dan Sinclairbe591062017-01-18 08:58:25 -0500336 if (m_ModeStack.size() > 1)
tsepezd19e9122016-11-02 15:43:18 -0700337 return false;
tsepezd19e9122016-11-02 15:43:18 -0700338 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400339}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500340
tsepezd19e9122016-11-02 15:43:18 -0700341bool CFDE_CSSSyntaxParser::AppendChar(FX_WCHAR wch) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400342 m_TextPlane.MoveNext();
343 if (m_TextData.GetLength() > 0 || wch > ' ') {
344 m_TextData.AppendChar(wch);
tsepezd19e9122016-11-02 15:43:18 -0700345 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400346 }
tsepezd19e9122016-11-02 15:43:18 -0700347 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400348}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500349
thestigcfb77cc2016-06-10 12:21:53 -0700350int32_t CFDE_CSSSyntaxParser::SaveTextData() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400351 m_iTextDatLen = m_TextData.TrimEnd();
352 m_TextData.Clear();
353 return m_iTextDatLen;
354}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500355
Dan Sinclairbe591062017-01-18 08:58:25 -0500356void CFDE_CSSSyntaxParser::SwitchMode(FDE_CSSSyntaxMode eMode) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400357 m_eMode = eMode;
358 SaveTextData();
359}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500360
thestigcfb77cc2016-06-10 12:21:53 -0700361int32_t CFDE_CSSSyntaxParser::SwitchToComment() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400362 int32_t iLength = m_TextData.GetLength();
Dan Sinclairbe591062017-01-18 08:58:25 -0500363 m_ModeStack.push(m_eMode);
364 SwitchMode(FDE_CSSSyntaxMode::Comment);
Dan Sinclair1770c022016-03-14 14:14:16 -0400365 return iLength;
366}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500367
tsepezd19e9122016-11-02 15:43:18 -0700368bool CFDE_CSSSyntaxParser::RestoreMode() {
Dan Sinclairbe591062017-01-18 08:58:25 -0500369 if (m_ModeStack.empty())
tsepezd19e9122016-11-02 15:43:18 -0700370 return false;
thestigcfb77cc2016-06-10 12:21:53 -0700371
Dan Sinclairbe591062017-01-18 08:58:25 -0500372 SwitchMode(m_ModeStack.top());
373 m_ModeStack.pop();
tsepezd19e9122016-11-02 15:43:18 -0700374 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400375}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500376
Dan Sinclair1770c022016-03-14 14:14:16 -0400377const FX_WCHAR* CFDE_CSSSyntaxParser::GetCurrentString(int32_t& iLength) const {
378 iLength = m_iTextDatLen;
379 return m_TextData.GetBuffer();
380}