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/fxfa/parser/xfa_locale.h"
8
9 #include <utility>
10
11 #include "core/fxcrt/fx_xml.h"
12 #include "xfa/fxfa/parser/cxfa_document.h"
13 #include "xfa/fxfa/parser/xfa_localemgr.h"
14 #include "xfa/fxfa/parser/xfa_object.h"
15 #include "xfa/fxfa/parser/xfa_utils.h"
16
17 static const FX_WCHAR g_FX_Percent[] = L"z,zzz,zzz,zzz,zzz,zzz%";
18 static const FX_WCHAR g_FX_Currency[] = L"$z,zzz,zzz,zzz,zzz,zz9.99";
19 static const FX_WCHAR g_FX_Decimal[] = L"z,zzz,zzz,zzz,zzz,zz9.zzz";
20 static const FX_WCHAR g_FX_Integer[] = L"z,zzz,zzz,zzz,zzz,zzz";
21
CXFA_XMLLocale(std::unique_ptr<CXML_Element> pLocaleData)22 CXFA_XMLLocale::CXFA_XMLLocale(std::unique_ptr<CXML_Element> pLocaleData)
23 : m_pLocaleData(std::move(pLocaleData)) {}
24
~CXFA_XMLLocale()25 CXFA_XMLLocale::~CXFA_XMLLocale() {}
26
GetName() const27 CFX_WideString CXFA_XMLLocale::GetName() const {
28 return m_pLocaleData ? m_pLocaleData->GetAttrValue("name") : CFX_WideString();
29 }
30
GetNumbericSymbol(FX_LOCALENUMSYMBOL eType,CFX_WideString & wsNumSymbol) const31 void CXFA_XMLLocale::GetNumbericSymbol(FX_LOCALENUMSYMBOL eType,
32 CFX_WideString& wsNumSymbol) const {
33 CFX_ByteString bsSymbols;
34 CFX_WideString wsName;
35 switch (eType) {
36 case FX_LOCALENUMSYMBOL_Decimal:
37 bsSymbols = "numberSymbols";
38 wsName = L"decimal";
39 break;
40 case FX_LOCALENUMSYMBOL_Grouping:
41 bsSymbols = "numberSymbols";
42 wsName = L"grouping";
43 break;
44 case FX_LOCALENUMSYMBOL_Percent:
45 bsSymbols = "numberSymbols";
46 wsName = L"percent";
47 break;
48 case FX_LOCALENUMSYMBOL_Minus:
49 bsSymbols = "numberSymbols";
50 wsName = L"minus";
51 break;
52 case FX_LOCALENUMSYMBOL_Zero:
53 bsSymbols = "numberSymbols";
54 wsName = L"zero";
55 break;
56 case FX_LOCALENUMSYMBOL_CurrencySymbol:
57 bsSymbols = "currencySymbols";
58 wsName = L"symbol";
59 break;
60 case FX_LOCALENUMSYMBOL_CurrencyName:
61 bsSymbols = "currencySymbols";
62 wsName = L"isoname";
63 break;
64 default:
65 return;
66 }
67 CXML_Element* pElement = m_pLocaleData->GetElement("", bsSymbols.AsStringC());
68 if (!pElement) {
69 return;
70 }
71 GetPattern(pElement,
72 CFX_ByteStringC(bsSymbols.c_str(), bsSymbols.GetLength() - 1),
73 wsName.AsStringC(), wsNumSymbol);
74 }
75
GetDateTimeSymbols(CFX_WideString & wsDtSymbol) const76 void CXFA_XMLLocale::GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const {
77 if (!m_pLocaleData) {
78 return;
79 }
80 CFX_ByteString bsSpace;
81 CXML_Element* pNumberSymbols =
82 m_pLocaleData->GetElement(bsSpace.AsStringC(), "dateTimeSymbols");
83 if (!pNumberSymbols) {
84 return;
85 }
86 wsDtSymbol = pNumberSymbols->GetContent(0);
87 }
88
GetMonthName(int32_t nMonth,CFX_WideString & wsMonthName,bool bAbbr) const89 void CXFA_XMLLocale::GetMonthName(int32_t nMonth,
90 CFX_WideString& wsMonthName,
91 bool bAbbr) const {
92 wsMonthName = GetCalendarSymbol("month", nMonth, bAbbr);
93 }
94
GetDayName(int32_t nWeek,CFX_WideString & wsDayName,bool bAbbr) const95 void CXFA_XMLLocale::GetDayName(int32_t nWeek,
96 CFX_WideString& wsDayName,
97 bool bAbbr) const {
98 wsDayName = GetCalendarSymbol("day", nWeek, bAbbr);
99 }
100
GetMeridiemName(CFX_WideString & wsMeridiemName,bool bAM) const101 void CXFA_XMLLocale::GetMeridiemName(CFX_WideString& wsMeridiemName,
102 bool bAM) const {
103 wsMeridiemName = GetCalendarSymbol("meridiem", bAM ? 0 : 1, false);
104 }
105
GetTimeZone(FX_TIMEZONE * tz) const106 void CXFA_XMLLocale::GetTimeZone(FX_TIMEZONE* tz) const {
107 CXFA_TimeZoneProvider provider;
108 provider.GetTimeZone(tz);
109 }
110
GetEraName(CFX_WideString & wsEraName,bool bAD) const111 void CXFA_XMLLocale::GetEraName(CFX_WideString& wsEraName, bool bAD) const {
112 wsEraName = GetCalendarSymbol("era", bAD ? 1 : 0, false);
113 }
114
GetCalendarSymbol(const CFX_ByteStringC & symbol,int index,bool bAbbr) const115 CFX_WideString CXFA_XMLLocale::GetCalendarSymbol(const CFX_ByteStringC& symbol,
116 int index,
117 bool bAbbr) const {
118 CFX_ByteString pstrSymbolNames = symbol + "Names";
119 CFX_WideString wsSymbolName = L"";
120 if (m_pLocaleData) {
121 CXML_Element* pChild = m_pLocaleData->GetElement("", "calendarSymbols");
122 if (pChild) {
123 CXML_Element* pSymbolNames =
124 pChild->GetElement("", pstrSymbolNames.AsStringC());
125 if (pSymbolNames) {
126 if ((!!pSymbolNames->GetAttrInteger("abbr")) != bAbbr) {
127 pSymbolNames = pChild->GetElement("", pstrSymbolNames.AsStringC(), 1);
128 }
129 if (pSymbolNames && (!!pSymbolNames->GetAttrInteger("abbr")) == bAbbr) {
130 CXML_Element* pSymbolName =
131 pSymbolNames->GetElement("", symbol, index);
132 if (pSymbolName) {
133 wsSymbolName = pSymbolName->GetContent(0);
134 }
135 }
136 }
137 }
138 }
139 return wsSymbolName;
140 }
141
GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType,CFX_WideString & wsPattern) const142 void CXFA_XMLLocale::GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType,
143 CFX_WideString& wsPattern) const {
144 CXML_Element* pElement = m_pLocaleData->GetElement("", "datePatterns");
145 if (!pElement) {
146 return;
147 }
148 CFX_WideString wsName;
149 switch (eType) {
150 case FX_LOCALEDATETIMESUBCATEGORY_Short:
151 wsName = L"short";
152 break;
153 case FX_LOCALEDATETIMESUBCATEGORY_Default:
154 case FX_LOCALEDATETIMESUBCATEGORY_Medium:
155 wsName = L"med";
156 break;
157 case FX_LOCALEDATETIMESUBCATEGORY_Full:
158 wsName = L"full";
159 break;
160 case FX_LOCALEDATETIMESUBCATEGORY_Long:
161 wsName = L"long";
162 break;
163 }
164 GetPattern(pElement, "datePattern", wsName.AsStringC(), wsPattern);
165 }
166
GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType,CFX_WideString & wsPattern) const167 void CXFA_XMLLocale::GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType,
168 CFX_WideString& wsPattern) const {
169 CXML_Element* pElement = m_pLocaleData->GetElement("", "timePatterns");
170 if (!pElement) {
171 return;
172 }
173 CFX_WideString wsName;
174 switch (eType) {
175 case FX_LOCALEDATETIMESUBCATEGORY_Short:
176 wsName = L"short";
177 break;
178 case FX_LOCALEDATETIMESUBCATEGORY_Default:
179 case FX_LOCALEDATETIMESUBCATEGORY_Medium:
180 wsName = L"med";
181 break;
182 case FX_LOCALEDATETIMESUBCATEGORY_Full:
183 wsName = L"full";
184 break;
185 case FX_LOCALEDATETIMESUBCATEGORY_Long:
186 wsName = L"long";
187 break;
188 }
189 GetPattern(pElement, "timePattern", wsName.AsStringC(), wsPattern);
190 }
191
GetNumPattern(FX_LOCALENUMSUBCATEGORY eType,CFX_WideString & wsPattern) const192 void CXFA_XMLLocale::GetNumPattern(FX_LOCALENUMSUBCATEGORY eType,
193 CFX_WideString& wsPattern) const {
194 CXML_Element* pElement = m_pLocaleData->GetElement("", "numberPatterns");
195 if (!pElement) {
196 return;
197 }
198 switch (eType) {
199 case FX_LOCALENUMPATTERN_Percent:
200 wsPattern = g_FX_Percent;
201 break;
202 case FX_LOCALENUMPATTERN_Currency:
203 wsPattern = g_FX_Currency;
204 break;
205 case FX_LOCALENUMPATTERN_Decimal:
206 wsPattern = g_FX_Decimal;
207 break;
208 case FX_LOCALENUMPATTERN_Integer:
209 wsPattern = g_FX_Integer;
210 break;
211 }
212 }
213
GetPattern(CXML_Element * pElement,const CFX_ByteStringC & bsTag,const CFX_WideStringC & wsName,CFX_WideString & wsPattern) const214 void CXFA_XMLLocale::GetPattern(CXML_Element* pElement,
215 const CFX_ByteStringC& bsTag,
216 const CFX_WideStringC& wsName,
217 CFX_WideString& wsPattern) const {
218 int32_t iCount = pElement->CountElements("", bsTag);
219 for (int32_t i = 0; i < iCount; i++) {
220 CXML_Element* pChild = pElement->GetElement("", bsTag, i);
221 if (pChild->GetAttrValue("name") == wsName) {
222 wsPattern = pChild->GetContent(0);
223 return;
224 }
225 }
226 }
227
CXFA_NodeLocale(CXFA_Node * pLocale)228 CXFA_NodeLocale::CXFA_NodeLocale(CXFA_Node* pLocale) : m_pLocale(pLocale) {}
229
~CXFA_NodeLocale()230 CXFA_NodeLocale::~CXFA_NodeLocale() {}
231
GetName() const232 CFX_WideString CXFA_NodeLocale::GetName() const {
233 return CFX_WideString(m_pLocale ? m_pLocale->GetCData(XFA_ATTRIBUTE_Name)
234 : nullptr);
235 }
236
GetNumbericSymbol(FX_LOCALENUMSYMBOL eType,CFX_WideString & wsNumSymbol) const237 void CXFA_NodeLocale::GetNumbericSymbol(FX_LOCALENUMSYMBOL eType,
238 CFX_WideString& wsNumSymbol) const {
239 switch (eType) {
240 case FX_LOCALENUMSYMBOL_Decimal:
241 wsNumSymbol = GetSymbol(XFA_Element::NumberSymbols, L"decimal");
242 break;
243 case FX_LOCALENUMSYMBOL_Grouping:
244 wsNumSymbol = GetSymbol(XFA_Element::NumberSymbols, L"grouping");
245 break;
246 case FX_LOCALENUMSYMBOL_Percent:
247 wsNumSymbol = GetSymbol(XFA_Element::NumberSymbols, L"percent");
248 break;
249 case FX_LOCALENUMSYMBOL_Minus:
250 wsNumSymbol = GetSymbol(XFA_Element::NumberSymbols, L"minus");
251 break;
252 case FX_LOCALENUMSYMBOL_Zero:
253 wsNumSymbol = GetSymbol(XFA_Element::NumberSymbols, L"zero");
254 break;
255 case FX_LOCALENUMSYMBOL_CurrencySymbol:
256 wsNumSymbol = GetSymbol(XFA_Element::CurrencySymbols, L"symbol");
257 break;
258 case FX_LOCALENUMSYMBOL_CurrencyName:
259 wsNumSymbol = GetSymbol(XFA_Element::CurrencySymbols, L"isoname");
260 break;
261 }
262 }
263
GetDateTimeSymbols(CFX_WideString & wsDtSymbol) const264 void CXFA_NodeLocale::GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const {
265 CXFA_Node* pSymbols =
266 m_pLocale ? m_pLocale->GetChild(0, XFA_Element::DateTimeSymbols)
267 : nullptr;
268 wsDtSymbol = pSymbols ? pSymbols->GetContent() : CFX_WideString();
269 }
270
GetMonthName(int32_t nMonth,CFX_WideString & wsMonthName,bool bAbbr) const271 void CXFA_NodeLocale::GetMonthName(int32_t nMonth,
272 CFX_WideString& wsMonthName,
273 bool bAbbr) const {
274 wsMonthName = GetCalendarSymbol(XFA_Element::MonthNames, nMonth, bAbbr);
275 }
276
GetDayName(int32_t nWeek,CFX_WideString & wsDayName,bool bAbbr) const277 void CXFA_NodeLocale::GetDayName(int32_t nWeek,
278 CFX_WideString& wsDayName,
279 bool bAbbr) const {
280 wsDayName = GetCalendarSymbol(XFA_Element::DayNames, nWeek, bAbbr);
281 }
282
GetMeridiemName(CFX_WideString & wsMeridiemName,bool bAM) const283 void CXFA_NodeLocale::GetMeridiemName(CFX_WideString& wsMeridiemName,
284 bool bAM) const {
285 wsMeridiemName =
286 GetCalendarSymbol(XFA_Element::MeridiemNames, bAM ? 0 : 1, false);
287 }
288
GetTimeZone(FX_TIMEZONE * tz) const289 void CXFA_NodeLocale::GetTimeZone(FX_TIMEZONE* tz) const {
290 CXFA_TimeZoneProvider provider;
291 provider.GetTimeZone(tz);
292 }
293
GetEraName(CFX_WideString & wsEraName,bool bAD) const294 void CXFA_NodeLocale::GetEraName(CFX_WideString& wsEraName, bool bAD) const {
295 wsEraName = GetCalendarSymbol(XFA_Element::EraNames, bAD ? 1 : 0, false);
296 }
297
GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType,CFX_WideString & wsPattern) const298 void CXFA_NodeLocale::GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType,
299 CFX_WideString& wsPattern) const {
300 switch (eType) {
301 case FX_LOCALEDATETIMESUBCATEGORY_Short:
302 wsPattern = GetSymbol(XFA_Element::DatePatterns, L"short");
303 break;
304 case FX_LOCALEDATETIMESUBCATEGORY_Medium:
305 case FX_LOCALEDATETIMESUBCATEGORY_Default:
306 wsPattern = GetSymbol(XFA_Element::DatePatterns, L"med");
307 break;
308 case FX_LOCALEDATETIMESUBCATEGORY_Full:
309 wsPattern = GetSymbol(XFA_Element::DatePatterns, L"full");
310 break;
311 case FX_LOCALEDATETIMESUBCATEGORY_Long:
312 wsPattern = GetSymbol(XFA_Element::DatePatterns, L"long");
313 break;
314 }
315 }
316
GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType,CFX_WideString & wsPattern) const317 void CXFA_NodeLocale::GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType,
318 CFX_WideString& wsPattern) const {
319 switch (eType) {
320 case FX_LOCALEDATETIMESUBCATEGORY_Short:
321 wsPattern = GetSymbol(XFA_Element::TimePatterns, L"short");
322 break;
323 case FX_LOCALEDATETIMESUBCATEGORY_Medium:
324 case FX_LOCALEDATETIMESUBCATEGORY_Default:
325 wsPattern = GetSymbol(XFA_Element::TimePatterns, L"med");
326 break;
327 case FX_LOCALEDATETIMESUBCATEGORY_Full:
328 wsPattern = GetSymbol(XFA_Element::TimePatterns, L"full");
329 break;
330 case FX_LOCALEDATETIMESUBCATEGORY_Long:
331 wsPattern = GetSymbol(XFA_Element::TimePatterns, L"long");
332 break;
333 }
334 }
335
GetNumPattern(FX_LOCALENUMSUBCATEGORY eType,CFX_WideString & wsPattern) const336 void CXFA_NodeLocale::GetNumPattern(FX_LOCALENUMSUBCATEGORY eType,
337 CFX_WideString& wsPattern) const {
338 switch (eType) {
339 case FX_LOCALENUMPATTERN_Percent:
340 wsPattern = g_FX_Percent;
341 break;
342 case FX_LOCALENUMPATTERN_Currency:
343 wsPattern = g_FX_Currency;
344 break;
345 case FX_LOCALENUMPATTERN_Decimal:
346 wsPattern = g_FX_Decimal;
347 break;
348 case FX_LOCALENUMPATTERN_Integer:
349 wsPattern = g_FX_Integer;
350 break;
351 }
352 }
353
GetNodeByName(CXFA_Node * pParent,const CFX_WideStringC & wsName) const354 CXFA_Node* CXFA_NodeLocale::GetNodeByName(CXFA_Node* pParent,
355 const CFX_WideStringC& wsName) const {
356 CXFA_Node* pChild =
357 pParent ? pParent->GetNodeItem(XFA_NODEITEM_FirstChild) : nullptr;
358 while (pChild) {
359 CFX_WideString wsChild;
360 if (pChild->GetAttribute(XFA_ATTRIBUTE_Name, wsChild)) {
361 if (wsChild == wsName) {
362 return pChild;
363 }
364 }
365 pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling);
366 }
367 return nullptr;
368 }
369
GetSymbol(XFA_Element eElement,const CFX_WideStringC & symbol_type) const370 CFX_WideString CXFA_NodeLocale::GetSymbol(
371 XFA_Element eElement,
372 const CFX_WideStringC& symbol_type) const {
373 CXFA_Node* pSymbols = m_pLocale ? m_pLocale->GetChild(0, eElement) : nullptr;
374 CXFA_Node* pSymbol = GetNodeByName(pSymbols, symbol_type);
375 return pSymbol ? pSymbol->GetContent() : CFX_WideString();
376 }
377
GetCalendarSymbol(XFA_Element eElement,int index,bool bAbbr) const378 CFX_WideString CXFA_NodeLocale::GetCalendarSymbol(XFA_Element eElement,
379 int index,
380 bool bAbbr) const {
381 CXFA_Node* pCalendar =
382 m_pLocale ? m_pLocale->GetChild(0, XFA_Element::CalendarSymbols)
383 : nullptr;
384 if (pCalendar) {
385 CXFA_Node* pNode = pCalendar->GetFirstChildByClass(eElement);
386 for (; pNode; pNode = pNode->GetNextSameClassSibling(eElement)) {
387 if (pNode->GetBoolean(XFA_ATTRIBUTE_Abbr) == bAbbr) {
388 CXFA_Node* pSymbol = pNode->GetChild(index, XFA_Element::Unknown);
389 return pSymbol ? pSymbol->GetContent() : CFX_WideString();
390 }
391 }
392 }
393 return CFX_WideString();
394 }
395