| 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_csssyntax.h" | |
| 8 | |
| 9 #include "xfa/src/fde/css/fde_cssdatatable.h" | |
| 10 #include "xfa/src/fgas/crt/fgas_codepage.h" | |
| 11 | |
| 12 #ifdef _cplusplus | |
| 13 extern "C" { | |
| 14 #endif | |
| 15 | |
| 16 inline FX_BOOL FDE_IsSelectorStart(FX_WCHAR wch) { | |
| 17 return wch == '.' || wch == '#' || wch == '*' || (wch >= 'a' && wch <= 'z') || | |
| 18 (wch >= 'A' && wch <= 'Z'); | |
| 19 } | |
| 20 | |
| 21 #ifdef _cplusplus | |
| 22 }; | |
| 23 #endif | |
| 24 | |
| 25 IFDE_CSSSyntaxParser* IFDE_CSSSyntaxParser::Create() { | |
| 26 return new CFDE_CSSSyntaxParser; | |
| 27 } | |
| 28 CFDE_CSSSyntaxParser::CFDE_CSSSyntaxParser() | |
| 29 : m_pStream(NULL), | |
| 30 m_iStreamPos(0), | |
| 31 m_iPlaneSize(0), | |
| 32 m_iTextDatLen(0), | |
| 33 m_dwCheck((FX_DWORD)-1), | |
| 34 m_eMode(FDE_CSSSYNTAXMODE_RuleSet), | |
| 35 m_eStatus(FDE_CSSSYNTAXSTATUS_None) {} | |
| 36 CFDE_CSSSyntaxParser::~CFDE_CSSSyntaxParser() { | |
| 37 m_TextData.Reset(); | |
| 38 m_TextPlane.Reset(); | |
| 39 } | |
| 40 FX_BOOL CFDE_CSSSyntaxParser::Init(IFX_Stream* pStream, | |
| 41 int32_t iCSSPlaneSize, | |
| 42 int32_t iTextDataSize, | |
| 43 FX_BOOL bOnlyDeclaration) { | |
| 44 FXSYS_assert(pStream != NULL && iCSSPlaneSize > 0 && iTextDataSize > 0); | |
| 45 Reset(bOnlyDeclaration); | |
| 46 if (!m_TextData.EstimateSize(iTextDataSize)) { | |
| 47 return FALSE; | |
| 48 } | |
| 49 uint8_t bom[4]; | |
| 50 m_pStream = pStream; | |
| 51 m_iStreamPos = m_pStream->GetBOM(bom); | |
| 52 m_iPlaneSize = iCSSPlaneSize; | |
| 53 return TRUE; | |
| 54 } | |
| 55 FX_BOOL CFDE_CSSSyntaxParser::Init(const FX_WCHAR* pBuffer, | |
| 56 int32_t iBufferSize, | |
| 57 int32_t iTextDatSize, | |
| 58 FX_BOOL bOnlyDeclaration) { | |
| 59 FXSYS_assert(pBuffer != NULL && iBufferSize > 0 && iTextDatSize > 0); | |
| 60 Reset(bOnlyDeclaration); | |
| 61 if (!m_TextData.EstimateSize(iTextDatSize)) { | |
| 62 return FALSE; | |
| 63 } | |
| 64 return m_TextPlane.AttachBuffer(pBuffer, iBufferSize); | |
| 65 } | |
| 66 void CFDE_CSSSyntaxParser::Reset(FX_BOOL bOnlyDeclaration) { | |
| 67 m_TextPlane.Reset(); | |
| 68 m_TextData.Reset(); | |
| 69 m_pStream = NULL; | |
| 70 m_iStreamPos = 0; | |
| 71 m_iTextDatLen = 0; | |
| 72 m_dwCheck = (FX_DWORD)-1; | |
| 73 m_eStatus = FDE_CSSSYNTAXSTATUS_None; | |
| 74 m_eMode = bOnlyDeclaration ? FDE_CSSSYNTAXMODE_PropertyName | |
| 75 : FDE_CSSSYNTAXMODE_RuleSet; | |
| 76 } | |
| 77 FDE_CSSSYNTAXSTATUS CFDE_CSSSyntaxParser::DoSyntaxParse() { | |
| 78 while (m_eStatus >= FDE_CSSSYNTAXSTATUS_None) { | |
| 79 if (m_TextPlane.IsEOF()) { | |
| 80 if (m_pStream == NULL) { | |
| 81 if (m_eMode == FDE_CSSSYNTAXMODE_PropertyValue && | |
| 82 m_TextData.GetLength() > 0) { | |
| 83 SaveTextData(); | |
| 84 return m_eStatus = FDE_CSSSYNTAXSTATUS_PropertyValue; | |
| 85 } | |
| 86 return m_eStatus = FDE_CSSSYNTAXSTATUS_EOS; | |
| 87 } | |
| 88 FX_BOOL bEOS; | |
| 89 int32_t iLen = m_TextPlane.LoadFromStream(m_pStream, m_iStreamPos, | |
| 90 m_iPlaneSize, bEOS); | |
| 91 m_iStreamPos = m_pStream->GetPosition(); | |
| 92 if (iLen < 1) { | |
| 93 if (m_eMode == FDE_CSSSYNTAXMODE_PropertyValue && | |
| 94 m_TextData.GetLength() > 0) { | |
| 95 SaveTextData(); | |
| 96 return m_eStatus = FDE_CSSSYNTAXSTATUS_PropertyValue; | |
| 97 } | |
| 98 return m_eStatus = FDE_CSSSYNTAXSTATUS_EOS; | |
| 99 } | |
| 100 } | |
| 101 FX_WCHAR wch; | |
| 102 while (!m_TextPlane.IsEOF()) { | |
| 103 wch = m_TextPlane.GetChar(); | |
| 104 switch (m_eMode) { | |
| 105 case FDE_CSSSYNTAXMODE_RuleSet: | |
| 106 switch (wch) { | |
| 107 case '@': | |
| 108 m_TextPlane.MoveNext(); | |
| 109 SwitchMode(FDE_CSSSYNTAXMODE_AtRule); | |
| 110 break; | |
| 111 case '}': | |
| 112 m_TextPlane.MoveNext(); | |
| 113 if (RestoreMode()) { | |
| 114 return FDE_CSSSYNTAXSTATUS_DeclClose; | |
| 115 } else { | |
| 116 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error; | |
| 117 } | |
| 118 break; | |
| 119 case '/': | |
| 120 if (m_TextPlane.GetNextChar() == '*') { | |
| 121 m_ModeStack.Push(m_eMode); | |
| 122 SwitchMode(FDE_CSSSYNTAXMODE_Comment); | |
| 123 break; | |
| 124 } | |
| 125 default: | |
| 126 if (wch <= ' ') { | |
| 127 m_TextPlane.MoveNext(); | |
| 128 } else if (FDE_IsSelectorStart(wch)) { | |
| 129 SwitchMode(FDE_CSSSYNTAXMODE_Selector); | |
| 130 return FDE_CSSSYNTAXSTATUS_StyleRule; | |
| 131 } else { | |
| 132 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error; | |
| 133 } | |
| 134 break; | |
| 135 } | |
| 136 break; | |
| 137 case FDE_CSSSYNTAXMODE_Selector: | |
| 138 switch (wch) { | |
| 139 case ',': | |
| 140 m_TextPlane.MoveNext(); | |
| 141 SwitchMode(FDE_CSSSYNTAXMODE_Selector); | |
| 142 if (m_iTextDatLen > 0) { | |
| 143 return FDE_CSSSYNTAXSTATUS_Selector; | |
| 144 } | |
| 145 break; | |
| 146 case '{': | |
| 147 if (m_TextData.GetLength() > 0) { | |
| 148 SaveTextData(); | |
| 149 return FDE_CSSSYNTAXSTATUS_Selector; | |
| 150 } else { | |
| 151 m_TextPlane.MoveNext(); | |
| 152 m_ModeStack.Push(FDE_CSSSYNTAXMODE_RuleSet); | |
| 153 SwitchMode(FDE_CSSSYNTAXMODE_PropertyName); | |
| 154 return FDE_CSSSYNTAXSTATUS_DeclOpen; | |
| 155 } | |
| 156 break; | |
| 157 case '/': | |
| 158 if (m_TextPlane.GetNextChar() == '*') { | |
| 159 if (SwitchToComment() > 0) { | |
| 160 return FDE_CSSSYNTAXSTATUS_Selector; | |
| 161 } | |
| 162 break; | |
| 163 } | |
| 164 default: | |
| 165 AppendChar(wch); | |
| 166 break; | |
| 167 } | |
| 168 break; | |
| 169 case FDE_CSSSYNTAXMODE_PropertyName: | |
| 170 switch (wch) { | |
| 171 case ':': | |
| 172 m_TextPlane.MoveNext(); | |
| 173 SwitchMode(FDE_CSSSYNTAXMODE_PropertyValue); | |
| 174 return FDE_CSSSYNTAXSTATUS_PropertyName; | |
| 175 case '}': | |
| 176 m_TextPlane.MoveNext(); | |
| 177 if (RestoreMode()) { | |
| 178 return FDE_CSSSYNTAXSTATUS_DeclClose; | |
| 179 } else { | |
| 180 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error; | |
| 181 } | |
| 182 break; | |
| 183 case '/': | |
| 184 if (m_TextPlane.GetNextChar() == '*') { | |
| 185 if (SwitchToComment() > 0) { | |
| 186 return FDE_CSSSYNTAXSTATUS_PropertyName; | |
| 187 } | |
| 188 break; | |
| 189 } | |
| 190 default: | |
| 191 AppendChar(wch); | |
| 192 break; | |
| 193 } | |
| 194 break; | |
| 195 case FDE_CSSSYNTAXMODE_PropertyValue: | |
| 196 switch (wch) { | |
| 197 case ';': | |
| 198 m_TextPlane.MoveNext(); | |
| 199 case '}': | |
| 200 SwitchMode(FDE_CSSSYNTAXMODE_PropertyName); | |
| 201 return FDE_CSSSYNTAXSTATUS_PropertyValue; | |
| 202 case '/': | |
| 203 if (m_TextPlane.GetNextChar() == '*') { | |
| 204 if (SwitchToComment() > 0) { | |
| 205 return FDE_CSSSYNTAXSTATUS_PropertyValue; | |
| 206 } | |
| 207 break; | |
| 208 } | |
| 209 default: | |
| 210 AppendChar(wch); | |
| 211 break; | |
| 212 } | |
| 213 break; | |
| 214 case FDE_CSSSYNTAXMODE_Comment: | |
| 215 if (wch == '/' && m_TextData.GetLength() > 0 && | |
| 216 m_TextData.GetAt(m_TextData.GetLength() - 1) == '*') { | |
| 217 RestoreMode(); | |
| 218 } else { | |
| 219 m_TextData.AppendChar(wch); | |
| 220 } | |
| 221 m_TextPlane.MoveNext(); | |
| 222 break; | |
| 223 case FDE_CSSSYNTAXMODE_MediaType: | |
| 224 switch (wch) { | |
| 225 case ',': | |
| 226 m_TextPlane.MoveNext(); | |
| 227 SwitchMode(FDE_CSSSYNTAXMODE_MediaType); | |
| 228 if (m_iTextDatLen > 0) { | |
| 229 return FDE_CSSSYNTAXSTATUS_MediaType; | |
| 230 } | |
| 231 break; | |
| 232 case '{': { | |
| 233 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement(); | |
| 234 if (pMode == NULL || *pMode != FDE_CSSSYNTAXMODE_MediaRule) { | |
| 235 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error; | |
| 236 } | |
| 237 if (m_TextData.GetLength() > 0) { | |
| 238 SaveTextData(); | |
| 239 return FDE_CSSSYNTAXSTATUS_MediaType; | |
| 240 } else { | |
| 241 m_TextPlane.MoveNext(); | |
| 242 *pMode = FDE_CSSSYNTAXMODE_RuleSet; | |
| 243 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet); | |
| 244 return FDE_CSSSYNTAXSTATUS_DeclOpen; | |
| 245 } | |
| 246 } break; | |
| 247 case ';': { | |
| 248 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement(); | |
| 249 if (pMode == NULL || *pMode != FDE_CSSSYNTAXMODE_Import) { | |
| 250 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error; | |
| 251 } | |
| 252 if (m_TextData.GetLength() > 0) { | |
| 253 SaveTextData(); | |
| 254 if (IsImportEnabled()) { | |
| 255 return FDE_CSSSYNTAXSTATUS_MediaType; | |
| 256 } | |
| 257 } else { | |
| 258 FX_BOOL bEnabled = IsImportEnabled(); | |
| 259 m_TextPlane.MoveNext(); | |
| 260 m_ModeStack.Pop(); | |
| 261 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet); | |
| 262 if (bEnabled) { | |
| 263 DisableImport(); | |
| 264 return FDE_CSSSYNTAXSTATUS_ImportClose; | |
| 265 } | |
| 266 } | |
| 267 } break; | |
| 268 case '/': | |
| 269 if (m_TextPlane.GetNextChar() == '*') { | |
| 270 if (SwitchToComment() > 0) { | |
| 271 return FDE_CSSSYNTAXSTATUS_MediaType; | |
| 272 } | |
| 273 break; | |
| 274 } | |
| 275 default: | |
| 276 AppendChar(wch); | |
| 277 break; | |
| 278 } | |
| 279 break; | |
| 280 case FDE_CSSSYNTAXMODE_URI: { | |
| 281 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement(); | |
| 282 if (pMode == NULL || *pMode != FDE_CSSSYNTAXMODE_Import) { | |
| 283 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error; | |
| 284 } | |
| 285 if (wch <= ' ' || wch == ';') { | |
| 286 int32_t iURIStart, iURILength = m_TextData.GetLength(); | |
| 287 if (iURILength > 0 && | |
| 288 FDE_ParseCSSURI(m_TextData.GetBuffer(), iURILength, iURIStart, | |
| 289 iURILength)) { | |
| 290 m_TextData.Subtract(iURIStart, iURILength); | |
| 291 SwitchMode(FDE_CSSSYNTAXMODE_MediaType); | |
| 292 if (IsImportEnabled()) { | |
| 293 return FDE_CSSSYNTAXSTATUS_URI; | |
| 294 } else { | |
| 295 break; | |
| 296 } | |
| 297 } | |
| 298 } | |
| 299 AppendChar(wch); | |
| 300 } break; | |
| 301 case FDE_CSSSYNTAXMODE_AtRule: | |
| 302 if (wch > ' ') { | |
| 303 AppendChar(wch); | |
| 304 } else { | |
| 305 int32_t iLen = m_TextData.GetLength(); | |
| 306 const FX_WCHAR* psz = m_TextData.GetBuffer(); | |
| 307 if (FXSYS_wcsncmp(L"charset", psz, iLen) == 0) { | |
| 308 SwitchMode(FDE_CSSSYNTAXMODE_Charset); | |
| 309 } else if (FXSYS_wcsncmp(L"import", psz, iLen) == 0) { | |
| 310 m_ModeStack.Push(FDE_CSSSYNTAXMODE_Import); | |
| 311 SwitchMode(FDE_CSSSYNTAXMODE_URI); | |
| 312 if (IsImportEnabled()) { | |
| 313 return FDE_CSSSYNTAXSTATUS_ImportRule; | |
| 314 } else { | |
| 315 break; | |
| 316 } | |
| 317 } else if (FXSYS_wcsncmp(L"media", psz, iLen) == 0) { | |
| 318 m_ModeStack.Push(FDE_CSSSYNTAXMODE_MediaRule); | |
| 319 SwitchMode(FDE_CSSSYNTAXMODE_MediaType); | |
| 320 return FDE_CSSSYNTAXSTATUS_MediaRule; | |
| 321 } else if (FXSYS_wcsncmp(L"font-face", psz, iLen) == 0) { | |
| 322 SwitchMode(FDE_CSSSYNTAXMODE_Selector); | |
| 323 return FDE_CSSSYNTAXSTATUS_FontFaceRule; | |
| 324 } else if (FXSYS_wcsncmp(L"page", psz, iLen) == 0) { | |
| 325 SwitchMode(FDE_CSSSYNTAXMODE_Selector); | |
| 326 return FDE_CSSSYNTAXSTATUS_PageRule; | |
| 327 } else { | |
| 328 SwitchMode(FDE_CSSSYNTAXMODE_UnknownRule); | |
| 329 } | |
| 330 } | |
| 331 break; | |
| 332 case FDE_CSSSYNTAXMODE_Charset: | |
| 333 if (wch == ';') { | |
| 334 m_TextPlane.MoveNext(); | |
| 335 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet); | |
| 336 if (IsCharsetEnabled()) { | |
| 337 DisableCharset(); | |
| 338 if (m_iTextDatLen > 0) { | |
| 339 if (m_pStream != NULL) { | |
| 340 FX_WORD wCodePage = FX_GetCodePageFormStringW( | |
| 341 m_TextData.GetBuffer(), m_iTextDatLen); | |
| 342 if (wCodePage < 0xFFFF && | |
| 343 m_pStream->GetCodePage() != wCodePage) { | |
| 344 m_pStream->SetCodePage(wCodePage); | |
| 345 } | |
| 346 } | |
| 347 return FDE_CSSSYNTAXSTATUS_Charset; | |
| 348 } | |
| 349 } | |
| 350 } else { | |
| 351 AppendChar(wch); | |
| 352 } | |
| 353 break; | |
| 354 case FDE_CSSSYNTAXMODE_UnknownRule: | |
| 355 if (wch == ';') { | |
| 356 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet); | |
| 357 } | |
| 358 m_TextPlane.MoveNext(); | |
| 359 break; | |
| 360 default: | |
| 361 FXSYS_assert(FALSE); | |
| 362 break; | |
| 363 } | |
| 364 } | |
| 365 } | |
| 366 return m_eStatus; | |
| 367 } | |
| 368 FX_BOOL CFDE_CSSSyntaxParser::IsImportEnabled() const { | |
| 369 if ((m_dwCheck & FDE_CSSSYNTAXCHECK_AllowImport) == 0) { | |
| 370 return FALSE; | |
| 371 } | |
| 372 if (m_ModeStack.GetSize() > 1) { | |
| 373 return FALSE; | |
| 374 } | |
| 375 return TRUE; | |
| 376 } | |
| 377 inline FX_BOOL CFDE_CSSSyntaxParser::AppendChar(FX_WCHAR wch) { | |
| 378 m_TextPlane.MoveNext(); | |
| 379 if (m_TextData.GetLength() > 0 || wch > ' ') { | |
| 380 m_TextData.AppendChar(wch); | |
| 381 return TRUE; | |
| 382 } | |
| 383 return FALSE; | |
| 384 } | |
| 385 inline int32_t CFDE_CSSSyntaxParser::SaveTextData() { | |
| 386 m_iTextDatLen = m_TextData.TrimEnd(); | |
| 387 m_TextData.Clear(); | |
| 388 return m_iTextDatLen; | |
| 389 } | |
| 390 inline void CFDE_CSSSyntaxParser::SwitchMode(FDE_CSSSYNTAXMODE eMode) { | |
| 391 m_eMode = eMode; | |
| 392 SaveTextData(); | |
| 393 } | |
| 394 inline int32_t CFDE_CSSSyntaxParser::SwitchToComment() { | |
| 395 int32_t iLength = m_TextData.GetLength(); | |
| 396 m_ModeStack.Push(m_eMode); | |
| 397 SwitchMode(FDE_CSSSYNTAXMODE_Comment); | |
| 398 return iLength; | |
| 399 } | |
| 400 inline FX_BOOL CFDE_CSSSyntaxParser::RestoreMode() { | |
| 401 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement(); | |
| 402 if (pMode == NULL) { | |
| 403 return FALSE; | |
| 404 } | |
| 405 SwitchMode(*pMode); | |
| 406 m_ModeStack.Pop(); | |
| 407 return TRUE; | |
| 408 } | |
| 409 const FX_WCHAR* CFDE_CSSSyntaxParser::GetCurrentString(int32_t& iLength) const { | |
| 410 iLength = m_iTextDatLen; | |
| 411 return m_TextData.GetBuffer(); | |
| 412 } | |
| 413 CFDE_CSSTextBuf::CFDE_CSSTextBuf() | |
| 414 : m_bExtBuf(FALSE), | |
| 415 m_pBuffer(NULL), | |
| 416 m_iBufLen(0), | |
| 417 m_iDatLen(0), | |
| 418 m_iDatPos(0) {} | |
| 419 CFDE_CSSTextBuf::~CFDE_CSSTextBuf() { | |
| 420 Reset(); | |
| 421 } | |
| 422 void CFDE_CSSTextBuf::Reset() { | |
| 423 if (!m_bExtBuf) { | |
| 424 FX_Free(m_pBuffer); | |
| 425 m_pBuffer = NULL; | |
| 426 } | |
| 427 m_iDatPos = m_iDatLen = m_iBufLen; | |
| 428 } | |
| 429 FX_BOOL CFDE_CSSTextBuf::AttachBuffer(const FX_WCHAR* pBuffer, | |
| 430 int32_t iBufLen) { | |
| 431 Reset(); | |
| 432 m_pBuffer = (FX_WCHAR*)pBuffer; | |
| 433 m_iDatLen = m_iBufLen = iBufLen; | |
| 434 return m_bExtBuf = TRUE; | |
| 435 } | |
| 436 FX_BOOL CFDE_CSSTextBuf::EstimateSize(int32_t iAllocSize) { | |
| 437 FXSYS_assert(iAllocSize > 0); | |
| 438 Clear(); | |
| 439 m_bExtBuf = FALSE; | |
| 440 return ExpandBuf(iAllocSize); | |
| 441 } | |
| 442 int32_t CFDE_CSSTextBuf::LoadFromStream(IFX_Stream* pTxtStream, | |
| 443 int32_t iStreamOffset, | |
| 444 int32_t iMaxChars, | |
| 445 FX_BOOL& bEOS) { | |
| 446 FXSYS_assert(iStreamOffset >= 0 && iMaxChars > 0); | |
| 447 Clear(); | |
| 448 m_bExtBuf = FALSE; | |
| 449 if (!ExpandBuf(iMaxChars)) { | |
| 450 return 0; | |
| 451 } | |
| 452 if (pTxtStream->GetPosition() != iStreamOffset) { | |
| 453 pTxtStream->Seek(FX_STREAMSEEK_Begin, iStreamOffset); | |
| 454 } | |
| 455 m_iDatLen = pTxtStream->ReadString(m_pBuffer, iMaxChars, bEOS); | |
| 456 return m_iDatLen; | |
| 457 } | |
| 458 FX_BOOL CFDE_CSSTextBuf::ExpandBuf(int32_t iDesiredSize) { | |
| 459 if (m_bExtBuf) { | |
| 460 return FALSE; | |
| 461 } | |
| 462 if (!m_pBuffer) { | |
| 463 m_pBuffer = FX_Alloc(FX_WCHAR, iDesiredSize); | |
| 464 } else if (m_iBufLen != iDesiredSize) { | |
| 465 m_pBuffer = FX_Realloc(FX_WCHAR, m_pBuffer, iDesiredSize); | |
| 466 } else { | |
| 467 return TRUE; | |
| 468 } | |
| 469 if (!m_pBuffer) { | |
| 470 m_iBufLen = 0; | |
| 471 return FALSE; | |
| 472 } | |
| 473 m_iBufLen = iDesiredSize; | |
| 474 return TRUE; | |
| 475 } | |
| 476 void CFDE_CSSTextBuf::Subtract(int32_t iStart, int32_t iLength) { | |
| 477 FXSYS_assert(iStart >= 0 && iLength > 0); | |
| 478 if (iLength > m_iDatLen - iStart) { | |
| 479 iLength = m_iDatLen - iStart; | |
| 480 } | |
| 481 if (iLength < 0) { | |
| 482 iLength = 0; | |
| 483 } else { | |
| 484 FXSYS_memmove(m_pBuffer, m_pBuffer + iStart, iLength * sizeof(FX_WCHAR)); | |
| 485 } | |
| 486 m_iDatLen = iLength; | |
| 487 } | |
| OLD | NEW |