1 // Copyright 2017 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/cxfa_xmllocale.h"
8 
9 #include <utility>
10 
11 #include "core/fxcrt/xml/cxml_content.h"
12 #include "core/fxcrt/xml/cxml_element.h"
13 #include "xfa/fxfa/parser/cxfa_document.h"
14 #include "xfa/fxfa/parser/cxfa_localemgr.h"
15 #include "xfa/fxfa/parser/cxfa_nodelocale.h"
16 #include "xfa/fxfa/parser/cxfa_timezoneprovider.h"
17 #include "xfa/fxfa/parser/xfa_utils.h"
18 
CXFA_XMLLocale(std::unique_ptr<CXML_Element> pLocaleData)19 CXFA_XMLLocale::CXFA_XMLLocale(std::unique_ptr<CXML_Element> pLocaleData)
20     : m_pLocaleData(std::move(pLocaleData)) {}
21 
~CXFA_XMLLocale()22 CXFA_XMLLocale::~CXFA_XMLLocale() {}
23 
GetName() const24 WideString CXFA_XMLLocale::GetName() const {
25   return m_pLocaleData ? m_pLocaleData->GetAttrValue("name") : WideString();
26 }
27 
GetNumbericSymbol(FX_LOCALENUMSYMBOL eType) const28 WideString CXFA_XMLLocale::GetNumbericSymbol(FX_LOCALENUMSYMBOL eType) const {
29   ByteString bsSymbols;
30   WideString wsName;
31   switch (eType) {
32     case FX_LOCALENUMSYMBOL_Decimal:
33       bsSymbols = "numberSymbols";
34       wsName = L"decimal";
35       break;
36     case FX_LOCALENUMSYMBOL_Grouping:
37       bsSymbols = "numberSymbols";
38       wsName = L"grouping";
39       break;
40     case FX_LOCALENUMSYMBOL_Percent:
41       bsSymbols = "numberSymbols";
42       wsName = L"percent";
43       break;
44     case FX_LOCALENUMSYMBOL_Minus:
45       bsSymbols = "numberSymbols";
46       wsName = L"minus";
47       break;
48     case FX_LOCALENUMSYMBOL_Zero:
49       bsSymbols = "numberSymbols";
50       wsName = L"zero";
51       break;
52     case FX_LOCALENUMSYMBOL_CurrencySymbol:
53       bsSymbols = "currencySymbols";
54       wsName = L"symbol";
55       break;
56     case FX_LOCALENUMSYMBOL_CurrencyName:
57       bsSymbols = "currencySymbols";
58       wsName = L"isoname";
59       break;
60     default:
61       return WideString();
62   }
63   CXML_Element* pElement =
64       m_pLocaleData->GetElement("", bsSymbols.AsStringView(), 0);
65   if (!pElement)
66     return WideString();
67 
68   return GetPattern(
69       pElement, ByteStringView(bsSymbols.c_str(), bsSymbols.GetLength() - 1),
70       wsName.AsStringView());
71 }
72 
GetDateTimeSymbols() const73 WideString CXFA_XMLLocale::GetDateTimeSymbols() const {
74   if (!m_pLocaleData)
75     return WideString();
76 
77   CXML_Element* pNumberSymbols =
78       m_pLocaleData->GetElement("", "dateTimeSymbols", 0);
79   if (!pNumberSymbols)
80     return WideString();
81 
82   CXML_Content* pContent = ToContent(pNumberSymbols->GetChild(0));
83   if (!pContent)
84     return WideString();
85 
86   return pContent->m_Content;
87 }
88 
GetMonthName(int32_t nMonth,bool bAbbr) const89 WideString CXFA_XMLLocale::GetMonthName(int32_t nMonth, bool bAbbr) const {
90   return GetCalendarSymbol("month", nMonth, bAbbr);
91 }
92 
GetDayName(int32_t nWeek,bool bAbbr) const93 WideString CXFA_XMLLocale::GetDayName(int32_t nWeek, bool bAbbr) const {
94   return GetCalendarSymbol("day", nWeek, bAbbr);
95 }
96 
GetMeridiemName(bool bAM) const97 WideString CXFA_XMLLocale::GetMeridiemName(bool bAM) const {
98   return GetCalendarSymbol("meridiem", bAM ? 0 : 1, false);
99 }
100 
GetTimeZone() const101 FX_TIMEZONE CXFA_XMLLocale::GetTimeZone() const {
102   return CXFA_TimeZoneProvider().GetTimeZone();
103 }
104 
GetEraName(bool bAD) const105 WideString CXFA_XMLLocale::GetEraName(bool bAD) const {
106   return GetCalendarSymbol("era", bAD ? 1 : 0, false);
107 }
108 
GetCalendarSymbol(const ByteStringView & symbol,int index,bool bAbbr) const109 WideString CXFA_XMLLocale::GetCalendarSymbol(const ByteStringView& symbol,
110                                              int index,
111                                              bool bAbbr) const {
112   if (index < 0 || !m_pLocaleData)
113     return WideString();
114 
115   CXML_Element* pChild = m_pLocaleData->GetElement("", "calendarSymbols", 0);
116   if (!pChild)
117     return WideString();
118 
119   ByteString pstrSymbolNames = symbol + "Names";
120   CXML_Element* pSymbolNames =
121       pChild->GetElement("", pstrSymbolNames.AsStringView(), 0);
122   if (!pSymbolNames)
123     return WideString();
124 
125   if ((!!pSymbolNames->GetAttrInteger("abbr")) != bAbbr)
126     pSymbolNames = pChild->GetElement("", pstrSymbolNames.AsStringView(), 1);
127 
128   if (!pSymbolNames || (!!pSymbolNames->GetAttrInteger("abbr")) != bAbbr)
129     return WideString();
130 
131   CXML_Element* pSymbolName = pSymbolNames->GetElement("", symbol, index);
132   if (!pSymbolName)
133     return WideString();
134 
135   CXML_Content* pContent = ToContent(pSymbolName->GetChild(0));
136   return pContent ? pContent->m_Content : WideString();
137 }
138 
GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType) const139 WideString CXFA_XMLLocale::GetDatePattern(
140     FX_LOCALEDATETIMESUBCATEGORY eType) const {
141   CXML_Element* pElement = m_pLocaleData->GetElement("", "datePatterns", 0);
142   if (!pElement)
143     return WideString();
144 
145   WideString wsName;
146   switch (eType) {
147     case FX_LOCALEDATETIMESUBCATEGORY_Short:
148       wsName = L"short";
149       break;
150     case FX_LOCALEDATETIMESUBCATEGORY_Default:
151     case FX_LOCALEDATETIMESUBCATEGORY_Medium:
152       wsName = L"med";
153       break;
154     case FX_LOCALEDATETIMESUBCATEGORY_Full:
155       wsName = L"full";
156       break;
157     case FX_LOCALEDATETIMESUBCATEGORY_Long:
158       wsName = L"long";
159       break;
160   }
161   return GetPattern(pElement, "datePattern", wsName.AsStringView());
162 }
163 
GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType) const164 WideString CXFA_XMLLocale::GetTimePattern(
165     FX_LOCALEDATETIMESUBCATEGORY eType) const {
166   CXML_Element* pElement = m_pLocaleData->GetElement("", "timePatterns", 0);
167   if (!pElement)
168     return WideString();
169 
170   WideString wsName;
171   switch (eType) {
172     case FX_LOCALEDATETIMESUBCATEGORY_Short:
173       wsName = L"short";
174       break;
175     case FX_LOCALEDATETIMESUBCATEGORY_Default:
176     case FX_LOCALEDATETIMESUBCATEGORY_Medium:
177       wsName = L"med";
178       break;
179     case FX_LOCALEDATETIMESUBCATEGORY_Full:
180       wsName = L"full";
181       break;
182     case FX_LOCALEDATETIMESUBCATEGORY_Long:
183       wsName = L"long";
184       break;
185   }
186   return GetPattern(pElement, "timePattern", wsName.AsStringView());
187 }
188 
GetNumPattern(FX_LOCALENUMSUBCATEGORY eType) const189 WideString CXFA_XMLLocale::GetNumPattern(FX_LOCALENUMSUBCATEGORY eType) const {
190   return m_pLocaleData->GetElement("", "numberPatterns", 0)
191              ? XFA_PatternToString(eType)
192              : WideString();
193 }
194 
GetPattern(CXML_Element * pElement,const ByteStringView & bsTag,const WideStringView & wsName) const195 WideString CXFA_XMLLocale::GetPattern(CXML_Element* pElement,
196                                       const ByteStringView& bsTag,
197                                       const WideStringView& wsName) const {
198   size_t iCount = pElement->CountElements("", bsTag);
199   for (size_t i = 0; i < iCount; i++) {
200     CXML_Element* pChild = pElement->GetElement("", bsTag, i);
201     if (pChild->GetAttrValue("name") == wsName) {
202       CXML_Content* pContent = ToContent(pChild->GetChild(0));
203       return pContent ? pContent->m_Content : WideString();
204     }
205   }
206   return WideString();
207 }
208