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