• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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