include/svl/zformat.hxx | 11 ++++++++--- sc/source/core/data/documen4.cxx | 17 +++++++++++++---- svl/source/numbers/zformat.cxx | 16 ++++++++++++++++ 3 files changed, 37 insertions(+), 7 deletions(-)
New commits: commit eedfa91e777423cb3cd025c8eafd7e031c98f6b9 Author: Eike Rathke <er...@redhat.com> AuthorDate: Wed Sep 1 15:35:11 2021 +0200 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Fri Sep 3 16:05:49 2021 +0200 Resolves: tdf#144209 Handle General containing formats in RoundValueAsShown() Calling SvNumberformat::GetThousandDivisorPrecision() for a "AA "General format resulted in 3000 as that was implemented for tdf#106253 without taking into account that ImpSvNumberformatInfo::nThousand may be abused under some conditions, which here is having FLAG_STANDARD_IN_FORMAT = 1000 as nThousand, multiplied by 3 gives 3000. Subtracted from the 0 precision gave -3000 decimals for which of course the new rounding produced 0 where it previously simply ignored the decimals and returned the original value. Change-Id: I66afaf1e2d8b2654d9f7cc8cfb66389357fb742d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121447 Reviewed-by: Eike Rathke <er...@redhat.com> Tested-by: Jenkins (cherry picked from commit 71b003a12f8afdff42a25786ad0a12ddd6609d59) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121460 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-by: Michael Stahl <michael.st...@allotropia.de> Reviewed-by: Caolán McNamara <caol...@redhat.com> Tested-by: Caolán McNamara <caol...@redhat.com> diff --git a/include/svl/zformat.hxx b/include/svl/zformat.hxx index 976488257218..abbf92e92af8 100644 --- a/include/svl/zformat.hxx +++ b/include/svl/zformat.hxx @@ -271,10 +271,15 @@ public: { return NumFor[nIx].Info().nCntPre; } /** Count of hidden integer digits with thousands divisor: - * formats like "0," to show only thousands + formats like "0," to show only thousands. + + Works only with SvNumFormatType::NUMBER and SvNumFormatType::CURRENCY, + returns 0 otherwise. + + Returns SvNumberFormatter::UNLIMITED_PRECISION for formats that contain + the General keyword. */ - sal_uInt16 GetThousandDivisorPrecision( sal_uInt16 nIx = 0 ) const - { return NumFor[nIx].Info().nThousand * 3; } + sal_uInt16 GetThousandDivisorPrecision( sal_uInt16 nIx = 0 ) const; //! Read/write access on a special sal_uInt16 component, may only be used on the //! standard format 0, 10000, ... and only by the number formatter! diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx index aee431660d0a..9d124f5acc2f 100644 --- a/sc/source/core/data/documen4.cxx +++ b/sc/source/core/data/documen4.cxx @@ -640,8 +640,12 @@ double ScDocument::RoundValueAsShown( double fVal, sal_uInt32 nFormat, const ScI SvNumFormatType nType = pFormat->GetMaskedType(); if (nType != SvNumFormatType::DATE && nType != SvNumFormatType::TIME && nType != SvNumFormatType::DATETIME ) { - short nPrecision; - if ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0) + // MSVC doesn't recognize all paths init nPrecision and wails about + // "potentially uninitialized local variable 'nPrecision' used" + // so init to some random sensible value preserving all decimals. + short nPrecision = 20; + bool bStdPrecision = ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0); + if (!bStdPrecision) { sal_uInt16 nIdx = pFormat->GetSubformatIndex( fVal ); nPrecision = static_cast<short>(pFormat->GetFormatPrecision( nIdx )); @@ -678,13 +682,18 @@ double ScDocument::RoundValueAsShown( double fVal, sal_uInt32 nFormat, const ScI case SvNumFormatType::NUMBER: case SvNumFormatType::CURRENCY: { // tdf#106253 Thousands divisors for format "0," - nPrecision -= pFormat->GetThousandDivisorPrecision( nIdx ); + const sal_uInt16 nTD = pFormat->GetThousandDivisorPrecision( nIdx ); + if (nTD == SvNumberFormatter::UNLIMITED_PRECISION) + // Format contains General keyword, handled below. + bStdPrecision = true; + else + nPrecision -= nTD; break; } default: break; } } - else + if (bStdPrecision) { nPrecision = static_cast<short>(GetDocOptions().GetStdPrecision()); // #i115512# no rounding for automatic decimals diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx index 255bfb09b5f7..bf95fd717cb1 100644 --- a/svl/source/numbers/zformat.cxx +++ b/svl/source/numbers/zformat.cxx @@ -5946,6 +5946,22 @@ OUString SvNumberformat::GetFormatStringForTimePrecision( int nPrecision ) const return sString.makeStringAndClear(); } +sal_uInt16 SvNumberformat::GetThousandDivisorPrecision( sal_uInt16 nIx ) const +{ + if (nIx >= 4) + return 0; + + const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info(); + + if (rInfo.eScannedType != SvNumFormatType::NUMBER && rInfo.eScannedType != SvNumFormatType::CURRENCY) + return 0; + + if (rInfo.nThousand == FLAG_STANDARD_IN_FORMAT) + return SvNumberFormatter::UNLIMITED_PRECISION; + + return rInfo.nThousand * 3; +} + const CharClass& SvNumberformat::rChrCls() const { return rScan.GetChrCls();