Home | History | Annotate | Download | only in parser
      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 
     22 CXFA_XMLLocale::CXFA_XMLLocale(std::unique_ptr<CXML_Element> pLocaleData)
     23     : m_pLocaleData(std::move(pLocaleData)) {}
     24 
     25 CXFA_XMLLocale::~CXFA_XMLLocale() {}
     26 
     27 CFX_WideString CXFA_XMLLocale::GetName() const {
     28   return m_pLocaleData ? m_pLocaleData->GetAttrValue("name") : CFX_WideString();
     29 }
     30 
     31 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 
     76 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 
     89 void CXFA_XMLLocale::GetMonthName(int32_t nMonth,
     90                                   CFX_WideString& wsMonthName,
     91                                   bool bAbbr) const {
     92   wsMonthName = GetCalendarSymbol("month", nMonth, bAbbr);
     93 }
     94 
     95 void CXFA_XMLLocale::GetDayName(int32_t nWeek,
     96                                 CFX_WideString& wsDayName,
     97                                 bool bAbbr) const {
     98   wsDayName = GetCalendarSymbol("day", nWeek, bAbbr);
     99 }
    100 
    101 void CXFA_XMLLocale::GetMeridiemName(CFX_WideString& wsMeridiemName,
    102                                      bool bAM) const {
    103   wsMeridiemName = GetCalendarSymbol("meridiem", bAM ? 0 : 1, false);
    104 }
    105 
    106 void CXFA_XMLLocale::GetTimeZone(FX_TIMEZONE* tz) const {
    107   CXFA_TimeZoneProvider provider;
    108   provider.GetTimeZone(tz);
    109 }
    110 
    111 void CXFA_XMLLocale::GetEraName(CFX_WideString& wsEraName, bool bAD) const {
    112   wsEraName = GetCalendarSymbol("era", bAD ? 1 : 0, false);
    113 }
    114 
    115 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 
    142 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 
    167 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 
    192 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 
    214 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 
    228 CXFA_NodeLocale::CXFA_NodeLocale(CXFA_Node* pLocale) : m_pLocale(pLocale) {}
    229 
    230 CXFA_NodeLocale::~CXFA_NodeLocale() {}
    231 
    232 CFX_WideString CXFA_NodeLocale::GetName() const {
    233   return CFX_WideString(m_pLocale ? m_pLocale->GetCData(XFA_ATTRIBUTE_Name)
    234                                   : nullptr);
    235 }
    236 
    237 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 
    264 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 
    271 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 
    277 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 
    283 void CXFA_NodeLocale::GetMeridiemName(CFX_WideString& wsMeridiemName,
    284                                       bool bAM) const {
    285   wsMeridiemName =
    286       GetCalendarSymbol(XFA_Element::MeridiemNames, bAM ? 0 : 1, false);
    287 }
    288 
    289 void CXFA_NodeLocale::GetTimeZone(FX_TIMEZONE* tz) const {
    290   CXFA_TimeZoneProvider provider;
    291   provider.GetTimeZone(tz);
    292 }
    293 
    294 void CXFA_NodeLocale::GetEraName(CFX_WideString& wsEraName, bool bAD) const {
    295   wsEraName = GetCalendarSymbol(XFA_Element::EraNames, bAD ? 1 : 0, false);
    296 }
    297 
    298 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 
    317 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 
    336 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 
    354 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 
    370 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 
    378 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