You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
224 lines
7.0 KiB
224 lines
7.0 KiB
// Copyright 2017 PDFium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
|
|
|
|
#include "xfa/fxfa/parser/cxfa_xmllocale.h"
|
|
|
|
#include <utility>
|
|
|
|
#include "core/fxcrt/cfx_readonlymemorystream.h"
|
|
#include "core/fxcrt/fx_codepage.h"
|
|
#include "core/fxcrt/xml/cfx_xmldocument.h"
|
|
#include "core/fxcrt/xml/cfx_xmlelement.h"
|
|
#include "core/fxcrt/xml/cfx_xmlparser.h"
|
|
#include "third_party/base/ptr_util.h"
|
|
#include "xfa/fxfa/parser/cxfa_document.h"
|
|
#include "xfa/fxfa/parser/cxfa_localemgr.h"
|
|
#include "xfa/fxfa/parser/cxfa_nodelocale.h"
|
|
#include "xfa/fxfa/parser/cxfa_timezoneprovider.h"
|
|
#include "xfa/fxfa/parser/xfa_utils.h"
|
|
|
|
namespace {
|
|
|
|
constexpr wchar_t kNumberSymbols[] = L"numberSymbols";
|
|
constexpr wchar_t kNumberSymbol[] = L"numberSymbol";
|
|
constexpr wchar_t kCurrencySymbols[] = L"currencySymbols";
|
|
constexpr wchar_t kCurrencySymbol[] = L"currencySymbol";
|
|
|
|
} // namespace
|
|
|
|
// static
|
|
std::unique_ptr<CXFA_XMLLocale> CXFA_XMLLocale::Create(
|
|
pdfium::span<uint8_t> data) {
|
|
auto stream = pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(data);
|
|
CFX_XMLParser parser(stream);
|
|
auto doc = parser.Parse();
|
|
if (!doc)
|
|
return nullptr;
|
|
|
|
CFX_XMLElement* locale = nullptr;
|
|
for (auto* child = doc->GetRoot()->GetFirstChild(); child;
|
|
child = child->GetNextSibling()) {
|
|
CFX_XMLElement* elem = ToXMLElement(child);
|
|
if (elem && elem->GetName().EqualsASCII("locale")) {
|
|
locale = elem;
|
|
break;
|
|
}
|
|
}
|
|
if (!locale)
|
|
return nullptr;
|
|
|
|
return pdfium::MakeUnique<CXFA_XMLLocale>(std::move(doc), locale);
|
|
}
|
|
|
|
CXFA_XMLLocale::CXFA_XMLLocale(std::unique_ptr<CFX_XMLDocument> doc,
|
|
CFX_XMLElement* locale)
|
|
: xml_doc_(std::move(doc)), locale_(locale) {
|
|
ASSERT(xml_doc_);
|
|
ASSERT(locale_);
|
|
}
|
|
|
|
CXFA_XMLLocale::~CXFA_XMLLocale() {}
|
|
|
|
WideString CXFA_XMLLocale::GetName() const {
|
|
return locale_->GetAttribute(L"name");
|
|
}
|
|
|
|
WideString CXFA_XMLLocale::GetDecimalSymbol() const {
|
|
CFX_XMLElement* patterns = locale_->GetFirstChildNamed(kNumberSymbols);
|
|
return patterns ? GetPattern(patterns, kNumberSymbol, L"decimal")
|
|
: WideString();
|
|
}
|
|
|
|
WideString CXFA_XMLLocale::GetGroupingSymbol() const {
|
|
CFX_XMLElement* patterns = locale_->GetFirstChildNamed(kNumberSymbols);
|
|
return patterns ? GetPattern(patterns, kNumberSymbol, L"grouping")
|
|
: WideString();
|
|
}
|
|
|
|
WideString CXFA_XMLLocale::GetPercentSymbol() const {
|
|
CFX_XMLElement* patterns = locale_->GetFirstChildNamed(kNumberSymbols);
|
|
return patterns ? GetPattern(patterns, kNumberSymbol, L"percent")
|
|
: WideString();
|
|
}
|
|
|
|
WideString CXFA_XMLLocale::GetMinusSymbol() const {
|
|
CFX_XMLElement* patterns = locale_->GetFirstChildNamed(kNumberSymbols);
|
|
return patterns ? GetPattern(patterns, kNumberSymbol, L"minus")
|
|
: WideString();
|
|
}
|
|
|
|
WideString CXFA_XMLLocale::GetCurrencySymbol() const {
|
|
CFX_XMLElement* patterns = locale_->GetFirstChildNamed(kCurrencySymbols);
|
|
return patterns ? GetPattern(patterns, kCurrencySymbol, L"symbol")
|
|
: WideString();
|
|
}
|
|
|
|
WideString CXFA_XMLLocale::GetDateTimeSymbols() const {
|
|
CFX_XMLElement* symbols = locale_->GetFirstChildNamed(L"dateTimeSymbols");
|
|
return symbols ? symbols->GetTextData() : WideString();
|
|
}
|
|
|
|
WideString CXFA_XMLLocale::GetMonthName(int32_t nMonth, bool bAbbr) const {
|
|
return GetCalendarSymbol(L"month", nMonth, bAbbr);
|
|
}
|
|
|
|
WideString CXFA_XMLLocale::GetDayName(int32_t nWeek, bool bAbbr) const {
|
|
return GetCalendarSymbol(L"day", nWeek, bAbbr);
|
|
}
|
|
|
|
WideString CXFA_XMLLocale::GetMeridiemName(bool bAM) const {
|
|
return GetCalendarSymbol(L"meridiem", bAM ? 0 : 1, false);
|
|
}
|
|
|
|
FX_TIMEZONE CXFA_XMLLocale::GetTimeZone() const {
|
|
return CXFA_TimeZoneProvider().GetTimeZone();
|
|
}
|
|
|
|
WideString CXFA_XMLLocale::GetEraName(bool bAD) const {
|
|
return GetCalendarSymbol(L"era", bAD ? 1 : 0, false);
|
|
}
|
|
|
|
WideString CXFA_XMLLocale::GetCalendarSymbol(WideStringView symbol,
|
|
size_t index,
|
|
bool bAbbr) const {
|
|
CFX_XMLElement* child = locale_->GetFirstChildNamed(L"calendarSymbols");
|
|
if (!child)
|
|
return WideString();
|
|
|
|
WideString pstrSymbolNames = symbol + L"Names";
|
|
CFX_XMLElement* name_child = nullptr;
|
|
for (auto* name = child->GetFirstChild(); name;
|
|
name = name->GetNextSibling()) {
|
|
CFX_XMLElement* elem = ToXMLElement(name);
|
|
if (!elem || elem->GetName() != pstrSymbolNames)
|
|
continue;
|
|
|
|
WideString abbr = elem->GetAttribute(L"abbr");
|
|
bool abbr_value = false;
|
|
if (!abbr.IsEmpty())
|
|
abbr_value = abbr.EqualsASCII("1");
|
|
if (abbr_value != bAbbr)
|
|
continue;
|
|
|
|
name_child = elem;
|
|
break;
|
|
}
|
|
if (!name_child)
|
|
return WideString();
|
|
|
|
CFX_XMLElement* sym_element = name_child->GetNthChildNamed(symbol, index);
|
|
return sym_element ? sym_element->GetTextData() : WideString();
|
|
}
|
|
|
|
WideString CXFA_XMLLocale::GetDatePattern(
|
|
FX_LOCALEDATETIMESUBCATEGORY eType) const {
|
|
CFX_XMLElement* patterns = locale_->GetFirstChildNamed(L"datePatterns");
|
|
if (!patterns)
|
|
return WideString();
|
|
|
|
WideString wsName;
|
|
switch (eType) {
|
|
case FX_LOCALEDATETIMESUBCATEGORY_Short:
|
|
wsName = L"short";
|
|
break;
|
|
case FX_LOCALEDATETIMESUBCATEGORY_Default:
|
|
case FX_LOCALEDATETIMESUBCATEGORY_Medium:
|
|
wsName = L"med";
|
|
break;
|
|
case FX_LOCALEDATETIMESUBCATEGORY_Full:
|
|
wsName = L"full";
|
|
break;
|
|
case FX_LOCALEDATETIMESUBCATEGORY_Long:
|
|
wsName = L"long";
|
|
break;
|
|
}
|
|
return GetPattern(patterns, L"datePattern", wsName.AsStringView());
|
|
}
|
|
|
|
WideString CXFA_XMLLocale::GetTimePattern(
|
|
FX_LOCALEDATETIMESUBCATEGORY eType) const {
|
|
CFX_XMLElement* patterns = locale_->GetFirstChildNamed(L"timePatterns");
|
|
if (!patterns)
|
|
return WideString();
|
|
|
|
WideString wsName;
|
|
switch (eType) {
|
|
case FX_LOCALEDATETIMESUBCATEGORY_Short:
|
|
wsName = L"short";
|
|
break;
|
|
case FX_LOCALEDATETIMESUBCATEGORY_Default:
|
|
case FX_LOCALEDATETIMESUBCATEGORY_Medium:
|
|
wsName = L"med";
|
|
break;
|
|
case FX_LOCALEDATETIMESUBCATEGORY_Full:
|
|
wsName = L"full";
|
|
break;
|
|
case FX_LOCALEDATETIMESUBCATEGORY_Long:
|
|
wsName = L"long";
|
|
break;
|
|
}
|
|
return GetPattern(patterns, L"timePattern", wsName.AsStringView());
|
|
}
|
|
|
|
WideString CXFA_XMLLocale::GetNumPattern(FX_LOCALENUMSUBCATEGORY eType) const {
|
|
CFX_XMLElement* patterns = locale_->GetFirstChildNamed(L"numberPatterns");
|
|
return patterns ? XFA_PatternToString(eType) : WideString();
|
|
}
|
|
|
|
WideString CXFA_XMLLocale::GetPattern(CFX_XMLElement* patterns,
|
|
WideStringView bsTag,
|
|
WideStringView wsName) const {
|
|
for (auto* child = patterns->GetFirstChild(); child;
|
|
child = child->GetNextSibling()) {
|
|
CFX_XMLElement* pattern = ToXMLElement(child);
|
|
if (pattern && pattern->GetName() == bsTag &&
|
|
pattern->GetAttribute(L"name") == wsName) {
|
|
return pattern->GetTextData();
|
|
}
|
|
}
|
|
return WideString();
|
|
}
|