blob: 436a94b67ba9e74108e3307ba7aed5e742d1c548 [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
7#include "xfa/fde/css/fde_csssyntax.h"
8
9#include "xfa/fde/css/fde_cssdatatable.h"
10#include "xfa/fgas/crt/fgas_codepage.h"
11
thestigcfb77cc2016-06-10 12:21:53 -070012namespace {
Dan Sinclair1770c022016-03-14 14:14:16 -040013
thestigcfb77cc2016-06-10 12:21:53 -070014bool FDE_IsSelectorStart(FX_WCHAR wch) {
Dan Sinclair1770c022016-03-14 14:14:16 -040015 return wch == '.' || wch == '#' || wch == '*' || (wch >= 'a' && wch <= 'z') ||
16 (wch >= 'A' && wch <= 'Z');
17}
18
thestigcfb77cc2016-06-10 12:21:53 -070019} // namespace
Dan Sinclair1770c022016-03-14 14:14:16 -040020
Dan Sinclair1770c022016-03-14 14:14:16 -040021CFDE_CSSSyntaxParser::CFDE_CSSSyntaxParser()
thestigcfb77cc2016-06-10 12:21:53 -070022 : m_pStream(nullptr),
Dan Sinclair1770c022016-03-14 14:14:16 -040023 m_iStreamPos(0),
24 m_iPlaneSize(0),
25 m_iTextDatLen(0),
tsepez736f28a2016-03-25 14:19:51 -070026 m_dwCheck((uint32_t)-1),
Dan Sinclair1770c022016-03-14 14:14:16 -040027 m_eMode(FDE_CSSSYNTAXMODE_RuleSet),
dsinclair34965452016-07-18 13:14:49 -070028 m_eStatus(FDE_CSSSYNTAXSTATUS_None),
29 m_ModeStack(100) {}
30
Dan Sinclair1770c022016-03-14 14:14:16 -040031CFDE_CSSSyntaxParser::~CFDE_CSSSyntaxParser() {
32 m_TextData.Reset();
33 m_TextPlane.Reset();
34}
dsinclair34965452016-07-18 13:14:49 -070035
tsepezd19e9122016-11-02 15:43:18 -070036bool CFDE_CSSSyntaxParser::Init(IFX_Stream* pStream,
37 int32_t iCSSPlaneSize,
38 int32_t iTextDataSize,
39 bool bOnlyDeclaration) {
thestigcfb77cc2016-06-10 12:21:53 -070040 ASSERT(pStream && iCSSPlaneSize > 0 && iTextDataSize > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -040041 Reset(bOnlyDeclaration);
42 if (!m_TextData.EstimateSize(iTextDataSize)) {
tsepezd19e9122016-11-02 15:43:18 -070043 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -040044 }
45 uint8_t bom[4];
46 m_pStream = pStream;
47 m_iStreamPos = m_pStream->GetBOM(bom);
48 m_iPlaneSize = iCSSPlaneSize;
tsepezd19e9122016-11-02 15:43:18 -070049 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -040050}
tsepezd19e9122016-11-02 15:43:18 -070051bool CFDE_CSSSyntaxParser::Init(const FX_WCHAR* pBuffer,
52 int32_t iBufferSize,
53 int32_t iTextDatSize,
54 bool bOnlyDeclaration) {
thestigcfb77cc2016-06-10 12:21:53 -070055 ASSERT(pBuffer && iBufferSize > 0 && iTextDatSize > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -040056 Reset(bOnlyDeclaration);
57 if (!m_TextData.EstimateSize(iTextDatSize)) {
tsepezd19e9122016-11-02 15:43:18 -070058 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -040059 }
60 return m_TextPlane.AttachBuffer(pBuffer, iBufferSize);
61}
tsepezd19e9122016-11-02 15:43:18 -070062void CFDE_CSSSyntaxParser::Reset(bool bOnlyDeclaration) {
Dan Sinclair1770c022016-03-14 14:14:16 -040063 m_TextPlane.Reset();
64 m_TextData.Reset();
thestigcfb77cc2016-06-10 12:21:53 -070065 m_pStream = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -040066 m_iStreamPos = 0;
67 m_iTextDatLen = 0;
tsepez736f28a2016-03-25 14:19:51 -070068 m_dwCheck = (uint32_t)-1;
Dan Sinclair1770c022016-03-14 14:14:16 -040069 m_eStatus = FDE_CSSSYNTAXSTATUS_None;
70 m_eMode = bOnlyDeclaration ? FDE_CSSSYNTAXMODE_PropertyName
71 : FDE_CSSSYNTAXMODE_RuleSet;
72}
73FDE_CSSSYNTAXSTATUS CFDE_CSSSyntaxParser::DoSyntaxParse() {
74 while (m_eStatus >= FDE_CSSSYNTAXSTATUS_None) {
75 if (m_TextPlane.IsEOF()) {
thestigcfb77cc2016-06-10 12:21:53 -070076 if (!m_pStream) {
Dan Sinclair1770c022016-03-14 14:14:16 -040077 if (m_eMode == FDE_CSSSYNTAXMODE_PropertyValue &&
78 m_TextData.GetLength() > 0) {
79 SaveTextData();
80 return m_eStatus = FDE_CSSSYNTAXSTATUS_PropertyValue;
81 }
82 return m_eStatus = FDE_CSSSYNTAXSTATUS_EOS;
83 }
tsepezd19e9122016-11-02 15:43:18 -070084 bool bEOS;
Dan Sinclair1770c022016-03-14 14:14:16 -040085 int32_t iLen = m_TextPlane.LoadFromStream(m_pStream, m_iStreamPos,
86 m_iPlaneSize, bEOS);
87 m_iStreamPos = m_pStream->GetPosition();
88 if (iLen < 1) {
89 if (m_eMode == FDE_CSSSYNTAXMODE_PropertyValue &&
90 m_TextData.GetLength() > 0) {
91 SaveTextData();
92 return m_eStatus = FDE_CSSSYNTAXSTATUS_PropertyValue;
93 }
94 return m_eStatus = FDE_CSSSYNTAXSTATUS_EOS;
95 }
96 }
97 FX_WCHAR wch;
98 while (!m_TextPlane.IsEOF()) {
99 wch = m_TextPlane.GetChar();
100 switch (m_eMode) {
101 case FDE_CSSSYNTAXMODE_RuleSet:
102 switch (wch) {
103 case '@':
104 m_TextPlane.MoveNext();
105 SwitchMode(FDE_CSSSYNTAXMODE_AtRule);
106 break;
107 case '}':
108 m_TextPlane.MoveNext();
109 if (RestoreMode()) {
110 return FDE_CSSSYNTAXSTATUS_DeclClose;
111 } else {
112 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error;
113 }
114 break;
115 case '/':
116 if (m_TextPlane.GetNextChar() == '*') {
117 m_ModeStack.Push(m_eMode);
118 SwitchMode(FDE_CSSSYNTAXMODE_Comment);
119 break;
120 }
121 default:
122 if (wch <= ' ') {
123 m_TextPlane.MoveNext();
124 } else if (FDE_IsSelectorStart(wch)) {
125 SwitchMode(FDE_CSSSYNTAXMODE_Selector);
126 return FDE_CSSSYNTAXSTATUS_StyleRule;
127 } else {
128 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error;
129 }
130 break;
131 }
132 break;
133 case FDE_CSSSYNTAXMODE_Selector:
134 switch (wch) {
135 case ',':
136 m_TextPlane.MoveNext();
137 SwitchMode(FDE_CSSSYNTAXMODE_Selector);
138 if (m_iTextDatLen > 0) {
139 return FDE_CSSSYNTAXSTATUS_Selector;
140 }
141 break;
142 case '{':
143 if (m_TextData.GetLength() > 0) {
144 SaveTextData();
145 return FDE_CSSSYNTAXSTATUS_Selector;
146 } else {
147 m_TextPlane.MoveNext();
148 m_ModeStack.Push(FDE_CSSSYNTAXMODE_RuleSet);
149 SwitchMode(FDE_CSSSYNTAXMODE_PropertyName);
150 return FDE_CSSSYNTAXSTATUS_DeclOpen;
151 }
152 break;
153 case '/':
154 if (m_TextPlane.GetNextChar() == '*') {
155 if (SwitchToComment() > 0) {
156 return FDE_CSSSYNTAXSTATUS_Selector;
157 }
158 break;
159 }
160 default:
161 AppendChar(wch);
162 break;
163 }
164 break;
165 case FDE_CSSSYNTAXMODE_PropertyName:
166 switch (wch) {
167 case ':':
168 m_TextPlane.MoveNext();
169 SwitchMode(FDE_CSSSYNTAXMODE_PropertyValue);
170 return FDE_CSSSYNTAXSTATUS_PropertyName;
171 case '}':
172 m_TextPlane.MoveNext();
173 if (RestoreMode()) {
174 return FDE_CSSSYNTAXSTATUS_DeclClose;
175 } else {
176 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error;
177 }
178 break;
179 case '/':
180 if (m_TextPlane.GetNextChar() == '*') {
181 if (SwitchToComment() > 0) {
182 return FDE_CSSSYNTAXSTATUS_PropertyName;
183 }
184 break;
185 }
186 default:
187 AppendChar(wch);
188 break;
189 }
190 break;
191 case FDE_CSSSYNTAXMODE_PropertyValue:
192 switch (wch) {
193 case ';':
194 m_TextPlane.MoveNext();
195 case '}':
196 SwitchMode(FDE_CSSSYNTAXMODE_PropertyName);
197 return FDE_CSSSYNTAXSTATUS_PropertyValue;
198 case '/':
199 if (m_TextPlane.GetNextChar() == '*') {
200 if (SwitchToComment() > 0) {
201 return FDE_CSSSYNTAXSTATUS_PropertyValue;
202 }
203 break;
204 }
205 default:
206 AppendChar(wch);
207 break;
208 }
209 break;
210 case FDE_CSSSYNTAXMODE_Comment:
211 if (wch == '/' && m_TextData.GetLength() > 0 &&
212 m_TextData.GetAt(m_TextData.GetLength() - 1) == '*') {
213 RestoreMode();
214 } else {
215 m_TextData.AppendChar(wch);
216 }
217 m_TextPlane.MoveNext();
218 break;
219 case FDE_CSSSYNTAXMODE_MediaType:
220 switch (wch) {
221 case ',':
222 m_TextPlane.MoveNext();
223 SwitchMode(FDE_CSSSYNTAXMODE_MediaType);
224 if (m_iTextDatLen > 0) {
225 return FDE_CSSSYNTAXSTATUS_MediaType;
226 }
227 break;
228 case '{': {
229 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement();
thestigcfb77cc2016-06-10 12:21:53 -0700230 if (!pMode || *pMode != FDE_CSSSYNTAXMODE_MediaRule)
Dan Sinclair1770c022016-03-14 14:14:16 -0400231 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error;
thestigcfb77cc2016-06-10 12:21:53 -0700232
Dan Sinclair1770c022016-03-14 14:14:16 -0400233 if (m_TextData.GetLength() > 0) {
234 SaveTextData();
235 return FDE_CSSSYNTAXSTATUS_MediaType;
236 } else {
237 m_TextPlane.MoveNext();
238 *pMode = FDE_CSSSYNTAXMODE_RuleSet;
239 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
240 return FDE_CSSSYNTAXSTATUS_DeclOpen;
241 }
242 } break;
243 case ';': {
244 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement();
thestigcfb77cc2016-06-10 12:21:53 -0700245 if (!pMode || *pMode != FDE_CSSSYNTAXMODE_Import)
Dan Sinclair1770c022016-03-14 14:14:16 -0400246 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error;
thestigcfb77cc2016-06-10 12:21:53 -0700247
Dan Sinclair1770c022016-03-14 14:14:16 -0400248 if (m_TextData.GetLength() > 0) {
249 SaveTextData();
250 if (IsImportEnabled()) {
251 return FDE_CSSSYNTAXSTATUS_MediaType;
252 }
253 } else {
tsepezd19e9122016-11-02 15:43:18 -0700254 bool bEnabled = IsImportEnabled();
Dan Sinclair1770c022016-03-14 14:14:16 -0400255 m_TextPlane.MoveNext();
256 m_ModeStack.Pop();
257 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
258 if (bEnabled) {
259 DisableImport();
260 return FDE_CSSSYNTAXSTATUS_ImportClose;
261 }
262 }
263 } break;
264 case '/':
265 if (m_TextPlane.GetNextChar() == '*') {
266 if (SwitchToComment() > 0) {
267 return FDE_CSSSYNTAXSTATUS_MediaType;
268 }
269 break;
270 }
271 default:
272 AppendChar(wch);
273 break;
274 }
275 break;
276 case FDE_CSSSYNTAXMODE_URI: {
277 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement();
thestigcfb77cc2016-06-10 12:21:53 -0700278 if (!pMode || *pMode != FDE_CSSSYNTAXMODE_Import)
Dan Sinclair1770c022016-03-14 14:14:16 -0400279 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error;
thestigcfb77cc2016-06-10 12:21:53 -0700280
Dan Sinclair1770c022016-03-14 14:14:16 -0400281 if (wch <= ' ' || wch == ';') {
282 int32_t iURIStart, iURILength = m_TextData.GetLength();
283 if (iURILength > 0 &&
284 FDE_ParseCSSURI(m_TextData.GetBuffer(), iURILength, iURIStart,
285 iURILength)) {
286 m_TextData.Subtract(iURIStart, iURILength);
287 SwitchMode(FDE_CSSSYNTAXMODE_MediaType);
288 if (IsImportEnabled()) {
289 return FDE_CSSSYNTAXSTATUS_URI;
290 } else {
291 break;
292 }
293 }
294 }
295 AppendChar(wch);
296 } break;
297 case FDE_CSSSYNTAXMODE_AtRule:
298 if (wch > ' ') {
299 AppendChar(wch);
300 } else {
301 int32_t iLen = m_TextData.GetLength();
302 const FX_WCHAR* psz = m_TextData.GetBuffer();
303 if (FXSYS_wcsncmp(L"charset", psz, iLen) == 0) {
304 SwitchMode(FDE_CSSSYNTAXMODE_Charset);
305 } else if (FXSYS_wcsncmp(L"import", psz, iLen) == 0) {
306 m_ModeStack.Push(FDE_CSSSYNTAXMODE_Import);
307 SwitchMode(FDE_CSSSYNTAXMODE_URI);
308 if (IsImportEnabled()) {
309 return FDE_CSSSYNTAXSTATUS_ImportRule;
310 } else {
311 break;
312 }
313 } else if (FXSYS_wcsncmp(L"media", psz, iLen) == 0) {
314 m_ModeStack.Push(FDE_CSSSYNTAXMODE_MediaRule);
315 SwitchMode(FDE_CSSSYNTAXMODE_MediaType);
316 return FDE_CSSSYNTAXSTATUS_MediaRule;
317 } else if (FXSYS_wcsncmp(L"font-face", psz, iLen) == 0) {
318 SwitchMode(FDE_CSSSYNTAXMODE_Selector);
319 return FDE_CSSSYNTAXSTATUS_FontFaceRule;
320 } else if (FXSYS_wcsncmp(L"page", psz, iLen) == 0) {
321 SwitchMode(FDE_CSSSYNTAXMODE_Selector);
322 return FDE_CSSSYNTAXSTATUS_PageRule;
323 } else {
324 SwitchMode(FDE_CSSSYNTAXMODE_UnknownRule);
325 }
326 }
327 break;
328 case FDE_CSSSYNTAXMODE_Charset:
329 if (wch == ';') {
330 m_TextPlane.MoveNext();
331 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
332 if (IsCharsetEnabled()) {
333 DisableCharset();
334 if (m_iTextDatLen > 0) {
thestigcfb77cc2016-06-10 12:21:53 -0700335 if (m_pStream) {
dsinclairfc2cdf82016-05-19 18:07:11 -0700336 uint16_t wCodePage = FX_GetCodePageFromStringW(
Dan Sinclair1770c022016-03-14 14:14:16 -0400337 m_TextData.GetBuffer(), m_iTextDatLen);
338 if (wCodePage < 0xFFFF &&
339 m_pStream->GetCodePage() != wCodePage) {
340 m_pStream->SetCodePage(wCodePage);
341 }
342 }
343 return FDE_CSSSYNTAXSTATUS_Charset;
344 }
345 }
346 } else {
347 AppendChar(wch);
348 }
349 break;
350 case FDE_CSSSYNTAXMODE_UnknownRule:
351 if (wch == ';') {
352 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
353 }
354 m_TextPlane.MoveNext();
355 break;
356 default:
tsepezd19e9122016-11-02 15:43:18 -0700357 ASSERT(false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400358 break;
359 }
360 }
361 }
362 return m_eStatus;
363}
tsepezd19e9122016-11-02 15:43:18 -0700364bool CFDE_CSSSyntaxParser::IsImportEnabled() const {
Dan Sinclair1770c022016-03-14 14:14:16 -0400365 if ((m_dwCheck & FDE_CSSSYNTAXCHECK_AllowImport) == 0) {
tsepezd19e9122016-11-02 15:43:18 -0700366 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400367 }
368 if (m_ModeStack.GetSize() > 1) {
tsepezd19e9122016-11-02 15:43:18 -0700369 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400370 }
tsepezd19e9122016-11-02 15:43:18 -0700371 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400372}
tsepezd19e9122016-11-02 15:43:18 -0700373bool CFDE_CSSSyntaxParser::AppendChar(FX_WCHAR wch) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400374 m_TextPlane.MoveNext();
375 if (m_TextData.GetLength() > 0 || wch > ' ') {
376 m_TextData.AppendChar(wch);
tsepezd19e9122016-11-02 15:43:18 -0700377 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400378 }
tsepezd19e9122016-11-02 15:43:18 -0700379 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400380}
thestigcfb77cc2016-06-10 12:21:53 -0700381int32_t CFDE_CSSSyntaxParser::SaveTextData() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400382 m_iTextDatLen = m_TextData.TrimEnd();
383 m_TextData.Clear();
384 return m_iTextDatLen;
385}
thestigcfb77cc2016-06-10 12:21:53 -0700386void CFDE_CSSSyntaxParser::SwitchMode(FDE_CSSSYNTAXMODE eMode) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400387 m_eMode = eMode;
388 SaveTextData();
389}
thestigcfb77cc2016-06-10 12:21:53 -0700390int32_t CFDE_CSSSyntaxParser::SwitchToComment() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400391 int32_t iLength = m_TextData.GetLength();
392 m_ModeStack.Push(m_eMode);
393 SwitchMode(FDE_CSSSYNTAXMODE_Comment);
394 return iLength;
395}
tsepezd19e9122016-11-02 15:43:18 -0700396bool CFDE_CSSSyntaxParser::RestoreMode() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400397 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement();
thestigcfb77cc2016-06-10 12:21:53 -0700398 if (!pMode)
tsepezd19e9122016-11-02 15:43:18 -0700399 return false;
thestigcfb77cc2016-06-10 12:21:53 -0700400
Dan Sinclair1770c022016-03-14 14:14:16 -0400401 SwitchMode(*pMode);
402 m_ModeStack.Pop();
tsepezd19e9122016-11-02 15:43:18 -0700403 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400404}
405const FX_WCHAR* CFDE_CSSSyntaxParser::GetCurrentString(int32_t& iLength) const {
406 iLength = m_iTextDatLen;
407 return m_TextData.GetBuffer();
408}
409CFDE_CSSTextBuf::CFDE_CSSTextBuf()
tsepezd19e9122016-11-02 15:43:18 -0700410 : m_bExtBuf(false),
thestigcfb77cc2016-06-10 12:21:53 -0700411 m_pBuffer(nullptr),
Dan Sinclair1770c022016-03-14 14:14:16 -0400412 m_iBufLen(0),
413 m_iDatLen(0),
414 m_iDatPos(0) {}
415CFDE_CSSTextBuf::~CFDE_CSSTextBuf() {
416 Reset();
417}
418void CFDE_CSSTextBuf::Reset() {
419 if (!m_bExtBuf) {
420 FX_Free(m_pBuffer);
thestigcfb77cc2016-06-10 12:21:53 -0700421 m_pBuffer = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400422 }
423 m_iDatPos = m_iDatLen = m_iBufLen;
424}
tsepezd19e9122016-11-02 15:43:18 -0700425bool CFDE_CSSTextBuf::AttachBuffer(const FX_WCHAR* pBuffer, int32_t iBufLen) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400426 Reset();
brucedawson2f109ab2016-05-27 16:13:13 -0700427 m_pBuffer = const_cast<FX_WCHAR*>(pBuffer);
Dan Sinclair1770c022016-03-14 14:14:16 -0400428 m_iDatLen = m_iBufLen = iBufLen;
tsepezd19e9122016-11-02 15:43:18 -0700429 return m_bExtBuf = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400430}
tsepezd19e9122016-11-02 15:43:18 -0700431bool CFDE_CSSTextBuf::EstimateSize(int32_t iAllocSize) {
dsinclair43854a52016-04-27 12:26:00 -0700432 ASSERT(iAllocSize > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -0400433 Clear();
tsepezd19e9122016-11-02 15:43:18 -0700434 m_bExtBuf = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400435 return ExpandBuf(iAllocSize);
436}
437int32_t CFDE_CSSTextBuf::LoadFromStream(IFX_Stream* pTxtStream,
438 int32_t iStreamOffset,
439 int32_t iMaxChars,
tsepezd19e9122016-11-02 15:43:18 -0700440 bool& bEOS) {
dsinclair43854a52016-04-27 12:26:00 -0700441 ASSERT(iStreamOffset >= 0 && iMaxChars > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -0400442 Clear();
tsepezd19e9122016-11-02 15:43:18 -0700443 m_bExtBuf = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400444 if (!ExpandBuf(iMaxChars)) {
445 return 0;
446 }
447 if (pTxtStream->GetPosition() != iStreamOffset) {
448 pTxtStream->Seek(FX_STREAMSEEK_Begin, iStreamOffset);
449 }
450 m_iDatLen = pTxtStream->ReadString(m_pBuffer, iMaxChars, bEOS);
451 return m_iDatLen;
452}
tsepezd19e9122016-11-02 15:43:18 -0700453bool CFDE_CSSTextBuf::ExpandBuf(int32_t iDesiredSize) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400454 if (m_bExtBuf) {
tsepezd19e9122016-11-02 15:43:18 -0700455 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400456 }
457 if (!m_pBuffer) {
458 m_pBuffer = FX_Alloc(FX_WCHAR, iDesiredSize);
459 } else if (m_iBufLen != iDesiredSize) {
460 m_pBuffer = FX_Realloc(FX_WCHAR, m_pBuffer, iDesiredSize);
461 } else {
tsepezd19e9122016-11-02 15:43:18 -0700462 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400463 }
464 if (!m_pBuffer) {
465 m_iBufLen = 0;
tsepezd19e9122016-11-02 15:43:18 -0700466 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400467 }
468 m_iBufLen = iDesiredSize;
tsepezd19e9122016-11-02 15:43:18 -0700469 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400470}
471void CFDE_CSSTextBuf::Subtract(int32_t iStart, int32_t iLength) {
dsinclair43854a52016-04-27 12:26:00 -0700472 ASSERT(iStart >= 0 && iLength > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -0400473 if (iLength > m_iDatLen - iStart) {
474 iLength = m_iDatLen - iStart;
475 }
476 if (iLength < 0) {
477 iLength = 0;
478 } else {
479 FXSYS_memmove(m_pBuffer, m_pBuffer + iStart, iLength * sizeof(FX_WCHAR));
480 }
481 m_iDatLen = iLength;
482}