26 #include <osl/diagnose.h>
27 #include <rtl/math.hxx>
28 #include <rtl/ustrbuf.hxx>
46 #include <string_view>
54 struct SvXMLNumFmtEntry
60 SvXMLNumFmtEntry(
const OUString& rN, sal_uInt32 nK,
bool bR ) :
61 aName(rN), nKey(nK), bRemoveAfterUse(bR) {}
77 const uno::Reference<uno::XComponentContext>& rxContext );
82 void AddKey( sal_uInt32 nKey,
const OUString& rName,
bool bRemoveAfterUse );
83 void SetUsed( sal_uInt32 nKey );
118 OUStringBuffer aContent;
126 SvXMLNumFmtElementContext(
SvXMLImport& rImport, sal_Int32 nElement,
128 const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList );
131 sal_Int32 nElement,
const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList )
override;
132 virtual void SAL_CALL
characters(
const OUString& rChars )
override;
133 virtual void SAL_CALL
endFastElement(sal_Int32 nElement)
override;
135 void AddEmbeddedElement( sal_Int32 nFormatPos,
const OUString& rContent );
140 SvXMLNumFmtElementContext& rParent;
141 OUStringBuffer aContent;
142 sal_Int32 nTextPosition;
145 SvXMLNumFmtEmbeddedTextContext(
SvXMLImport& rImport, sal_Int32 nElement,
146 SvXMLNumFmtElementContext& rParentContext,
147 const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList );
149 virtual void SAL_CALL
characters(
const OUString& rChars )
override;
150 virtual void SAL_CALL
endFastElement(sal_Int32 nElement)
override;
160 SvXMLNumFmtMapContext(
SvXMLImport& rImport, sal_Int32 nElement,
162 const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList );
164 virtual void SAL_CALL
endFastElement(sal_Int32 nElement)
override;
174 SvXMLNumFmtPropContext(
SvXMLImport& rImport, sal_Int32 nElement,
176 const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList );
178 virtual void SAL_CALL
endFastElement(sal_Int32 nElement)
override;
209 #define XML_NUMF_COLORCOUNT 10
247 struct SvXMLDefaultDateFormat
289 const uno::Reference<uno::XComponentContext>& rxContext )
293 SAL_WARN_IF( !rxContext.is(),
"xmloff",
"got no service manager" );
300 if (rObj.aName == rName)
308 if ( bRemoveAfterUse )
315 if (rObj.nKey == nKey && !rObj.bRemoveAfterUse)
317 bRemoveAfterUse =
false;
335 if (rObj.nKey == nKey)
337 rObj.bRemoveAfterUse =
false;
357 if (rObj.bRemoveAfterUse )
360 if (pFormat && (pFormat->
GetType() & SvNumFormatType::DEFINED))
379 SvXMLNumFmtMapContext::SvXMLNumFmtMapContext(
SvXMLImport& rImport,
382 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList ) :
384 rParent( rParentContext )
388 OUString sValue = aIter.toString();
389 switch(aIter.getToken())
403 void SvXMLNumFmtMapContext::endFastElement(sal_Int32 )
405 rParent.AddCondition( sCondition, sName );
412 SvXMLNumFmtPropContext::SvXMLNumFmtPropContext(
SvXMLImport& rImport,
415 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList ) :
417 rParent( rParentContext ),
423 switch ( aIter.getToken())
427 bColSet = ::
sax::Converter::convertColor( m_nColor, aIter.toView() );
435 void SvXMLNumFmtPropContext::endFastElement(sal_Int32 )
438 rParent.AddColor( m_nColor );
445 SvXMLNumFmtEmbeddedTextContext::SvXMLNumFmtEmbeddedTextContext(
SvXMLImport& rImport,
447 SvXMLNumFmtElementContext& rParentContext,
448 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList ) :
450 rParent( rParentContext ),
460 nTextPosition = nAttrVal;
467 void SvXMLNumFmtEmbeddedTextContext::characters(
const OUString& rChars )
469 aContent.append( rChars );
472 void SvXMLNumFmtEmbeddedTextContext::endFastElement(sal_Int32 )
474 rParent.AddEmbeddedElement( nTextPosition, aContent.makeStringAndClear() );
488 (cChar ==
' ' && cTS == cNBSP)) )
502 if ( ( cChar ==
' ' ||
521 ( cChar ==
'(' || cChar ==
')' ) )
530 sal_Int32
nLength = rContent.getLength();
532 if ((nLength == 1 &&
lcl_ValidChar( rContent[0], rParent)) ||
534 ((rContent[0] ==
' ' && rContent[1] ==
'-') ||
535 (rContent[1] ==
' ' &&
lcl_ValidChar( rContent[0], rParent)))))
549 sal_Int32
nPos = rContent.indexOf(
'%' );
552 if ( nPos + 1 < nLength )
554 if ( nPos + 2 == nLength &&
lcl_ValidChar( rContent[nPos + 1], rParent ) )
561 rContent.insert( nPos + 1,
'"' );
562 rContent.append(
'"' );
574 rContent.insert( nPos,
'"' );
575 rContent.insert( 0,
'"' );
587 bool bEscape = ( rContent.indexOf(
'"' ) >= 0 );
592 OUString aInsert(
"\"\\\"" );
595 while ( nPos < rContent.getLength() )
597 if ( rContent[nPos] ==
'"' )
599 rContent.insert( nPos, aInsert );
600 nPos += aInsert.getLength();
607 rContent.insert( 0,
'"' );
608 rContent.append(
'"' );
614 if ( rContent.getLength() > 2 &&
615 rContent[0] ==
'"' &&
618 rContent.remove(0, 2);
621 sal_Int32 nLen = rContent.getLength();
623 rContent[nLen - 1] ==
'"' &&
624 rContent[nLen - 2] ==
'"' )
626 rContent.truncate(nLen - 2);
634 SvXMLNumFmtElementContext::SvXMLNumFmtElementContext(
SvXMLImport& rImport,
637 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList ) :
639 rParent( rParentContext ),
647 bool bAttrBool(
false);
648 bool bVarDecimals =
false;
649 bool bIsMaxDenominator =
false;
654 switch (aIter.getToken())
666 aNumInfo.nMinDecimalDigits = nAttrVal;
670 aNumInfo.nInteger = nAttrVal;
673 if (::
sax::Converter::convertBool( bAttrBool, aIter.toView() ))
674 aNumInfo.bGrouping = bAttrBool;
677 if (::
sax::Converter::convertDouble( fAttrDouble, aIter.toView() ))
678 aNumInfo.fDisplayFactor = fAttrDouble;
681 if ( aIter.toView() ==
" " )
683 aNumInfo.bDecAlign =
true;
687 if ( aIter.isEmpty() )
690 aNumInfo.bDecReplace =
true;
699 aNumInfo.nExpInterval = nAttrVal;
703 if (::
sax::Converter::convertBool( bAttrBool, aIter.toView() ))
704 aNumInfo.bExpSign = bAttrBool;
708 aNumInfo.nMinNumerDigits = nAttrVal;
712 aNumInfo.nMinDenomDigits = nAttrVal;
716 aNumInfo.nMaxNumerDigits = nAttrVal;
721 aNumInfo.nFracDenominator = nAttrVal;
722 bIsMaxDenominator =
false;
727 if (::
sax::Converter::
convertNumber( nAttrVal, aIter.toView(), 1 ) && aNumInfo.nFracDenominator <= 0)
729 aNumInfo.nFracDenominator = nAttrVal;
730 bIsMaxDenominator =
true;
736 aNumInfo.nZerosNumerDigits = nAttrVal;
741 aNumInfo.nZerosDenomDigits = nAttrVal;
745 aNumInfo.aIntegerFractionDelimiter = aIter.
toString();
748 aLanguageTagODF.maRfcLanguageTag = aIter.
toString();
751 aLanguageTagODF.maLanguage = aIter.
toString();
754 aLanguageTagODF.maScript = aIter.
toString();
757 aLanguageTagODF.maCountry = aIter.
toString();
763 if (::
sax::Converter::convertBool( bAttrBool, aIter.toView() ))
764 bTextual = bAttrBool;
773 if ( aNumInfo.nMinDecimalDigits == -1)
775 if ( bVarDecimals || aNumInfo.bDecReplace )
776 aNumInfo.nMinDecimalDigits = 0;
778 aNumInfo.nMinDecimalDigits = aNumInfo.nDecimals;
780 if ( aNumInfo.nZerosDenomDigits > 0 )
782 if ( aNumInfo.nMinDenomDigits < aNumInfo.nZerosDenomDigits )
783 aNumInfo.nMinDenomDigits = aNumInfo.nZerosDenomDigits;
786 aNumInfo.nZerosDenomDigits = 0;
787 if ( aNumInfo.nMinDenomDigits >= 0 )
788 if ( aNumInfo.nMaxDenomDigits < aNumInfo.nMinDenomDigits )
789 aNumInfo.nMaxDenomDigits = ( aNumInfo.nMinDenomDigits ? aNumInfo.nMinDenomDigits : 1 );
790 if ( aNumInfo.nZerosNumerDigits > 0 )
792 if ( aNumInfo.nMinNumerDigits < aNumInfo.nZerosNumerDigits )
793 aNumInfo.nMinNumerDigits = aNumInfo.nZerosNumerDigits;
796 aNumInfo.nZerosNumerDigits = 0;
797 if ( aNumInfo.nMinNumerDigits >= 0 )
798 if ( aNumInfo.nMaxNumerDigits < aNumInfo.nMinNumerDigits )
799 aNumInfo.nMaxNumerDigits = ( aNumInfo.nMinNumerDigits ? aNumInfo.nMinNumerDigits : 1 );
800 if ( bIsMaxDenominator && aNumInfo.nFracDenominator > 0 )
802 aNumInfo.nMaxDenomDigits = floor( log10( aNumInfo.nFracDenominator ) ) + 1;
803 aNumInfo.nFracDenominator = -1;
805 if ( aNumInfo.nMaxDenomDigits > 0 )
807 if ( aNumInfo.nMinDenomDigits < 0 )
808 aNumInfo.nMinDenomDigits = 0;
809 else if ( aNumInfo.nMinDenomDigits > aNumInfo.nMaxDenomDigits )
810 aNumInfo.nMinDenomDigits = aNumInfo.nMaxDenomDigits;
813 if ( !aLanguageTagODF.
isEmpty() )
816 if ( nElementLang == LANGUAGE_DONTKNOW )
820 if ( aNumInfo.aIntegerFractionDelimiter.isEmpty() )
821 aNumInfo.aIntegerFractionDelimiter =
" ";
824 css::uno::Reference< css::xml::sax::XFastContextHandler > SvXMLNumFmtElementContext::createFastChildContext(
826 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
830 if ( nType == SvXMLStyleTokens::Number &&
833 return new SvXMLNumFmtEmbeddedTextContext( GetImport(), nElement, *
this, xAttrList );
840 void SvXMLNumFmtElementContext::characters(
const OUString& rChars )
842 aContent.append( rChars );
845 void SvXMLNumFmtElementContext::AddEmbeddedElement( sal_Int32 nFormatPos,
const OUString& rContent )
847 if (rContent.isEmpty())
850 auto iterPair = aNumInfo.m_EmbeddedElements.emplace(nFormatPos, rContent);
851 if (!iterPair.second)
853 iterPair.first->second += rContent;
856 void SvXMLNumFmtElementContext::endFastElement(sal_Int32 )
858 bool bEffLong = bLong;
861 case SvXMLStyleTokens::Text:
862 if ( rParent.HasLongDoW() &&
863 std::u16string_view(aContent) == rParent.GetLocaleData().getLongDateDayOfWeekSep() )
868 if ( rParent.ReplaceNfKeyword( NF_KEY_NNN, NF_KEY_NNNN ) )
873 rParent.SetHasLongDoW(
false );
875 if ( !aContent.isEmpty() )
878 rParent.AddToCode( aContent.makeStringAndClear() );
883 aContent.append(
"\"\"");
884 rParent.AddToCode( aContent.makeStringAndClear() );
885 rParent.SetHasTrailingEmptyText(
true);
889 case SvXMLStyleTokens::Number:
890 rParent.AddNumber( aNumInfo );
893 case SvXMLStyleTokens::CurrencySymbol:
894 rParent.AddCurrency( aContent.makeStringAndClear(), nElementLang );
897 case SvXMLStyleTokens::TextContent:
898 rParent.AddToCode(
'@');
900 case SvXMLStyleTokens::FillCharacter:
901 if ( !aContent.isEmpty() )
903 rParent.AddToCode(
'*' );
904 rParent.AddToCode( aContent[0] );
907 case SvXMLStyleTokens::Boolean:
911 case SvXMLStyleTokens::Day:
912 rParent.UpdateCalendar( sCalendar );
915 rParent.AddNfKeyword(
916 sal::static_int_cast< sal_uInt16 >(
917 bEffLong ? NF_KEY_DD : NF_KEY_D ) );
919 case SvXMLStyleTokens::Month:
920 rParent.UpdateCalendar( sCalendar );
923 rParent.AddNfKeyword(
924 sal::static_int_cast< sal_uInt16 >(
926 ? ( bEffLong ? NF_KEY_MMMM : NF_KEY_MMM )
927 : ( bEffLong ? NF_KEY_MM : NF_KEY_M ) ) );
929 case SvXMLStyleTokens::Year:
936 rParent.UpdateCalendar( sCalendar);
938 if (eCal == SvXMLNumFormatContext::ImplicitCalendar::SECONDARY
939 || eCal == SvXMLNumFormatContext::ImplicitCalendar::SECONDARY_FROM_OTHER)
941 rParent.AddNfKeyword(
942 sal::static_int_cast< sal_uInt16 >(
943 bEffLong ? NF_KEY_EEC : NF_KEY_EC ) );
947 rParent.AddNfKeyword(
948 sal::static_int_cast< sal_uInt16 >(
949 bEffLong ? NF_KEY_YYYY : NF_KEY_YY ) );
953 case SvXMLStyleTokens::Era:
954 rParent.UpdateCalendar( sCalendar );
956 rParent.AddNfKeyword(
957 sal::static_int_cast< sal_uInt16 >(
958 bEffLong ? NF_KEY_GGG : NF_KEY_G ) );
961 case SvXMLStyleTokens::DayOfWeek:
966 rParent.UpdateCalendar( sCalendar);
968 if (eCal == SvXMLNumFormatContext::ImplicitCalendar::SECONDARY
969 || eCal == SvXMLNumFormatContext::ImplicitCalendar::SECONDARY_FROM_OTHER)
971 rParent.AddNfKeyword(
972 sal::static_int_cast< sal_uInt16 >(
973 bEffLong ? NF_KEY_AAAA : NF_KEY_AAA ) );
977 rParent.AddNfKeyword(
978 sal::static_int_cast< sal_uInt16 >(
979 bEffLong ? NF_KEY_NNNN : NF_KEY_NN ) );
983 case SvXMLStyleTokens::WeekOfYear:
984 rParent.UpdateCalendar( sCalendar );
985 rParent.AddNfKeyword( NF_KEY_WW );
987 case SvXMLStyleTokens::Quarter:
988 rParent.UpdateCalendar( sCalendar );
989 rParent.AddNfKeyword(
990 sal::static_int_cast< sal_uInt16 >(
991 bEffLong ? NF_KEY_QQ : NF_KEY_Q ) );
993 case SvXMLStyleTokens::Hours:
994 rParent.AddNfKeyword(
995 sal::static_int_cast< sal_uInt16 >(
996 bEffLong ? NF_KEY_HH : NF_KEY_H ) );
998 case SvXMLStyleTokens::AmPm:
1000 rParent.AddNfKeyword( NF_KEY_AMPM );
1002 case SvXMLStyleTokens::Minutes:
1003 rParent.AddNfKeyword(
1004 sal::static_int_cast< sal_uInt16 >(
1005 bEffLong ? NF_KEY_MMI : NF_KEY_MI ) );
1007 case SvXMLStyleTokens::Seconds:
1008 rParent.AddNfKeyword(
1009 sal::static_int_cast< sal_uInt16 >(
1010 bEffLong ? NF_KEY_SS : NF_KEY_S ) );
1011 if ( aNumInfo.nDecimals > 0 )
1014 rParent.AddToCode(rParent.GetLocaleData().getNumDecimalSep());
1015 for (sal_Int32 i=0;
i<aNumInfo.nDecimals;
i++)
1017 rParent.AddToCode(
'0');
1022 case SvXMLStyleTokens::Fraction:
1024 if ( aNumInfo.nInteger >= 0 )
1027 aNumInfo.nDecimals = 0;
1028 rParent.AddNumber( aNumInfo );
1029 OUStringBuffer sIntegerFractionDelimiter(aNumInfo.aIntegerFractionDelimiter);
1031 rParent.AddToCode( sIntegerFractionDelimiter.makeStringAndClear() );
1037 for (i=aNumInfo.nMaxNumerDigits; i > 0; i--)
1039 if ( i > aNumInfo.nMinNumerDigits )
1040 rParent.AddToCode(
'#' );
1041 else if ( i > aNumInfo.nZerosNumerDigits )
1042 rParent.AddToCode(
'?' );
1044 rParent.AddToCode(
'0' );
1046 rParent.AddToCode(
'/' );
1047 if ( aNumInfo.nFracDenominator > 0 )
1049 rParent.AddToCode( OUString::number( aNumInfo.nFracDenominator ) );
1053 for (i=aNumInfo.nMaxDenomDigits; i > 0 ; i--)
1055 if ( i > aNumInfo.nMinDenomDigits )
1056 rParent.AddToCode(
'#' );
1057 else if ( i > aNumInfo.nZerosDenomDigits )
1058 rParent.AddToCode(
'?' );
1060 rParent.AddToCode(
'0' );
1066 case SvXMLStyleTokens::ScientificNumber:
1069 if( !aNumInfo.bGrouping && aNumInfo.nExpInterval > aNumInfo.nInteger )
1071 for (sal_Int32 i=aNumInfo.nInteger; i<aNumInfo.nExpInterval; i++)
1073 rParent.AddToCode(
'#' );
1076 rParent.AddNumber( aNumInfo );
1078 if ( aNumInfo.bExpSign )
1079 rParent.AddToCode( u
"E+" );
1081 rParent.AddToCode( u
"E" );
1082 for (sal_Int32 i=0; i<aNumInfo.nExpDigits; i++)
1084 rParent.AddToCode(
'0' );
1090 assert(
false &&
"invalid element ID");
1100 for (
const auto & rEntry : aDefaultDateFormats)
1102 if ( bSystem == rEntry.bSystem &&
1111 return sal::static_int_cast< sal_uInt16 >(rEntry.eFormat);
1124 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList,
1128 pStyles( &rStyles ),
1131 eImplicitCalendar(ImplicitCalendar::
DEFAULT),
1133 bAutoOrder(
false ),
1134 bFromSystem(
false ),
1138 bHasExtraText(
false ),
1139 bHasTrailingEmptyText(
false ),
1140 bHasLongDoW(
false ),
1141 bHasDateTime(
false ),
1142 bRemoveAfterUse(
false ),
1150 bDateNoDefault(
false )
1153 css::i18n::NativeNumberXmlAttributes aNatNumAttr;
1155 bool bAttrBool(
false);
1159 switch (aIter.getToken())
1165 aLanguageTagODF.maRfcLanguageTag = aIter.
toString();
1168 aLanguageTagODF.maLanguage = aIter.
toString();
1171 aLanguageTagODF.maScript = aIter.
toString();
1174 aLanguageTagODF.maCountry = aIter.
toString();
1180 if (::
sax::Converter::convertBool( bAttrBool, aIter.toView() ))
1181 bAutoOrder = bAttrBool;
1187 if (::
sax::Converter::convertBool( bAttrBool, aIter.toView() ))
1188 bTruncate = bAttrBool;
1193 if (::
sax::Converter::convertBool( bAttrBool, aIter.toView() ))
1194 bRemoveAfterUse = bAttrBool;
1217 if (!aLanguageTagODF.
isEmpty())
1220 if ( nFormatLang == LANGUAGE_DONTKNOW )
1224 if (aNatNumAttr.Format.isEmpty() && aSpellout.isEmpty())
1227 LanguageTag aLanguageTag( OUString(), aNatNumAttr.Locale.Language,
1228 std::u16string_view(), aNatNumAttr.Locale.Country);
1229 aNatNumAttr.Locale = aLanguageTag.getLocale(
false);
1232 if ( !aSpellout.isEmpty() )
1234 aFormatCode.append(
"[NatNum12 " );
1235 aFormatCode.append( aSpellout );
1238 if ( !pFormatter )
return;
1240 sal_Int32
nNatNum = pFormatter->
GetNatNum()->convertFromXmlAttributes( aNatNumAttr );
1241 aFormatCode.append(
"[NatNum" );
1242 aFormatCode.append( nNatNum );
1245 LanguageType eLang = aLanguageTag.getLanguageType(
false );
1246 if ( eLang == LANGUAGE_DONTKNOW )
1248 if ( eLang != nFormatLang && eLang != LANGUAGE_SYSTEM )
1250 aFormatCode.append(
"][$-" );
1252 aFormatCode.append(OUString::number(static_cast<sal_uInt16>(eLang), 16).toAsciiUpperCase());
1254 aFormatCode.append(
']' );
1258 const OUString& rName,
1259 const uno::Reference<xml::sax::XFastAttributeList>& ,
1264 pStyles( &rStyles ),
1267 eImplicitCalendar(ImplicitCalendar::
DEFAULT),
1268 nFormatLang( nLang ),
1269 bAutoOrder(
false ),
1270 bFromSystem(
false ),
1274 bHasExtraText(
false ),
1275 bHasTrailingEmptyText(
false ),
1276 bHasLongDoW(
false ),
1277 bHasDateTime(
false ),
1278 bRemoveAfterUse(
false ),
1286 bDateNoDefault(
false )
1297 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
1305 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1306 *
this, SvXMLStyleTokens::Text, xAttrList );
1310 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1311 *
this, SvXMLStyleTokens::FillCharacter, xAttrList );
1314 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1315 *
this, SvXMLStyleTokens::Number, xAttrList );
1318 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1319 *
this, SvXMLStyleTokens::ScientificNumber, xAttrList );
1322 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1323 *
this, SvXMLStyleTokens::Fraction, xAttrList );
1326 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1327 *
this, SvXMLStyleTokens::CurrencySymbol, xAttrList );
1330 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1331 *
this, SvXMLStyleTokens::Day, xAttrList );
1334 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1335 *
this, SvXMLStyleTokens::Month, xAttrList );
1338 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1339 *
this, SvXMLStyleTokens::Year, xAttrList );
1342 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1343 *
this, SvXMLStyleTokens::Era, xAttrList );
1346 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1347 *
this, SvXMLStyleTokens::DayOfWeek, xAttrList );
1350 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1351 *
this, SvXMLStyleTokens::WeekOfYear, xAttrList );
1354 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1355 *
this, SvXMLStyleTokens::Quarter, xAttrList );
1358 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1359 *
this, SvXMLStyleTokens::Hours, xAttrList );
1362 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1363 *
this, SvXMLStyleTokens::AmPm, xAttrList );
1366 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1367 *
this, SvXMLStyleTokens::Minutes, xAttrList );
1370 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1371 *
this, SvXMLStyleTokens::Seconds, xAttrList );
1374 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1375 *
this, SvXMLStyleTokens::Boolean, xAttrList );
1378 pContext =
new SvXMLNumFmtElementContext(
GetImport(), nElement,
1379 *
this, SvXMLStyleTokens::TextContent, xAttrList );
1383 pContext =
new SvXMLNumFmtPropContext(
GetImport(), nElement,
1390 pContext =
new SvXMLNumFmtMapContext(
GetImport(), nElement,
1450 comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>( xFormatsSupplier );
1473 OSL_FAIL(
"no number formatter");
1485 SAL_INFO(
"xmloff.style",
"invalid style:map references containing style");
1513 OUString sFormat =
aFormatCode.makeStringAndClear();
1561 OUString aFormatStr( sFormat );
1565 sal_Int32 nErrPos = 0;
1568 if ( !bOk && nErrPos == 0 && aFormatStr != sFormat )
1617 OSL_FAIL(
"invalid number format");
1663 sal_uInt16 nPrec = 0;
1664 sal_uInt16 nLeading = 0;
1666 nPrec =
static_cast<sal_uInt16
>(rInfo.
nDecimals);
1668 nLeading =
static_cast<sal_uInt16
>(rInfo.
nInteger);
1694 sal_uInt16 nGenPrec = nPrec;
1702 if ( nEmbeddedCount )
1707 bGrouping,
false, nGenPrec, nLeading ));
1709 if ( rInfo.
nExpDigits >= 0 && nLeading == 0 && !bGrouping && nEmbeddedCount == 0 )
1714 aNumStr.stripStart(
'#');
1720 sal_Int32 nDigits = rInfo.
nInteger;
1722 if ( nIntegerEnd < 0 )
1723 nIntegerEnd = aNumStr.getLength();
1724 while ( nIndex >= 0 && nIndex < nIntegerEnd )
1726 if ( ( nIndex = aNumStr.indexOf(
'#', nIndex ) ) >= 0 )
1737 aNumStr.insert( 0,
'#' );
1741 if ( nEmbeddedCount )
1750 nZeroPos = aNumStr.getLength();
1755 if ( nLastFormatPos >= nZeroPos )
1760 sal_Int32 nAddCount = nLastFormatPos + 1 - nZeroPos;
1763 aNumStr.insert(0,
'#');
1765 nZeroPos = nZeroPos + nAddCount;
1771 sal_Int32
const nFormatPos = it.first;
1772 sal_Int32 nInsertPos = nZeroPos - nFormatPos;
1773 if ( nFormatPos >= 0 && nInsertPos >= 0 )
1778 aNumStr.insert(nInsertPos,
'"');
1779 aNumStr.insert(nInsertPos, it.second);
1780 aNumStr.insert(nInsertPos,
'"');
1806 sal_Int32 nSepCount =
static_cast<sal_Int32
>(::rtl::math::round( log10(rInfo.
fDisplayFactor) / 3.0 ));
1807 if ( nSepCount > 0 )
1810 for ( sal_Int32 i=0; i<nSepCount; i++ )
1817 bool bAutomatic =
false;
1818 OUString aSymbol = rContent;
1819 if ( aSymbol.isEmpty())
1825 OUString sCurString, sDummy;
1827 aSymbol = sCurString;
1844 if ( nLength > 1 &&
aFormatCode[nLength - 1] ==
'"' )
1850 sal_Int32 nFirst = nLength - 2;
1851 while ( nFirst >= 0 &&
aFormatCode[nFirst] !=
'"' )
1859 if ( nLength > nFirst + 2 )
1860 aFormatCode.append( aOld.subView( nFirst + 1, nLength - nFirst - 2 ) );
1875 aFormatCode.append(
"-" + OUString(OUString::number(sal_uInt16(nLang), 16)).toAsciiUpperCase());
1896 if ( nIndex == NF_KEY_H || nIndex ==
NF_KEY_HH ||
1897 nIndex == NF_KEY_MI || nIndex ==
NF_KEY_MMI ||
1898 nIndex == NF_KEY_S || nIndex ==
NF_KEY_SS )
1942 static bool lcl_IsAtEnd( OUStringBuffer& rBuffer,
const OUString& rToken )
1944 sal_Int32 nBufLen = rBuffer.getLength();
1945 sal_Int32 nTokLen = rToken.getLength();
1947 if ( nTokLen > nBufLen )
1950 sal_Int32 nStartPos = nBufLen - nTokLen;
1951 for ( sal_Int32 nTokPos = 0; nTokPos < nTokLen; nTokPos++ )
1952 if ( rToken[ nTokPos ] != rBuffer[nStartPos + nTokPos] )
1990 rCondition.startsWith(
"value()", &sRealCond)) )
1996 bool bDefaultCond =
false;
2001 bDefaultCond =
true;
2007 bDefaultCond =
true;
2013 sal_Int32
nPos = sRealCond.indexOf(
"!=" );
2016 sRealCond = sRealCond.replaceAt( nPos, 2,
u"<>" );
2019 nPos = sRealCond.indexOf(
'.' );
2024 if ( rDecSep.getLength() > 1 || rDecSep[0] !=
'.' )
2026 sRealCond = sRealCond.replaceAt( nPos, 1, rDecSep );
2053 OUStringBuffer aColName;
2055 if (nColor == aNumFmtStdColors[i])
2061 if ( !aColName.isEmpty() )
2063 aColName.insert( 0,
'[' );
2064 aColName.append(
']' );
2065 aFormatCode.insert( 0, aColName.makeStringAndClear() );
2077 ImplicitCalendar::DEFAULT_FROM_OTHER : ImplicitCalendar::DEFAULT);
2082 ImplicitCalendar::DEFAULT_FROM_OTHER : ImplicitCalendar::DEFAULT);
2088 ImplicitCalendar::SECONDARY_FROM_OTHER : ImplicitCalendar::SECONDARY);
2093 ImplicitCalendar::SECONDARY_FROM_OTHER : ImplicitCalendar::SECONDARY);
2105 bool bSameDefault =
false;
2106 if (
sCalendar.isEmpty() || rNewCalendar.isEmpty())
2113 bSameDefault = (rNewCalendar == rDefaultCalendar ||
sCalendar == rDefaultCalendar);
2118 if (rNewCalendar.isEmpty())
2145 const uno::Reference<util::XNumberFormatsSupplier>& rSupp,
2146 const uno::Reference<uno::XComponentContext>& rxContext )
2148 SAL_WARN_IF( !rxContext.is(),
"xmloff",
"got no service manager" );
2152 comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>( rSupp );
2156 pData = std::make_unique<SvXMLNumImpData>( pFormatter, rxContext );
2161 const uno::Reference<uno::XComponentContext>& rxContext )
2163 SAL_WARN_IF( !rxContext.is(),
"xmloff",
"got no service manager" );
2165 pData = std::make_unique<SvXMLNumImpData>( pNumberFormatter, rxContext );
2171 pData->RemoveVolatileFormats();
2177 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList,
2209 pData.get(), nStyleToken, xAttrList, rStyles );
2214 if (
pData->GetNumberFormatter())
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
const Color aNumFmtStdColors[XML_NUMF_COLORCOUNT]
void AddNumber(const SvXMLNumberInfo &rInfo)
NF_INDEX_TABLE_RESERVED_START
sal_Int32 nMinDecimalDigits
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_LIGHTMAGENTA
the SvXMLTypeConverter converts values of various types from their internal representation to the tex...
sal_uInt16 getCurrDigits() const
LanguageType getLanguageType(bool bResolveSystem=true) const
NF_DATETIME_SYS_DDMMYYYY_HHMMSS
std::unique_ptr< sal_Int32[]> pData
ImplicitCalendar eImplicitCalendar
SvXMLDateElementAttributes eDateSecs
constexpr size_t NF_MAX_FORMAT_SYMBOLS
virtual ~SvXMLNumFormatContext() override
sal_Int32 nZerosDenomDigits
SvXMLNumFormatContext(SvXMLImport &rImport, sal_Int32 nElement, SvXMLNumImpData *pNewData, SvXMLStylesTokens nNewType, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList, SvXMLStylesContext &rStyles)
SvXMLImport & GetImport()
SvXMLDateElementAttributes eDateDay
const std::shared_ptr< css::i18n::Calendar2 > & getDefaultCalendar() const
OUString aIntegerFractionDelimiter
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
LanguageTag getLanguageTag() const
Best call this only once per instance, it recreates a LanguageTag instance on every call...
SvNumberFormatter * pFormatter
SvXMLStyleContext * CreateChildContext(SvXMLImport &rImport, sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList, SvXMLStylesContext &rStyles)
sal_Int32 nMinNumerDigits
const LocaleDataWrapper & GetLocaleData(LanguageType nLang)
sal_uInt32 GetKeyForName(std::u16string_view rName)
LanguageType GetLanguageForKey(sal_Int32 nKey) const
sal_Int32 nMaxNumerDigits
sal_Int32 nZerosNumerDigits
constexpr sal_uInt32 NUMBERFORMAT_ENTRY_NOT_FOUND
void RemoveVolatileFormats()
#define XMLOFF_WARN_UNKNOWN(area, rIter)
std::vector< MyCondition > aMyConditions
static OUString getPrefixAndNameFromToken(sal_Int32 nToken)
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_LIGHTRED
SvXMLStylesContext * pStyles
const OUString & getNumDecimalSep() const
void SetUsed(sal_uInt32 nKey)
SvXMLDateElementAttributes eDateMonth
#define XML_NUMF_COLORCOUNT
void AddCurrency(const OUString &rContent, LanguageType nLang)
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
std::map< sal_Int32, OUString > m_EmbeddedElements
bool doesSecondaryCalendarUseEC(std::u16string_view rName) const
sal_Int32 nMaxDenomDigits
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_GRAY
SvXMLDateElementAttributes eDateDOW
NF_DATETIME_SYS_DDMMYYYY_HHMM
bool ReplaceNfKeyword(sal_uInt16 nOld, sal_uInt16 nNew)
sal_Int32 nMinDenomDigits
OUStringBuffer aConditions
SvXMLImportContext(SvXMLImport &rImport)
A contexts constructor does anything that is required if an element starts.
OUStringBuffer aFormatCode
std::vector< SvXMLNumFmtEntry > m_NameEntries
const uno::Reference< uno::XComponentContext > m_xContext
SvXMLDateElementAttributes eDateHours
void AddColor(Color nColor)
SvXMLNumFmtHelper(const css::uno::Reference< css::util::XNumberFormatsSupplier > &rSupp, const css::uno::Reference< css::uno::XComponentContext > &rxContext)
const SvXMLDefaultDateFormat aDefaultDateFormats[]
bool bHasTrailingEmptyText
This class deliberately does not support XWeak, to improve performance when loading large documents...
const SvXMLEnumMapEntry< bool > aStyleValueMap[]
Map an XMLTokenEnum to an enum value.
void UpdateCalendar(const OUString &rNewCalendar)
void AddCondition(const sal_Int32 nIndex)
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_LIGHTCYAN
const SvXMLEnumMapEntry< bool > aFormatSourceMap[]
#define SAL_WARN_IF(condition, area, stream)
const OUString & GetName() const
SvXMLNumImpData(SvNumberFormatter *pFmt, const uno::Reference< uno::XComponentContext > &rxContext)
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 ...
NF_DATE_SYS_NNNNDMMMMYYYY
std::unique_ptr< SvXMLNumImpData > pData
Handling of tokens in XML:
void AddKey(sal_uInt32 nKey, const OUString &rName, bool bRemoveAfterUse)
void AddNumberStyle(sal_Int32 nKey, const OUString &sName)
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_WHITE
#define SAL_INFO(area, stream)
std::unique_ptr< LocaleDataWrapper > pLocaleData
virtual css::uno::Reference< XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
sal_Int32 nFracDenominator
OUString aImplicitCalendar[2]
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BROWN
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_LIGHTGREEN
if(aStr!=aBuf) UpdateName_Impl(m_xFollowLb.get()
static sal_uInt16 GetDefaultDateFormat(SvXMLDateElementAttributes eDOW, SvXMLDateElementAttributes eDay, SvXMLDateElementAttributes eMonth, SvXMLDateElementAttributes eYear, SvXMLDateElementAttributes eHours, SvXMLDateElementAttributes eMins, SvXMLDateElementAttributes eSecs, bool bSystem)
#define XML_ELEMENT(prefix, name)
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BLACK
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_YELLOW
SvXMLStylesTokens GetType() const
static void lcl_EnquoteIfNecessary(OUStringBuffer &rContent, const SvXMLNumFormatContext &rParent)
SAL_DLLPRIVATE sal_Int32 PrivateGetKey()
void AddToCode(std::u16string_view rString)
const OUString & getNumThousandSep() const
const SvXMLStyleContext * FindStyleChildContext(XmlStyleFamily nFamily, const OUString &rName, bool bCreateIndex=false) const
SvXMLDateElementAttributes eDateMins
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_LIGHTBLUE
static bool lcl_ValidChar(sal_Unicode cChar, const SvXMLNumFormatContext &rParent)
NF_DATETIME_SYSTEM_SHORT_HHMM
#define SAL_WARN(area, stream)
#define XMLOFF_WARN_UNKNOWN_ELEMENT(area, token)
SvXMLDateElementAttributes eDateYear
SvNumberFormatter * GetNumberFormatter() const
uno::Reference< uno::XComponentContext > m_xContext
virtual void CreateAndInsert(bool bOverwrite) override
const LocaleDataWrapper & GetLocaleData() const
Helper to gather the single language tag relevant attributes during reading ODF and form a resulting ...
virtual void SAL_CALL characters(const OUString &aChars) override
This method is called for all characters that are contained in the current element.
bool IsSystemLanguage() const
determine whether number format uses the system language
void AddNfKeyword(sal_uInt16 nIndex)
OUString toString(OptionInfo const *info)
bool m_bDetectedRangeSegmentation false
static bool convertNumber(sal_Int32 &rValue, std::u16string_view aString, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32)
static bool lcl_IsAtEnd(OUStringBuffer &rBuffer, const OUString &rToken)