26#include <osl/diagnose.h>
27#include <rtl/math.hxx>
28#include <rtl/ustrbuf.hxx>
55struct SvXMLNumFmtEntry
61 SvXMLNumFmtEntry( OUString aN, sal_uInt32 nK,
bool bR ) :
62 aName(
std::move(aN)), nKey(nK), bRemoveAfterUse(bR) {}
78 const uno::Reference<uno::XComponentContext>& rxContext );
83 void AddKey( sal_uInt32 nKey,
const OUString& rName,
bool bRemoveAfterUse );
84 void SetUsed( sal_uInt32 nKey );
114enum class SvXMLStyleTokens;
119 SvXMLStyleTokens
nType;
120 OUStringBuffer aContent;
128 SvXMLNumFmtElementContext( SvXMLImport& rImport, sal_Int32 nElement,
130 const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList );
133 sal_Int32 nElement,
const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList )
override;
134 virtual void SAL_CALL
characters(
const OUString& rChars )
override;
135 virtual void SAL_CALL
endFastElement(sal_Int32 nElement)
override;
137 void AddEmbeddedElement( sal_Int32 nFormatPos,
const OUString& rContent );
142 SvXMLNumFmtElementContext& rParent;
143 OUStringBuffer aContent;
144 sal_Int32 nTextPosition;
147 SvXMLNumFmtEmbeddedTextContext( SvXMLImport& rImport, sal_Int32 nElement,
148 SvXMLNumFmtElementContext& rParentContext,
149 const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList );
151 virtual void SAL_CALL
characters(
const OUString& rChars )
override;
152 virtual void SAL_CALL
endFastElement(sal_Int32 nElement)
override;
162 SvXMLNumFmtMapContext( SvXMLImport& rImport, sal_Int32 nElement,
164 const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList );
166 virtual void SAL_CALL
endFastElement(sal_Int32 nElement)
override;
176 SvXMLNumFmtPropContext( SvXMLImport& rImport, sal_Int32 nElement,
178 const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList );
180 virtual void SAL_CALL
endFastElement(sal_Int32 nElement)
override;
183enum class SvXMLStyleTokens
211#define XML_NUMF_COLORCOUNT 10
249struct SvXMLDefaultDateFormat
291 const uno::Reference<uno::XComponentContext>& rxContext )
295 SAL_WARN_IF( !rxContext.is(),
"xmloff",
"got no service manager" );
302 if (rObj.aName == rName)
310 if ( bRemoveAfterUse )
317 if (rObj.nKey == nKey && !rObj.bRemoveAfterUse)
319 bRemoveAfterUse =
false;
337 if (rObj.nKey == nKey)
339 rObj.bRemoveAfterUse =
false;
359 if (rObj.bRemoveAfterUse )
362 if (pFormat && (pFormat->
GetType() & SvNumFormatType::DEFINED))
381SvXMLNumFmtMapContext::SvXMLNumFmtMapContext( SvXMLImport& rImport,
384 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList ) :
386 rParent( rParentContext )
390 OUString sValue = aIter.toString();
391 switch(aIter.getToken())
405void SvXMLNumFmtMapContext::endFastElement(sal_Int32 )
407 rParent.AddCondition( sCondition, sName );
414SvXMLNumFmtPropContext::SvXMLNumFmtPropContext( SvXMLImport& rImport,
417 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList ) :
419 rParent( rParentContext ),
425 switch ( aIter.getToken())
429 bColSet = ::
sax::Converter::convertColor( m_nColor, aIter.toView() );
437void SvXMLNumFmtPropContext::endFastElement(sal_Int32 )
440 rParent.AddColor( m_nColor );
447SvXMLNumFmtEmbeddedTextContext::SvXMLNumFmtEmbeddedTextContext( SvXMLImport& rImport,
449 SvXMLNumFmtElementContext& rParentContext,
450 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList ) :
452 rParent( rParentContext ),
462 nTextPosition = nAttrVal;
469void SvXMLNumFmtEmbeddedTextContext::characters(
const OUString& rChars )
471 aContent.append( rChars );
474void SvXMLNumFmtEmbeddedTextContext::endFastElement(sal_Int32 )
476 rParent.AddEmbeddedElement( nTextPosition, aContent.makeStringAndClear() );
490 (cChar ==
' ' && cTS == cNBSP)) )
507 if ( ( cChar ==
' ' ||
526 ( cChar ==
'(' || cChar ==
')' ) )
535 sal_Int32
nLength = rContent.getLength();
541 ((rContent[0] ==
' ' && rContent[1] ==
'-') ||
542 (rContent[1] ==
' ' &&
lcl_ValidChar( rContent[0], rParent))))))
556 sal_Int32
nPos = rContent.indexOf(
'%' );
568 rContent.insert(
nPos + 1,
'"' );
569 rContent.append(
'"' );
581 rContent.insert(
nPos,
'"' );
582 rContent.insert( 0,
'"' );
594 bool bEscape = ( rContent.indexOf(
'"' ) >= 0 );
599 OUString aInsert(
"\"\\\"" );
602 while (
nPos < rContent.getLength() )
604 if ( rContent[
nPos] ==
'"' )
606 rContent.insert(
nPos, aInsert );
607 nPos += aInsert.getLength();
614 rContent.insert( 0,
'"' );
615 rContent.append(
'"' );
621 if ( rContent.getLength() > 2 &&
622 rContent[0] ==
'"' &&
625 rContent.remove(0, 2);
628 sal_Int32 nLen = rContent.getLength();
630 rContent[nLen - 1] ==
'"' &&
631 rContent[nLen - 2] ==
'"' )
633 rContent.truncate(nLen - 2);
641SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport,
644 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList ) :
646 rParent( rParentContext ),
654 bool bAttrBool(
false);
655 bool bVarDecimals =
false;
656 bool bIsMaxDenominator =
false;
661 switch (aIter.getToken())
667 aNumInfo.nDecimals = std::min<sal_Int32>(nAttrVal, NF_MAX_FORMAT_SYMBOLS);
673 aNumInfo.nMinDecimalDigits = nAttrVal;
677 aNumInfo.nInteger = nAttrVal;
682 aNumInfo.nBlankInteger = nAttrVal;
685 if (::
sax::Converter::convertBool( bAttrBool, aIter.toView() ))
686 aNumInfo.bGrouping = bAttrBool;
689 if (::
sax::Converter::convertDouble( fAttrDouble, aIter.toView() ))
690 aNumInfo.fDisplayFactor = fAttrDouble;
693 if ( aIter.toView() ==
" " )
695 aNumInfo.bDecAlign =
true;
699 if ( aIter.isEmpty() )
702 aNumInfo.bDecReplace =
true;
711 aNumInfo.nExpInterval = nAttrVal;
715 if (::
sax::Converter::convertBool( bAttrBool, aIter.toView() ))
716 aNumInfo.bExpSign = bAttrBool;
720 aNumInfo.nMinNumerDigits = nAttrVal;
724 aNumInfo.nMinDenomDigits = nAttrVal;
728 aNumInfo.nMaxNumerDigits = nAttrVal;
733 aNumInfo.nFracDenominator = nAttrVal;
734 bIsMaxDenominator =
false;
739 if (::
sax::Converter::
convertNumber( nAttrVal, aIter.toView(), 1 ) && aNumInfo.nFracDenominator <= 0)
741 aNumInfo.nFracDenominator = nAttrVal;
742 bIsMaxDenominator =
true;
748 aNumInfo.nZerosNumerDigits = nAttrVal;
753 aNumInfo.nZerosDenomDigits = nAttrVal;
757 aNumInfo.aIntegerFractionDelimiter = aIter.
toString();
760 aLanguageTagODF.maRfcLanguageTag = aIter.
toString();
763 aLanguageTagODF.maLanguage = aIter.
toString();
766 aLanguageTagODF.maScript = aIter.
toString();
769 aLanguageTagODF.maCountry = aIter.
toString();
775 if (::
sax::Converter::convertBool( bAttrBool, aIter.toView() ))
776 bTextual = bAttrBool;
785 if ( aNumInfo.nBlankInteger > aNumInfo.nInteger )
786 aNumInfo.nInteger = aNumInfo.nBlankInteger;
787 if ( aNumInfo.nMinDecimalDigits == -1)
789 if ( bVarDecimals || aNumInfo.bDecReplace )
790 aNumInfo.nMinDecimalDigits = 0;
792 aNumInfo.nMinDecimalDigits = aNumInfo.nDecimals;
794 if ( aNumInfo.nZerosDenomDigits > 0 )
796 if ( aNumInfo.nMinDenomDigits < aNumInfo.nZerosDenomDigits )
797 aNumInfo.nMinDenomDigits = aNumInfo.nZerosDenomDigits;
800 aNumInfo.nZerosDenomDigits = 0;
801 if ( aNumInfo.nMinDenomDigits >= 0 )
802 if ( aNumInfo.nMaxDenomDigits < aNumInfo.nMinDenomDigits )
803 aNumInfo.nMaxDenomDigits = ( aNumInfo.nMinDenomDigits ? aNumInfo.nMinDenomDigits : 1 );
804 if ( aNumInfo.nZerosNumerDigits > 0 )
806 if ( aNumInfo.nMinNumerDigits < aNumInfo.nZerosNumerDigits )
807 aNumInfo.nMinNumerDigits = aNumInfo.nZerosNumerDigits;
810 aNumInfo.nZerosNumerDigits = 0;
811 if ( aNumInfo.nMinNumerDigits >= 0 )
812 if ( aNumInfo.nMaxNumerDigits < aNumInfo.nMinNumerDigits )
813 aNumInfo.nMaxNumerDigits = ( aNumInfo.nMinNumerDigits ? aNumInfo.nMinNumerDigits : 1 );
814 if ( bIsMaxDenominator && aNumInfo.nFracDenominator > 0 )
816 aNumInfo.nMaxDenomDigits = floor( log10( aNumInfo.nFracDenominator ) ) + 1;
817 aNumInfo.nFracDenominator = -1;
819 if ( aNumInfo.nMaxDenomDigits > 0 )
821 if ( aNumInfo.nMinDenomDigits < 0 )
822 aNumInfo.nMinDenomDigits = 0;
823 else if ( aNumInfo.nMinDenomDigits > aNumInfo.nMaxDenomDigits )
824 aNumInfo.nMinDenomDigits = aNumInfo.nMaxDenomDigits;
827 if ( !aLanguageTagODF.
isEmpty() )
830 if ( nElementLang == LANGUAGE_DONTKNOW )
834 if ( aNumInfo.aIntegerFractionDelimiter.isEmpty() )
835 aNumInfo.aIntegerFractionDelimiter =
" ";
838css::uno::Reference< css::xml::sax::XFastContextHandler > SvXMLNumFmtElementContext::createFastChildContext(
840 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
844 if ( nType == SvXMLStyleTokens::Number &&
847 return new SvXMLNumFmtEmbeddedTextContext( GetImport(), nElement, *
this, xAttrList );
854void SvXMLNumFmtElementContext::characters(
const OUString& rChars )
856 aContent.append( rChars );
859void SvXMLNumFmtElementContext::AddEmbeddedElement( sal_Int32 nFormatPos,
const OUString& rContent )
861 if (rContent.isEmpty())
864 auto iterPair = aNumInfo.m_EmbeddedElements.emplace(nFormatPos, rContent);
865 if (!iterPair.second)
867 iterPair.first->second += rContent;
870void SvXMLNumFmtElementContext::endFastElement(sal_Int32 )
872 bool bEffLong = bLong;
875 case SvXMLStyleTokens::Text:
876 if ( rParent.HasLongDoW() &&
877 std::u16string_view(aContent) == rParent.GetLocaleData().getLongDateDayOfWeekSep() )
882 if ( rParent.ReplaceNfKeyword( NF_KEY_NNN, NF_KEY_NNNN ) )
887 rParent.SetHasLongDoW(
false );
889 if ( !aContent.isEmpty() )
892 rParent.AddToCode( aContent );
893 aContent.setLength(0);
898 aContent.append(
"\"\"");
899 rParent.AddToCode( aContent );
900 aContent.setLength(0);
901 rParent.SetHasTrailingEmptyText(
true);
905 case SvXMLStyleTokens::Number:
906 rParent.AddNumber( aNumInfo );
909 case SvXMLStyleTokens::CurrencySymbol:
910 rParent.AddCurrency( aContent.makeStringAndClear(), nElementLang );
913 case SvXMLStyleTokens::TextContent:
914 rParent.AddToCode(
'@');
916 case SvXMLStyleTokens::FillCharacter:
917 if ( !aContent.isEmpty() )
919 rParent.AddToCode(
'*' );
920 rParent.AddToCode( aContent[0] );
923 case SvXMLStyleTokens::Boolean:
924 rParent.AddNfKeyword( NF_KEY_BOOLEAN );
927 case SvXMLStyleTokens::Day:
928 rParent.UpdateCalendar( sCalendar );
931 rParent.AddNfKeyword(
932 sal::static_int_cast< sal_uInt16 >(
933 bEffLong ? NF_KEY_DD : NF_KEY_D ) );
935 case SvXMLStyleTokens::Month:
936 rParent.UpdateCalendar( sCalendar );
939 rParent.AddNfKeyword(
940 sal::static_int_cast< sal_uInt16 >(
942 ? ( bEffLong ? NF_KEY_MMMM : NF_KEY_MMM )
943 : ( bEffLong ? NF_KEY_MM : NF_KEY_M ) ) );
945 case SvXMLStyleTokens::Year:
952 rParent.UpdateCalendar( sCalendar);
954 if (eCal == SvXMLNumFormatContext::ImplicitCalendar::SECONDARY
955 || eCal == SvXMLNumFormatContext::ImplicitCalendar::SECONDARY_FROM_OTHER)
957 rParent.AddNfKeyword(
958 sal::static_int_cast< sal_uInt16 >(
959 bEffLong ? NF_KEY_EEC : NF_KEY_EC ) );
963 rParent.AddNfKeyword(
964 sal::static_int_cast< sal_uInt16 >(
965 bEffLong ? NF_KEY_YYYY : NF_KEY_YY ) );
969 case SvXMLStyleTokens::Era:
970 rParent.UpdateCalendar( sCalendar );
972 rParent.AddNfKeyword(
973 sal::static_int_cast< sal_uInt16 >(
974 bEffLong ? NF_KEY_GGG : NF_KEY_G ) );
977 case SvXMLStyleTokens::DayOfWeek:
982 rParent.UpdateCalendar( sCalendar);
984 if (eCal == SvXMLNumFormatContext::ImplicitCalendar::SECONDARY
985 || eCal == SvXMLNumFormatContext::ImplicitCalendar::SECONDARY_FROM_OTHER)
987 rParent.AddNfKeyword(
988 sal::static_int_cast< sal_uInt16 >(
989 bEffLong ? NF_KEY_AAAA : NF_KEY_AAA ) );
993 rParent.AddNfKeyword(
994 sal::static_int_cast< sal_uInt16 >(
995 bEffLong ? NF_KEY_NNNN : NF_KEY_NN ) );
999 case SvXMLStyleTokens::WeekOfYear:
1000 rParent.UpdateCalendar( sCalendar );
1001 rParent.AddNfKeyword( NF_KEY_WW );
1003 case SvXMLStyleTokens::Quarter:
1004 rParent.UpdateCalendar( sCalendar );
1005 rParent.AddNfKeyword(
1006 sal::static_int_cast< sal_uInt16 >(
1007 bEffLong ? NF_KEY_QQ : NF_KEY_Q ) );
1009 case SvXMLStyleTokens::Hours:
1010 rParent.AddNfKeyword(
1011 sal::static_int_cast< sal_uInt16 >(
1012 bEffLong ? NF_KEY_HH : NF_KEY_H ) );
1014 case SvXMLStyleTokens::AmPm:
1016 rParent.AddNfKeyword( NF_KEY_AMPM );
1018 case SvXMLStyleTokens::Minutes:
1019 rParent.AddNfKeyword(
1020 sal::static_int_cast< sal_uInt16 >(
1021 bEffLong ? NF_KEY_MMI : NF_KEY_MI ) );
1023 case SvXMLStyleTokens::Seconds:
1024 rParent.AddNfKeyword(
1025 sal::static_int_cast< sal_uInt16 >(
1026 bEffLong ? NF_KEY_SS : NF_KEY_S ) );
1027 if ( aNumInfo.nDecimals > 0 )
1030 rParent.AddToCode(rParent.GetLocaleData().getNumDecimalSep());
1031 for (sal_Int32 i=0;
i<aNumInfo.nDecimals;
i++)
1033 rParent.AddToCode(
'0');
1038 case SvXMLStyleTokens::Fraction:
1040 if ( aNumInfo.nInteger >= 0 )
1043 aNumInfo.nDecimals = 0;
1044 rParent.AddNumber( aNumInfo );
1045 OUStringBuffer sIntegerFractionDelimiter(aNumInfo.aIntegerFractionDelimiter);
1047 rParent.AddToCode( sIntegerFractionDelimiter );
1053 for (i=aNumInfo.nMaxNumerDigits; i > 0; i--)
1055 if ( i > aNumInfo.nMinNumerDigits )
1056 rParent.AddToCode(
'#' );
1057 else if ( i > aNumInfo.nZerosNumerDigits )
1058 rParent.AddToCode(
'?' );
1060 rParent.AddToCode(
'0' );
1062 rParent.AddToCode(
'/' );
1063 if ( aNumInfo.nFracDenominator > 0 )
1065 rParent.AddToCode( OUString::number( aNumInfo.nFracDenominator ) );
1069 for (i=aNumInfo.nMaxDenomDigits; i > 0 ; i--)
1071 if ( i > aNumInfo.nMinDenomDigits )
1072 rParent.AddToCode(
'#' );
1073 else if ( i > aNumInfo.nZerosDenomDigits )
1074 rParent.AddToCode(
'?' );
1076 rParent.AddToCode(
'0' );
1082 case SvXMLStyleTokens::ScientificNumber:
1085 if( !aNumInfo.bGrouping && aNumInfo.nExpInterval > aNumInfo.nInteger )
1087 for (sal_Int32 i=aNumInfo.nInteger; i<aNumInfo.nExpInterval; i++)
1089 rParent.AddToCode(
'#' );
1092 rParent.AddNumber( aNumInfo );
1094 if ( aNumInfo.bExpSign )
1095 rParent.AddToCode( u
"E+" );
1097 rParent.AddToCode( u
"E" );
1098 for (sal_Int32 i=0;
i<aNumInfo.nExpDigits;
i++)
1100 rParent.AddToCode(
'0' );
1106 assert(
false &&
"invalid element ID");
1118 if ( bSystem == rEntry.bSystem &&
1127 return sal::static_int_cast< sal_uInt16 >(rEntry.eFormat);
1140 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList,
1144 pStyles( &rStyles ),
1147 eImplicitCalendar(ImplicitCalendar::
DEFAULT),
1149 bAutoOrder( false ),
1150 bFromSystem( false ),
1154 bHasExtraText( false ),
1155 bHasTrailingEmptyText( false ),
1156 bHasLongDoW( false ),
1157 bHasDateTime( false ),
1158 bRemoveAfterUse( false ),
1166 bDateNoDefault( false )
1169 css::i18n::NativeNumberXmlAttributes aNatNumAttr;
1171 bool bAttrBool(
false);
1175 switch (aIter.getToken())
1181 aLanguageTagODF.maRfcLanguageTag = aIter.
toString();
1184 aLanguageTagODF.maLanguage = aIter.
toString();
1187 aLanguageTagODF.maScript = aIter.
toString();
1190 aLanguageTagODF.maCountry = aIter.
toString();
1196 if (::
sax::Converter::convertBool( bAttrBool, aIter.toView() ))
1197 bAutoOrder = bAttrBool;
1203 if (::
sax::Converter::convertBool( bAttrBool, aIter.toView() ))
1204 bTruncate = bAttrBool;
1209 if (::
sax::Converter::convertBool( bAttrBool, aIter.toView() ))
1210 bRemoveAfterUse = bAttrBool;
1233 if (!aLanguageTagODF.
isEmpty())
1236 if ( nFormatLang == LANGUAGE_DONTKNOW )
1240 if (aNatNumAttr.Format.isEmpty() && aSpellout.isEmpty())
1243 LanguageTag aLanguageTag( OUString(), aNatNumAttr.Locale.Language,
1244 std::u16string_view(), aNatNumAttr.Locale.Country);
1245 aNatNumAttr.Locale = aLanguageTag.getLocale(
false);
1248 if ( !aSpellout.isEmpty() )
1250 aFormatCode.append(
"[NatNum12 " );
1251 aFormatCode.append( aSpellout );
1254 if ( !pFormatter )
return;
1256 sal_Int32
nNatNum = pFormatter->
GetNatNum()->convertFromXmlAttributes( aNatNumAttr );
1257 aFormatCode.append(
"[NatNum" );
1258 aFormatCode.append( nNatNum );
1261 LanguageType eLang = aLanguageTag.getLanguageType(
false );
1262 if ( eLang == LANGUAGE_DONTKNOW )
1264 if ( eLang != nFormatLang && eLang != LANGUAGE_SYSTEM )
1266 aFormatCode.append(
"][$-" );
1268 aFormatCode.append(OUString::number(
static_cast<sal_uInt16
>(eLang), 16).toAsciiUpperCase());
1270 aFormatCode.append(
']' );
1274 const OUString& rName,
1275 const uno::Reference<xml::sax::XFastAttributeList>& ,
1280 pStyles( &rStyles ),
1283 eImplicitCalendar(ImplicitCalendar::
DEFAULT),
1284 nFormatLang( nLang ),
1285 bAutoOrder( false ),
1286 bFromSystem( false ),
1290 bHasExtraText( false ),
1291 bHasTrailingEmptyText( false ),
1292 bHasLongDoW( false ),
1293 bHasDateTime( false ),
1294 bRemoveAfterUse( false ),
1302 bDateNoDefault( false )
1313 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
1321 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1322 *
this, SvXMLStyleTokens::Text, xAttrList );
1326 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1327 *
this, SvXMLStyleTokens::FillCharacter, xAttrList );
1330 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1331 *
this, SvXMLStyleTokens::Number, xAttrList );
1334 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1335 *
this, SvXMLStyleTokens::ScientificNumber, xAttrList );
1338 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1339 *
this, SvXMLStyleTokens::Fraction, xAttrList );
1342 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1343 *
this, SvXMLStyleTokens::CurrencySymbol, xAttrList );
1346 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1347 *
this, SvXMLStyleTokens::Day, xAttrList );
1350 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1351 *
this, SvXMLStyleTokens::Month, xAttrList );
1354 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1355 *
this, SvXMLStyleTokens::Year, xAttrList );
1358 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1359 *
this, SvXMLStyleTokens::Era, xAttrList );
1362 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1363 *
this, SvXMLStyleTokens::DayOfWeek, xAttrList );
1366 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1367 *
this, SvXMLStyleTokens::WeekOfYear, xAttrList );
1370 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1371 *
this, SvXMLStyleTokens::Quarter, xAttrList );
1374 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1375 *
this, SvXMLStyleTokens::Hours, xAttrList );
1378 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1379 *
this, SvXMLStyleTokens::AmPm, xAttrList );
1382 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1383 *
this, SvXMLStyleTokens::Minutes, xAttrList );
1386 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1387 *
this, SvXMLStyleTokens::Seconds, xAttrList );
1390 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1391 *
this, SvXMLStyleTokens::Boolean, xAttrList );
1394 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1395 *
this, SvXMLStyleTokens::TextContent, xAttrList );
1399 pContext =
new SvXMLNumFmtPropContext(
GetImport(), nElement,
1406 pContext =
new SvXMLNumFmtMapContext(
GetImport(), nElement,
1414 SAL_WARN(
"xmloff.core",
"No context for unknown-element " << SvXMLImport::getPrefixAndNameFromToken(nElement));
1466 comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>( xFormatsSupplier );
1489 OSL_FAIL(
"no number formatter");
1501 SAL_INFO(
"xmloff.style",
"invalid style:map references containing style");
1530 OUString sFormat =
aFormatCode.makeStringAndClear();
1577 OUString aFormatStr( sFormat );
1581 sal_Int32 nErrPos = 0;
1584 if ( !bOk && nErrPos == 0 && aFormatStr != sFormat )
1633 OSL_FAIL(
"invalid number format");
1679 sal_uInt16 nPrec = 0;
1680 sal_uInt16 nLeading = 0;
1682 nPrec =
static_cast<sal_uInt16
>(rInfo.
nDecimals);
1684 nLeading =
static_cast<sal_uInt16
>(rInfo.
nInteger);
1710 sal_uInt16 nGenPrec = nPrec;
1723 bGrouping,
false, nGenPrec, nLeading ));
1725 if ( rInfo.
nExpDigits >= 0 && nLeading == 0 && !bGrouping && nEmbeddedCount == 0 )
1730 aNumStr.stripStart(
'#');
1739 if ( nIntegerEnd < 0 )
1740 nIntegerEnd = aNumStr.getLength();
1741 while ( nIndex < nIntegerEnd && nBlanks > 0 )
1743 if ( aNumStr[
nIndex] ==
'0' )
1755 sal_Int32 nDigits = rInfo.
nInteger;
1757 if ( nIntegerEnd < 0 )
1758 nIntegerEnd = aNumStr.getLength();
1761 if ( (
nIndex = aNumStr.indexOf(
'#',
nIndex ) ) >= 0 )
1772 aNumStr.insert( 0,
'#' );
1784 aNumStr.append( cAdd );
1787 if ( nEmbeddedCount )
1796 nZeroPos = aNumStr.getLength();
1801 if ( nLastFormatPos >= nZeroPos )
1806 sal_Int32 nAddCount = nLastFormatPos + 1 - nZeroPos;
1809 aNumStr.insert(0,
'#');
1811 nZeroPos = nZeroPos + nAddCount;
1817 sal_Int32
const nFormatPos = it.first;
1818 sal_Int32 nInsertPos = nZeroPos - nFormatPos;
1819 if ( nInsertPos >= 0 )
1824 aNumStr.insert(nInsertPos, OUString::Concat(
"\"") + it.second +
"\"");
1839 sal_Int32 nSepCount =
static_cast<sal_Int32
>(::rtl::math::round( log10(rInfo.
fDisplayFactor) / 3.0 ));
1840 if ( nSepCount > 0 )
1843 for ( sal_Int32
i=0;
i<nSepCount;
i++ )
1850 bool bAutomatic =
false;
1851 OUString aSymbol = rContent;
1852 if ( aSymbol.isEmpty())
1858 OUString sCurString, sDummy;
1860 aSymbol = sCurString;
1883 sal_Int32 nFirst =
nLength - 2;
1884 while ( nFirst >= 0 &&
aFormatCode[nFirst] !=
'"' )
1908 aFormatCode.append(
"-" + OUString(OUString::number(sal_uInt16(nLang), 16)).toAsciiUpperCase());
1975static bool lcl_IsAtEnd( OUStringBuffer& rBuffer, std::u16string_view rToken )
1977 sal_Int32 nBufLen = rBuffer.getLength();
1978 sal_Int32 nTokLen = rToken.size();
1980 if ( nTokLen > nBufLen )
1983 sal_Int32 nStartPos = nBufLen - nTokLen;
1984 for ( sal_Int32 nTokPos = 0; nTokPos < nTokLen; nTokPos++ )
1985 if ( rToken[ nTokPos ] != rBuffer[nStartPos + nTokPos] )
2023 rCondition.startsWith(
"value()", &sRealCond)) )
2029 bool bDefaultCond =
false;
2034 bDefaultCond =
true;
2040 bDefaultCond =
true;
2046 sal_Int32
nPos = sRealCond.indexOf(
"!=" );
2049 sRealCond = sRealCond.replaceAt(
nPos, 2,
u"<>" );
2052 nPos = sRealCond.indexOf(
'.' );
2057 if ( rDecSep.getLength() > 1 || rDecSep[0] !=
'.' )
2059 sRealCond = sRealCond.replaceAt(
nPos, 1, rDecSep );
2086 OUStringBuffer aColName;
2094 if ( !aColName.isEmpty() )
2096 aColName.insert( 0,
'[' );
2097 aColName.append(
']' );
2110 ImplicitCalendar::DEFAULT_FROM_OTHER : ImplicitCalendar::DEFAULT);
2115 ImplicitCalendar::DEFAULT_FROM_OTHER : ImplicitCalendar::DEFAULT);
2121 ImplicitCalendar::SECONDARY_FROM_OTHER : ImplicitCalendar::SECONDARY);
2126 ImplicitCalendar::SECONDARY_FROM_OTHER : ImplicitCalendar::SECONDARY);
2138 bool bSameDefault =
false;
2139 if (
sCalendar.isEmpty() || rNewCalendar.isEmpty())
2146 bSameDefault = (rNewCalendar == rDefaultCalendar ||
sCalendar == rDefaultCalendar);
2151 if (rNewCalendar.isEmpty())
2178 const uno::Reference<util::XNumberFormatsSupplier>& rSupp,
2179 const uno::Reference<uno::XComponentContext>& rxContext )
2181 SAL_WARN_IF( !rxContext.is(),
"xmloff",
"got no service manager" );
2185 comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>( rSupp );
2189 pData = std::make_unique<SvXMLNumImpData>( pFormatter, rxContext );
2194 const uno::Reference<uno::XComponentContext>& rxContext )
2196 SAL_WARN_IF( !rxContext.is(),
"xmloff",
"got no service manager" );
2198 pData = std::make_unique<SvXMLNumImpData>( pNumberFormatter, rxContext );
2204 pData->RemoveVolatileFormats();
2210 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList,
2242 pData.get(), nStyleToken, xAttrList, rStyles );
2247 if (
pData->GetNumberFormatter())
const uno::Reference< uno::XComponentContext > m_xContext
LanguageType getLanguageType(bool bResolveSystem=true) const
const OUString & getNumThousandSep() const
const std::shared_ptr< css::i18n::Calendar2 > & getDefaultCalendar() const
const OUString & getNumDecimalSep() const
bool doesSecondaryCalendarUseEC(std::u16string_view rName) const
sal_uInt16 getCurrDigits() const
This class deliberately does not support XWeak, to improve performance when loading large documents.
virtual void SAL_CALL endFastElement(sal_Int32 Element) override
endFastElement is called before a context will be destructed, but after an elements context has been ...
SvXMLImport & GetImport()
SvXMLImportContext(SvXMLImport &rImport)
A contexts constructor does anything that is required if an element starts.
virtual css::uno::Reference< XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual void SAL_CALL characters(const OUString &aChars) override
This method is called for all characters that are contained in the current element.
static sal_uInt16 GetDefaultDateFormat(SvXMLDateElementAttributes eDOW, SvXMLDateElementAttributes eDay, SvXMLDateElementAttributes eMonth, SvXMLDateElementAttributes eYear, SvXMLDateElementAttributes eHours, SvXMLDateElementAttributes eMins, SvXMLDateElementAttributes eSecs, bool bSystem)
LanguageType GetLanguageForKey(sal_Int32 nKey) const
SvXMLStyleContext * CreateChildContext(SvXMLImport &rImport, sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList, SvXMLStylesContext &rStyles)
SvXMLNumFmtHelper(const css::uno::Reference< css::util::XNumberFormatsSupplier > &rSupp, const css::uno::Reference< css::uno::XComponentContext > &rxContext)
std::unique_ptr< SvXMLNumImpData > pData
SvXMLDateElementAttributes eDateDOW
SvXMLDateElementAttributes eDateHours
OUStringBuffer aFormatCode
SvXMLDateElementAttributes eDateMins
SvXMLStylesContext * pStyles
const LocaleDataWrapper & GetLocaleData() const
void AddColor(Color nColor)
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
SvXMLDateElementAttributes eDateYear
SvXMLDateElementAttributes eDateDay
void AddNfKeyword(sal_uInt16 nIndex)
bool bHasTrailingEmptyText
SvXMLNumFormatContext(SvXMLImport &rImport, sal_Int32 nElement, SvXMLNumImpData *pNewData, SvXMLStylesTokens nNewType, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList, SvXMLStylesContext &rStyles)
OUString aImplicitCalendar[2]
void AddCondition(const sal_Int32 nIndex)
ImplicitCalendar eImplicitCalendar
SAL_DLLPRIVATE sal_Int32 PrivateGetKey()
SvXMLDateElementAttributes eDateMonth
virtual void CreateAndInsert(bool bOverwrite) override
bool IsSystemLanguage() const
determine whether number format uses the system language
void AddToCode(std::u16string_view rString)
SvXMLStylesTokens GetType() const
SvXMLDateElementAttributes eDateSecs
OUStringBuffer aConditions
bool ReplaceNfKeyword(sal_uInt16 nOld, sal_uInt16 nNew)
void AddCurrency(const OUString &rContent, LanguageType nLang)
void AddNumber(const SvXMLNumberInfo &rInfo)
std::vector< MyCondition > aMyConditions
void UpdateCalendar(const OUString &rNewCalendar)
virtual ~SvXMLNumFormatContext() override
uno::Reference< uno::XComponentContext > m_xContext
std::vector< SvXMLNumFmtEntry > m_NameEntries
void AddKey(sal_uInt32 nKey, const OUString &rName, bool bRemoveAfterUse)
SvNumberFormatter * pFormatter
std::unique_ptr< LocaleDataWrapper > pLocaleData
const LocaleDataWrapper & GetLocaleData(LanguageType nLang)
sal_uInt32 GetKeyForName(std::u16string_view rName)
SvXMLNumImpData(SvNumberFormatter *pFmt, const uno::Reference< uno::XComponentContext > &rxContext)
void RemoveVolatileFormats()
void SetUsed(sal_uInt32 nKey)
SvNumberFormatter * GetNumberFormatter() const
const OUString & GetName() const
const SvXMLStyleContext * FindStyleChildContext(XmlStyleFamily nFamily, const OUString &rName, bool bCreateIndex=false) const
the SvXMLTypeConverter converts values of various types from their internal representation to the tex...
static bool convertNumber(sal_Int32 &rValue, std::u16string_view aString, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32)
constexpr ::Color COL_LIGHTRED(0xFF, 0x00, 0x00)
constexpr ::Color COL_GRAY(0x80, 0x80, 0x80)
constexpr ::Color COL_WHITE(0xFF, 0xFF, 0xFF)
constexpr ::Color COL_LIGHTCYAN(0x00, 0xFF, 0xFF)
constexpr ::Color COL_LIGHTMAGENTA(0xFF, 0x00, 0xFF)
constexpr ::Color COL_BROWN(0x80, 0x80, 0x00)
constexpr ::Color COL_YELLOW(0xFF, 0xFF, 0x00)
constexpr ::Color COL_LIGHTBLUE(0x00, 0x00, 0xFF)
constexpr ::Color COL_LIGHTGREEN(0x00, 0xFF, 0x00)
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
if(aStr !=aBuf) UpdateName_Impl(m_xFollowLb.get()
std::unique_ptr< sal_Int32[]> pData
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
OUString toString(OptionInfo const *info)
Handling of tokens in XML:
@ XML_DECIMAL_REPLACEMENT
@ XML_INTEGER_FRACTION_DELIMITER
@ XML_FORCED_EXPONENT_SIGN
@ XML_ZEROS_NUMERATOR_DIGITS
@ XML_MAX_NUMERATOR_DIGITS
@ XML_TRUNCATE_ON_OVERFLOW
@ XML_MAX_DENOMINATOR_VALUE
@ XML_TRANSLITERATION_STYLE
@ XML_ZEROS_DENOMINATOR_DIGITS
@ XML_TRANSLITERATION_FORMAT
@ XML_MAX_BLANK_INTEGER_DIGITS
@ XML_TRANSLITERATION_COUNTRY
@ XML_MIN_NUMERATOR_DIGITS
@ XML_TRANSLITERATION_SPELLOUT
@ XML_MIN_EXPONENT_DIGITS
@ XML_MIN_DENOMINATOR_DIGITS
@ XML_TRANSLITERATION_LANGUAGE
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Helper to gather the single language tag relevant attributes during reading ODF and form a resulting ...
LanguageTag getLanguageTag() const
Best call this only once per instance, it recreates a LanguageTag instance on every call.
sal_Int32 nMinNumerDigits
sal_Int32 nMinDecimalDigits
sal_Int32 nZerosNumerDigits
sal_Int32 nExpDigits
Number of '?' in integer part.
OUString aIntegerFractionDelimiter
sal_Int32 nZerosDenomDigits
sal_Int32 nBlankInteger
Total min number of digits in integer part ('0' + '?')
sal_Int32 nMaxNumerDigits
sal_Int32 nFracDenominator
std::map< sal_Int32, OUString > m_EmbeddedElements
sal_Int32 nMinDenomDigits
sal_Int32 nMaxDenomDigits
#define XMLOFF_WARN_UNKNOWN_ELEMENT(area, token)
#define XMLOFF_WARN_UNKNOWN(area, rIter)
#define XML_ELEMENT(prefix, name)
const SvXMLDefaultDateFormat aDefaultDateFormats[]
#define XML_NUMF_COLORCOUNT
const SvXMLEnumMapEntry< bool > aStyleValueMap[]
const SvXMLEnumMapEntry< bool > aFormatSourceMap[]
static bool lcl_ValidChar(sal_Unicode cChar, const SvXMLNumFormatContext &rParent)
static bool lcl_IsAtEnd(OUStringBuffer &rBuffer, std::u16string_view rToken)
const Color aNumFmtStdColors[XML_NUMF_COLORCOUNT]
static void lcl_EnquoteIfNecessary(OUStringBuffer &rContent, const SvXMLNumFormatContext &rParent)
SvXMLDateElementAttributes
constexpr size_t NF_MAX_FORMAT_SYMBOLS
NF_DATETIME_SYS_DDMMYYYY_HHMMSS
NF_INDEX_TABLE_RESERVED_START
NF_DATE_SYS_NNNNDMMMMYYYY
NF_DATETIME_SYS_DDMMYYYY_HHMM
NF_DATETIME_SYSTEM_SHORT_HHMM
constexpr sal_uInt32 NUMBERFORMAT_ENTRY_NOT_FOUND