23#include <officecfg/Office/Common.hxx>
34#include <com/sun/star/i18n/KNumberFormatUsage.hpp>
35#include <com/sun/star/i18n/KNumberFormatType.hpp>
36#include <com/sun/star/i18n/FormatElement.hpp>
37#include <com/sun/star/i18n/Currency2.hpp>
38#include <com/sun/star/i18n/NumberFormatCode.hpp>
39#include <com/sun/star/i18n/XNumberFormatCode.hpp>
40#include <com/sun/star/i18n/NumberFormatMapper.hpp>
43#include <osl/mutex.hxx>
52#include <rtl/strbuf.hxx>
53#include <rtl/math.hxx>
67#define ZF_STANDARD_PERCENT 10
68#define ZF_STANDARD_CURRENCY 20
69#define ZF_STANDARD_DATE 30
70#define ZF_STANDARD_TIME 60
71#define ZF_STANDARD_DURATION (ZF_STANDARD_TIME + 4)
72#define ZF_STANDARD_DATETIME 70
73#define ZF_STANDARD_SCIENTIFIC 80
74#define ZF_STANDARD_FRACTION 85
78#define ZF_STANDARD_DATE_SYS_DMMMYYYY (ZF_STANDARD_DATE + 10)
79#define ZF_STANDARD_DATE_SYS_DMMMMYYYY (ZF_STANDARD_DATE + 11)
80#define ZF_STANDARD_DATE_SYS_NNDMMMYY (ZF_STANDARD_DATE + 12)
81#define ZF_STANDARD_DATE_SYS_NNDMMMMYYYY (ZF_STANDARD_DATE + 13)
82#define ZF_STANDARD_DATE_SYS_NNNNDMMMMYYYY (ZF_STANDARD_DATE + 14)
83#define ZF_STANDARD_DATE_DIN_DMMMYYYY (ZF_STANDARD_DATE + 15)
84#define ZF_STANDARD_DATE_DIN_DMMMMYYYY (ZF_STANDARD_DATE + 16)
85#define ZF_STANDARD_DATE_DIN_MMDD (ZF_STANDARD_DATE + 17)
86#define ZF_STANDARD_DATE_DIN_YYMMDD (ZF_STANDARD_DATE + 18)
87#define ZF_STANDARD_DATE_DIN_YYYYMMDD (ZF_STANDARD_DATE + 19)
88#define ZF_STANDARD_DATE_WW (ZF_STANDARD_DATE + 20)
90#define ZF_STANDARD_LOGICAL SV_MAX_COUNT_STANDARD_FORMATS-1
91#define ZF_STANDARD_TEXT SV_MAX_COUNT_STANDARD_FORMATS
96 "NfIndexTableOffset does not match i18npool's locale data predefined format code index bounds.");
99 "NfIndexTableOffset crosses i18npool's locale data reserved format code index bounds.\n"
100 "You will need to adapt all locale data files defining index values "
101 "(formatIndex=\"...\") in that range and increment those and when done "
102 "adjust nFirstFreeFormatIndex in include/i18npool/reservedconstants.hxx");
107#define UNKNOWN_SUBSTITUTE LANGUAGE_ENGLISH_US
182 std::vector< SvNumberFormatter* >
227 if ( nHint & ConfigurationHints::Locale )
233 if ( nHint & ConfigurationHints::Currency )
236 pFormatter->ResetDefaultSystemCurrency();
238 if ( nHint & ConfigurationHints::DatePatterns )
241 pFormatter->InvalidateDateAcceptancePatterns();
263 std::set< LanguageType > theInstalledLocales;
270#define NF_BANKSYMBOL_FIX_POSITION 1
370 static osl::Mutex* persistentMutex(
new osl::Mutex);
372 return *persistentMutex;
457 auto it =
aFTable.find( nCLOffset );
458 while ( it !=
aFTable.end() && (nKey = it->first) >= nCLOffset && nKey <= nMaxBuiltin )
465 while ( it !=
aFTable.end() && (nKey = it->first) >= nCLOffset && nKey < nNextCL )
467 aOldTable[ nKey ] = it->second.release();
479 sal_uInt32 nLastKey = nMaxBuiltin;
481 while ( !aOldTable.empty() )
483 nKey = aOldTable.begin()->first;
484 if ( nLastKey < nKey )
488 std::unique_ptr<SvNumberformat> pOldEntry(aOldTable.begin()->second);
489 aOldTable.erase( nKey );
490 OUString aString( pOldEntry->GetFormatstring() );
497 sal_Int32 nCheckPos = -1;
500 if ( nCheckPos == 0 )
512 if (
aFTable.emplace( nKey, std::move(pNewEntry) ).second )
517 DBG_ASSERT( bCheck,
"SvNumberFormatter::ReplaceSystemCL: couldn't convert" );
523 css::uno::Reference< css::i18n::XNumberFormatCode > xNFC = i18n::NumberFormatMapper::create(
m_xContext );
575 sal_Int32& nCheckPos,
579 bool bReplaceBooleanEquivalent)
583 if (rString.isEmpty())
595 std::unique_ptr<SvNumberformat> p_Entry(
new SvNumberformat(rString,
600 bReplaceBooleanEquivalent));
618 nKey =
ImpIsEntry(p_Entry->GetFormatstring(),CLOffset, eLge);
625 SAL_WARN(
"svl.numbers",
"SvNumberFormatter::PutEntry: too many formats for CL");
627 else if (!
aFTable.emplace(
nPos+1, std::move(p_Entry)).second)
629 SAL_WARN(
"svl.numbers",
"SvNumberFormatter::PutEntry: dup position");
643 sal_Int32& nCheckPos,
648 bool bConvertDateOrder,
649 bool bReplaceBooleanEquivalent )
657 pFormatScanner->SetConvertMode(eLnge, eNewLnge,
false, bConvertDateOrder);
658 bRes =
PutEntry(rString, nCheckPos,
nType, nKey, eLnge, bReplaceBooleanEquivalent);
671 const OUString aSaveString = rString;
675 const sal_Int32 nSaveCheckPos = nCheckPos;
677 const sal_uInt32 nSaveKey = nKey;
678 const bool bTargetRes =
PutEntry(rString, nCheckPos,
nType, nKey, eNewLnge,
false);
685 SAL_WARN(
"svl.numbers",
"SvNumberFormatter::PutandConvertEntry: can't scan boolean replacement");
687 rString = aSaveString;
688 nCheckPos = nSaveCheckPos;
699 sal_Int32& nCheckPos,
719 bool & rNewInserted, sal_Int32 & rCheckPos )
723 rNewInserted =
false;
727 if (rString.isEmpty())
733 sal_uInt32 nOrig =
GetEntryKey( rString, eSysLnge );
747 OUString aTmp( rString);
752 SAL_WARN(
"svl.numbers",
"SvNumberFormatter::GetIndexPuttingAndConverting: bad format code string for current locale");
762 rNewInserted =
PutEntry( rString, rCheckPos, rType, nKey, eLnge);
765 SAL_WARN(
"svl.numbers",
"SvNumberFormatter::GetIndexPuttingAndConverting: bad format code string for specified locale");
785 rNewInserted =
false;
804 sal_uInt32 nOffset = 0;
825 rKeywords[
i] = rTable[
i];
889 const Color* pColor =
nullptr;
890 OUString aFormatStr, aTemp;
892 aFormatStr +=
"\"" + aTemp +
"\";\"" + aTemp +
"\";\"";
894 aFormatStr += aTemp +
"\"";
918 bool bSystemLanguage =
false;
922 bSystemLanguage =
true;
930 OUString aTemp( pEntry->GetFormatstring());
936 "SvNumberFormatter::GetFormatStringForExcel - format code not convertible");
938 pEntry = rTempFormatter.
GetEntry( nTempKey);
958 aFormatStr = pEntry->GetMappedFormatstring( rKeywords, *rTempFormatter.
GetLocaleData(), nLang,
966 SAL_WARN(
"svl.numbers",
"SvNumberFormatter::GetFormatStringForExcel - format not found: " << nKey);
969 if (aFormatStr.isEmpty())
970 aFormatStr =
"General";
984 SAL_WARN(
"svl.numbers",
"GetKeyword: invalid index");
999 sal_uInt32 nOffset = 0;
1013 sal_uInt32 nCLOffset,
1017 auto it =
aFTable.find( nCLOffset);
1019 it !=
aFTable.end() && it->second->GetLanguage() == eLnge )
1021 if ( rString == it->second->GetFormatstring() )
1100 for ( sal_Int32 j = 0; j < xSeq.getLength(); j++ )
1102 sal_Int16 nIdx = xSeq[j].formatIndex;
1103 OUStringBuffer aDupes;
1104 for ( sal_Int32
i = 0;
i < xSeq.getLength();
i++ )
1106 if (
i != j && xSeq[
i].formatIndex == nIdx )
1108 aDupes.append( OUString::number(
i) +
"(" + xSeq[
i].formatKey +
") ");
1111 if ( !aDupes.isEmpty() )
1113 OUString aMsg =
"XML locale data FormatElement formatindex dupe: "
1114 + OUString::number(nIdx)
1115 +
"\nFormatElements: "
1116 + OUString::number( j )
1164 auto it =
aFTable.find( CLOffset);
1168 while (it !=
aFTable.end() && it->second->GetLanguage() ==
ActLnge)
1170 (*pFormatTable)[ it->first ] = it->second.get();
1176 while (it !=
aFTable.end() && it->second->GetLanguage() ==
ActLnge)
1178 if ((it->second->GetType()) &
eType)
1179 (*pFormatTable)[ it->first ] = it->second.get();
1189 FIndex = nDefaultIndex;
1196 sal_uInt32& F_Index,
1236 res =
pStringScanner->IsNumberFormat(sString, RType, fOutNumber, pFormat, eInputOptions);
1257 if (
pStringScanner->GetNumericsCount() > 3 || fOutNumber < 0.0 )
1266 else if ( fOutNumber >= 1.0 || fOutNumber < 0.0 )
1312 if (eOldType == eNewType)
1411 auto it2 =
aFTable.find( CLOffset );
1412 while ( it2 !=
aFTable.end() && (nKey = it2->first ) >= CLOffset && nKey < nStopKey )
1417 nDefaultFormat = nKey;
1451 return nDefaultFormat;
1515 if ( fNumber < 0.0 )
1522 double fSeconds = fNumber * 86400;
1523 if ( floor( fSeconds + 0.5 ) * 100 != floor( fSeconds * 100 + 0.5 ) )
1525 if ( bForceDuration || bSign || fSeconds >= 3600 )
1532 if ( bForceDuration || bSign || fNumber >= 1.0 )
1564 if (0.0 <= fNumber && fNumber < 1.0)
1570 else if (fabs( fNumber) * 24 < 0x7fff)
1578 else if (rtl::math::approxFloor( fNumber) != fNumber)
1602 sal_uInt32 nKey = nFIndex;
1614 if (rtl::math::approxFloor( fNumber) != fNumber)
1633 if (fNumber < 0.0 || fNumber >= 1.0)
1638 if (fabs( fNumber) * 24 < 0x7fff)
1675 OUString& sOutString,
1676 bool bFiltering,
bool bForceSystemLocale)
1679 const Color* pColor;
1680 sal_uInt32 nRealKey = nFIndex;
1702 bool bPrecChanged =
false;
1714 bPrecChanged =
true;
1722 if (nKey != nRealKey)
1733 bPrecChanged =
true;
1748 bPrecChanged =
true;
1762 OUString& sOutString,
1763 const Color** ppColor,
1764 bool bUseStarFormat )
1777 sOutString = sString;
1782 if ( bUseStarFormat )
1787 if ( bUseStarFormat )
1796 OUString& sOutString,
1797 const Color** ppColor,
1798 bool bUseStarFormat )
1801 if (
bNoZero && fOutNumber == 0.0)
1810 if ( bUseStarFormat )
1813 if ( bUseStarFormat )
1818 double fPreviewNumber,
1819 OUString& sOutString,
1820 const Color** ppColor,
1822 bool bUseStarFormat )
1825 if (sFormatString.isEmpty())
1835 sal_Int32 nCheckPos = -1;
1836 OUString sTmpString = sFormatString;
1848 GetOutputString(fPreviewNumber, nKey, sOutString, ppColor, bUseStarFormat);
1852 if ( bUseStarFormat )
1857 if ( bUseStarFormat )
1871 double fPreviewNumber,
1872 OUString& sOutString,
1873 const Color** ppColor,
1877 if (sFormatString.isEmpty())
1891 sal_uInt32 nKey =
ImpIsEntry( aFormatStringUpper, nCLOffset, eLnge );
1899 std::optional<SvNumberformat> pEntry;
1900 sal_Int32 nCheckPos = -1;
1901 OUString sTmpString;
1905 sTmpString = sFormatString;
1918 sTmpString = sFormatString;
1924 if ( !bEnglishFormat )
1927 pEntry->GetFormatstring() ) )
1932 sTmpString = sFormatString;
1939 sal_Int32 nCheckPos2 = -1;
1941 eFormatLang = eLnge;
1943 sTmpString = sFormatString;
1954 sTmpString = sFormatString;
1965 pEntry->GetOutputString( fPreviewNumber, sOutString, ppColor );
1972 const OUString& sPreviewString,
1973 OUString& sOutString,
1974 const Color** ppColor,
1978 if (sFormatString.isEmpty())
1988 sal_Int32 nCheckPos = -1;
1989 OUString sTmpString = sFormatString;
2016 sOutString = sPreviewString;
2031 if (sFormatString.isEmpty())
2042 sal_Int32 nCheckPos = -1;
2043 OUString sTmpString = sFormatString;
2063 sal_uInt32 nPos,
bool bAfterChangingSystemCL,
2064 sal_Int16 nOrgIndex )
2069 " Please see description in include/svl/zforlist.hxx at end of enum NfIndexTableOffset");
2071 "reserved formatIndex, see warning above");
2073 OUString aCodeStr( rCode.Code );
2075 rCode.Usage == css::i18n::KNumberFormatUsage::CURRENCY &&
2078 if ( aCodeStr.indexOf(
"[$" ) >= 0)
2085 OUString aMsg =
"SvNumberFormatter::ImpInsertFormat: no [$...] on currency format code, index " +
2086 OUString::number( rCode.Index) +
2093 sal_Int32 nCheckPos = 0;
2094 std::unique_ptr<SvNumberformat> pFormat(
new SvNumberformat(aCodeStr,
2103 OUString aMsg =
"SvNumberFormatter::ImpInsertFormat: bad format code, index " +
2104 OUString::number( rCode.Index ) +
2122 switch ( nOrgIndex )
2132 OUString aMsg =
"SvNumberFormatter::ImpInsertFormat: dup format code, index "
2133 + OUString::number( rCode.Index )
2146 OUString aMsg =
"SvNumberFormatter::ImpInsertFormat: too many format codes, index "
2147 + OUString::number( rCode.Index )
2155 auto pFormat2 = pFormat.get();
2156 if ( !
aFTable.emplace(
nPos, std::move(pFormat) ).second )
2160 OUString aMsg =
"ImpInsertFormat: can't insert number format key pos: "
2161 + OUString::number(
nPos )
2163 + OUString::number( rCode.Index )
2170 SAL_WARN(
"svl.numbers",
"SvNumberFormatter::ImpInsertFormat: dup position");
2174 if ( rCode.Default )
2175 pFormat2->SetStandard();
2176 if ( !rCode.DefaultName.isEmpty() )
2177 pFormat2->SetComment( rCode.DefaultName );
2184 sal_uInt16& nPrecision,
2185 sal_uInt16& nLeadingCnt)
2192 nPrecision, nLeadingCnt);
2242 if (nLang == eSaveLang)
2265 bool& bThousand,
bool& IsRed, sal_uInt16& nPrecision,
2276 OUString aTmpStr( rFormatString );
2277 sal_Int32 nCheckPos = 0;
2280 if ( nCheckPos == 0 )
2302 bool bAppendPrec =
true;
2303 sal_uInt16 nPrec, nLeading;
2304 bool bThousand, bIsRed;
2326 bAppendPrec =
false;
2348 default:
aStr =
"G";
2354 aStr += OUString::number(nPrec);
2369 css::uno::Sequence< css::i18n::NumberFormatCode >& rSeq,
2372 auto pSeq = std::find_if(std::cbegin(rSeq), std::cend(rSeq),
2373 [nTabOff](
const css::i18n::NumberFormatCode& rCode) {
return rCode.Index == nTabOff; });
2374 if (pSeq != std::cend(rSeq))
2375 return static_cast<sal_Int32
>(std::distance(std::cbegin(rSeq), pSeq));
2381 OUString aMsg =
"SvNumberFormatter::ImpGetFormatCodeIndex: not found: "
2382 + OUString::number( nTabOff );
2385 if ( rSeq.hasElements() )
2388 pSeq = std::find_if(std::cbegin(rSeq), std::cend(rSeq),
2389 [](
const css::i18n::NumberFormatCode& rCode) {
return rCode.Default; });
2390 if (pSeq != std::cend(rSeq))
2391 return static_cast<sal_Int32
>(std::distance(std::cbegin(rSeq), pSeq));
2397 pSeq = std::find_if(std::cbegin(rSeq), std::cend(rSeq),
2399 if (pSeq != std::cend(rSeq))
2400 return static_cast<sal_Int32
>(std::distance(std::cbegin(rSeq), pSeq));
2402 pSeq = std::find_if(std::cbegin(rSeq), std::cend(rSeq),
2403 [](
const css::i18n::NumberFormatCode& rCode) {
return rCode.Index ==
NF_CURRENCY_1000INT; });
2404 if (pSeq != std::cend(rSeq))
2405 return static_cast<sal_Int32
>(std::distance(std::cbegin(rSeq), pSeq));
2410 rSeq = { css::i18n::NumberFormatCode() };
2418 css::i18n::NumberFormatCode * pFormatArr,
2426 OUStringBuffer aMsg;
2427 sal_Int32 nElem, nShort, nMedium, nLong, nShortDef, nMediumDef, nLongDef;
2428 nShort = nMedium = nLong = nShortDef = nMediumDef = nLongDef = -1;
2429 for ( nElem = 0; nElem < nCnt; nElem++ )
2431 switch ( pFormatArr[nElem].
Type )
2433 case i18n::KNumberFormatType::SHORT :
2436 case i18n::KNumberFormatType::MEDIUM :
2439 case i18n::KNumberFormatType::LONG :
2443 aMsg.append(
"unknown type");
2445 if ( pFormatArr[nElem].
Default )
2447 switch ( pFormatArr[nElem].
Type )
2449 case i18n::KNumberFormatType::SHORT :
2450 if ( nShortDef != -1 )
2451 aMsg.append(
"dupe short type default");
2454 case i18n::KNumberFormatType::MEDIUM :
2455 if ( nMediumDef != -1 )
2456 aMsg.append(
"dupe medium type default");
2459 case i18n::KNumberFormatType::LONG :
2460 if ( nLongDef != -1 )
2461 aMsg.append(
"dupe long type default");
2466 if (!aMsg.isEmpty())
2468 aMsg.insert(0,
"SvNumberFormatter::ImpAdjustFormatCodeDefault: ");
2469 aMsg.append(
"\nXML locale data FormatElement formatindex: "
2470 + OUString::number(
static_cast<sal_Int32
>(pFormatArr[nElem].
Index)));
2475 if ( nShort != -1 && nShortDef == -1 )
2476 aMsg.append(
"no short type default ");
2477 if ( nMedium != -1 && nMediumDef == -1 )
2478 aMsg.append(
"no medium type default ");
2479 if ( nLong != -1 && nLongDef == -1 )
2480 aMsg.append(
"no long type default ");
2481 if (!aMsg.isEmpty())
2483 aMsg.insert(0,
"SvNumberFormatter::ImpAdjustFormatCodeDefault: ");
2484 aMsg.append(
"\nXML locale data FormatElement group of: ");
2491 sal_Int32 nElem, nDef, nMedium;
2492 nDef = nMedium = -1;
2493 for ( nElem = 0; nElem < nCnt; nElem++ )
2495 if ( pFormatArr[nElem].
Default )
2497 switch ( pFormatArr[nElem].
Type )
2499 case i18n::KNumberFormatType::MEDIUM :
2500 nDef = nMedium = nElem;
2502 case i18n::KNumberFormatType::LONG :
2503 if ( nMedium == -1 )
2509 pFormatArr[nElem].Default =
false;
2515 pFormatArr[nDef].Default =
true;
2520 auto it =
aFTable.find( nKey);
2522 return it->second.get();
2534 auto it =
aFTable.find( nKey);
2536 return it->second.get();
2571 auto it =
aFTable.find( nKey);
2572 return it ==
aFTable.end() ? nullptr : it->second.get();
2578 if (bOldConvertMode)
2584 css::uno::Reference< css::i18n::XNumberFormatCode > xNFC = i18n::NumberFormatMapper::create(
m_xContext );
2588 uno::Sequence< i18n::NumberFormatCode > aFormatSeq = xNFC->getAllFormatCode( i18n::KNumberFormatUsage::FIXED_NUMBER, aLocale );
2601 appendLocaleInfo(
u"SvNumberFormatter::ImpGenerateFormats: General format not NUMBER"));
2612 appendLocaleInfo(
u"SvNumberFormatter::ImpGenerateFormats: General format not insertable, nothing will work"));
2619 sal_Int32 nCheckPos = 0;
2624 pNewFormat->SetStandard();
2626 std::move(pNewFormat)).second )
2628 SAL_WARN(
"svl.numbers",
"SvNumberFormatter::ImpGenerateFormats: dup position Boolean");
2636 pNewFormat->SetStandard();
2638 std::move(pNewFormat)).second )
2640 SAL_WARN(
"svl.numbers",
"SvNumberFormatter::ImpGenerateFormats: dup position Text");
2671 aFormatSeq = xNFC->getAllFormatCode( i18n::KNumberFormatUsage::PERCENT_NUMBER, aLocale );
2687 aFormatSeq = xNFC->getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY, aLocale );
2697 auto aFormat = aFormatSeq[nIdx];
2698 aFormat.Default =
false;
2704 aFormat = aFormatSeq[nIdx];
2705 aFormat.Default =
false;
2711 aFormat = aFormatSeq[nIdx];
2712 aFormat.Default =
false;
2718 aFormat = aFormatSeq[nIdx];
2719 aFormat.Default =
false;
2725 aFormat = aFormatSeq[nIdx];
2726 aFormat.Default =
false;
2732 aFormat = aFormatSeq[nIdx];
2733 aFormat.Default =
false;
2739 aFormatSeq = xNFC->getAllFormatCode( i18n::KNumberFormatUsage::DATE, aLocale );
2849 aFormatSeq = xNFC->getAllFormatCode( i18n::KNumberFormatUsage::TIME, aLocale );
2889 aFormatSeq = xNFC->getAllFormatCode( i18n::KNumberFormatUsage::DATE_TIME, aLocale );
2908 i18n::NumberFormatCode aSingleFormatCode;
2909 aSingleFormatCode.Usage = i18n::KNumberFormatUsage::DATE_TIME;
2912 aSingleFormatCode.Code =
2925 aSingleFormatCode.Code =
2938 aSingleFormatCode.Code =
2951 aSingleFormatCode.Code =
2966 aFormatSeq = xNFC->getAllFormatCode( i18n::KNumberFormatUsage::SCIENTIFIC_NUMBER, aLocale );
2981 aSingleFormatCode.Usage = i18n::KNumberFormatUsage::FRACTION_NUMBER;
2984 aSingleFormatCode.Code =
"# ?/?";
2990 aSingleFormatCode.Code =
"# ?\?/?\?";
2996 aSingleFormatCode.Code =
"# ?\?\?/?\?\?";
3001 aSingleFormatCode.Code =
"# ?/2";
3006 aSingleFormatCode.Code =
"# ?/4";
3011 aSingleFormatCode.Code =
"# ?/8";
3016 aSingleFormatCode.Code =
"# ?\?/16";
3021 aSingleFormatCode.Code =
"# ?\?/10";
3026 aSingleFormatCode.Code =
"# ?\?/100";
3032 aSingleFormatCode.Code = rKeyword[
NF_KEY_WW];
3038 if ( !bNoAdditionalFormats )
3042 if (bOldConvertMode)
3050 css::uno::Reference< css::i18n::XNumberFormatCode >
const & rNumberFormatCode,
3051 bool bAfterChangingSystemCL )
3056 SAL_WARN(
"svl.numbers",
"ImpGenerateAdditionalFormats: no GENERAL format" );
3064 uno::Sequence< i18n::NumberFormatCode > aFormatSeq = rNumberFormatCode->getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY, aLocale );
3065 sal_Int32 nCodes = aFormatSeq.getLength();
3066 auto aNonConstRange = asNonConstRange(aFormatSeq);
3068 for ( i18n::NumberFormatCode& rFormat : aNonConstRange )
3072 SAL_WARN(
"svl.numbers",
"ImpGenerateAdditionalFormats: too many formats" );
3079 sal_Int16 nOrgIndex = rFormat.Index;
3080 rFormat.Index = sal::static_int_cast< sal_Int16 >(
3083 bool bDefault = rFormat.Default;
3084 rFormat.Default =
false;
3086 bAfterChangingSystemCL, nOrgIndex ) )
3088 pNewFormat->SetAdditionalBuiltin();
3091 rFormat.Index = nOrgIndex;
3092 rFormat.Default = bDefault;
3102 aFormatSeq = rNumberFormatCode->getAllFormatCodes( aLocale );
3103 for (
const auto& rFormat : std::as_const(aFormatSeq) )
3107 SAL_WARN(
"svl.numbers",
"ImpGenerateAdditionalFormats: too many formats" );
3113 bAfterChangingSystemCL ) )
3115 pNewFormat->SetAdditionalBuiltin();
3127 sal_Int32
nLength = sFormat.getLength();
3128 for ( sal_Int32
i=nStartPos; i<nLength && i>=0 ;
i++ )
3133 i = sFormat.indexOf(
'\"',
i+1);
3136 i = sFormat.indexOf(
']',
i+1);
3162 sal_uInt16 nPrecision,
3163 sal_uInt16 nLeadingZeros)
3181 OUStringBuffer sString;
3186 assert(pFormat &&
"with !pFormat eType can only be SvNumFormatType::UNDEFINED");
3189 else if (nLeadingZeros == 0)
3192 sString.append(
'#');
3197 sString.append(
"###");
3201 sString.append(
"#" + rThSep);
3202 padToLength(sString, sString.getLength() + nDigitsInFirstGroup,
'#');
3208 for (sal_uInt16
i = 0;
i < nLeadingZeros;
i++)
3210 if (bThousand &&
i > 0 &&
i == aGrouping.
getPos())
3212 sString.insert(0, rThSep);
3215 sString.insert(0,
'0');
3220 for (sal_Int32
i = nLeadingZeros;
i < nDigits;
i++)
3222 if (
i % nDigitsInFirstGroup == 0 )
3223 sString.insert(0, rThSep);
3224 sString.insert(0,
'#');
3231 padToLength(sString, sString.getLength() + nPrecision,
'0');
3236 const OUString sNegNatNumModifier = pFormat ?
3249 sal_Int32 nIndexE =
ImpPosToken( sOldFormatString,
'E' );
3252 sal_Int32 nIndexSep =
ImpPosToken( sOldFormatString,
';', nIndexE );
3253 if (nIndexSep > nIndexE)
3254 sString.append( sOldFormatString.subView(nIndexE, nIndexSep - nIndexE) );
3256 sString.append( sOldFormatString.subView(nIndexE) );
3261 OUStringBuffer sNegStr(sString);
3263 const NfCurrencyEntry* pEntry;
3265 bool isPosNatNum12 = sPosNatNumModifier.startsWith(
"[NatNum12" );
3266 bool isNegNatNum12 = sNegNatNumModifier.startsWith(
"[NatNum12" );
3267 if ( !isPosNatNum12 || !isNegNatNum12 )
3273 sal_uInt16 nPosiForm = NfCurrencyEntry::GetEffectivePositiveFormat(
3275 pEntry->GetPositiveFormat(), bBank );
3276 sal_uInt16 nNegaForm = NfCurrencyEntry::GetEffectiveNegativeFormat(
3278 pEntry->GetNegativeFormat(), bBank );
3279 if ( !isPosNatNum12 )
3280 pEntry->CompletePositiveFormatString( sString, bBank, nPosiForm );
3281 if ( !isNegNatNum12 )
3282 pEntry->CompleteNegativeFormatString( sNegStr, bBank, nNegaForm );
3286 sal_uInt16 nPosiForm = NfCurrencyEntry::GetEffectivePositiveFormat(
3289 sal_uInt16 nNegaForm = NfCurrencyEntry::GetEffectiveNegativeFormat(
3292 if ( !isPosNatNum12 )
3293 NfCurrencyEntry::CompletePositiveFormatString( sString, aCurr, nPosiForm );
3294 if ( !isNegNatNum12 )
3295 NfCurrencyEntry::CompleteNegativeFormatString( sNegStr, aCurr, nNegaForm );
3300 OUString aSymbol, aAbbrev;
3302 if ( !isPosNatNum12 )
3303 NfCurrencyEntry::CompletePositiveFormatString( sString,
3305 if ( !isNegNatNum12 )
3306 NfCurrencyEntry::CompleteNegativeFormatString( sNegStr,
3310 sString.append(
';' );
3315 sString.append( sNegNatNumModifier );
3316 if ( isNegNatNum12 )
3318 sString.append(
'-' );
3320 sString.append(sNegStr);
3325 if ( aIntegerFractionDelimiterString ==
" " )
3326 sString.append( aIntegerFractionDelimiterString );
3329 sString.append(
"\"" + aIntegerFractionDelimiterString +
"\"" );
3333 if ( nPrecision > 0 )
3334 padToLength(sString, sString.getLength() + nPrecision,
'?');
3336 sString.append(
'#' );
3340 bool insertBrackets =
false;
3345 if (IsRed || insertBrackets)
3347 OUStringBuffer sTmpStr(sString);
3351 sTmpStr.append(
"_)");
3353 sTmpStr.append(
';');
3359 sTmpStr.append( sNegNatNumModifier );
3363 sTmpStr.append(
"(" + sString +
")");
3367 sTmpStr.append(
"-" + sString);
3372 sString.insert( 0, sPosNatNumModifier );
3373 return sString.makeStringAndClear();
3395 sal_uInt32 nKey =
ImpIsEntry(sStr, CLOffset, eLnge);
3467 sal_uInt32 nCLOffset = 0;
3468 sal_uInt32 nOldKey, nOffset, nNewKey;
3470 for (
const auto& rEntry : rTable.
aFTable)
3473 nOldKey = rEntry.first;
3481 nNewKey = nCLOffset + nOffset;
3485 if (!
aFTable.emplace( nNewKey, std::move(pNewEntry)).second)
3487 SAL_WARN(
"svl.numbers",
"SvNumberFormatter::MergeFormatter: dup position");
3490 if (nNewKey != nOldKey)
3492 (*pMergeTable)[nOldKey] = nNewKey;
3498 nNewKey =
ImpIsEntry(pNewEntry->GetFormatstring(),
3508 SAL_WARN(
"svl.numbers",
"SvNumberFormatter::MergeFormatter: too many formats for CL");
3510 else if (!
aFTable.emplace( nNewKey, std::move(pNewEntry)).second)
3512 SAL_WARN(
"svl.numbers",
"SvNumberFormatter::MergeFormatter: dup position");
3520 if (nNewKey != nOldKey)
3522 (*pMergeTable)[nOldKey] = nNewKey;
3540 sal_uInt32 nOldKey = rEntry.first;
3541 aMap[ nOldKey ] = rEntry.second;
3566 return nCLOffset + nOffset;
3644 return officecfg::Office::Common::DateFormat::TwoDigitYear::get();
3651 SAL_INFO(
"svl",
"Resetting the currency table.");
3664 return theCurrencyTable();
3690 for ( sal_uInt16 j = 0; j <
nCount; j++ )
3706 for ( sal_uInt16 j = 0; j <
nCount; j++ )
3709 rTable[j].GetBankSymbol() == rAbbrev )
3720 std::u16string_view rAbbrev )
3725 for ( sal_uInt16 j = 0; j <
nCount; j++ )
3727 if ( rTable[j].GetSymbol() == rSymbol &&
3728 rTable[j].GetBankSymbol() == rAbbrev )
3743 SetDefaultSystemCurrency( aAbbrev, eLang );
3757 if ( !rAbbrev.empty() )
3759 for ( sal_uInt16 j = 0; j <
nCount; j++ )
3761 if ( rTable[j].
GetLanguage() == eLang && rTable[j].GetBankSymbol() == rAbbrev )
3770 for ( sal_uInt16 j = 0; j <
nCount; j++ )
3804 DBG_ASSERT( aCurrList.size(),
"where is the NewCurrency System standard format?!?" );
3809 DBG_ASSERT( nCheck == 0,
"NewCurrency CheckError" );
3811 "nDefaultSystemCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND" );
3828 auto it2 =
aFTable.lower_bound( CLOffset );
3829 while ( it2 !=
aFTable.end() && (nKey = it2->first) >= CLOffset && nKey < nStopKey )
3834 nDefaultCurrencyFormat = nKey;
3846 DBG_ASSERT( aCurrList.size(),
"where is the NewCurrency standard format?" );
3847 if ( !aCurrList.empty() )
3853 nDefaultCurrencyFormat,
ActLnge );
3854 DBG_ASSERT( nCheck == 0,
"NewCurrency CheckError" );
3856 "nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND" );
3870 return nDefaultCurrencyFormat;
3877 const NfCurrencyEntry*& pFoundEntry,
bool& bFoundBank,
const NfCurrencyEntry* pData,
3878 sal_uInt16 nPos, std::u16string_view rSymbol )
3881 if (
pData->GetSymbol() == rSymbol )
3886 else if (
pData->GetBankSymbol() == rSymbol )
3895 if ( pFoundEntry && pFoundEntry !=
pData )
3897 pFoundEntry =
nullptr;
3911 pFoundEntry =
pData;
3916 pFoundEntry =
pData;
3924 const NfCurrencyEntry** ppEntry ,
3936 OUString aSymbol, aExtension;
3939 OUStringBuffer sBuff(128);
3942 bool bFoundBank =
false;
3945 bFoundBank, aSymbol, aExtension, pFormat->
GetLanguage(),
3949 *ppEntry = pFoundEntry;
3951 *pBank = bFoundBank;
3952 rStr = pFoundEntry->BuildSymbolString(bFoundBank);
3955 if ( rStr.isEmpty() )
3958 if ( aSymbol.indexOf(
'-' ) != -1 ||
3959 aSymbol.indexOf(
']' ) != -1 )
3961 sBuff.append(
"\"" + aSymbol +
"\"");
3965 sBuff.append(aSymbol);
3967 if ( !aExtension.isEmpty() )
3969 sBuff.append(aExtension);
3973 rStr = sBuff.makeStringAndClear();
3984 std::u16string_view rSymbol,
3985 std::u16string_view rExtension,
3987 bool bOnlyStringLanguage )
3989 sal_Int32 nExtLen = rExtension.size();
4004 nExtLang = -nExtLang;
4005 SAL_WARN_IF(nExtLang > 0xFFFF,
"svl.numbers",
"Out of range Lang Id: " << nExtLang <<
" from input string: " << OUString(rExtension));
4013 const NfCurrencyEntry* pFoundEntry =
nullptr;
4021 for ( sal_uInt16 j = 0; j <
nCount && bCont; j++ )
4024 if ( eLang == eExtLang ||
4029 &rTable[j], j, rSymbol );
4035 if ( pFoundEntry || !bCont || (bOnlyStringLanguage && nExtLen) )
4039 if ( !bOnlyStringLanguage )
4042 for ( sal_uInt16 j = 0; j <
nCount && bCont; j++ )
4045 if ( eLang == eFormatLanguage ||
4050 &rTable[j], j, rSymbol );
4055 if ( pFoundEntry || !bCont )
4064 for ( sal_uInt16 j = 0; j <
nCount && bCont; j++ )
4067 &rTable[j], j, rSymbol );
4078 const css::uno::Sequence< css::i18n::Currency2 >
4081 auto pCurrency = std::find_if(xCurrencies.begin(), xCurrencies.end(),
4082 [](
const css::i18n::Currency2& rCurrency) { return rCurrency.UsedInCompatibleFormatCodes; });
4083 if (pCurrency != xCurrencies.end())
4085 rSymbol = pCurrency->Symbol;
4086 rAbbrev = pCurrency->BankSymbol;
4093 appendLocaleInfo(
u"GetCompatibilityCurrency: none?"));
4103 switch ( rCurr.GetPositiveFormat() )
4114 switch ( rCurr.GetNegativeFormat() )
4146 return theInstalledLocales.find( eLang) != theInstalledLocales.end();
4156 static bool bInitializing =
false;
4161 bInitializing =
true;
4164 std::optional<LocaleDataWrapper> pLocaleData(std::in_place,
4165 ::comphelper::getProcessComponentContext(),
4168 OUString aConfiguredCurrencyAbbrev;
4171 aConfiguredCurrencyAbbrev, eConfiguredCurrencyLanguage );
4172 sal_uInt16 nSecondarySystemCurrencyPosition = 0;
4173 sal_uInt16 nMatchingSystemCurrencyPosition = 0;
4176 auto& rCurrencyTable = theCurrencyTable();
4177 rCurrencyTable.insert(
4178 rCurrencyTable.begin(),
4180 sal_uInt16 nCurrencyPos = 1;
4183 sal_Int32 nLocaleCount = xLoc.getLength();
4184 SAL_INFO(
"svl.numbers",
"number of locales: \"" << nLocaleCount <<
"\"" );
4185 NfCurrencyTable &rLegacyOnlyCurrencyTable = theLegacyOnlyCurrencyTable();
4186 sal_uInt16 nLegacyOnlyCurrencyPos = 0;
4187 for ( css::lang::Locale
const & rLocale : xLoc )
4190 theInstalledLocales.insert( eLang);
4191 pLocaleData.emplace(
4192 ::comphelper::getProcessComponentContext(),
4194 Sequence< Currency2 > aCurrSeq = pLocaleData->getAllCurrencies();
4195 sal_Int32 nCurrencyCount = aCurrSeq.getLength();
4196 Currency2
const *
const pCurrencies = aCurrSeq.getConstArray();
4200 for ( nDefault = 0; nDefault < nCurrencyCount; nDefault++ )
4202 if ( pCurrencies[nDefault].
Default )
4205 std::optional<NfCurrencyEntry> pEntry;
4206 if ( nDefault < nCurrencyCount )
4208 pEntry.emplace(pCurrencies[nDefault], *pLocaleData, eLang);
4212 pEntry.emplace(*pLocaleData, eLang);
4219 pEntry->GetBankSymbol() == aConfiguredCurrencyAbbrev &&
4220 pEntry->GetLanguage() == eConfiguredCurrencyLanguage )
4224 if ( !nMatchingSystemCurrencyPosition &&
4225 pEntry->GetLanguage() == eSysLang )
4227 nMatchingSystemCurrencyPosition = nCurrencyPos;
4229 rCurrencyTable.insert(
4230 rCurrencyTable.begin() + nCurrencyPos++, std::move(*pEntry));
4232 if ( nCurrencyCount > 1 )
4234 sal_Int32 nCurrency;
4235 for ( nCurrency = 0; nCurrency < nCurrencyCount; nCurrency++ )
4237 if (pCurrencies[nCurrency].LegacyOnly)
4239 rLegacyOnlyCurrencyTable.
insert(
4240 rLegacyOnlyCurrencyTable.
begin() + nLegacyOnlyCurrencyPos++,
4242 pCurrencies[nCurrency], *pLocaleData, eLang));
4244 else if ( nCurrency != nDefault )
4246 pEntry.emplace(pCurrencies[nCurrency], *pLocaleData, eLang);
4248 bool bInsert =
true;
4249 sal_uInt16
n = rCurrencyTable.size();
4250 sal_uInt16 aCurrencyIndex = 1;
4251 for ( sal_uInt16 j=1; j<
n; j++ )
4253 if ( rCurrencyTable[aCurrencyIndex++] == *pEntry )
4265 if ( !nSecondarySystemCurrencyPosition &&
4266 (!aConfiguredCurrencyAbbrev.isEmpty() ?
4267 pEntry->GetBankSymbol() == aConfiguredCurrencyAbbrev :
4268 pEntry->GetLanguage() == eConfiguredCurrencyLanguage) )
4270 nSecondarySystemCurrencyPosition = nCurrencyPos;
4272 if ( !nMatchingSystemCurrencyPosition &&
4273 pEntry->GetLanguage() == eSysLang )
4275 nMatchingSystemCurrencyPosition = nCurrencyPos;
4277 rCurrencyTable.insert(
4278 rCurrencyTable.begin() + nCurrencyPos++, std::move(*pEntry));
4292 "SvNumberFormatter::ImpInitCurrencyTable: configured currency not in I18N locale data.");
4303 "SvNumberFormatter::ImpInitCurrencyTable: system currency not in I18N locale data.");
4305 pLocaleData.reset();
4307 bInitializing =
false;
4316 NfWSStringsDtor::const_iterator it( std::find( rStrArr.begin(), rStrArr.end(), rFormat));
4317 if (it != rStrArr.end())
4318 return it - rStrArr.begin();
4320 rStrArr.push_back( rFormat);
4321 return rStrArr.size() - 1;
4326 const NfCurrencyEntry& rCurr,
4334 sal_uInt16 nDefault = 0;
4338 OUString aPositiveBank = rCurr.BuildPositiveFormatString(
true, *
xLocaleData);
4339 OUString aNegativeBank = rCurr.BuildNegativeFormatString(
true, *
xLocaleData );
4341 OUString format1 = aPositiveBank
4346 OUString format2 = aPositiveBank
4356 OUString aPositive = rCurr.BuildPositiveFormatString(
false, *
xLocaleData );
4357 OUString aNegative = rCurr.BuildNegativeFormatString(
false, *
xLocaleData );
4363 if (rCurr.GetDigits())
4365 OUString aPositiveNoDec = rCurr.BuildPositiveFormatString(
false, *
xLocaleData, 0);
4366 OUString aNegativeNoDec = rCurr.BuildNegativeFormatString(
false, *
xLocaleData, 0 );
4367 OUString aPositiveDashed = rCurr.BuildPositiveFormatString(
false, *
xLocaleData, 2);
4368 OUString aNegativeDashed = rCurr.BuildNegativeFormatString(
false, *
xLocaleData, 2);
4370 format1 = aPositiveNoDec
4374 format3 = aPositiveNoDec
4379 format5 = aPositiveDashed
4394 if (rCurr.GetDigits())
4399 if (rCurr.GetDigits())
4404 if (rCurr.GetDigits())
4417 SvNumberFormatterIndexTable::const_iterator it =
pMergeTable->find(nOldFmt);
4437 if ( nYear < (nTwoDigitYearStart % 100) )
4439 return nYear + (((nTwoDigitYearStart / 100) + 1) * 100);
4443 return nYear + ((nTwoDigitYearStart / 100) * 100);
4461NfCurrencyEntry::NfCurrencyEntry(
const css::i18n::Currency & rCurr,
4464 aSymbol = rCurr.Symbol;
4465 aBankSymbol = rCurr.BankSymbol;
4469 nDigits = rCurr.DecimalPlaces;
4475 return aSymbol == r.aSymbol
4476 && aBankSymbol == r.aBankSymbol
4477 && eLanguage == r.eLanguage
4481OUString NfCurrencyEntry::BuildSymbolString(
bool bBank,
4482 bool bWithoutExtension)
const
4484 OUStringBuffer
aBuf(
"[$");
4487 aBuf.append(aBankSymbol);
4491 if ( aSymbol.indexOf(
'-' ) >= 0 ||
4492 aSymbol.indexOf(
']' ) >= 0)
4494 aBuf.append(
"\"" + aSymbol +
"\"");
4498 aBuf.append(aSymbol);
4500 if ( !bWithoutExtension && eLanguage != LANGUAGE_DONTKNOW && eLanguage != LANGUAGE_SYSTEM )
4502 sal_Int32 nLang =
static_cast<sal_uInt16
>(eLanguage);
4503 aBuf.append(
"-" + OUString::number(nLang, 16).toAsciiUpperCase());
4507 return aBuf.makeStringAndClear();
4510OUString NfCurrencyEntry::Impl_BuildFormatStringNumChars(
const LocaleDataWrapper& rLoc,
4511 sal_uInt16 nDecimalFormat)
const
4514 if (nDecimalFormat && nDigits)
4517 sal_Unicode cDecimalChar = nDecimalFormat == 2 ?
'-' : cZeroChar;
4518 for (sal_uInt16 i = 0;
i < nDigits; ++
i)
4520 aBuf.append(cDecimalChar);
4523 return aBuf.makeStringAndClear();
4527OUString NfCurrencyEntry::BuildPositiveFormatString(
bool bBank,
const LocaleDataWrapper& rLoc,
4528 sal_uInt16 nDecimalFormat)
const
4530 OUStringBuffer sBuf(Impl_BuildFormatStringNumChars(rLoc, nDecimalFormat));
4532 nPositiveFormat, bBank );
4533 CompletePositiveFormatString(sBuf, bBank, nPosiForm);
4534 return sBuf.makeStringAndClear();
4538OUString NfCurrencyEntry::BuildNegativeFormatString(
bool bBank,
4541 OUStringBuffer sBuf(Impl_BuildFormatStringNumChars(rLoc, nDecimalFormat));
4543 nNegativeFormat, bBank );
4544 CompleteNegativeFormatString(sBuf, bBank, nNegaForm);
4545 return sBuf.makeStringAndClear();
4549void NfCurrencyEntry::CompletePositiveFormatString(OUStringBuffer& rStr,
bool bBank,
4550 sal_uInt16 nPosiForm)
const
4552 OUString aSymStr = BuildSymbolString(bBank);
4553 NfCurrencyEntry::CompletePositiveFormatString( rStr, aSymStr, nPosiForm );
4557void NfCurrencyEntry::CompleteNegativeFormatString(OUStringBuffer& rStr,
bool bBank,
4558 sal_uInt16 nNegaForm)
const
4560 OUString aSymStr = BuildSymbolString(bBank);
4561 NfCurrencyEntry::CompleteNegativeFormatString( rStr, aSymStr, nNegaForm );
4566void NfCurrencyEntry::CompletePositiveFormatString(OUStringBuffer& rStr, std::u16string_view rSymStr,
4567 sal_uInt16 nPositiveFormat)
4569 switch( nPositiveFormat )
4572 rStr.insert(0, rSymStr);
4575 rStr.append(rSymStr);
4579 rStr.insert(0, OUString::Concat(rSymStr) +
" ");
4585 rStr.append(rSymStr);
4589 SAL_WARN(
"svl.numbers",
"NfCurrencyEntry::CompletePositiveFormatString: unknown option");
4596void NfCurrencyEntry::CompleteNegativeFormatString(OUStringBuffer& rStr,
4597 std::u16string_view rSymStr,
4598 sal_uInt16 nNegativeFormat)
4600 switch( nNegativeFormat )
4604 rStr.insert(0, OUString::Concat(
"(") + rSymStr);
4610 rStr.insert(0, OUString::Concat(
"-") + rSymStr);
4615 rStr.insert(0, OUString::Concat(rSymStr) +
"-");
4620 rStr.insert(0, rSymStr);
4626 rStr.insert(0,
'(');
4627 rStr.append(rSymStr);
4633 rStr.append(rSymStr);
4634 rStr.insert(0,
'-');
4640 rStr.append(rSymStr);
4645 rStr.append(rSymStr);
4652 rStr.append(rSymStr);
4653 rStr.insert(0,
'-');
4658 rStr.insert(0, OUString::Concat(
"-") + rSymStr +
" ");
4664 rStr.append(rSymStr);
4670 rStr.insert(0, OUString::Concat(rSymStr) +
" -");
4675 rStr.insert(0, OUString::Concat(rSymStr) +
" ");
4683 rStr.append(rSymStr);
4688 rStr.insert(0, OUString::Concat(
"(") + rSymStr +
" ");
4694 rStr.insert(0,
'(');
4696 rStr.append(rSymStr);
4701 SAL_WARN(
"svl.numbers",
"NfCurrencyEntry::CompleteNegativeFormatString: unknown option");
4708sal_uInt16 NfCurrencyEntry::GetEffectivePositiveFormat( sal_uInt16 nIntlFormat,
4709 sal_uInt16 nCurrFormat,
bool bBank )
4713#if NF_BANKSYMBOL_FIX_POSITION
4717 switch ( nIntlFormat )
4730 SAL_WARN(
"svl.numbers",
"NfCurrencyEntry::GetEffectivePositiveFormat: unknown option");
4745 switch ( nIntlFormat )
4771 SAL_WARN(
"svl.numbers",
"lcl_MergeNegativeParenthesisFormat: unknown option");
4775 switch ( nCurrFormat )
4827sal_uInt16 NfCurrencyEntry::GetEffectiveNegativeFormat( sal_uInt16 nIntlFormat,
4828 sal_uInt16 nCurrFormat,
bool bBank )
4832#if NF_BANKSYMBOL_FIX_POSITION
4835 switch ( nIntlFormat )
4884 SAL_WARN(
"svl.numbers",
"NfCurrencyEntry::GetEffectiveNegativeFormat: unknown option");
4889 else if ( nIntlFormat != nCurrFormat )
4891 switch ( nCurrFormat )
4895 nIntlFormat, nCurrFormat );
4898 nIntlFormat = nCurrFormat;
4901 nIntlFormat = nCurrFormat;
4904 nIntlFormat = nCurrFormat;
4908 nIntlFormat, nCurrFormat );
4911 nIntlFormat = nCurrFormat;
4914 nIntlFormat = nCurrFormat;
4917 nIntlFormat = nCurrFormat;
4920 nIntlFormat = nCurrFormat;
4923 nIntlFormat = nCurrFormat;
4926 nIntlFormat = nCurrFormat;
4929 nIntlFormat = nCurrFormat;
4932 nIntlFormat = nCurrFormat;
4935 nIntlFormat = nCurrFormat;
4939 nIntlFormat, nCurrFormat );
4943 nIntlFormat, nCurrFormat );
4946 SAL_WARN(
"svl.numbers",
"NfCurrencyEntry::GetEffectiveNegativeFormat: unknown option");
Reference< XComponentContext > m_xContext
OUString uppercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
LanguageType getLanguageType(bool bResolveSystem=true) const
const css::lang::Locale & getLocale(bool bResolveSystem=true) const
const OUString & getBcp47(bool bResolveSystem=true) const
bool equals(const LanguageTag &rLanguageTag) const
static LanguageType convertToLanguageType(const css::lang::Locale &rLocale, bool bResolveSystem=true)
LanguageTag & reset(const OUString &rBcp47LanguageTag)
const OUString & getDateSep() const
sal_uInt16 getCurrNegativeFormat() const
const OUString & getTime100SecSep() const
sal_Unicode getCurrZeroChar() const
const OUString & getNumThousandSep() const
const OUString & getCurrBankSymbol() const
css::uno::Sequence< css::i18n::Currency2 > getAllCurrencies() const
css::uno::Sequence< css::i18n::FormatElement > getAllFormats() const
LanguageTag getLoadedLanguageTag() const
const OUString & getCurrSymbol() const
static const css::uno::Sequence< css::lang::Locale > & getInstalledLocaleNames()
const OUString & getNumDecimalSepAlt() const
sal_uInt16 getCurrPositiveFormat() const
const OUString & getNumDecimalSep() const
static bool areChecksEnabled()
sal_uInt16 getCurrDigits() const
OUString appendLocaleInfo(std::u16string_view rDebugMsg) const
static void outputCheckMessage(std::u16string_view rMsg)
const css::uno::Sequence< sal_Int32 > & getDigitGrouping() const
const LanguageTag & getLanguageTag() const
static LanguageType getRealLanguage(LanguageType nLang)
void insert(const iterator &it, NfCurrencyEntry p)
void init(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::lang::Locale &rLocale)
void changeLocale(const css::lang::Locale &rLocale)
CalendarWrapper * get() const
const CharClass * get() const
void changeLocale(const css::uno::Reference< css::uno::XComponentContext > &xContext, const LanguageTag &rLanguageTag)
void init(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const LanguageTag &rLanguageTag)
void changeLocale(const LanguageTag &rLanguageTag)
LanguageType getCurrentLanguage() const
const LocaleDataWrapper * get() const
NativeNumberWrapper * get() const
void init(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
void changeLocale(LanguageType eLang)
const ::utl::TransliterationWrapper * get() const
void init(const css::uno::Reference< css::uno::XComponentContext > &rxContext, LanguageType eLang)
static void SetCurrencyChangeLink(const Link< LinkParamNone *, void > &rLink)
void GetCurrencyAbbrevAndLanguage(OUString &rAbbrev, LanguageType &eLang) const
const LanguageTag & GetLanguageTag() const
void AddListener(utl::ConfigurationListener *pListener)
void RemoveListener(utl::ConfigurationListener const *pListener)
DigitGroupingIterator & advance()
bool isEqual(const OUString &rStr1, const OUString &rStr2) const
#define DBG_ASSERT(sCon, aError)
#define LANGUAGE_DONTKNOW
#define LANGUAGE_ENGLISH_US
#define LINK(Instance, Class, Member)
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
LanguageTag maLanguageTag
std::unique_ptr< sal_Int32[]> pData
B & padToLength(B &rBuffer, sal_Int32 nLen, U cFill)
OStringBuffer & padToLength(OStringBuffer &rBuffer, sal_Int32 nLength, char cFill='\0')
constexpr sal_Int16 nFirstFreeFormatIndex
constexpr sal_Int16 nStopPredefinedFormatIndex
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
HashMap_OWString_Interface aMap
::std::array< OUString, NF_KEYWORD_ENTRIES_COUNT > NfKeywordTable
@ NF_KEYWORD_ENTRIES_COUNT
constexpr bool operator==(TypedWhichId< T > const &lhs, TypedWhichId< T > rhs)
sal_uInt32 const indexTable[NF_INDEX_TABLE_ENTRIES]
#define ZF_STANDARD_DATETIME
#define ZF_STANDARD_DATE_SYS_NNNNDMMMMYYYY
#define ZF_STANDARD_DATE_SYS_NNDMMMYY
#define ZF_STANDARD_PERCENT
static std::ptrdiff_t addToCurrencyFormatsList(NfWSStringsDtor &rStrArr, const OUString &rFormat)
static sal_uInt16 lcl_MergeNegativeParenthesisFormat(sal_uInt16 nIntlFormat, sal_uInt16 nCurrFormat)
Call this only if nCurrFormat is really with parentheses!
#define ZF_STANDARD_DATE_SYS_DMMMMYYYY
#define ZF_STANDARD_DATE_DIN_YYMMDD
#define ZF_STANDARD_LOGICAL
#define ZF_STANDARD_DATE_SYS_DMMMYYYY
#define ZF_STANDARD_DURATION
#define ZF_STANDARD_DATE_SYS_NNDMMMMYYYY
#define ZF_STANDARD_DATE_DIN_DMMMYYYY
#define ZF_STANDARD_CURRENCY
#define ZF_STANDARD_SCIENTIFIC
#define ZF_STANDARD_DATE_DIN_DMMMMYYYY
static void lcl_CheckCurrencySymbolPosition(const NfCurrencyEntry &rCurr)
static OUString lcl_buildBooleanStringFormat(SvNumberformat *pEntry)
IMPL_STATIC_LINK_NOARG(SvNumberFormatter, CurrencyChangeLink, LinkParamNone *, void)
#define ZF_STANDARD_DATE_WW
#define ZF_STANDARD_FRACTION
#define ZF_STANDARD_DATE_DIN_MMDD
#define ZF_STANDARD_DATE_DIN_YYYYMMDD
#define UNKNOWN_SUBSTITUTE
std::vector< OUString > NfWSStringsDtor
std::unordered_map< sal_uInt16, sal_uInt32 > SvNumberFormatterIndexTable
std::map< sal_uInt32, SvNumberformat * > SvNumberFormatTable
This table is std::map because it needs to preserve insertion order, because the formats are roughly ...
constexpr sal_uInt32 NF_STANDARD_FORMAT_TEXT
The built-in @ Text format, offset within a locale, key in the locale the number formatter was constr...
SvNumFormatType
MAX_ULONG.
@ UNDEFINED
is used as a return value if no format exists.
@ TIME
selects time formats.
@ NUMBER
selects decimal number formats.
@ LOGICAL
selects boolean number formats.
@ CURRENCY
selects currency formats.
@ FRACTION
selects number formats for fractions.
@ ALL
selects all number formats.
@ TEXT
selects text number formats.
@ DATE
selects date formats.
@ PERCENT
selects percentage number formats.
@ DATETIME
selects number formats which contain date and time.
@ SCIENTIFIC
selects scientific number formats.
@ DEFINED
selects only user-defined number formats.
std::unordered_map< sal_uInt32, sal_uInt32 > SvNumberFormatterMergeMap
NfEvalDateFormat
enum values for <method>SvNumberFormatter::SetEvalDateFormat</method>
@ NF_EVALDATEFORMAT_INTL
DateFormat only from International, default.
#define SV_COUNTRY_LANGUAGE_OFFSET
NfIndexTableOffset
enum values for <method>SvNumberFormatter::GetFormatIndex</method>
@ NF_DATETIME_SYS_DDMMYYYY_HHMMSS
@ NF_DATETIME_ISO_YYYYMMDDTHHMMSS000
@ NF_CURRENCY_1000DEC2_RED
@ NF_INDEX_TABLE_RESERVED_START
@ NF_CURRENCY_1000DEC2_DASHED
@ NF_DATETIME_ISO_YYYYMMDD_HHMMSS000
@ NF_DATE_SYS_NNNNDMMMMYYYY
@ NF_CURRENCY_1000INT_RED
@ NF_DATETIME_SYS_DDMMYYYY_HHMM
@ NF_DATE_SYS_NNDMMMMYYYY
@ NF_DATETIME_ISO_YYYYMMDD_HHMMSS
@ NF_CURRENCY_1000DEC2_CCC
@ NF_DATETIME_ISO_YYYYMMDDTHHMMSS
@ NF_DATETIME_SYSTEM_SHORT_HHMM
SvNumInputOptions
Input options to be used with IsNumberFormat()
constexpr sal_uInt32 NUMBERFORMAT_ENTRY_NOT_FOUND
#define SV_MAX_COUNT_STANDARD_FORMATS