Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fxfa / src / parser / xfa_locale.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 #include "xfa_locale.h"\r
20 const static FX_LPCWSTR g_FX_Percent =  (FX_LPCWSTR)L"z,zzz,zzz,zzz,zzz,zzz%";\r
21 const static FX_LPCWSTR g_FX_Currency = (FX_LPCWSTR)L"$z,zzz,zzz,zzz,zzz,zz9.99";\r
22 const static FX_LPCWSTR g_FX_Decimal = (FX_LPCWSTR)L"z,zzz,zzz,zzz,zzz,zz9.zzz";\r
23 const static FX_LPCWSTR g_FX_Integer = (FX_LPCWSTR)L"z,zzz,zzz,zzz,zzz,zzz";\r
24 CXFA_XMLLocale::CXFA_XMLLocale(CXML_Element* pLocaleData)\r
25 {\r
26     m_pLocaleData = pLocaleData;\r
27 }\r
28 CXFA_XMLLocale::~CXFA_XMLLocale()\r
29 {\r
30     if (m_pLocaleData) {\r
31         delete m_pLocaleData;\r
32     }\r
33 }\r
34 void CXFA_XMLLocale::Release()\r
35 {\r
36     delete this;\r
37 }\r
38 CFX_WideString CXFA_XMLLocale::GetName()\r
39 {\r
40     return m_pLocaleData ? m_pLocaleData->GetAttrValue(FX_BSTRC("name")) : CFX_WideString();\r
41 }\r
42 void CXFA_XMLLocale::GetNumbericSymbol(FX_LOCALENUMSYMBOL eType, CFX_WideString& wsNumSymbol) const\r
43 {\r
44     CFX_ByteString bsSymbols;\r
45     CFX_WideString wsName;\r
46     switch (eType) {\r
47         case FX_LOCALENUMSYMBOL_Decimal:\r
48             bsSymbols = FX_BSTRC("numberSymbols");\r
49             wsName = FX_WSTRC(L"decimal");\r
50             break;\r
51         case FX_LOCALENUMSYMBOL_Grouping:\r
52             bsSymbols = FX_BSTRC("numberSymbols");\r
53             wsName = FX_WSTRC(L"grouping");\r
54             break;\r
55         case FX_LOCALENUMSYMBOL_Percent:\r
56             bsSymbols = FX_BSTRC("numberSymbols");\r
57             wsName = FX_WSTRC(L"percent");\r
58             break;\r
59         case FX_LOCALENUMSYMBOL_Minus:\r
60             bsSymbols = (FX_BSTRC("numberSymbols"));\r
61             wsName = FX_WSTRC(L"minus");\r
62             break;\r
63         case FX_LOCALENUMSYMBOL_Zero:\r
64             bsSymbols = (FX_BSTRC("numberSymbols"));\r
65             wsName = FX_WSTRC(L"zero");\r
66             break;\r
67         case FX_LOCALENUMSYMBOL_CurrencySymbol:\r
68             bsSymbols = (FX_BSTRC("currencySymbols"));\r
69             wsName = FX_WSTRC(L"symbol");\r
70             break;\r
71         case FX_LOCALENUMSYMBOL_CurrencyName:\r
72             bsSymbols = (FX_BSTRC("currencySymbols"));\r
73             wsName = FX_WSTRC(L"isoname");\r
74             break;\r
75         default:\r
76             return;\r
77     }\r
78     CXML_Element* pElement = m_pLocaleData->GetElement(FX_BSTRC(""), bsSymbols);\r
79     if (!pElement) {\r
80         return;\r
81     }\r
82     GetPattern(pElement, CFX_ByteStringC((FX_LPCSTR)bsSymbols, bsSymbols.GetLength() - 1), wsName, wsNumSymbol);\r
83 }\r
84 void CXFA_XMLLocale::GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const\r
85 {\r
86     if (!m_pLocaleData) {\r
87         return;\r
88     }\r
89     CFX_ByteString bsSpace;\r
90     CXML_Element* pNumberSymbols = m_pLocaleData->GetElement(bsSpace, FX_BSTRC("dateTimeSymbols"));\r
91     if (!pNumberSymbols) {\r
92         return;\r
93     }\r
94     wsDtSymbol = pNumberSymbols->GetContent(0);\r
95 }\r
96 void CXFA_XMLLocale::GetMonthName(FX_INT32 nMonth, CFX_WideString& wsMonthName, FX_BOOL bAbbr ) const\r
97 {\r
98     wsMonthName = GetCalendarSymbol(FX_BSTRC("month"), nMonth, bAbbr);\r
99 }\r
100 void CXFA_XMLLocale::GetDayName(FX_INT32 nWeek, CFX_WideString& wsDayName, FX_BOOL bAbbr ) const\r
101 {\r
102     wsDayName = GetCalendarSymbol(FX_BSTRC("day"), nWeek, bAbbr);\r
103 }\r
104 void CXFA_XMLLocale::GetMeridiemName(CFX_WideString& wsMeridiemName, FX_BOOL bAM ) const\r
105 {\r
106     wsMeridiemName = GetCalendarSymbol(FX_BSTRC("meridiem"), bAM ? 0 : 1, FALSE);\r
107 }\r
108 void CXFA_XMLLocale::GetTimeZone(FX_TIMEZONE& tz) const\r
109 {\r
110     IXFA_TimeZoneProvider* pProvider = IXFA_TimeZoneProvider::Get();\r
111     pProvider->GetTimeZone(tz);\r
112 }\r
113 void CXFA_XMLLocale::GetEraName(CFX_WideString& wsEraName, FX_BOOL bAD ) const\r
114 {\r
115     wsEraName = GetCalendarSymbol(FX_BSTRC("era"), bAD ? 1 : 0, FALSE);\r
116 }\r
117 CFX_WideString CXFA_XMLLocale::GetCalendarSymbol(FX_BSTR symbol, int index, FX_BOOL bAbbr) const\r
118 {\r
119     CFX_ByteString pstrSymbolNames = symbol + "Names";\r
120     CFX_WideString wsSymbolName = L"";\r
121     if (m_pLocaleData) {\r
122         CXML_Element *pChild = m_pLocaleData->GetElement("", FX_BSTRC("calendarSymbols"));\r
123         if (pChild) {\r
124             CXML_Element *pSymbolNames = pChild->GetElement("", pstrSymbolNames);\r
125             if (pSymbolNames) {\r
126                 if (pSymbolNames->GetAttrInteger(FX_BSTRC("abbr")) != bAbbr) {\r
127                     pSymbolNames = pChild->GetElement("", pstrSymbolNames, 1);\r
128                 }\r
129                 if (pSymbolNames && pSymbolNames->GetAttrInteger(FX_BSTRC("abbr")) == bAbbr) {\r
130                     CXML_Element *pSymbolName = pSymbolNames->GetElement("", symbol, index);\r
131                     if (pSymbolName) {\r
132                         wsSymbolName = pSymbolName->GetContent(0);\r
133                     }\r
134                 }\r
135             }\r
136         }\r
137     }\r
138     return wsSymbolName;\r
139 }\r
140 void CXFA_XMLLocale::GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType, CFX_WideString& wsPattern) const\r
141 {\r
142     CXML_Element* pElement = m_pLocaleData->GetElement(FX_BSTRC(""), FX_BSTRC("datePatterns"));\r
143     if (pElement == NULL) {\r
144         return;\r
145     }\r
146     CFX_WideString wsName;\r
147     switch (eType) {\r
148         case FX_LOCALEDATETIMESUBCATEGORY_Short:\r
149             wsName = L"short";\r
150             break;\r
151         case FX_LOCALEDATETIMESUBCATEGORY_Default:\r
152         case FX_LOCALEDATETIMESUBCATEGORY_Medium:\r
153             wsName = L"med";\r
154             break;\r
155         case FX_LOCALEDATETIMESUBCATEGORY_Full:\r
156             wsName = L"full";\r
157             break;\r
158         case FX_LOCALEDATETIMESUBCATEGORY_Long:\r
159             wsName = L"long";\r
160             break;\r
161     }\r
162     GetPattern(pElement, FX_BSTRC("datePattern"), wsName, wsPattern);\r
163 }\r
164 void CXFA_XMLLocale::GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType, CFX_WideString& wsPattern) const\r
165 {\r
166     CXML_Element* pElement = m_pLocaleData->GetElement(FX_BSTRC(""), FX_BSTRC("timePatterns"));\r
167     if (pElement == NULL) {\r
168         return;\r
169     }\r
170     CFX_WideString wsName;\r
171     switch (eType) {\r
172         case FX_LOCALEDATETIMESUBCATEGORY_Short:\r
173             wsName = L"short";\r
174             break;\r
175         case FX_LOCALEDATETIMESUBCATEGORY_Default:\r
176         case FX_LOCALEDATETIMESUBCATEGORY_Medium:\r
177             wsName = L"med";\r
178             break;\r
179         case FX_LOCALEDATETIMESUBCATEGORY_Full:\r
180             wsName = L"full";\r
181             break;\r
182         case FX_LOCALEDATETIMESUBCATEGORY_Long:\r
183             wsName = L"long";\r
184             break;\r
185     }\r
186     GetPattern(pElement, FX_BSTRC("timePattern"), wsName, wsPattern);\r
187 }\r
188 void CXFA_XMLLocale::GetNumPattern(FX_LOCALENUMSUBCATEGORY eType, CFX_WideString& wsPattern) const\r
189 {\r
190     CXML_Element* pElement = m_pLocaleData->GetElement(FX_BSTRC(""), FX_BSTRC("numberPatterns"));\r
191     if (pElement == NULL) {\r
192         return;\r
193     }\r
194     switch (eType) {\r
195         case FX_LOCALENUMPATTERN_Percent:\r
196             wsPattern = g_FX_Percent;\r
197             break;\r
198         case FX_LOCALENUMPATTERN_Currency:\r
199             wsPattern = g_FX_Currency;\r
200             break;\r
201         case FX_LOCALENUMPATTERN_Decimal:\r
202             wsPattern = g_FX_Decimal;\r
203             break;\r
204         case FX_LOCALENUMPATTERN_Integer:\r
205             wsPattern = g_FX_Integer;\r
206             break;\r
207     }\r
208 }\r
209 void CXFA_XMLLocale::GetPattern(CXML_Element* pElement, FX_BSTR bsTag, FX_WSTR wsName, CFX_WideString& wsPattern) const\r
210 {\r
211     FX_INT32 iCount = pElement->CountElements(FX_BSTRC(""), bsTag);\r
212     for (FX_INT32 i = 0; i < iCount; i++) {\r
213         CXML_Element* pChild = pElement->GetElement(FX_BSTRC(""), bsTag, i);\r
214         if (pChild->GetAttrValue(FX_BSTRC("name")) == wsName) {\r
215             wsPattern = pChild->GetContent(0);\r
216             return;\r
217         }\r
218     }\r
219 }\r
220 CXFA_NodeLocale::CXFA_NodeLocale(CXFA_Node *pLocale)\r
221 {\r
222     m_pLocale = pLocale;\r
223 }\r
224 CXFA_NodeLocale::~CXFA_NodeLocale()\r
225 {\r
226 }\r
227 void CXFA_NodeLocale::Release()\r
228 {\r
229     delete this;\r
230 }\r
231 CFX_WideString CXFA_NodeLocale::GetName()\r
232 {\r
233     return m_pLocale ? m_pLocale->GetCData(XFA_ATTRIBUTE_Name) : NULL;\r
234 }\r
235 void CXFA_NodeLocale::GetNumbericSymbol(FX_LOCALENUMSYMBOL eType, CFX_WideString& wsNumSymbol) const\r
236 {\r
237     switch (eType) {\r
238         case FX_LOCALENUMSYMBOL_Decimal:\r
239             wsNumSymbol = GetSymbol(XFA_ELEMENT_NumberSymbols, FX_WSTRC(L"decimal"));\r
240             break;\r
241         case FX_LOCALENUMSYMBOL_Grouping:\r
242             wsNumSymbol = GetSymbol(XFA_ELEMENT_NumberSymbols, FX_WSTRC(L"grouping"));\r
243             break;\r
244         case FX_LOCALENUMSYMBOL_Percent:\r
245             wsNumSymbol = GetSymbol(XFA_ELEMENT_NumberSymbols, FX_WSTRC(L"percent"));\r
246             break;\r
247         case FX_LOCALENUMSYMBOL_Minus:\r
248             wsNumSymbol = GetSymbol(XFA_ELEMENT_NumberSymbols, FX_WSTRC(L"minus"));\r
249             break;\r
250         case FX_LOCALENUMSYMBOL_Zero:\r
251             wsNumSymbol = GetSymbol(XFA_ELEMENT_NumberSymbols, FX_WSTRC(L"zero"));\r
252             break;\r
253         case FX_LOCALENUMSYMBOL_CurrencySymbol:\r
254             wsNumSymbol = GetSymbol(XFA_ELEMENT_CurrencySymbols, FX_WSTRC(L"symbol"));\r
255             break;\r
256         case FX_LOCALENUMSYMBOL_CurrencyName:\r
257             wsNumSymbol = GetSymbol(XFA_ELEMENT_CurrencySymbols, FX_WSTRC(L"isoname"));\r
258             break;\r
259     }\r
260 }\r
261 void CXFA_NodeLocale::GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const\r
262 {\r
263     CXFA_Node *pSymbols = m_pLocale ? m_pLocale->GetChild(0, XFA_ELEMENT_DateTimeSymbols) : NULL;\r
264     wsDtSymbol = pSymbols ? pSymbols->GetContent() : CFX_WideString();\r
265 }\r
266 void CXFA_NodeLocale::GetMonthName(FX_INT32 nMonth, CFX_WideString& wsMonthName, FX_BOOL bAbbr ) const\r
267 {\r
268     wsMonthName = GetCalendarSymbol(XFA_ELEMENT_MonthNames, nMonth, bAbbr);\r
269 }\r
270 void CXFA_NodeLocale::GetDayName(FX_INT32 nWeek, CFX_WideString& wsDayName, FX_BOOL bAbbr ) const\r
271 {\r
272     wsDayName = GetCalendarSymbol(XFA_ELEMENT_DayNames, nWeek, bAbbr);\r
273 }\r
274 void CXFA_NodeLocale::GetMeridiemName(CFX_WideString& wsMeridiemName, FX_BOOL bAM ) const\r
275 {\r
276     wsMeridiemName = GetCalendarSymbol(XFA_ELEMENT_MeridiemNames, bAM ? 0 : 1, FALSE);\r
277 }\r
278 void CXFA_NodeLocale::GetTimeZone(FX_TIMEZONE& tz) const\r
279 {\r
280     IXFA_TimeZoneProvider* pProvider = IXFA_TimeZoneProvider::Get();\r
281     pProvider->GetTimeZone(tz);\r
282 }\r
283 void CXFA_NodeLocale::GetEraName(CFX_WideString& wsEraName, FX_BOOL bAD ) const\r
284 {\r
285     wsEraName = GetCalendarSymbol(XFA_ELEMENT_EraNames, bAD ? 1 : 0, FALSE);\r
286 }\r
287 void CXFA_NodeLocale::GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType, CFX_WideString& wsPattern) const\r
288 {\r
289     switch (eType) {\r
290         case FX_LOCALEDATETIMESUBCATEGORY_Short:\r
291             wsPattern = GetSymbol(XFA_ELEMENT_DatePatterns, FX_WSTRC(L"short"));\r
292             break;\r
293         case FX_LOCALEDATETIMESUBCATEGORY_Medium:\r
294         case FX_LOCALEDATETIMESUBCATEGORY_Default:\r
295             wsPattern = GetSymbol(XFA_ELEMENT_DatePatterns, FX_WSTRC(L"med"));\r
296             break;\r
297         case FX_LOCALEDATETIMESUBCATEGORY_Full:\r
298             wsPattern = GetSymbol(XFA_ELEMENT_DatePatterns, FX_WSTRC(L"full"));\r
299             break;\r
300         case FX_LOCALEDATETIMESUBCATEGORY_Long:\r
301             wsPattern = GetSymbol(XFA_ELEMENT_DatePatterns, FX_WSTRC(L"long"));\r
302             break;\r
303     }\r
304 }\r
305 void CXFA_NodeLocale::GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType, CFX_WideString& wsPattern) const\r
306 {\r
307     switch (eType) {\r
308         case FX_LOCALEDATETIMESUBCATEGORY_Short:\r
309             wsPattern = GetSymbol(XFA_ELEMENT_TimePatterns, FX_WSTRC(L"short"));\r
310             break;\r
311         case FX_LOCALEDATETIMESUBCATEGORY_Medium:\r
312         case FX_LOCALEDATETIMESUBCATEGORY_Default:\r
313             wsPattern = GetSymbol(XFA_ELEMENT_TimePatterns, FX_WSTRC(L"med"));\r
314             break;\r
315         case FX_LOCALEDATETIMESUBCATEGORY_Full:\r
316             wsPattern = GetSymbol(XFA_ELEMENT_TimePatterns, FX_WSTRC(L"full"));\r
317             break;\r
318         case FX_LOCALEDATETIMESUBCATEGORY_Long:\r
319             wsPattern = GetSymbol(XFA_ELEMENT_TimePatterns, FX_WSTRC(L"long"));\r
320             break;\r
321     }\r
322 }\r
323 void CXFA_NodeLocale::GetNumPattern(FX_LOCALENUMSUBCATEGORY eType, CFX_WideString& wsPattern) const\r
324 {\r
325     switch (eType) {\r
326         case FX_LOCALENUMPATTERN_Percent:\r
327             wsPattern = g_FX_Percent;\r
328             break;\r
329         case FX_LOCALENUMPATTERN_Currency:\r
330             wsPattern = g_FX_Currency;\r
331             break;\r
332         case FX_LOCALENUMPATTERN_Decimal:\r
333             wsPattern = g_FX_Decimal;\r
334             break;\r
335         case FX_LOCALENUMPATTERN_Integer:\r
336             wsPattern = g_FX_Integer;\r
337             break;\r
338     }\r
339 }\r
340 CXFA_Node* CXFA_NodeLocale::GetNodeByName(CXFA_Node *pParent, FX_WSTR wsName) const\r
341 {\r
342     CXFA_Node *pChild = pParent ? pParent->GetNodeItem(XFA_NODEITEM_FirstChild) : NULL;\r
343     while (pChild) {\r
344         CFX_WideString wsChild;\r
345         if (pChild->GetAttribute(XFA_ATTRIBUTE_Name, wsChild)) {\r
346             if (wsChild == wsName) {\r
347                 return pChild;\r
348             }\r
349         }\r
350         pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling);\r
351     }\r
352     return NULL;\r
353 }\r
354 CFX_WideString CXFA_NodeLocale::GetSymbol(XFA_ELEMENT eElement, FX_WSTR symbol_type) const\r
355 {\r
356     CXFA_Node *pSymbols = m_pLocale ? m_pLocale->GetChild(0, eElement) : NULL;\r
357     CXFA_Node *pSymbol = GetNodeByName(pSymbols, symbol_type);\r
358     return pSymbol ? pSymbol->GetContent() : CFX_WideString();\r
359 }\r
360 CFX_WideString CXFA_NodeLocale::GetCalendarSymbol(XFA_ELEMENT eElement, int index, FX_BOOL bAbbr) const\r
361 {\r
362     CXFA_Node *pCalendar = m_pLocale ? m_pLocale->GetChild(0, XFA_ELEMENT_CalendarSymbols) : NULL;\r
363     if (pCalendar) {\r
364         CXFA_Node *pNode = pCalendar->GetFirstChildByClass(eElement);\r
365         for (; pNode; pNode = pNode->GetNextSameClassSibling(eElement)) {\r
366             if (pNode->GetBoolean(XFA_ATTRIBUTE_Abbr) == bAbbr) {\r
367                 CXFA_Node *pSymbol = pNode->GetChild(index, XFA_ELEMENT_UNKNOWN);\r
368                 return pSymbol ? pSymbol->GetContent() : CFX_WideString();\r
369             }\r
370         }\r
371     }\r
372     return CFX_WideString();\r
373 }\r