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/foxitlib.h" 8 #include "xfa/src/fxfa/src/common/xfa_utils.h" 9 #include "xfa/src/fxfa/src/common/xfa_object.h" 10 #include "xfa/src/fxfa/src/common/xfa_document.h" 11 #include "xfa/src/fxfa/src/common/xfa_parser.h" 12 #include "xfa/src/fxfa/src/common/xfa_script.h" 13 #include "xfa/src/fxfa/src/common/xfa_docdata.h" 14 #include "xfa/src/fxfa/src/common/xfa_doclayout.h" 15 #include "xfa/src/fxfa/src/common/xfa_localemgr.h" 16 #include "xfa/src/fxfa/src/common/xfa_fm2jsapi.h" 17 static const FX_DOUBLE fraction_scales[] = {0.1, 18 0.01, 19 0.001, 20 0.0001, 21 0.00001, 22 0.000001, 23 0.0000001, 24 0.00000001, 25 0.000000001, 26 0.0000000001, 27 0.00000000001, 28 0.000000000001, 29 0.0000000000001, 30 0.00000000000001, 31 0.000000000000001, 32 0.0000000000000001}; 33 CXFA_LocaleValue::CXFA_LocaleValue() { 34 m_dwType = XFA_VT_NULL; 35 m_bValid = TRUE; 36 m_pLocaleMgr = NULL; 37 } 38 CXFA_LocaleValue::CXFA_LocaleValue(const CXFA_LocaleValue& value) { 39 m_dwType = XFA_VT_NULL; 40 m_bValid = TRUE; 41 m_pLocaleMgr = NULL; 42 *this = value; 43 } 44 CXFA_LocaleValue::CXFA_LocaleValue(FX_DWORD dwType, 45 CXFA_LocaleMgr* pLocaleMgr) { 46 m_dwType = dwType; 47 m_bValid = (m_dwType != XFA_VT_NULL); 48 m_pLocaleMgr = pLocaleMgr; 49 } 50 CXFA_LocaleValue::CXFA_LocaleValue(FX_DWORD dwType, 51 const CFX_WideString& wsValue, 52 CXFA_LocaleMgr* pLocaleMgr) { 53 m_wsValue = wsValue; 54 m_dwType = dwType; 55 m_pLocaleMgr = pLocaleMgr; 56 m_bValid = ValidateCanonicalValue(wsValue, dwType); 57 } 58 CXFA_LocaleValue::CXFA_LocaleValue(FX_DWORD dwType, 59 const CFX_WideString& wsValue, 60 const CFX_WideString& wsFormat, 61 IFX_Locale* pLocale, 62 CXFA_LocaleMgr* pLocaleMgr) { 63 m_pLocaleMgr = pLocaleMgr; 64 m_bValid = TRUE; 65 m_dwType = dwType; 66 m_bValid = ParsePatternValue(wsValue, wsFormat, pLocale); 67 } 68 CXFA_LocaleValue& CXFA_LocaleValue::operator=(const CXFA_LocaleValue& value) { 69 m_wsValue = value.m_wsValue; 70 m_dwType = value.m_dwType; 71 m_bValid = value.m_bValid; 72 m_pLocaleMgr = value.m_pLocaleMgr; 73 return *this; 74 } 75 CXFA_LocaleValue::~CXFA_LocaleValue() {} 76 static FX_LOCALECATEGORY XFA_ValugeCategory(FX_LOCALECATEGORY eCategory, 77 FX_DWORD dwValueType) { 78 if (eCategory == FX_LOCALECATEGORY_Unknown) { 79 switch (dwValueType) { 80 case XFA_VT_BOOLEAN: 81 case XFA_VT_INTEGER: 82 case XFA_VT_DECIMAL: 83 case XFA_VT_FLOAT: 84 return FX_LOCALECATEGORY_Num; 85 case XFA_VT_TEXT: 86 return FX_LOCALECATEGORY_Text; 87 case XFA_VT_DATE: 88 return FX_LOCALECATEGORY_Date; 89 case XFA_VT_TIME: 90 return FX_LOCALECATEGORY_Time; 91 case XFA_VT_DATETIME: 92 return FX_LOCALECATEGORY_DateTime; 93 } 94 } 95 return eCategory; 96 } 97 FX_BOOL CXFA_LocaleValue::ValidateValue(const CFX_WideString& wsValue, 98 const CFX_WideString& wsPattern, 99 IFX_Locale* pLocale, 100 CFX_WideString* pMatchFormat) { 101 CFX_WideString wsOutput; 102 IFX_Locale* locale = m_pLocaleMgr->GetDefLocale(); 103 if (pLocale) { 104 m_pLocaleMgr->SetDefLocale(pLocale); 105 } 106 IFX_FormatString* pFormat = IFX_FormatString::Create(m_pLocaleMgr, FALSE); 107 CFX_WideStringArray wsPatterns; 108 pFormat->SplitFormatString(wsPattern, wsPatterns); 109 FX_BOOL bRet = FALSE; 110 int32_t iCount = wsPatterns.GetSize(); 111 int32_t i = 0; 112 for (; i < iCount && !bRet; i++) { 113 CFX_WideString wsFormat = wsPatterns[i]; 114 FX_LOCALECATEGORY eCategory = pFormat->GetCategory(wsFormat); 115 eCategory = XFA_ValugeCategory(eCategory, m_dwType); 116 switch (eCategory) { 117 case FX_LOCALECATEGORY_Null: 118 bRet = pFormat->ParseNull(wsValue, wsFormat); 119 if (!bRet) { 120 bRet = wsValue.IsEmpty(); 121 } 122 break; 123 case FX_LOCALECATEGORY_Zero: 124 bRet = pFormat->ParseZero(wsValue, wsFormat); 125 if (!bRet) { 126 bRet = wsValue == FX_WSTRC(L"0"); 127 } 128 break; 129 case FX_LOCALECATEGORY_Num: { 130 CFX_WideString fNum; 131 bRet = pFormat->ParseNum(wsValue, wsFormat, fNum); 132 if (!bRet) { 133 bRet = pFormat->FormatNum(wsValue, wsFormat, wsOutput); 134 } 135 break; 136 } 137 case FX_LOCALECATEGORY_Text: 138 bRet = pFormat->ParseText(wsValue, wsFormat, wsOutput); 139 wsOutput.Empty(); 140 if (!bRet) { 141 bRet = pFormat->FormatText(wsValue, wsFormat, wsOutput); 142 } 143 break; 144 case FX_LOCALECATEGORY_Date: { 145 CFX_Unitime dt; 146 bRet = ValidateCanonicalDate(wsValue, dt); 147 if (!bRet) { 148 bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date, 149 dt); 150 if (!bRet) { 151 bRet = pFormat->FormatDateTime(wsValue, wsFormat, wsOutput, 152 FX_DATETIMETYPE_Date); 153 } 154 } 155 break; 156 } 157 case FX_LOCALECATEGORY_Time: { 158 CFX_Unitime dt; 159 bRet = 160 pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time, dt); 161 if (!bRet) { 162 bRet = pFormat->FormatDateTime(wsValue, wsFormat, wsOutput, 163 FX_DATETIMETYPE_Time); 164 } 165 break; 166 } 167 case FX_LOCALECATEGORY_DateTime: { 168 CFX_Unitime dt; 169 bRet = pFormat->ParseDateTime(wsValue, wsFormat, 170 FX_DATETIMETYPE_DateTime, dt); 171 if (!bRet) { 172 bRet = pFormat->FormatDateTime(wsValue, wsFormat, wsOutput, 173 FX_DATETIMETYPE_DateTime); 174 } 175 break; 176 } 177 default: 178 bRet = FALSE; 179 break; 180 } 181 } 182 if (bRet && pMatchFormat) { 183 *pMatchFormat = wsPatterns[i - 1]; 184 } 185 pFormat->Release(); 186 if (pLocale) { 187 m_pLocaleMgr->SetDefLocale(locale); 188 } 189 return bRet; 190 } 191 CFX_WideString CXFA_LocaleValue::GetValue() const { 192 return m_wsValue; 193 } 194 FX_DWORD CXFA_LocaleValue::GetType() const { 195 return m_dwType; 196 } 197 void CXFA_LocaleValue::SetValue(const CFX_WideString& wsValue, 198 FX_DWORD dwType) { 199 m_wsValue = wsValue; 200 m_dwType = dwType; 201 } 202 CFX_WideString CXFA_LocaleValue::GetText() const { 203 if (m_bValid && m_dwType == XFA_VT_TEXT) { 204 return m_wsValue; 205 } 206 return CFX_WideString(); 207 } 208 FX_FLOAT CXFA_LocaleValue::GetNum() const { 209 if (m_bValid && (m_dwType == XFA_VT_BOOLEAN || m_dwType == XFA_VT_INTEGER || 210 m_dwType == XFA_VT_DECIMAL || m_dwType == XFA_VT_FLOAT)) { 211 int64_t nIntegral = 0; 212 FX_DWORD dwFractional = 0; 213 int32_t nExponent = 0; 214 int cc = 0; 215 FX_BOOL bNegative = FALSE, bExpSign = FALSE; 216 const FX_WCHAR* str = (const FX_WCHAR*)m_wsValue; 217 int len = m_wsValue.GetLength(); 218 while (XFA_IsSpace(str[cc]) && cc < len) { 219 cc++; 220 } 221 if (cc >= len) { 222 return 0; 223 } 224 if (str[0] == '+') { 225 cc++; 226 } else if (str[0] == '-') { 227 bNegative = TRUE; 228 cc++; 229 } 230 int nIntegralLen = 0; 231 while (cc < len) { 232 if (str[cc] == '.' || !XFA_IsDigit(str[cc]) || nIntegralLen > 17) { 233 break; 234 } 235 nIntegral = nIntegral * 10 + str[cc] - '0'; 236 cc++; 237 nIntegralLen++; 238 } 239 nIntegral = bNegative ? -nIntegral : nIntegral; 240 int scale = 0; 241 double fraction = 0.0; 242 if (cc < len && str[cc] == '.') { 243 cc++; 244 while (cc < len) { 245 fraction += fraction_scales[scale] * (str[cc] - '0'); 246 scale++; 247 cc++; 248 if (scale == sizeof fraction_scales / sizeof(double) || 249 !XFA_IsDigit(str[cc])) { 250 break; 251 } 252 } 253 dwFractional = (FX_DWORD)(fraction * 4294967296.0); 254 } 255 if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) { 256 cc++; 257 if (cc < len) { 258 if (str[cc] == '+') { 259 cc++; 260 } else if (str[cc] == '-') { 261 bExpSign = TRUE; 262 cc++; 263 } 264 } 265 while (cc < len) { 266 if (str[cc] == '.' || !XFA_IsDigit(str[cc])) { 267 break; 268 } 269 nExponent = nExponent * 10 + str[cc] - '0'; 270 cc++; 271 } 272 nExponent = bExpSign ? -nExponent : nExponent; 273 } 274 FX_FLOAT fValue = (FX_FLOAT)(dwFractional / 4294967296.0); 275 fValue = nIntegral + (nIntegral >= 0 ? fValue : -fValue); 276 if (nExponent != 0) { 277 fValue *= FXSYS_pow(10, (FX_FLOAT)nExponent); 278 } 279 return fValue; 280 } 281 return 0; 282 } 283 FX_DOUBLE CXFA_LocaleValue::GetDoubleNum() const { 284 if (m_bValid && (m_dwType == XFA_VT_BOOLEAN || m_dwType == XFA_VT_INTEGER || 285 m_dwType == XFA_VT_DECIMAL || m_dwType == XFA_VT_FLOAT)) { 286 int64_t nIntegral = 0; 287 FX_DWORD dwFractional = 0; 288 int32_t nExponent = 0; 289 int32_t cc = 0; 290 FX_BOOL bNegative = FALSE, bExpSign = FALSE; 291 const FX_WCHAR* str = (const FX_WCHAR*)m_wsValue; 292 int len = m_wsValue.GetLength(); 293 while (XFA_IsSpace(str[cc]) && cc < len) { 294 cc++; 295 } 296 if (cc >= len) { 297 return 0; 298 } 299 if (str[0] == '+') { 300 cc++; 301 } else if (str[0] == '-') { 302 bNegative = TRUE; 303 cc++; 304 } 305 int32_t nIntegralLen = 0; 306 while (cc < len) { 307 if (str[cc] == '.' || !XFA_IsDigit(str[cc]) || nIntegralLen > 17) { 308 break; 309 } 310 nIntegral = nIntegral * 10 + str[cc] - '0'; 311 cc++; 312 nIntegralLen++; 313 } 314 nIntegral = bNegative ? -nIntegral : nIntegral; 315 int32_t scale = 0; 316 FX_DOUBLE fraction = 0.0; 317 if (cc < len && str[cc] == '.') { 318 cc++; 319 while (cc < len) { 320 fraction += fraction_scales[scale] * (str[cc] - '0'); 321 scale++; 322 cc++; 323 if (scale == sizeof fraction_scales / sizeof(FX_DOUBLE) || 324 !XFA_IsDigit(str[cc])) { 325 break; 326 } 327 } 328 dwFractional = (FX_DWORD)(fraction * 4294967296.0); 329 } 330 if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) { 331 cc++; 332 if (cc < len) { 333 if (str[cc] == '+') { 334 cc++; 335 } else if (str[cc] == '-') { 336 bExpSign = TRUE; 337 cc++; 338 } 339 } 340 while (cc < len) { 341 if (str[cc] == '.' || !XFA_IsDigit(str[cc])) { 342 break; 343 } 344 nExponent = nExponent * 10 + str[cc] - '0'; 345 cc++; 346 } 347 nExponent = bExpSign ? -nExponent : nExponent; 348 } 349 FX_DOUBLE dValue = (dwFractional / 4294967296.0); 350 dValue = nIntegral + (nIntegral >= 0 ? dValue : -dValue); 351 if (nExponent != 0) { 352 dValue *= FXSYS_pow(10, (FX_FLOAT)nExponent); 353 } 354 return dValue; 355 } 356 return 0; 357 } 358 CFX_Unitime CXFA_LocaleValue::GetDate() const { 359 if (m_bValid && m_dwType == XFA_VT_DATE) { 360 CFX_Unitime dt; 361 FX_DateFromCanonical(m_wsValue, dt); 362 return dt; 363 } 364 return CFX_Unitime(); 365 } 366 CFX_Unitime CXFA_LocaleValue::GetTime() const { 367 if (m_bValid && m_dwType == XFA_VT_TIME) { 368 CFX_Unitime dt(0); 369 FXSYS_assert(m_pLocaleMgr); 370 FX_TimeFromCanonical(m_wsValue, dt, m_pLocaleMgr->GetDefLocale()); 371 return dt; 372 } 373 return CFX_Unitime(); 374 } 375 CFX_Unitime CXFA_LocaleValue::GetDateTime() const { 376 if (m_bValid && m_dwType == XFA_VT_DATETIME) { 377 int32_t index = m_wsValue.Find('T'); 378 CFX_Unitime dt; 379 FX_DateFromCanonical(m_wsValue.Left(index), dt); 380 FXSYS_assert(m_pLocaleMgr); 381 FX_TimeFromCanonical(m_wsValue.Right(m_wsValue.GetLength() - index - 1), dt, 382 m_pLocaleMgr->GetDefLocale()); 383 return dt; 384 } 385 return CFX_Unitime(); 386 } 387 FX_BOOL CXFA_LocaleValue::SetText(const CFX_WideString& wsText) { 388 m_dwType = XFA_VT_TEXT; 389 m_wsValue = wsText; 390 return TRUE; 391 } 392 FX_BOOL CXFA_LocaleValue::SetText(const CFX_WideString& wsText, 393 const CFX_WideString& wsFormat, 394 IFX_Locale* pLocale) { 395 m_dwType = XFA_VT_TEXT; 396 return m_bValid = ParsePatternValue(wsText, wsFormat, pLocale); 397 } 398 FX_BOOL CXFA_LocaleValue::SetNum(FX_FLOAT fNum) { 399 m_dwType = XFA_VT_FLOAT; 400 m_wsValue.Format(L"%.8g", (FX_DOUBLE)fNum); 401 return TRUE; 402 } 403 FX_BOOL CXFA_LocaleValue::SetNum(const CFX_WideString& wsNum, 404 const CFX_WideString& wsFormat, 405 IFX_Locale* pLocale) { 406 m_dwType = XFA_VT_FLOAT; 407 return m_bValid = ParsePatternValue(wsNum, wsFormat, pLocale); 408 } 409 FX_BOOL CXFA_LocaleValue::SetDate(const CFX_Unitime& d) { 410 m_dwType = XFA_VT_DATE; 411 m_wsValue.Format(L"%04d-%02d-%02d", d.GetYear(), d.GetMonth(), d.GetDay()); 412 return TRUE; 413 } 414 FX_BOOL CXFA_LocaleValue::SetDate(const CFX_WideString& wsDate, 415 const CFX_WideString& wsFormat, 416 IFX_Locale* pLocale) { 417 m_dwType = XFA_VT_DATE; 418 return m_bValid = ParsePatternValue(wsDate, wsFormat, pLocale); 419 } 420 FX_BOOL CXFA_LocaleValue::SetTime(const CFX_Unitime& t) { 421 m_dwType = XFA_VT_TIME; 422 m_wsValue.Format(L"%02d:%02d:%02d", t.GetHour(), t.GetMinute(), 423 t.GetSecond()); 424 if (t.GetMillisecond() > 0) { 425 CFX_WideString wsTemp; 426 wsTemp.Format(L"%:03d", t.GetMillisecond()); 427 m_wsValue += wsTemp; 428 } 429 return TRUE; 430 } 431 FX_BOOL CXFA_LocaleValue::SetTime(const CFX_WideString& wsTime, 432 const CFX_WideString& wsFormat, 433 IFX_Locale* pLocale) { 434 m_dwType = XFA_VT_TIME; 435 return m_bValid = ParsePatternValue(wsTime, wsFormat, pLocale); 436 } 437 FX_BOOL CXFA_LocaleValue::SetDateTime(const CFX_Unitime& dt) { 438 m_dwType = XFA_VT_DATETIME; 439 m_wsValue.Format(L"%04d-%02d-%02dT%02d:%02d:%02d", dt.GetYear(), 440 dt.GetMonth(), dt.GetDay(), dt.GetHour(), dt.GetMinute(), 441 dt.GetSecond()); 442 if (dt.GetMillisecond() > 0) { 443 CFX_WideString wsTemp; 444 wsTemp.Format(L"%:03d", dt.GetMillisecond()); 445 m_wsValue += wsTemp; 446 } 447 return TRUE; 448 } 449 FX_BOOL CXFA_LocaleValue::SetDateTime(const CFX_WideString& wsDateTime, 450 const CFX_WideString& wsFormat, 451 IFX_Locale* pLocale) { 452 m_dwType = XFA_VT_DATETIME; 453 return m_bValid = ParsePatternValue(wsDateTime, wsFormat, pLocale); 454 } 455 FX_BOOL CXFA_LocaleValue::FormatPatterns(CFX_WideString& wsResult, 456 const CFX_WideString& wsFormat, 457 IFX_Locale* pLocale, 458 XFA_VALUEPICTURE eValueType) const { 459 wsResult.Empty(); 460 FX_BOOL bRet = FALSE; 461 IFX_FormatString* pFormat = IFX_FormatString::Create(m_pLocaleMgr, FALSE); 462 CFX_WideStringArray wsPatterns; 463 pFormat->SplitFormatString(wsFormat, wsPatterns); 464 int32_t iCount = wsPatterns.GetSize(); 465 for (int32_t i = 0; i < iCount; i++) { 466 bRet = FormatSinglePattern(wsResult, wsPatterns[i], pLocale, eValueType); 467 if (bRet) { 468 break; 469 } 470 } 471 pFormat->Release(); 472 return bRet; 473 } 474 FX_BOOL CXFA_LocaleValue::FormatSinglePattern( 475 CFX_WideString& wsResult, 476 const CFX_WideString& wsFormat, 477 IFX_Locale* pLocale, 478 XFA_VALUEPICTURE eValueType) const { 479 IFX_Locale* locale = m_pLocaleMgr->GetDefLocale(); 480 if (pLocale) { 481 m_pLocaleMgr->SetDefLocale(pLocale); 482 } 483 wsResult.Empty(); 484 FX_BOOL bRet = FALSE; 485 IFX_FormatString* pFormat = IFX_FormatString::Create(m_pLocaleMgr, FALSE); 486 FX_LOCALECATEGORY eCategory = pFormat->GetCategory(wsFormat); 487 eCategory = XFA_ValugeCategory(eCategory, m_dwType); 488 switch (eCategory) { 489 case FX_LOCALECATEGORY_Null: 490 if (m_wsValue.IsEmpty()) { 491 bRet = pFormat->FormatNull(wsFormat, wsResult); 492 } 493 break; 494 case FX_LOCALECATEGORY_Zero: 495 if (m_wsValue == FX_WSTRC(L"0")) { 496 bRet = pFormat->FormatZero(wsFormat, wsResult); 497 } 498 break; 499 case FX_LOCALECATEGORY_Num: 500 bRet = pFormat->FormatNum(m_wsValue, wsFormat, wsResult); 501 break; 502 case FX_LOCALECATEGORY_Text: 503 bRet = pFormat->FormatText(m_wsValue, wsFormat, wsResult); 504 break; 505 case FX_LOCALECATEGORY_Date: 506 bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, wsResult, 507 FX_DATETIMETYPE_Date); 508 break; 509 case FX_LOCALECATEGORY_Time: 510 bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, wsResult, 511 FX_DATETIMETYPE_Time); 512 break; 513 case FX_LOCALECATEGORY_DateTime: 514 bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, wsResult, 515 FX_DATETIMETYPE_DateTime); 516 break; 517 default: 518 wsResult = m_wsValue; 519 bRet = TRUE; 520 } 521 pFormat->Release(); 522 if (!bRet && (eCategory != FX_LOCALECATEGORY_Num || 523 eValueType != XFA_VALUEPICTURE_Display)) { 524 wsResult = m_wsValue; 525 } 526 if (pLocale) { 527 m_pLocaleMgr->SetDefLocale(locale); 528 } 529 return bRet; 530 } 531 static FX_BOOL XFA_ValueSplitDateTime(const CFX_WideString& wsDateTime, 532 CFX_WideString& wsDate, 533 CFX_WideString& wsTime) { 534 wsDate = L""; 535 wsTime = L""; 536 if (wsDateTime.IsEmpty()) { 537 return FALSE; 538 } 539 int nSplitIndex = -1; 540 nSplitIndex = wsDateTime.Find('T'); 541 if (nSplitIndex < 0) { 542 nSplitIndex = wsDateTime.Find(' '); 543 } 544 if (nSplitIndex < 0) { 545 return FALSE; 546 } 547 wsDate = wsDateTime.Left(nSplitIndex); 548 wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex - 1); 549 return TRUE; 550 } 551 FX_BOOL CXFA_LocaleValue::ValidateCanonicalValue(const CFX_WideString& wsValue, 552 FX_DWORD dwVType) { 553 if (wsValue.IsEmpty()) { 554 return TRUE; 555 } 556 CFX_Unitime dt; 557 switch (dwVType) { 558 case XFA_VT_DATE: { 559 if (ValidateCanonicalDate(wsValue, dt)) { 560 return TRUE; 561 } 562 CFX_WideString wsDate, wsTime; 563 if (XFA_ValueSplitDateTime(wsValue, wsDate, wsTime) && 564 ValidateCanonicalDate(wsDate, dt)) { 565 return TRUE; 566 } 567 return FALSE; 568 } 569 case XFA_VT_TIME: { 570 if (ValidateCanonicalTime(wsValue)) { 571 return TRUE; 572 } 573 CFX_WideString wsDate, wsTime; 574 if (XFA_ValueSplitDateTime(wsValue, wsDate, wsTime) && 575 ValidateCanonicalTime(wsTime)) { 576 return TRUE; 577 } 578 return FALSE; 579 } 580 case XFA_VT_DATETIME: { 581 CFX_WideString wsDate, wsTime; 582 if (XFA_ValueSplitDateTime(wsValue, wsDate, wsTime) && 583 ValidateCanonicalDate(wsDate, dt) && ValidateCanonicalTime(wsTime)) { 584 return TRUE; 585 } 586 } break; 587 } 588 return TRUE; 589 } 590 FX_BOOL CXFA_LocaleValue::ValidateCanonicalDate(const CFX_WideString& wsDate, 591 CFX_Unitime& unDate) { 592 const FX_WORD LastDay[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 593 const FX_WORD wCountY = 4, wCountM = 2, wCountD = 2; 594 int nLen = wsDate.GetLength(); 595 if (nLen < wCountY || nLen > wCountY + wCountM + wCountD + 2) { 596 return FALSE; 597 } 598 FX_BOOL bSymbol = (wsDate.Find(0x2D) == -1) ? FALSE : TRUE; 599 FX_WORD wYear = 0, wMonth = 0, wDay = 0; 600 const FX_WCHAR* pDate = (const FX_WCHAR*)wsDate; 601 int nIndex = 0, nStart = 0; 602 while (pDate[nIndex] != '\0' && nIndex < wCountY) { 603 if (!XFA_IsDigit(pDate[nIndex])) { 604 return FALSE; 605 } 606 wYear = (pDate[nIndex] - '0') + wYear * 10; 607 nIndex++; 608 } 609 if (bSymbol) { 610 if (pDate[nIndex] != 0x2D) { 611 return FALSE; 612 } 613 nIndex++; 614 } 615 nStart = nIndex; 616 while (pDate[nIndex] != '\0' && nIndex - nStart < wCountM && nIndex < nLen) { 617 if (!XFA_IsDigit(pDate[nIndex])) { 618 return FALSE; 619 } 620 wMonth = (pDate[nIndex] - '0') + wMonth * 10; 621 nIndex++; 622 } 623 if (bSymbol) { 624 if (pDate[nIndex] != 0x2D) { 625 return FALSE; 626 } 627 nIndex++; 628 } 629 nStart = nIndex; 630 while (pDate[nIndex] != '\0' && nIndex - nStart < wCountD && nIndex < nLen) { 631 if (!XFA_IsDigit(pDate[nIndex])) { 632 return FALSE; 633 } 634 wDay = (pDate[nIndex] - '0') + wDay * 10; 635 nIndex++; 636 } 637 if (nIndex != nLen) { 638 return FALSE; 639 } 640 if (wYear < 1900 || wYear > 2029) { 641 return FALSE; 642 } 643 if (wMonth < 1 || wMonth > 12) { 644 if (wMonth == 0 && nLen == wCountY) { 645 return TRUE; 646 } 647 return FALSE; 648 } 649 if (wDay < 1) { 650 if (wDay == 0 && (nLen == wCountY + wCountM)) { 651 return TRUE; 652 } 653 return FALSE; 654 } 655 if (wMonth == 2) { 656 if (wYear % 400 == 0 || (wYear % 100 != 0 && wYear % 4 == 0)) { 657 if (wDay > 29) { 658 return FALSE; 659 } 660 } else { 661 if (wDay > 28) { 662 return FALSE; 663 } 664 } 665 } else if (wDay > LastDay[wMonth - 1]) { 666 return FALSE; 667 } 668 CFX_Unitime ut; 669 ut.Set(wYear, static_cast<uint8_t>(wMonth), static_cast<uint8_t>(wDay)); 670 unDate = unDate + ut; 671 return TRUE; 672 } 673 FX_BOOL CXFA_LocaleValue::ValidateCanonicalTime(const CFX_WideString& wsTime) { 674 int nLen = wsTime.GetLength(); 675 if (nLen < 2) { 676 return FALSE; 677 } 678 const FX_WORD wCountH = 2, wCountM = 2, wCountS = 2, wCountF = 3; 679 FX_BOOL bSymbol = (wsTime.Find(':') == -1) ? FALSE : TRUE; 680 FX_WORD wHour = 0, wMinute = 0, wSecond = 0, wFraction = 0; 681 const FX_WCHAR* pTime = (const FX_WCHAR*)wsTime; 682 int nIndex = 0, nStart = 0; 683 while (pTime[nIndex] != '\0' && nIndex - nStart < wCountH) { 684 if (!XFA_IsDigit(pTime[nIndex])) { 685 return FALSE; 686 } 687 wHour = (pTime[nIndex] - '0') + wHour * 10; 688 nIndex++; 689 } 690 if (bSymbol) { 691 if (nIndex < nLen && pTime[nIndex] != ':') { 692 return FALSE; 693 } 694 nIndex++; 695 } 696 nStart = nIndex; 697 while (pTime[nIndex] != '\0' && nIndex - nStart < wCountM && nIndex < nLen) { 698 if (!XFA_IsDigit(pTime[nIndex])) { 699 return FALSE; 700 } 701 wMinute = (pTime[nIndex] - '0') + wMinute * 10; 702 nIndex++; 703 } 704 if (bSymbol) { 705 if (nIndex < nLen && pTime[nIndex] != ':') { 706 return FALSE; 707 } 708 nIndex++; 709 } 710 nStart = nIndex; 711 while (pTime[nIndex] != '\0' && nIndex - nStart < wCountS && nIndex < nLen) { 712 if (!XFA_IsDigit(pTime[nIndex])) { 713 return FALSE; 714 } 715 wSecond = (pTime[nIndex] - '0') + wSecond * 10; 716 nIndex++; 717 } 718 if (wsTime.Find('.') > 0) { 719 if (pTime[nIndex] != '.') { 720 return FALSE; 721 } 722 nIndex++; 723 nStart = nIndex; 724 while (pTime[nIndex] != '\0' && nIndex - nStart < wCountF && 725 nIndex < nLen) { 726 if (!XFA_IsDigit(pTime[nIndex])) { 727 return FALSE; 728 } 729 wFraction = (pTime[nIndex] - '0') + wFraction * 10; 730 nIndex++; 731 } 732 } 733 if (nIndex < nLen) { 734 if (pTime[nIndex] == 'Z') { 735 nIndex++; 736 } else if (pTime[nIndex] == '-' || pTime[nIndex] == '+') { 737 int16_t nOffsetH = 0, nOffsetM = 0; 738 nIndex++; 739 nStart = nIndex; 740 while (pTime[nIndex] != '\0' && nIndex - nStart < wCountH && 741 nIndex < nLen) { 742 if (!XFA_IsDigit(pTime[nIndex])) { 743 return FALSE; 744 } 745 nOffsetH = (pTime[nIndex] - '0') + nOffsetH * 10; 746 nIndex++; 747 } 748 if (bSymbol) { 749 if (nIndex < nLen && pTime[nIndex] != ':') { 750 return FALSE; 751 } 752 nIndex++; 753 } 754 nStart = nIndex; 755 while (pTime[nIndex] != '\0' && nIndex - nStart < wCountM && 756 nIndex < nLen) { 757 if (!XFA_IsDigit(pTime[nIndex])) { 758 return FALSE; 759 } 760 nOffsetM = (pTime[nIndex] - '0') + nOffsetM * 10; 761 nIndex++; 762 } 763 if (nOffsetH > 12) { 764 return FALSE; 765 } 766 if (nOffsetM >= 60) { 767 return FALSE; 768 } 769 } 770 } 771 if (nIndex != nLen) { 772 return FALSE; 773 } 774 if (wHour >= 24) { 775 return FALSE; 776 } 777 if (wMinute >= 60) { 778 return FALSE; 779 } 780 if (wSecond >= 60) { 781 return FALSE; 782 } 783 if (wFraction > 999) { 784 return FALSE; 785 } 786 return TRUE; 787 } 788 FX_BOOL CXFA_LocaleValue::ValidateCanonicalDateTime( 789 const CFX_WideString& wsDateTime) { 790 CFX_WideString wsDate, wsTime; 791 if (wsDateTime.IsEmpty()) { 792 return FALSE; 793 } 794 int nSplitIndex = -1; 795 nSplitIndex = wsDateTime.Find('T'); 796 if (nSplitIndex < 0) { 797 nSplitIndex = wsDateTime.Find(' '); 798 } 799 if (nSplitIndex < 0) { 800 return FALSE; 801 } 802 wsDate = wsDateTime.Left(nSplitIndex); 803 wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex - 1); 804 CFX_Unitime dt; 805 return ValidateCanonicalDate(wsDate, dt) && ValidateCanonicalTime(wsTime); 806 } 807 FX_BOOL CXFA_LocaleValue::ParsePatternValue(const CFX_WideString& wsValue, 808 const CFX_WideString& wsPattern, 809 IFX_Locale* pLocale) { 810 IFX_Locale* locale = m_pLocaleMgr->GetDefLocale(); 811 if (pLocale) { 812 m_pLocaleMgr->SetDefLocale(pLocale); 813 } 814 IFX_FormatString* pFormat = IFX_FormatString::Create(m_pLocaleMgr, FALSE); 815 CFX_WideStringArray wsPatterns; 816 pFormat->SplitFormatString(wsPattern, wsPatterns); 817 FX_BOOL bRet = FALSE; 818 int32_t iCount = wsPatterns.GetSize(); 819 for (int32_t i = 0; i < iCount && !bRet; i++) { 820 CFX_WideString wsFormat = wsPatterns[i]; 821 FX_LOCALECATEGORY eCategory = pFormat->GetCategory(wsFormat); 822 eCategory = XFA_ValugeCategory(eCategory, m_dwType); 823 switch (eCategory) { 824 case FX_LOCALECATEGORY_Null: 825 bRet = pFormat->ParseNull(wsValue, wsFormat); 826 if (bRet) { 827 m_wsValue.Empty(); 828 } 829 break; 830 case FX_LOCALECATEGORY_Zero: 831 bRet = pFormat->ParseZero(wsValue, wsFormat); 832 if (bRet) { 833 m_wsValue = FX_WSTRC(L"0"); 834 } 835 break; 836 case FX_LOCALECATEGORY_Num: { 837 CFX_WideString fNum; 838 bRet = pFormat->ParseNum(wsValue, wsFormat, fNum); 839 if (bRet) { 840 m_wsValue = fNum; 841 } 842 break; 843 } 844 case FX_LOCALECATEGORY_Text: 845 bRet = pFormat->ParseText(wsValue, wsFormat, m_wsValue); 846 break; 847 case FX_LOCALECATEGORY_Date: { 848 CFX_Unitime dt; 849 bRet = ValidateCanonicalDate(wsValue, dt); 850 if (!bRet) { 851 bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date, 852 dt); 853 } 854 if (bRet) { 855 SetDate(dt); 856 } 857 break; 858 } 859 case FX_LOCALECATEGORY_Time: { 860 CFX_Unitime dt; 861 bRet = 862 pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time, dt); 863 if (bRet) { 864 SetTime(dt); 865 } 866 break; 867 } 868 case FX_LOCALECATEGORY_DateTime: { 869 CFX_Unitime dt; 870 bRet = pFormat->ParseDateTime(wsValue, wsFormat, 871 FX_DATETIMETYPE_DateTime, dt); 872 if (bRet) { 873 SetDateTime(dt); 874 } 875 break; 876 } 877 default: 878 m_wsValue = wsValue; 879 bRet = TRUE; 880 break; 881 } 882 } 883 if (!bRet) { 884 m_wsValue = wsValue; 885 } 886 pFormat->Release(); 887 if (pLocale) { 888 m_pLocaleMgr->SetDefLocale(locale); 889 } 890 return bRet; 891 } 892 void CXFA_LocaleValue::GetNumbericFormat(CFX_WideString& wsFormat, 893 int32_t nIntLen, 894 int32_t nDecLen, 895 FX_BOOL bSign) { 896 FXSYS_assert(wsFormat.IsEmpty()); 897 FXSYS_assert(nIntLen >= -1 && nDecLen >= -1); 898 int32_t nTotalLen = (nIntLen >= 0 ? nIntLen : 2) + (bSign ? 1 : 0) + 899 (nDecLen >= 0 ? nDecLen : 2) + (nDecLen == 0 ? 0 : 1); 900 FX_WCHAR* lpBuf = wsFormat.GetBuffer(nTotalLen); 901 int32_t nPos = 0; 902 if (bSign) { 903 lpBuf[nPos++] = L's'; 904 } 905 if (nIntLen == -1) { 906 lpBuf[nPos++] = L'z'; 907 lpBuf[nPos++] = L'*'; 908 } else { 909 while (nIntLen) { 910 lpBuf[nPos++] = L'z'; 911 nIntLen--; 912 } 913 } 914 if (nDecLen != 0) { 915 lpBuf[nPos++] = L'.'; 916 } 917 if (nDecLen == -1) { 918 lpBuf[nPos++] = L'z'; 919 lpBuf[nPos++] = L'*'; 920 } else { 921 while (nDecLen) { 922 lpBuf[nPos++] = L'z'; 923 nDecLen--; 924 } 925 } 926 wsFormat.ReleaseBuffer(nTotalLen); 927 } 928 FX_BOOL CXFA_LocaleValue::ValidateNumericTemp(CFX_WideString& wsNumeric, 929 CFX_WideString& wsFormat, 930 IFX_Locale* pLocale, 931 int32_t* pos) { 932 if (wsFormat.IsEmpty() || wsNumeric.IsEmpty()) { 933 return TRUE; 934 } 935 const FX_WCHAR* pNum = wsNumeric.c_str(); 936 const FX_WCHAR* pFmt = wsFormat.c_str(); 937 int32_t n = 0, nf = 0; 938 FX_WCHAR c = pNum[n]; 939 FX_WCHAR cf = pFmt[nf]; 940 if (cf == L's') { 941 if (c == L'-' || c == L'+') { 942 ++n; 943 } 944 ++nf; 945 } 946 FX_BOOL bLimit = TRUE; 947 int32_t nCount = wsNumeric.GetLength(); 948 int32_t nCountFmt = wsFormat.GetLength(); 949 while (n < nCount && (bLimit ? nf < nCountFmt : TRUE) && 950 XFA_IsDigit(c = pNum[n])) { 951 if (bLimit == TRUE) { 952 if ((cf = pFmt[nf]) == L'*') { 953 bLimit = FALSE; 954 } else if (cf == L'z') { 955 nf++; 956 } else { 957 return FALSE; 958 } 959 } 960 n++; 961 } 962 if (n == nCount) { 963 return TRUE; 964 } 965 if (nf == nCountFmt) { 966 return FALSE; 967 } 968 while (nf < nCountFmt && (cf = pFmt[nf]) != L'.') { 969 FXSYS_assert(cf == L'z' || cf == L'*'); 970 ++nf; 971 } 972 CFX_WideString wsDecimalSymbol; 973 if (pLocale) { 974 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDecimalSymbol); 975 } else { 976 wsDecimalSymbol = CFX_WideString(L'.'); 977 } 978 if (pFmt[nf] != L'.') { 979 return FALSE; 980 } 981 if (wsDecimalSymbol != CFX_WideStringC(c) && c != L'.') { 982 return FALSE; 983 } 984 ++nf; 985 ++n; 986 bLimit = TRUE; 987 while (n < nCount && (bLimit ? nf < nCountFmt : TRUE) && 988 XFA_IsDigit(c = pNum[n])) { 989 if (bLimit == TRUE) { 990 if ((cf = pFmt[nf]) == L'*') { 991 bLimit = FALSE; 992 } else if (cf == L'z') { 993 nf++; 994 } else { 995 return FALSE; 996 } 997 } 998 n++; 999 } 1000 return n == nCount; 1001 } 1002