[ooo-build-commit] Branch 'ooo-build-3-1-1' - patches/dev300
Kohei Yoshida
kohei at kemper.freedesktop.org
Mon Oct 19 11:52:27 PDT 2009
patches/dev300/apply | 5
patches/dev300/calc-general-type-auto-decimal-officecfg.diff | 13
patches/dev300/calc-general-type-auto-decimal-sc.diff | 1175 ++++++++++-
patches/dev300/calc-general-type-auto-decimal-svtools.diff | 388 ++-
4 files changed, 1413 insertions(+), 168 deletions(-)
New commits:
commit 56b7de0e34099cafe1cce1d49485a0ff9dad5dbb
Author: Kohei Yoshida <kyoshida at novell.com>
Date: Mon Oct 19 14:50:09 2009 -0400
Backported auto decimal patches from master.
Note: these patches are not enabled in the default build.
* patches/dev300/apply:
* patches/dev300/calc-general-type-auto-decimal-officecfg.diff:
* patches/dev300/calc-general-type-auto-decimal-sc.diff:
* patches/dev300/calc-general-type-auto-decimal-svtools.diff:
diff --git a/patches/dev300/apply b/patches/dev300/apply
index 077a692..b311fc6 100644
--- a/patches/dev300/apply
+++ b/patches/dev300/apply
@@ -3440,8 +3440,9 @@ calc-selection-protected-cells.diff, n#542024, kohei
# When the cell format is 'General', automatically adjust the number of decimals
# to be displayed based on the cell value.
-calc-general-type-auto-decimal-sc.diff, n#541973, kohei
-calc-general-type-auto-decimal-svtools.diff, n#541973, kohei
+calc-general-type-auto-decimal-sc.diff, n#541973, kohei
+calc-general-type-auto-decimal-svtools.diff, n#541973, kohei
+calc-general-type-auto-decimal-officecfg.diff, n#541973, kohei
# Correctly encrypt zero bytes in the conditional formatting records.
calc-xls-export-encryption-condfmt-fix.diff, n#541058, kohei
diff --git a/patches/dev300/calc-general-type-auto-decimal-officecfg.diff b/patches/dev300/calc-general-type-auto-decimal-officecfg.diff
new file mode 100644
index 0000000..ed99008
--- /dev/null
+++ b/patches/dev300/calc-general-type-auto-decimal-officecfg.diff
@@ -0,0 +1,13 @@
+diff --git officecfg/registry/schema/org/openoffice/Office/Calc.xcs officecfg/registry/schema/org/openoffice/Office/Calc.xcs
+index 742dc7a..a6cccce 100644
+--- officecfg/registry/schema/org/openoffice/Office/Calc.xcs
++++ officecfg/registry/schema/org/openoffice/Office/Calc.xcs
+@@ -1209,7 +1209,7 @@
+ <desc>Specifies the number of decimals to be displayed for the Standard number format.</desc>
+ <label>Decimal places</label>
+ </info>
+- <value>2</value>
++ <value>-1</value>
+ </prop>
+ <prop oor:name="RegularExpressions" oor:type="xs:boolean">
+ <!-- UIHints: Tools - Options Spreadsheet Calculate [Check box] Enable regular expressions in formulas -->
diff --git a/patches/dev300/calc-general-type-auto-decimal-sc.diff b/patches/dev300/calc-general-type-auto-decimal-sc.diff
index 4cea62e..e255cc1 100644
--- a/patches/dev300/calc-general-type-auto-decimal-sc.diff
+++ b/patches/dev300/calc-general-type-auto-decimal-sc.diff
@@ -1,91 +1,1112 @@
-diff --git sc/inc/cellform.hxx sc/inc/cellform.hxx
-index a94ef54..d5c5b20 100644
---- sc/inc/cellform.hxx
-+++ sc/inc/cellform.hxx
-@@ -58,7 +58,7 @@ public:
- ScForceTextFmt eForceTextFmt = ftDontForce );
-
- static void GetInputString( ScBaseCell* pCell, ULONG nFormat, String& rString,
-- SvNumberFormatter& rFormatter );
-+ SvNumberFormatter& rFormatter, Color** ppColor = NULL );
- };
+diff --git sc/inc/docoptio.hxx sc/inc/docoptio.hxx
+index 81b80b9..1184554 100644
+--- sc/inc/docoptio.hxx
++++ sc/inc/docoptio.hxx
+@@ -43,7 +43,7 @@ class SC_DLLPUBLIC ScDocOptions
+ {
+ double fIterEps; // Epsilon-Wert dazu
+ USHORT nIterCount; // Anzahl
+- USHORT nPrecStandardFormat; // Nachkommastellen Standard
++ sal_uInt16 nPrecStandardFormat; // precision for standard format
+ USHORT nDay; // Nulldatum:
+ USHORT nMonth;
+ USHORT nYear;
+@@ -96,8 +96,8 @@ public:
+ inline int operator==( const ScDocOptions& rOpt ) const;
+ inline int operator!=( const ScDocOptions& rOpt ) const;
+
+- USHORT GetStdPrecision() const { return nPrecStandardFormat; }
+- void SetStdPrecision( USHORT n ) { nPrecStandardFormat = n; }
++ sal_uInt16 GetStdPrecision() const { return nPrecStandardFormat; }
++ void SetStdPrecision( sal_uInt16 n ) { nPrecStandardFormat = n; }
+
+ BOOL IsCalcAsShown() const { return bCalcAsShown; }
+ void SetCalcAsShown( BOOL bVal ) { bCalcAsShown = bVal; }
+diff --git sc/source/ui/inc/optdlg.hrc sc/source/ui/inc/optdlg.hrc
+index aaeb33d..5767bfb 100644
+--- sc/source/ui/inc/optdlg.hrc
++++ sc/source/ui/inc/optdlg.hrc
+@@ -74,6 +74,7 @@
+ #define BTN_MATCH 18
+ #define BTN_LOOKUP 19
+ #define BTN_REGEX 20
++#define BTN_GENERAL_PREC 21
+
+ // TP_VIEW:
+ #define BTN_VSCROLL 1
+diff --git sc/source/ui/inc/output.hxx sc/source/ui/inc/output.hxx
+index ea2aadc..07852a2 100644
+--- sc/source/ui/inc/output.hxx
++++ sc/source/ui/inc/output.hxx
+@@ -76,6 +76,15 @@ class ScOutputData
+ {
+ friend class ScDrawStringsVars;
+ private:
++ struct OutputAreaParam
++ {
++ Rectangle maAlignRect;
++ Rectangle maClipRect;
++ long mnColWidth;
++ bool mbLeftClip;
++ bool mbRightClip;
++ };
++
+ OutputDevice* pDev; // Device
+ OutputDevice* pRefDevice; // printer if used for preview
+ OutputDevice* pFmtDevice; // reference for text formatting
+@@ -155,19 +164,19 @@ private:
+ void GetVisibleCell( SCCOL nCol, SCROW nRow, SCTAB nTab, ScBaseCell*& rpCell );
+
+ BOOL IsAvailable( SCCOL nX, SCROW nY );
++
+ void GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY,
+- SCCOL nCellX, SCROW nCellY, long nNeeded,
+- const ScPatternAttr& rPattern,
+- USHORT nHorJustify, BOOL bCellIsValue,
+- BOOL bBreak, BOOL bOverwrite,
+- Rectangle& rAlignRect, Rectangle& rClipRect,
+- BOOL& rLeftClip, BOOL& rRightClip );
++ SCCOL nCellX, SCROW nCellY, long nNeeded,
++ const ScPatternAttr& rPattern,
++ USHORT nHorJustify, bool bCellIsValue,
++ bool bBreak, bool bOverwrite,
++ OutputAreaParam& rParam );
+
+ void ShrinkEditEngine( EditEngine& rEngine, const Rectangle& rAlignRect,
+ long nLeftM, long nTopM, long nRightM, long nBottomM,
+ BOOL bWidth, USHORT nOrient, long nAttrRotate, BOOL bPixelToLogic,
+ long& rEngineWidth, long& rEngineHeight, long& rNeededPixel,
+- BOOL& rLeftClip, BOOL& rRightClip );
++ bool& rLeftClip, bool& rRightClip );
+ void SetSyntaxColor( Font* pFont, ScBaseCell* pCell );
+ void SetEditSyntaxColor( EditEngine& rEngine, ScBaseCell* pCell );
+diff --git sc/source/ui/inc/tpcalc.hxx sc/source/ui/inc/tpcalc.hxx
+index 7052be4..3253f59 100644
+--- sc/source/ui/inc/tpcalc.hxx
++++ sc/source/ui/inc/tpcalc.hxx
+@@ -79,6 +79,7 @@ private:
+ CheckBox aBtnMatch;
+ CheckBox aBtnRegex;
+ CheckBox aBtnLookUp;
++ CheckBox aBtnGeneralPrec;
-diff --git sc/source/core/tool/cellform.cxx sc/source/core/tool/cellform.cxx
-index e6177b0..e17ef9c 100644
---- sc/source/core/tool/cellform.cxx
-+++ sc/source/core/tool/cellform.cxx
-@@ -159,8 +159,11 @@ void ScCellFormat::GetString( ScBaseCell* pCell, ULONG nFormat, String& rString,
+ FixedText aFtPrec;
+ NumericField aEdPrec;
+diff --git sc/source/ui/optdlg/tpcalc.cxx sc/source/ui/optdlg/tpcalc.cxx
+index 86a4476..d70bab7 100644
+--- sc/source/ui/optdlg/tpcalc.cxx
++++ sc/source/ui/optdlg/tpcalc.cxx
+@@ -91,6 +91,7 @@ ScTpCalcOptions::ScTpCalcOptions( Window* pParent,
+ aBtnMatch ( this, ScResId( BTN_MATCH ) ),
+ aBtnRegex ( this, ScResId( BTN_REGEX ) ),
+ aBtnLookUp ( this, ScResId( BTN_LOOKUP ) ),
++ aBtnGeneralPrec ( this, ScResId( BTN_GENERAL_PREC ) ),
+ aFtPrec ( this, ScResId( FT_PREC ) ),
+ aEdPrec ( this, ScResId( ED_PREC ) ),
+ pOldOptions ( new ScDocOptions(
+@@ -119,6 +120,7 @@ __EXPORT ScTpCalcOptions::~ScTpCalcOptions()
+ void ScTpCalcOptions::Init()
+ {
+ aBtnIterate .SetClickHdl( LINK( this, ScTpCalcOptions, CheckClickHdl ) );
++ aBtnGeneralPrec.SetClickHdl( LINK(this, ScTpCalcOptions, CheckClickHdl) );
+ aBtnDateStd .SetClickHdl( LINK( this, ScTpCalcOptions, RadioClickHdl ) );
+ aBtnDateSc10.SetClickHdl( LINK( this, ScTpCalcOptions, RadioClickHdl ) );
+ aBtnDate1904.SetClickHdl( LINK( this, ScTpCalcOptions, RadioClickHdl ) );
+@@ -153,7 +155,6 @@ void __EXPORT ScTpCalcOptions::Reset( const SfxItemSet& /* rCoreAttrs */ )
+ aBtnLookUp .Check( pLocalOptions->IsLookUpColRowNames() );
+ aBtnIterate.Check( pLocalOptions->IsIter() );
+ aEdSteps .SetValue( pLocalOptions->GetIterCount() );
+- aEdPrec .SetValue( pLocalOptions->GetStdPrecision() );
+ aEdEps .SetValue( pLocalOptions->GetIterEps(), 6 );
+
+ pLocalOptions->GetDate( d, m, y );
+@@ -171,6 +172,21 @@ void __EXPORT ScTpCalcOptions::Reset( const SfxItemSet& /* rCoreAttrs */ )
+ break;
+ }
+
++ sal_uInt16 nPrec = pLocalOptions->GetStdPrecision();
++ if (nPrec == SvNumberFormatter::UNLIMITED_PRECISION)
++ {
++ aFtPrec.Disable();
++ aEdPrec.Disable();
++ aBtnGeneralPrec.Check(false);
++ }
++ else
++ {
++ aBtnGeneralPrec.Check();
++ aFtPrec.Enable();
++ aEdPrec.Enable();
++ aEdPrec.SetValue(nPrec);
++ }
++
+ CheckClickHdl( &aBtnIterate );
}
- void ScCellFormat::GetInputString( ScBaseCell* pCell, ULONG nFormat, String& rString,
-- SvNumberFormatter& rFormatter )
-+ SvNumberFormatter& rFormatter, Color** ppColor )
+@@ -181,13 +197,18 @@ BOOL __EXPORT ScTpCalcOptions::FillItemSet( SfxItemSet& rCoreAttrs )
{
-+ if (ppColor)
-+ *ppColor = NULL;
+ // alle weiteren Optionen werden in den Handlern aktualisiert
+ pLocalOptions->SetIterCount( (USHORT)aEdSteps.GetValue() );
+- pLocalOptions->SetStdPrecision( (USHORT)aEdPrec.GetValue() );
+ pLocalOptions->SetIgnoreCase( !aBtnCase.IsChecked() );
+ pLocalOptions->SetCalcAsShown( aBtnCalc.IsChecked() );
+ pLocalOptions->SetMatchWholeCell( aBtnMatch.IsChecked() );
+ pLocalOptions->SetFormulaRegexEnabled( aBtnRegex.IsChecked() );
+ pLocalOptions->SetLookUpColRowNames( aBtnLookUp.IsChecked() );
+
++ if (aBtnGeneralPrec.IsChecked())
++ pLocalOptions->SetStdPrecision(
++ static_cast<sal_uInt16>(aEdPrec.GetValue()) );
++ else
++ pLocalOptions->SetStdPrecision( SvNumberFormatter::UNLIMITED_PRECISION );
+
- if (&rFormatter==NULL)
+ if ( *pLocalOptions != *pOldOptions )
{
- rString.Erase();
-@@ -173,17 +176,19 @@ void ScCellFormat::GetInputString( ScBaseCell* pCell, ULONG nFormat, String& rSt
- case CELLTYPE_STRING:
- {
- ((ScStringCell*)pCell)->GetString( rString );
-+ rFormatter.GetStringColor(nFormat, ppColor);
+ rCoreAttrs.Put( ScTpCalcItem( nWhichCalc, *pLocalOptions ) );
+@@ -248,19 +269,35 @@ IMPL_LINK( ScTpCalcOptions, RadioClickHdl, RadioButton*, pBtn )
+
+ //-----------------------------------------------------------------------
+
+-IMPL_LINK( ScTpCalcOptions, CheckClickHdl, CheckBox*, pBtn )
++IMPL_LINK( ScTpCalcOptions, CheckClickHdl, CheckBox*, pBtn )
+ {
+- if ( pBtn->IsChecked() )
++ if (pBtn == &aBtnGeneralPrec)
+ {
+- pLocalOptions->SetIter( TRUE );
+- aFtSteps.Enable(); aEdSteps.Enable();
+- aFtEps .Enable(); aEdEps .Enable();
++ if (pBtn->IsChecked())
++ {
++ aEdPrec.Enable();
++ aFtPrec.Enable();
++ }
++ else
++ {
++ aEdPrec.Disable();
++ aFtPrec.Disable();
++ }
+ }
+- else
++ else if (pBtn == &aBtnIterate)
+ {
+- pLocalOptions->SetIter( FALSE );
+- aFtSteps.Disable(); aEdSteps.Disable();
+- aFtEps .Disable(); aEdEps .Disable();
++ if ( pBtn->IsChecked() )
++ {
++ pLocalOptions->SetIter( TRUE );
++ aFtSteps.Enable(); aEdSteps.Enable();
++ aFtEps .Enable(); aEdEps .Enable();
++ }
++ else
++ {
++ pLocalOptions->SetIter( FALSE );
++ aFtSteps.Disable(); aEdSteps.Disable();
++ aFtEps .Disable(); aEdEps .Disable();
++ }
+ }
+
+ return 0;
+diff --git sc/source/ui/src/optdlg.src sc/source/ui/src/optdlg.src
+index dd4dd34..78f7864 100644
+--- sc/source/ui/src/optdlg.src
++++ sc/source/ui/src/optdlg.src
+@@ -122,22 +122,6 @@ TabPage RID_SCPAGE_CALC
+ Pos = MAP_APPFONT ( 6 , 64 ) ;
+ Size = MAP_APPFONT ( 248 , 8 ) ;
+ };
+- FixedText FT_PREC
+- {
+- Pos = MAP_APPFONT ( 150 , 77 ) ;
+- Size = MAP_APPFONT ( 72 , 8 ) ;
+- Text [ en-US ] = "~Decimal places" ;
+- Right = TRUE ;
+- };
+- NumericField ED_PREC
+- {
+- Border = TRUE ;
+- Pos = MAP_APPFONT ( 226 , 75 ) ;
+- Size = MAP_APPFONT ( 25 , 12 ) ;
+- Maximum = 20 ;
+- Spin = TRUE ;
+- Repeat = TRUE ;
+- };
+ CheckBox BTN_CASE
+ {
+ Pos = MAP_APPFONT ( 12 , 77 ) ;
+@@ -168,6 +152,28 @@ TabPage RID_SCPAGE_CALC
+ Size = MAP_APPFONT ( 239 , 10 ) ;
+ Text [ en-US ] = "~Automatically find column and row labels " ;
+ };
++ CheckBox BTN_GENERAL_PREC
++ {
++ Pos = MAP_APPFONT ( 12 , 147 ) ;
++ Size = MAP_APPFONT ( 136 , 10 ) ;
++ Text [ en-US ] = "Limit decimals for general number format" ;
++ };
++ FixedText FT_PREC
++ {
++ Pos = MAP_APPFONT ( 150 , 148 ) ;
++ Size = MAP_APPFONT ( 72 , 8 ) ;
++ Text [ en-US ] = "~Decimal places" ;
++ Right = TRUE ;
++ };
++ NumericField ED_PREC
++ {
++ Border = TRUE ;
++ Pos = MAP_APPFONT ( 226 , 146 ) ;
++ Size = MAP_APPFONT ( 25 , 12 ) ;
++ Maximum = 20 ;
++ Spin = TRUE ;
++ Repeat = TRUE ;
++ };
+ };
+
+ /**************************************************************************/
+diff --git sc/source/ui/unoobj/defltuno.cxx sc/source/ui/unoobj/defltuno.cxx
+index f91bb81..a6a4867 100644
+--- sc/source/ui/unoobj/defltuno.cxx
++++ sc/source/ui/unoobj/defltuno.cxx
+@@ -160,7 +160,7 @@ void SAL_CALL ScDocDefaultsObj::setPropertyValue(
+ sal_Int16 nValue = 0;
+ if (aValue >>= nValue)
+ {
+- aDocOpt.SetStdPrecision(static_cast<sal_uInt8> (nValue));
++ aDocOpt.SetStdPrecision(static_cast<sal_uInt16> (nValue));
+ pDoc->SetDocOptions(aDocOpt);
+ }
}
- break;
- case CELLTYPE_EDIT:
- {
- ((ScEditCell*)pCell)->GetString( rString );
-+ rFormatter.GetStringColor(nFormat, ppColor);
+diff --git sc/source/ui/view/output2.cxx sc/source/ui/view/output2.cxx
+index ef7f0c9..e51cda1 100644
+--- sc/source/ui/view/output2.cxx
++++ sc/source/ui/view/output2.cxx
+@@ -56,6 +56,7 @@
+ #include <svx/udlnitem.hxx>
+ #include <svx/unolingu.hxx>
+ #include <svtools/zforlist.hxx>
++#include <svtools/zformat.hxx>
+ #include <vcl/svapp.hxx>
+ #include <vcl/metric.hxx>
+ #include <vcl/outdev.hxx>
+@@ -111,6 +112,7 @@ class ScDrawStringsVars
+ String aString; // Inhalte
+ Size aTextSize;
+ long nOriginalWidth;
++ long nMaxDigitWidth;
+
+ ScBaseCell* pLastCell;
+ ULONG nValueFormat;
+@@ -135,7 +137,7 @@ public:
+ void SetPatternSimple( const ScPatternAttr* pNew, const SfxItemSet* pSet );
+
+ BOOL SetText( ScBaseCell* pCell ); // TRUE -> pOldPattern vergessen
+- void SetHashText();
++ void SetTextToWidthOrHash( ScBaseCell* pCell, long nWidth );
+ void SetAutoText( const String& rAutoText );
+
+ const ScPatternAttr* GetPattern() const { return pPattern; }
+@@ -164,6 +166,11 @@ public:
+ pCondSet->GetItemState( ATTR_FONT_HEIGHT, TRUE ); }
+
+ BOOL HasEditCharacters() const;
++
++private:
++ void SetHashText();
++ long GetMaxDigitWidth();
++ void TextChanged();
+ };
+
+ //==================================================================
+@@ -179,6 +186,7 @@ ScDrawStringsVars::ScDrawStringsVars(ScOutputData* pData, BOOL bPTL) :
+ nIndent ( 0 ),
+ bRotated ( FALSE ),
+ nOriginalWidth( 0 ),
++ nMaxDigitWidth( 0 ),
+ pLastCell ( NULL ),
+ nValueFormat( 0 ),
+ bLineBreak ( FALSE ),
+@@ -245,6 +253,7 @@ void ScDrawStringsVars::SetShrinkScale( long nScale, BYTE nScript )
+ void ScDrawStringsVars::SetPattern( const ScPatternAttr* pNew, const SfxItemSet* pSet,
+ ScBaseCell* pCell, BYTE nScript )
+ {
++ nMaxDigitWidth = 0;
+ pPattern = pNew;
+ pCondSet = pSet;
+
+@@ -396,6 +405,7 @@ void ScDrawStringsVars::SetPattern( const ScPatternAttr* pNew, const SfxItemSet*
+
+ void ScDrawStringsVars::SetPatternSimple( const ScPatternAttr* pNew, const SfxItemSet* pSet )
+ {
++ nMaxDigitWidth = 0;
+ // wird gerufen, wenn sich die Font-Variablen nicht aendern (!StringDiffer)
+
+ pPattern = pNew;
+@@ -470,28 +480,7 @@ BOOL ScDrawStringsVars::SetText( ScBaseCell* pCell )
+ pLastCell = NULL; // naechstes Mal wieder hierherkommen
}
- break;
- case CELLTYPE_VALUE:
+
+- OutputDevice* pRefDevice = pOutput->pRefDevice;
+- OutputDevice* pFmtDevice = pOutput->pFmtDevice;
+- aTextSize.Width() = pFmtDevice->GetTextWidth( aString );
+- aTextSize.Height() = pFmtDevice->GetTextHeight();
+-
+- if ( !pRefDevice->GetConnectMetaFile() || pRefDevice->GetOutDevType() == OUTDEV_PRINTER )
+- {
+- double fMul = pOutput->GetStretch();
+- aTextSize.Width() = (long)(aTextSize.Width() / fMul + 0.5);
+- }
+-
+- aTextSize.Height() = aMetric.GetAscent() + aMetric.GetDescent();
+- if ( GetOrient() != SVX_ORIENTATION_STANDARD )
+- {
+- long nTemp = aTextSize.Height();
+- aTextSize.Height() = aTextSize.Width();
+- aTextSize.Width() = nTemp;
+- }
+-
+- nOriginalWidth = aTextSize.Width();
+- if ( bPixelToLogic )
+- aTextSize = pRefDevice->LogicToPixel( aTextSize );
++ TextChanged();
+ }
+ // sonst String/Groesse behalten
+ }
+@@ -511,6 +500,52 @@ void ScDrawStringsVars::SetHashText()
+ SetAutoText( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("###")) );
+ }
+
++void ScDrawStringsVars::SetTextToWidthOrHash( ScBaseCell* pCell, long nWidth )
++{
++ if (!pCell)
++ return;
++
++ CellType eType = pCell->GetCellType();
++ if (eType != CELLTYPE_VALUE && eType != CELLTYPE_FORMULA)
++ // must be a value or formula cell.
++ return;
++
++ if (eType == CELLTYPE_FORMULA && !static_cast<ScFormulaCell*>(pCell)->IsValue())
++ // If it's formula, the result must be a value.
++ return;
++
++ ULONG nFormat = GetValueFormat();
++ if ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0)
++ {
++ // Not 'General' number format. Set hash text and bail out.
++ SetHashText();
++ return;
++ }
++
++ double fVal = (eType == CELLTYPE_VALUE) ?
++ static_cast<ScValueCell*>(pCell)->GetValue() : static_cast<ScFormulaCell*>(pCell)->GetValue();
++
++ const SvNumberformat* pNumFormat = pOutput->pDoc->GetFormatTable()->GetEntry(nFormat);
++ if (!pNumFormat)
++ return;
++
++ long nMaxDigit = GetMaxDigitWidth();
++ sal_uInt16 nNumDigits = static_cast<sal_uInt16>(nWidth / nMaxDigit);
++
++ if (!pNumFormat->GetOutputString(fVal, nNumDigits, aString))
++ // Failed to get output string. Bail out.
++ return;
++
++ if (pOutput->pFmtDevice->GetTextWidth(aString) > nWidth)
++ {
++ // Even after the decimal adjustment the text doesn't fit. Give up.
++ SetHashText();
++ return;
++ }
++
++ TextChanged();
++}
++
+ void ScDrawStringsVars::SetAutoText( const String& rAutoText )
+ {
+ aString = rAutoText;
+@@ -541,6 +576,47 @@ void ScDrawStringsVars::SetAutoText( const String& rAutoText )
+ pLastCell = NULL; // derselbe Text kann in der naechsten Zelle wieder passen
+ }
+
++long ScDrawStringsVars::GetMaxDigitWidth()
++{
++ if (nMaxDigitWidth > 0)
++ return nMaxDigitWidth;
++
++ sal_Char cZero = '0';
++ for (int i = 0; i < 10; ++i)
++ {
++ sal_Char cDigit = cZero + i;
++ long n = pOutput->pFmtDevice->GetTextWidth(String(cDigit));
++ nMaxDigitWidth = ::std::max(nMaxDigitWidth, n);
++ }
++ return nMaxDigitWidth;
++}
++
++void ScDrawStringsVars::TextChanged()
++{
++ OutputDevice* pRefDevice = pOutput->pRefDevice;
++ OutputDevice* pFmtDevice = pOutput->pFmtDevice;
++ aTextSize.Width() = pFmtDevice->GetTextWidth( aString );
++ aTextSize.Height() = pFmtDevice->GetTextHeight();
++
++ if ( !pRefDevice->GetConnectMetaFile() || pRefDevice->GetOutDevType() == OUTDEV_PRINTER )
++ {
++ double fMul = pOutput->GetStretch();
++ aTextSize.Width() = (long)(aTextSize.Width() / fMul + 0.5);
++ }
++
++ aTextSize.Height() = aMetric.GetAscent() + aMetric.GetDescent();
++ if ( GetOrient() != SVX_ORIENTATION_STANDARD )
++ {
++ long nTemp = aTextSize.Height();
++ aTextSize.Height() = aTextSize.Width();
++ aTextSize.Width() = nTemp;
++ }
++
++ nOriginalWidth = aTextSize.Width();
++ if ( bPixelToLogic )
++ aTextSize = pRefDevice->LogicToPixel( aTextSize );
++}
++
+ BOOL ScDrawStringsVars::HasEditCharacters() const
+ {
+ static const sal_Unicode pChars[] =
+@@ -922,29 +998,25 @@ BOOL ScOutputData::IsAvailable( SCCOL nX, SCROW nY )
+ // bCellIsValue: if set, don't extend into empty cells
+ // bBreak: if set, don't extend, and don't set clip marks (but rLeftClip/rRightClip is set)
+ // bOverwrite: if set, also extend into non-empty cells (for rotated text)
+-// rAlignRect: output: single or merged cell, used for alignment (visual rectangle)
+-// rClipRect: output: total output area, for clipping (visual)
+-// rLeftClip: output: need to clip at rClipRect left (visual) edge
+-// rRightClip: output: same for right
++// rParam output: various area parameters.
+
+ void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY,
+- SCCOL nCellX, SCROW nCellY, long nNeeded,
+- const ScPatternAttr& rPattern,
+- USHORT nHorJustify, BOOL bCellIsValue,
+- BOOL bBreak, BOOL bOverwrite,
+- Rectangle& rAlignRect, Rectangle& rClipRect,
+- BOOL& rLeftClip, BOOL& rRightClip )
++ SCCOL nCellX, SCROW nCellY, long nNeeded,
++ const ScPatternAttr& rPattern,
++ USHORT nHorJustify, bool bCellIsValue,
++ bool bBreak, bool bOverwrite,
++ OutputAreaParam& rParam )
+ {
+- // rThisRowInfo may be for a different row than nCellY, is still used for clip marks
++ // rThisRowInfo may be for a different row than nCellY, is still used for clip marks
+ RowInfo& rThisRowInfo = pRowInfo[nArrY];
+
+ long nLayoutSign = bLayoutRTL ? -1 : 1;
+
+- long nCellPosX = nPosX; // find nCellX position, starting at nX/nPosX
++ long nCellPosX = nPosX; // find nCellX position, starting at nX/nPosX
+ SCCOL nCompCol = nX;
+ while ( nCellX > nCompCol )
+ {
+- //! extra member function for width?
++ //! extra member function for width?
+ long nColWidth = ( nCompCol <= nX2 ) ?
+ pRowInfo[0].pCellInfo[nCompCol+1].nWidth :
+ (long) ( pDoc->GetColWidth( nCompCol, nTab ) * nPPTX );
+@@ -960,7 +1032,7 @@ void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY
+ nCellPosX -= nColWidth * nLayoutSign;
+ }
+
+- long nCellPosY = nPosY; // find nCellY position, starting at nArrY/nPosY
++ long nCellPosY = nPosY; // find nCellY position, starting at nArrY/nPosY
+ SCSIZE nCompArr = nArrY;
+ SCROW nCompRow = pRowInfo[nCompArr].nRowNo;
+ while ( nCellY > nCompRow )
+@@ -1005,28 +1077,30 @@ void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY
+ {
+ // take first row's height from row info
+ nMergeSizeY += rThisRowInfo.nHeight;
+- nDirect = 1; // skip in loop
++ nDirect = 1; // skip in loop
+ }
+ // following rows always from document
+ nMergeSizeY += (long) pDoc->GetScaledRowHeight( nCellY+nDirect, nCellY+nMergeRows-1, nTab, nPPTY);
+
+- --nMergeSizeX; // leave out the grid horizontally, also for alignment (align between grid lines)
++ --nMergeSizeX; // leave out the grid horizontally, also for alignment (align between grid lines)
++
++ rParam.mnColWidth = nMergeSizeX; // store the actual column width.
+
+ //
+ // construct the rectangles using logical left/right values (justify is called at the end)
+ //
+
+- // rAlignRect is the single cell or merged area, used for alignment.
++ // rAlignRect is the single cell or merged area, used for alignment.
+
+- rAlignRect.Left() = nCellPosX;
+- rAlignRect.Right() = nCellPosX + ( nMergeSizeX - 1 ) * nLayoutSign;
+- rAlignRect.Top() = nCellPosY;
+- rAlignRect.Bottom() = nCellPosY + nMergeSizeY - 1;
++ rParam.maAlignRect.Left() = nCellPosX;
++ rParam.maAlignRect.Right() = nCellPosX + ( nMergeSizeX - 1 ) * nLayoutSign;
++ rParam.maAlignRect.Top() = nCellPosY;
++ rParam.maAlignRect.Bottom() = nCellPosY + nMergeSizeY - 1;
+
+- // rClipRect is all cells that are used for output.
+- // For merged cells this is the same as rAlignRect, otherwise neighboring cells can also be used.
++ // rClipRect is all cells that are used for output.
++ // For merged cells this is the same as rAlignRect, otherwise neighboring cells can also be used.
+
+- rClipRect = rAlignRect;
++ rParam.maClipRect = rParam.maAlignRect;
+ if ( nNeeded > nMergeSizeX )
+ {
+ SvxCellHorJustify eHorJust = (SvxCellHorJustify)nHorJustify;
+@@ -1060,14 +1134,14 @@ void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY
+ SCCOL nLeftX = nCellX;
+ if ( !bMerged && !bCellIsValue && !bBreak )
+ {
+- // look for empty cells into which the text can be extended
++ // look for empty cells into which the text can be extended
+
+ while ( nRightMissing > 0 && nRightX < MAXCOL && ( bOverwrite || IsAvailable( nRightX+1, nCellY ) ) )
{
- double nValue = ((ScValueCell*)pCell)->GetValue();
-- rFormatter.GetInputLineString( nValue, nFormat, rString );
-+ rFormatter.GetInputLineString( nValue, nFormat, rString, ppColor );
+ ++nRightX;
+ long nAdd = (long) ( pDoc->GetColWidth( nRightX, nTab ) * nPPTX );
+ nRightMissing -= nAdd;
+- rClipRect.Right() += nAdd * nLayoutSign;
++ rParam.maClipRect.Right() += nAdd * nLayoutSign;
+
+ if ( rThisRowInfo.nRowNo == nCellY && nRightX >= nX1 && nRightX <= nX2 )
+ rThisRowInfo.pCellInfo[nRightX].bHideGrid = TRUE;
+@@ -1081,33 +1155,33 @@ void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY
+ --nLeftX;
+ long nAdd = (long) ( pDoc->GetColWidth( nLeftX, nTab ) * nPPTX );
+ nLeftMissing -= nAdd;
+- rClipRect.Left() -= nAdd * nLayoutSign;
++ rParam.maClipRect.Left() -= nAdd * nLayoutSign;
}
- break;
- case CELLTYPE_FORMULA:
-@@ -195,7 +200,7 @@ void ScCellFormat::GetInputString( ScBaseCell* pCell, ULONG nFormat, String& rSt
- else if (((ScFormulaCell*)pCell)->IsValue())
+ }
+
+- // Set flag and reserve space for clipping mark triangle,
+- // even if rThisRowInfo isn't for nCellY (merged cells).
++ // Set flag and reserve space for clipping mark triangle,
++ // even if rThisRowInfo isn't for nCellY (merged cells).
+ if ( nRightMissing > 0 && bMarkClipped && nRightX >= nX1 && nRightX <= nX2 && !bBreak && !bCellIsValue )
+ {
+ rThisRowInfo.pCellInfo[nRightX+1].nClipMark |= SC_CLIPMARK_RIGHT;
+ bAnyClipped = TRUE;
+ long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX );
+- rClipRect.Right() -= nMarkPixel * nLayoutSign;
++ rParam.maClipRect.Right() -= nMarkPixel * nLayoutSign;
+ }
+ if ( nLeftMissing > 0 && bMarkClipped && nLeftX >= nX1 && nLeftX <= nX2 && !bBreak && !bCellIsValue )
+ {
+ rThisRowInfo.pCellInfo[nLeftX+1].nClipMark |= SC_CLIPMARK_LEFT;
+ bAnyClipped = TRUE;
+ long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX );
+- rClipRect.Left() += nMarkPixel * nLayoutSign;
++ rParam.maClipRect.Left() += nMarkPixel * nLayoutSign;
+ }
+
+- rLeftClip = ( nLeftMissing > 0 );
+- rRightClip = ( nRightMissing > 0 );
++ rParam.mbLeftClip = ( nLeftMissing > 0 );
++ rParam.mbRightClip = ( nRightMissing > 0 );
+ }
+ else
+ {
+- rLeftClip = rRightClip = FALSE;
++ rParam.mbLeftClip = rParam.mbRightClip = FALSE;
+
+ // leave space for AutoFilter on screen
+ // (for automatic line break: only if not formatting for printer, as in ScColumn::GetNeededSize)
+@@ -1123,30 +1197,30 @@ void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY
+ // content fits even in the remaining area without the filter button
+ // -> align within that remaining area
+
+- rAlignRect.Right() -= nFilter * nLayoutSign;
+- rClipRect.Right() -= nFilter * nLayoutSign;
++ rParam.maAlignRect.Right() -= nFilter * nLayoutSign;
++ rParam.maClipRect.Right() -= nFilter * nLayoutSign;
+
+ // if a number doesn't fit, don't hide part of the number behind the button
+ // -> set clip flags, so "###" replacement is used (but also within the smaller area)
+
+ if ( !bFit )
+- rLeftClip = rRightClip = TRUE;
++ rParam.mbLeftClip = rParam.mbRightClip = TRUE;
+ }
+ }
+ }
+
+- // justify both rectangles for alignment calculation, use with DrawText etc.
++ // justify both rectangles for alignment calculation, use with DrawText etc.
+
+- rAlignRect.Justify();
+- rClipRect.Justify();
++ rParam.maAlignRect.Justify();
++ rParam.maClipRect.Justify();
+
+ #if 0
+ //! Test !!!
+ pDev->Push();
+ pDev->SetLineColor();
+ pDev->SetFillColor( COL_LIGHTGREEN );
+- pDev->DrawRect( pDev->PixelToLogic(rClipRect) );
+- pDev->DrawRect( rClipRect ); // print preview
++ pDev->DrawRect( pDev->PixelToLogic(rParam.maClipRect) );
++ pDev->DrawRect( rParam.maClipRect ); // print preview
+ pDev->Pop();
+ //! Test !!!
+ #endif
+@@ -1187,12 +1261,9 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic )
+ --nLoopStartX; // start before nX1 for rest of long text to the left
+
+ // variables for GetOutputArea
++ OutputAreaParam aAreaParam;
+ BOOL bCellIsValue = FALSE;
+- BOOL bLeftClip = FALSE;
+- BOOL bRightClip = FALSE;
+ long nNeededWidth = 0;
+- Rectangle aAlignRect;
+- Rectangle aClipRect;
+ SvxCellHorJustify eOutHorJust = SVX_HOR_JUSTIFY_STANDARD;
+ const ScPatternAttr* pPattern = NULL;
+ const SfxItemSet* pCondSet = NULL;
+@@ -1363,6 +1434,7 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic )
+ bNeedEdit = aVars.HasEditCharacters() ||
+ (bFormulaCell && ((ScFormulaCell*)pCell)->IsMultilineResult());
+ }
++ long nTotalMargin = 0;
+ if (bDoCell && !bNeedEdit)
{
- double nValue = ((ScFormulaCell*)pCell)->GetValue();
-- rFormatter.GetInputLineString( nValue, nFormat, rString );
-+ rFormatter.GetInputLineString( nValue, nFormat, rString, ppColor );
+ CellType eCellType = pCell->GetCellType();
+@@ -1384,14 +1456,17 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic )
+ BOOL bRepeat = aVars.IsRepeat() && !bBreak;
+ BOOL bShrink = aVars.IsShrink() && !bBreak && !bRepeat;
+
+- long nTotalMargin = (long) ( aVars.GetLeftTotal() * nPPTX ) +
+- (long) ( aVars.GetMargin()->GetRightMargin() * nPPTX );
++ nTotalMargin =
++ static_cast<long>(aVars.GetLeftTotal() * nPPTX) +
++ static_cast<long>(aVars.GetMargin()->GetRightMargin() * nPPTX);
++
+ nNeededWidth = aVars.GetTextSize().Width() + nTotalMargin;
++
+ // GetOutputArea gives justfied rectangles
+ GetOutputArea( nX, nArrY, nPosX, nPosY, nCellX, nCellY, nNeededWidth,
+- *pPattern, sal::static_int_cast<USHORT>(eOutHorJust),
+- bCellIsValue || bRepeat || bShrink, bBreak, FALSE,
+- aAlignRect, aClipRect, bLeftClip, bRightClip );
++ *pPattern, sal::static_int_cast<USHORT>(eOutHorJust),
++ bCellIsValue || bRepeat || bShrink, bBreak, FALSE,
++ aAreaParam );
+
+ if ( bShrink )
+ {
+@@ -1401,9 +1476,9 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic )
+ // DrawEdit is used to vertically scale 90 deg rotated text.
+ bNeedEdit = TRUE;
+ }
+- else if ( bLeftClip || bRightClip ) // horizontal
++ else if ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) // horizontal
+ {
+- long nAvailable = aAlignRect.GetWidth() - nTotalMargin;
++ long nAvailable = aAreaParam.maAlignRect.GetWidth() - nTotalMargin;
+ long nScaleSize = aVars.GetTextSize().Width(); // without margin
+
+ if ( nScaleSize > 0 ) // 0 if the text is empty (formulas, number formats)
+@@ -1427,16 +1502,16 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic )
+ // If even at half the size the font still isn't rendered smaller,
+ // fall back to normal clipping (showing ### for numbers).
+ if ( nNewSize <= nAvailable )
+- bLeftClip = bRightClip = FALSE;
++ aAreaParam.mbLeftClip = aAreaParam.mbRightClip = FALSE;
+
+ pOldPattern = NULL;
+ }
+ }
+ }
+
+- if ( bRepeat && !bLeftClip && !bRightClip )
++ if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip )
+ {
+- long nAvailable = aAlignRect.GetWidth() - nTotalMargin;
++ long nAvailable = aAreaParam.maAlignRect.GetWidth() - nTotalMargin;
+ long nRepeatSize = aVars.GetTextSize().Width(); // without margin
+ // When formatting for the printer, the text sizes don't always add up.
+ // Round down (too few repetitions) rather than exceeding the cell size then:
+@@ -1460,13 +1535,13 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic )
+ if ( bBreak )
+ {
+ if ( aVars.GetOrient() == SVX_ORIENTATION_STANDARD )
+- bNeedEdit = ( bLeftClip || bRightClip );
++ bNeedEdit = ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip );
+ else
+ {
+ long nHeight = aVars.GetTextSize().Height() +
+ (long)(aVars.GetMargin()->GetTopMargin()*nPPTY) +
+ (long)(aVars.GetMargin()->GetBottomMargin()*nPPTY);
+- bNeedEdit = ( nHeight > aClipRect.GetHeight() );
++ bNeedEdit = ( nHeight > aAreaParam.maClipRect.GetHeight() );
+ }
+ }
+ }
+@@ -1482,48 +1557,49 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic )
}
- else
+ if ( bDoCell )
{
-diff --git sc/source/ui/view/output2.cxx sc/source/ui/view/output2.cxx
-index 8942a38..5826bb1 100644
---- sc/source/ui/view/output2.cxx
-+++ sc/source/ui/view/output2.cxx
-@@ -454,12 +454,20 @@ BOOL ScDrawStringsVars::SetText( ScBaseCell* pCell )
-
- Color* pColor;
- ULONG nFormat = GetValueFormat();
-- ScCellFormat::GetString( pCell,
-- nFormat, aString, &pColor,
-- *pFormatter,
-- pOutput->bShowNullValues,
-- pOutput->bShowFormulas,
-- ftCheck );
-+
-+ if (static_cast<NfIndexTableOffset>(nFormat) == NF_NUMBER_STANDARD)
-+ // For 'General' format type, display the value the same way it
-+ // is displayed in the edit window, which automatically
-+ // adjusts the number of decimal places based on the value of
-+ // the cell.
-+ ScCellFormat::GetInputString(pCell, nFormat, aString, *pFormatter, &pColor);
-+ else
-+ ScCellFormat::GetString( pCell,
-+ nFormat, aString, &pColor,
-+ *pFormatter,
-+ pOutput->bShowNullValues,
-+ pOutput->bShowFormulas,
-+ ftCheck );
-
- if (aString.Len() > DRAWTEXT_MAX)
- aString.Erase(DRAWTEXT_MAX);
+- if ( bCellIsValue && ( bLeftClip || bRightClip ) )
++ if ( bCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
+ {
+- aVars.SetHashText();
++ // Adjust the decimals to fit the available column width.
++ aVars.SetTextToWidthOrHash(pCell, aAreaParam.mnColWidth - nTotalMargin);
+ nNeededWidth = aVars.GetTextSize().Width() +
+ (long) ( aVars.GetLeftTotal() * nPPTX ) +
+ (long) ( aVars.GetMargin()->GetRightMargin() * nPPTX );
+- if ( nNeededWidth <= aClipRect.GetWidth() )
+- bLeftClip = bRightClip = FALSE;
++ if ( nNeededWidth <= aAreaParam.maClipRect.GetWidth() )
++ aAreaParam.mbLeftClip = aAreaParam.mbRightClip = FALSE;
+
+ // If the "###" replacement doesn't fit into the cells, no clip marks
+ // are shown, as the "###" already denotes too little space.
+ // The rectangles from the first GetOutputArea call remain valid.
+ }
+
+- long nJustPosX = aAlignRect.Left(); // "justified" - effect of alignment will be added
+- long nJustPosY = aAlignRect.Top();
+- long nAvailWidth = aAlignRect.GetWidth();
+- long nOutHeight = aAlignRect.GetHeight();
++ long nJustPosX = aAreaParam.maAlignRect.Left(); // "justified" - effect of alignment will be added
++ long nJustPosY = aAreaParam.maAlignRect.Top();
++ long nAvailWidth = aAreaParam.maAlignRect.GetWidth();
++ long nOutHeight = aAreaParam.maAlignRect.GetHeight();
+
+- BOOL bOutside = ( aClipRect.Right() < nScrX || aClipRect.Left() >= nScrX + nScrW );
+- if ( aClipRect.Left() < nScrX )
++ BOOL bOutside = ( aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW );
++ if ( aAreaParam.maClipRect.Left() < nScrX )
+ {
+- aClipRect.Left() = nScrX;
+- bLeftClip = TRUE;
++ aAreaParam.maClipRect.Left() = nScrX;
++ aAreaParam.mbLeftClip = TRUE;
+ }
+- if ( aClipRect.Right() > nScrX + nScrW )
++ if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
+ {
+- aClipRect.Right() = nScrX + nScrW; //! minus one?
+- bRightClip = TRUE;
++ aAreaParam.maClipRect.Right() = nScrX + nScrW; //! minus one?
++ aAreaParam.mbRightClip = TRUE;
+ }
+
+- BOOL bHClip = bLeftClip || bRightClip;
++ BOOL bHClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
+ BOOL bVClip = FALSE;
+
+- if ( aClipRect.Top() < nScrY )
++ if ( aAreaParam.maClipRect.Top() < nScrY )
+ {
+- aClipRect.Top() = nScrY;
++ aAreaParam.maClipRect.Top() = nScrY;
+ bVClip = TRUE;
+ }
+- if ( aClipRect.Bottom() > nScrY + nScrH )
++ if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
+ {
+- aClipRect.Bottom() = nScrY + nScrH; //! minus one?
++ aAreaParam.maClipRect.Bottom() = nScrY + nScrH; //! minus one?
+ bVClip = TRUE;
+ }
+
+@@ -1606,27 +1682,27 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic )
+
+ if (!bHClip)
+ {
+- aClipRect.Left() = nScrX;
+- aClipRect.Right() = nScrX+nScrW;
++ aAreaParam.maClipRect.Left() = nScrX;
++ aAreaParam.maClipRect.Right() = nScrX+nScrW;
+ }
+ if (!bVClip)
+ {
+- aClipRect.Top() = nScrY;
+- aClipRect.Bottom() = nScrY+nScrH;
++ aAreaParam.maClipRect.Top() = nScrY;
++ aAreaParam.maClipRect.Bottom() = nScrY+nScrH;
+ }
+
+ // aClipRect is not used after SetClipRegion/IntersectClipRegion,
+ // so it can be modified here
+ if (bPixelToLogic)
+- aClipRect = pRefDevice->PixelToLogic( aClipRect );
++ aAreaParam.maClipRect = pRefDevice->PixelToLogic( aAreaParam.maClipRect );
+
+ if (bMetaFile)
+ {
+ pDev->Push();
+- pDev->IntersectClipRegion( aClipRect );
++ pDev->IntersectClipRegion( aAreaParam.maClipRect );
+ }
+ else
+- pDev->SetClipRegion( Region( aClipRect ) );
++ pDev->SetClipRegion( Region( aAreaParam.maClipRect ) );
+ }
+
+ Point aURLStart( nJustPosX, nJustPosY ); // copy before modifying for orientation
+@@ -1830,7 +1906,7 @@ long lcl_GetEditSize( EditEngine& rEngine, BOOL bWidth, BOOL bSwap, long nAttrRo
+ void ScOutputData::ShrinkEditEngine( EditEngine& rEngine, const Rectangle& rAlignRect,
+ long nLeftM, long nTopM, long nRightM, long nBottomM,
+ BOOL bWidth, USHORT nOrient, long nAttrRotate, BOOL bPixelToLogic,
+- long& rEngineWidth, long& rEngineHeight, long& rNeededPixel, BOOL& rLeftClip, BOOL& rRightClip )
++ long& rEngineWidth, long& rEngineHeight, long& rNeededPixel, bool& rLeftClip, bool& rRightClip )
+ {
+ if ( !bWidth )
+ {
+@@ -2152,10 +2228,7 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic)
+ nPosY = nScrY;
+ }
+
+- Rectangle aAlignRect;
+- Rectangle aClipRect;
+- BOOL bLeftClip = FALSE;
+- BOOL bRightClip = FALSE;
++ OutputAreaParam aAreaParam;
+
+ //
+ // Initial page size - large for normal text, cell size for automatic line breaks
+@@ -2170,23 +2243,22 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic)
+
+ //! handle nArrY == 0
+ GetOutputArea( nXForPos, nArrYForPos, nPosX, nPosY, nCellX, nCellY, 0,
+- *pPattern, sal::static_int_cast<USHORT>(eOutHorJust),
+- bCellIsValue, TRUE, FALSE,
+- aAlignRect, aClipRect, bLeftClip, bRightClip );
++ *pPattern, sal::static_int_cast<USHORT>(eOutHorJust),
++ bCellIsValue, true, false, aAreaParam );
+
+ //! special ScEditUtil handling if formatting for printer
+
+ if ( eOrient == SVX_ORIENTATION_TOPBOTTOM || eOrient == SVX_ORIENTATION_BOTTOMTOP )
+- aPaperSize.Width() = aAlignRect.GetHeight() - nTopM - nBottomM;
++ aPaperSize.Width() = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
+ else
+- aPaperSize.Width() = aAlignRect.GetWidth() - nLeftM - nRightM;
++ aPaperSize.Width() = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
+
+ if (bAsianVertical && bBreak)
+ {
+ // add some extra height (default margin value) for safety
+ // as long as GetEditArea isn't used below
+ long nExtraHeight = (long)( 20 * nPPTY );
+- aPaperSize.Height() = aAlignRect.GetHeight() - nTopM - nBottomM + nExtraHeight;
++ aPaperSize.Height() = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM + nExtraHeight;
+ }
+ }
+ if (bPixelToLogic)
+@@ -2375,26 +2447,26 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic)
+ {
+ // for break, the first GetOutputArea call is sufficient
+ GetOutputArea( nXForPos, nArrYForPos, nPosX, nPosY, nCellX, nCellY, nNeededPixel,
+- *pPattern, sal::static_int_cast<USHORT>(eOutHorJust),
+- bCellIsValue || bRepeat || bShrink, FALSE, FALSE,
+- aAlignRect, aClipRect, bLeftClip, bRightClip );
++ *pPattern, sal::static_int_cast<USHORT>(eOutHorJust),
++ bCellIsValue || bRepeat || bShrink, false, false, aAreaParam );
+
+ if ( bShrink )
+ {
+ BOOL bWidth = ( eOrient == SVX_ORIENTATION_STANDARD && !bAsianVertical );
+- ShrinkEditEngine( *pEngine, aAlignRect,
++ ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect,
+ nLeftM, nTopM, nRightM, nBottomM, bWidth,
+ sal::static_int_cast<USHORT>(eOrient), 0, bPixelToLogic,
+- nEngineWidth, nEngineHeight, nNeededPixel, bLeftClip, bRightClip );
++ nEngineWidth, nEngineHeight, nNeededPixel,
++ aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
+ }
+
+- if ( bRepeat && !bLeftClip && !bRightClip && pEngine->GetParagraphCount() == 1 )
++ if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && pEngine->GetParagraphCount() == 1 )
+ {
+ // First check if twice the space for the formatted text is available
+ // (otherwise just keep it unchanged).
+
+ long nFormatted = nNeededPixel - nLeftM - nRightM; // without margin
+- long nAvailable = aAlignRect.GetWidth() - nLeftM - nRightM;
++ long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
+ if ( nAvailable >= 2 * nFormatted )
+ {
+ // "repeat" is handled with unformatted text (for performance reasons)
+@@ -2428,7 +2500,7 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic)
+ }
+ }
+
+- if ( bCellIsValue && ( bLeftClip || bRightClip ) )
++ if ( bCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
+ {
+ pEngine->SetText( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("###")) );
+ nEngineWidth = (long) pEngine->CalcTextWidth();
+@@ -2451,11 +2523,11 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic)
+ }
+ }
+
+- long nStartX = aAlignRect.Left();
+- long nStartY = aAlignRect.Top();
+- long nCellWidth = aAlignRect.GetWidth();
++ long nStartX = aAreaParam.maAlignRect.Left();
++ long nStartY = aAreaParam.maAlignRect.Top();
++ long nCellWidth = aAreaParam.maAlignRect.GetWidth();
+ long nOutWidth = nCellWidth - 1 - nLeftM - nRightM;
+- long nOutHeight = aAlignRect.GetHeight() - nTopM - nBottomM;
++ long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
+
+ if ( bBreak || eOrient != SVX_ORIENTATION_STANDARD || bAsianVertical )
+ {
+@@ -2475,21 +2547,21 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic)
+ nStartX += nLeftM;
+ }
+
+- BOOL bOutside = ( aClipRect.Right() < nScrX || aClipRect.Left() >= nScrX + nScrW );
+- if ( aClipRect.Left() < nScrX )
++ BOOL bOutside = ( aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW );
++ if ( aAreaParam.maClipRect.Left() < nScrX )
+ {
+- aClipRect.Left() = nScrX;
+- bLeftClip = TRUE;
++ aAreaParam.maClipRect.Left() = nScrX;
++ aAreaParam.mbLeftClip = true;
+ }
+- if ( aClipRect.Right() > nScrX + nScrW )
++ if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
+ {
+- aClipRect.Right() = nScrX + nScrW; //! minus one?
+- bRightClip = TRUE;
++ aAreaParam.maClipRect.Right() = nScrX + nScrW; //! minus one?
++ aAreaParam.mbRightClip = true;
+ }
+
+ if ( !bHidden && !bOutside )
+ {
+- BOOL bClip = bLeftClip || bRightClip;
++ bool bClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
+ BOOL bSimClip = FALSE;
+
+ if ( bWrapFields )
+@@ -2498,14 +2570,14 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic)
+ bClip = TRUE;
+ }
+
+- if ( aClipRect.Top() < nScrY )
++ if ( aAreaParam.maClipRect.Top() < nScrY )
+ {
+- aClipRect.Top() = nScrY;
++ aAreaParam.maClipRect.Top() = nScrY;
+ bClip = TRUE;
+ }
+- if ( aClipRect.Bottom() > nScrY + nScrH )
++ if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
+ {
+- aClipRect.Bottom() = nScrY + nScrH; //! minus one?
++ aAreaParam.maClipRect.Bottom() = nScrY + nScrH; //! minus one?
+ bClip = TRUE;
+ }
+
+@@ -2557,8 +2629,8 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic)
+ bAnyClipped = TRUE;
+
+ long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX );
+- if ( aClipRect.Right() - nMarkPixel > aClipRect.Left() )
+- aClipRect.Right() -= nMarkPixel;
++ if ( aAreaParam.maClipRect.Right() - nMarkPixel > aAreaParam.maClipRect.Left() )
++ aAreaParam.maClipRect.Right() -= nMarkPixel;
+ }
+ }
+
+@@ -2582,9 +2654,9 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic)
+ // Clip marks are already handled in GetOutputArea
+
+ if (bPixelToLogic)
+- aLogicClip = pRefDevice->PixelToLogic( aClipRect );
++ aLogicClip = pRefDevice->PixelToLogic( aAreaParam.maClipRect );
+ else
+- aLogicClip = aClipRect;
++ aLogicClip = aAreaParam.maClipRect;
+
+ if (bClip) // bei bSimClip nur aClipRect initialisieren
+ {
+@@ -3218,10 +3290,7 @@ void ScOutputData::DrawRotated(BOOL bPixelToLogic)
+
+ // use GetOutputArea to hide the grid
+ // (clip region is done manually below)
+- BOOL bLeftClip = FALSE;
+- BOOL bRightClip = FALSE;
+- Rectangle aAlignRect;
+- Rectangle aClipRect;
++ OutputAreaParam aAreaParam;
+
+ SCCOL nCellX = nX;
+ SCROW nCellY = nY;
+@@ -3234,8 +3303,7 @@ void ScOutputData::DrawRotated(BOOL bPixelToLogic)
+
+ GetOutputArea( nX, nArrY, nCellStartX, nPosY, nCellX, nCellY, nNeededWidth,
+ *pPattern, sal::static_int_cast<USHORT>(eOutHorJust),
+- FALSE, FALSE, TRUE,
+- aAlignRect, aClipRect, bLeftClip, bRightClip );
++ FALSE, FALSE, TRUE, aAreaParam );
+
+ if ( bShrink )
+ {
+@@ -3243,19 +3311,19 @@ void ScOutputData::DrawRotated(BOOL bPixelToLogic)
+ pRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width() : nEngineWidth;
+ long nNeededPixel = nPixelWidth + nLeftM + nRightM;
+
+- bLeftClip = bRightClip = TRUE;
++ aAreaParam.mbLeftClip = aAreaParam.mbRightClip = TRUE;
+
+ // always do height
+- ShrinkEditEngine( *pEngine, aAlignRect, nLeftM, nTopM, nRightM, nBottomM,
++ ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect, nLeftM, nTopM, nRightM, nBottomM,
+ FALSE, sal::static_int_cast<USHORT>(eOrient), nAttrRotate, bPixelToLogic,
+- nEngineWidth, nEngineHeight, nNeededPixel, bLeftClip, bRightClip );
++ nEngineWidth, nEngineHeight, nNeededPixel, aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
+
+ if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
+ {
+ // do width only if rotating within the cell (standard mode)
+- ShrinkEditEngine( *pEngine, aAlignRect, nLeftM, nTopM, nRightM, nBottomM,
++ ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect, nLeftM, nTopM, nRightM, nBottomM,
+ TRUE, sal::static_int_cast<USHORT>(eOrient), nAttrRotate, bPixelToLogic,
+- nEngineWidth, nEngineHeight, nNeededPixel, bLeftClip, bRightClip );
++ nEngineWidth, nEngineHeight, nNeededPixel, aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
+ }
+
+ // nEngineWidth/nEngineHeight is updated in ShrinkEditEngine
+@@ -3309,19 +3377,19 @@ void ScOutputData::DrawRotated(BOOL bPixelToLogic)
+ }
+
+ if (bPixelToLogic)
+- aClipRect = pRefDevice->PixelToLogic( Rectangle(
++ aAreaParam.maClipRect = pRefDevice->PixelToLogic( Rectangle(
+ Point(nClipStartX,nClipStartY), aClipSize ) );
+ else
+- aClipRect = Rectangle(Point(nClipStartX, nClipStartY),
++ aAreaParam.maClipRect = Rectangle(Point(nClipStartX, nClipStartY),
+ aClipSize ); // Scale = 1
+
+ if (bMetaFile)
+ {
+ pDev->Push();
+- pDev->IntersectClipRegion( aClipRect );
++ pDev->IntersectClipRegion( aAreaParam.maClipRect );
+ }
+ else
+- pDev->SetClipRegion( Region( aClipRect ) );
++ pDev->SetClipRegion( Region( aAreaParam.maClipRect ) );
+ }
+
+ Point aLogicStart;
diff --git a/patches/dev300/calc-general-type-auto-decimal-svtools.diff b/patches/dev300/calc-general-type-auto-decimal-svtools.diff
index a0c0111..4de3095 100644
--- a/patches/dev300/calc-general-type-auto-decimal-svtools.diff
+++ b/patches/dev300/calc-general-type-auto-decimal-svtools.diff
@@ -1,122 +1,332 @@
diff --git svtools/inc/svtools/zforlist.hxx svtools/inc/svtools/zforlist.hxx
-index bb4a589..069930e 100644
+index bb4a589..2ae53fc 100644
--- svtools/inc/svtools/zforlist.hxx
+++ svtools/inc/svtools/zforlist.hxx
-@@ -492,11 +492,16 @@ public:
- void GetOutputString( String& sString, sal_uInt32 nFIndex,
- String& sOutString, Color** ppColor );
-
-+ void GetStringColor( sal_uInt32 nFIndex, Color** ppColor );
-+
- /** Format a number according to the standard default format matching
- the given format index */
- void GetInputLineString( const double& fOutNumber,
- sal_uInt32 nFIndex, String& sOutString );
+@@ -336,6 +336,11 @@ class SvNumberFormatterRegistry_Impl;
+ class SVT_DLLPUBLIC SvNumberFormatter
+ {
+ public:
++ /**
++ * We can't technically have an "infinite" value, so we use an arbitrary
++ * upper precision threshold to represent the "unlimited" precision.
++ */
++ static const sal_uInt16 UNLIMITED_PRECISION;
-+ void GetInputLineString( const double& fOutNumber,
-+ sal_uInt32 nFIndex, String& sOutString, Color** ppColor );
-+
- /** Format a number according to a format code string to be scanned.
- @return
- <FALSE/> if format code contains an error
+ /// Preferred ctor with service manager and language/country enum
+ SvNumberFormatter(
+@@ -586,7 +591,7 @@ public:
+ /// Return the reference date
+ Date* GetNullDate();
+ /// Return the standard decimal precision
+- short GetStandardPrec();
++ sal_uInt16 GetStandardPrec();
+ /// Return whether zero suppression is switched on
+ BOOL GetNoZero() { return bNoZero; }
+ /** Get the type of a format (or NUMBERFORMAT_UNDEFINED if no entry),
diff --git svtools/inc/svtools/zformat.hxx svtools/inc/svtools/zformat.hxx
-index 4c52b10..d502bb6 100644
+index 4c52b10..8158524 100644
--- svtools/inc/svtools/zformat.hxx
+++ svtools/inc/svtools/zformat.hxx
-@@ -241,6 +241,7 @@ public:
+@@ -239,6 +239,12 @@ public:
+ // in fact that could be any string used in number formats.
+ static void LoadString( SvStream& rStream, String& rStr );
++ /**
++ * Get output string from a numeric value that fits the number of
++ * characters specified.
++ */
++ bool GetOutputString( double fNumber, sal_uInt16 nCharCount, String& rOutString ) const;
++
BOOL GetOutputString( double fNumber, String& OutString, Color** ppColor );
BOOL GetOutputString( String& sString, String& OutString, Color** ppColor );
-+ void GetStringColor( Color** ppColor );
- // True if type text
- BOOL IsTextFormat() const { return (eType & NUMBERFORMAT_TEXT) != 0; }
+@@ -490,6 +496,7 @@ private:
+
+ // standard number output
+ SVT_DLLPRIVATE void ImpGetOutputStandard( double& fNumber, String& OutString );
++ SVT_DLLPRIVATE void ImpGetOutputStdToPrecision( double& rNumber, String& rOutString, sal_uInt16 nPrecision ) const;
+ // numbers in input line
+ SVT_DLLPRIVATE void ImpGetOutputInputLine( double fNumber, String& OutString );
+
diff --git svtools/source/numbers/zforlist.cxx svtools/source/numbers/zforlist.cxx
-index 4b13774..ceedb05 100644
+index 4b13774..85807ce 100644
--- svtools/source/numbers/zforlist.cxx
+++ svtools/source/numbers/zforlist.cxx
-@@ -1488,9 +1488,16 @@ void SvNumberFormatter::GetInputLineString(const double& fOutNumber,
- sal_uInt32 nFIndex,
- String& sOutString)
- {
-+ Color* pColor;
-+ GetInputLineString(fOutNumber, nFIndex, sOutString, &pColor);
-+}
+@@ -70,6 +70,7 @@
+ #include <rtl/instance.hxx>
+
+ #include <math.h>
++#include <limits>
+
+ using namespace ::com::sun::star;
+ using namespace ::com::sun::star::uno;
+@@ -192,6 +193,8 @@ SV_IMPL_PTRARR( NfWSStringsDtor, String* );
+
+ /***********************Funktionen SvNumberFormatter**************************/
+
++const sal_uInt16 SvNumberFormatter::UNLIMITED_PRECISION = ::std::numeric_limits<sal_uInt16>::max();
+
-+void SvNumberFormatter::GetInputLineString(const double& fOutNumber,
-+ sal_uInt32 nFIndex,
-+ String& sOutString, Color** ppColor)
-+{
- SvNumberformat* pFormat;
- short nOldPrec;
-- Color* pColor;
- pFormat = (SvNumberformat*) aFTable.Get(nFIndex);
- if (!pFormat)
- pFormat = aFTable.Get(ZF_STANDARD);
-@@ -1531,7 +1538,13 @@ void SvNumberFormatter::GetInputLineString(const double& fOutNumber,
+ SvNumberFormatter::SvNumberFormatter(
+ const Reference< XMultiServiceFactory >& xSMgr,
+ LanguageType eLang )
+@@ -352,7 +355,7 @@ void SvNumberFormatter::ChangeStandardPrec(short nPrec)
+ pFormatScanner->ChangeStandardPrec(nPrec);
+ }
+
+-short SvNumberFormatter::GetStandardPrec()
++sal_uInt16 SvNumberFormatter::GetStandardPrec()
+ {
+ return pFormatScanner->GetStandardPrec();
+ }
+@@ -1508,7 +1511,7 @@ void SvNumberFormatter::GetInputLineString(const double& fOutNumber,
+ if (eType != NUMBERFORMAT_PERCENT) // spaeter Sonderbehandlung %
+ eType = NUMBERFORMAT_NUMBER;
+ nOldPrec = pFormatScanner->GetStandardPrec();
+- ChangeStandardPrec(300); // Merkwert
++ ChangeStandardPrec(UNLIMITED_PRECISION); // Merkwert
+ }
+ sal_uInt32 nKey = nFIndex;
+ switch ( eType )
+@@ -1529,7 +1532,7 @@ void SvNumberFormatter::GetInputLineString(const double& fOutNumber,
+ if ( eType == NUMBERFORMAT_TIME && pFormat->GetFormatPrecision() )
+ {
nOldPrec = pFormatScanner->GetStandardPrec();
- ChangeStandardPrec(300); // Merkwert
+- ChangeStandardPrec(300); // Merkwert
++ ChangeStandardPrec(UNLIMITED_PRECISION); // Merkwert
}
-- pFormat->GetOutputString(fOutNumber, sOutString, &pColor);
-+ if (ppColor)
-+ pFormat->GetOutputString(fOutNumber, sOutString, ppColor);
-+ else
-+ {
-+ Color* pColor; // throw away the color info.
-+ pFormat->GetOutputString(fOutNumber, sOutString, &pColor);
-+ }
+ pFormat->GetOutputString(fOutNumber, sOutString, &pColor);
}
- if (nOldPrec != -1)
- ChangeStandardPrec(nOldPrec);
-@@ -1574,6 +1587,21 @@ void SvNumberFormatter::GetOutputString(String& sString,
+diff --git svtools/source/numbers/zformat.cxx svtools/source/numbers/zformat.cxx
+index 368fb16..2be8168 100644
+--- svtools/source/numbers/zformat.cxx
++++ svtools/source/numbers/zformat.cxx
+@@ -57,6 +57,9 @@
+ #include "numhead.hxx"
+ #include <unotools/digitgroupingiterator.hxx>
+ #include "nfsymbol.hxx"
++
++#include <cmath>
++
+ using namespace svt;
+
+ namespace {
+@@ -66,6 +69,9 @@ struct Gregorian
+ return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("gregorian"));
}
+ };
++
++const sal_uInt16 UPPER_PRECISION = 300; // entirely arbitrary...
++
}
-+void SvNumberFormatter::GetStringColor( sal_uInt32 nFIndex, Color** ppColor)
+ const double _D_MAX_U_LONG_ = (double) 0xffffffff; // 4294967295.0
+@@ -1777,47 +1783,62 @@ void SvNumberformat::Build50Formatstring( String& rStr ) const
+
+ void SvNumberformat::ImpGetOutputStandard(double& fNumber, String& OutString)
+ {
+- USHORT nStandardPrec = rScan.GetStandardPrec();
++ sal_uInt16 nStandardPrec = rScan.GetStandardPrec();
++
+ if ( fabs(fNumber) > 1.0E15 ) // #58531# war E16
++ {
++ nStandardPrec = ::std::min(nStandardPrec, static_cast<sal_uInt16>(14)); // limits to 14 decimals
+ OutString = ::rtl::math::doubleToUString( fNumber,
+ rtl_math_StringFormat_E, nStandardPrec /*2*/,
+ GetFormatter().GetNumDecimalSep().GetChar(0));
++ }
+ else
+- {
++ ImpGetOutputStdToPrecision(fNumber, OutString, nStandardPrec);
++}
++
++void SvNumberformat::ImpGetOutputStdToPrecision(double& rNumber, String& rOutString, sal_uInt16 nPrecision) const
+{
-+ if (!ppColor)
-+ return;
++ // Make sure the precision doesn't go over the maximum allowable precision.
++ nPrecision = ::std::min(UPPER_PRECISION, nPrecision);
+
-+ SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(nFIndex);
-+ if (!pFormat)
-+ pFormat = aFTable.Get(ZF_STANDARD_TEXT);
+ #if 0
+ {
+- // debugger test case for ANSI standard correctness
+- ::rtl::OUString aTest;
+- // expect 0.00123 OK
+- aTest = ::rtl::math::doubleToUString( 0.001234567,
+- rtl_math_StringFormat_G, 3, '.', sal_True );
+- // expect 123 OK
+- aTest = ::rtl::math::doubleToUString( 123.4567,
+- rtl_math_StringFormat_G, 3, '.', sal_True );
+- // expect 123.5 OK
+- aTest = ::rtl::math::doubleToUString( 123.4567,
+- rtl_math_StringFormat_G, 4, '.', sal_True );
+- // expect 1e+03 (as 999.6 rounded to 3 significant digits results in
+- // 1000 with an exponent equal to significant digits)
+- // Currently (24-Jan-2003) we do fail in this case and output 1000
+- // instead, negligible.
+- aTest = ::rtl::math::doubleToUString( 999.6,
+- rtl_math_StringFormat_G, 3, '.', sal_True );
+- // expect what? result is 1.2e+004
+- aTest = ::rtl::math::doubleToUString( 12345.6789,
+- rtl_math_StringFormat_G, -3, '.', sal_True );
++ // debugger test case for ANSI standard correctness
++ ::rtl::OUString aTest;
++ // expect 0.00123 OK
++ aTest = ::rtl::math::doubleToUString( 0.001234567,
++ rtl_math_StringFormat_G, 3, '.', sal_True );
++ // expect 123 OK
++ aTest = ::rtl::math::doubleToUString( 123.4567,
++ rtl_math_StringFormat_G, 3, '.', sal_True );
++ // expect 123.5 OK
++ aTest = ::rtl::math::doubleToUString( 123.4567,
++ rtl_math_StringFormat_G, 4, '.', sal_True );
++ // expect 1e+03 (as 999.6 rounded to 3 significant digits results in
++ // 1000 with an exponent equal to significant digits)
++ // Currently (24-Jan-2003) we do fail in this case and output 1000
++ // instead, negligible.
++ aTest = ::rtl::math::doubleToUString( 999.6,
++ rtl_math_StringFormat_G, 3, '.', sal_True );
++ // expect what? result is 1.2e+004
++ aTest = ::rtl::math::doubleToUString( 12345.6789,
++ rtl_math_StringFormat_G, -3, '.', sal_True );
+ }
+ #endif
+
+- OutString = ::rtl::math::doubleToUString( fNumber,
+- rtl_math_StringFormat_F, nStandardPrec /*2*/,
+- GetFormatter().GetNumDecimalSep().GetChar(0), sal_True );
+- if (OutString.GetChar(0) == '-' &&
+- OutString.GetTokenCount('0') == OutString.Len())
+- OutString.EraseLeadingChars('-'); // nicht -0
+- }
+- ImpTransliterate( OutString, NumFor[0].GetNatNum() );
+- return;
++ // If truncating the value to desired precision alters the original value,
++ // we should show the trailing zeros, otherwise strip them.
++ double fRounded = ::rtl::math::round(rNumber, nPrecision);
++ bool bRemoveZeros = ::rtl::math::approxEqual(fRounded, rNumber);
+
-+ if (pFormat->IsTextFormat() || pFormat->HasTextFormat())
-+ pFormat->GetStringColor(ppColor);
-+ else
-+ *ppColor = NULL;
-+}
++ rOutString = ::rtl::math::doubleToUString( rNumber,
++ rtl_math_StringFormat_F, nPrecision /*2*/,
++ GetFormatter().GetNumDecimalSep().GetChar(0), bRemoveZeros );
++ if (rOutString.GetChar(0) == '-' &&
++ rOutString.GetTokenCount('0') == rOutString.Len())
++ rOutString.EraseLeadingChars('-'); // nicht -0
+
- BOOL SvNumberFormatter::GetPreviewString(const String& sFormatString,
- double fPreviewNumber,
- String& sOutString,
-diff --git svtools/source/numbers/zformat.cxx svtools/source/numbers/zformat.cxx
-index 368fb16..65c0592 100644
---- svtools/source/numbers/zformat.cxx
-+++ svtools/source/numbers/zformat.cxx
-@@ -1915,6 +1915,25 @@ BOOL SvNumberformat::GetOutputString(String& sString,
++ ImpTransliterate( rOutString, NumFor[0].GetNatNum() );
+ }
+
+ void SvNumberformat::ImpGetOutputInputLine(double fNumber, String& OutString)
+@@ -1958,6 +1979,62 @@ ULONG SvNumberformat::ImpGGTRound(ULONG x, ULONG y)
}
- return FALSE;
}
+
++namespace {
+
-+void SvNumberformat::GetStringColor( Color** ppColor )
++void lcl_GetOutputStringScientific(
++ double fNumber, sal_uInt16 nCharCount, const SvNumberFormatter& rFormatter, String& rOutString)
+{
-+ if (!ppColor)
-+ return;
-+
-+ USHORT nIx;
-+ if (eType & NUMBERFORMAT_TEXT)
-+ nIx = 0;
-+ else if (NumFor[3].GetnAnz() > 0)
-+ nIx = 3;
-+ else
++ bool bSign = ::rtl::math::isSignBitSet(fNumber);
++
++ // 1.000E+015 (one digit and the decimal point, and the five chars for the exponential part, totalling 7).
++ sal_uInt16 nPrec = nCharCount > 7 ? nCharCount - 7 : 0;
++ if (nPrec && bSign)
++ // Make room for the negative sign.
++ --nPrec;
++
++ nPrec = ::std::min(nPrec, static_cast<sal_uInt16>(14)); // limit to 14 decimals.
++
++ rOutString = ::rtl::math::doubleToUString(
++ fNumber, rtl_math_StringFormat_E, nPrec, rFormatter.GetNumDecimalSep().GetChar(0));
++}
++
++}
++
++bool SvNumberformat::GetOutputString(double fNumber, sal_uInt16 nCharCount, String& rOutString) const
++{
++ using namespace std;
++
++ if (eType != NUMBERFORMAT_NUMBER)
++ return false;
++
++ double fTestNum = fNumber;
++ bool bSign = ::rtl::math::isSignBitSet(fTestNum);
++ if (bSign)
++ fTestNum = -fTestNum;
++
++ sal_uInt16 nDigitPre = static_cast<sal_uInt16>(ceil(log10(fTestNum)));
++ if (nDigitPre > 15)
+ {
-+ *ppColor = NULL; // no change of color
-+ return;
++ lcl_GetOutputStringScientific(fNumber, nCharCount, GetFormatter(), rOutString);
++ return true;
+ }
-+ *ppColor = NumFor[nIx].GetColor();
++
++ sal_uInt16 nPrec = nCharCount >= nDigitPre ? nCharCount - nDigitPre : 0;
++ if (nPrec && bSign)
++ // Subtract the negative sign.
++ --nPrec;
++ if (nPrec)
++ // Subtract the decimal point.
++ --nPrec;
++
++ ImpGetOutputStdToPrecision(fNumber, rOutString, nPrec);
++ if (rOutString.Len() > nCharCount)
++ // String still wider than desired. Switch to scientific notation.
++ lcl_GetOutputStringScientific(fNumber, nCharCount, GetFormatter(), rOutString);
++
++ return true;
+}
+
- /*
- void SvNumberformat::GetNextFareyNumber(ULONG nPrec, ULONG x0, ULONG x1,
- ULONG y0, ULONG y1,
+ BOOL SvNumberformat::GetOutputString(double fNumber,
+ String& OutString,
+ Color** ppColor)
+@@ -1981,7 +2058,7 @@ BOOL SvNumberformat::GetOutputString(double fNumber,
+ BOOL bHadStandard = FALSE;
+ if (bStandard) // einzelne Standardformate
+ {
+- if (rScan.GetStandardPrec() == 300) // alle Zahlformate InputLine
++ if (rScan.GetStandardPrec() == SvNumberFormatter::UNLIMITED_PRECISION) // alle Zahlformate InputLine
+ {
+ ImpGetOutputInputLine(fNumber, OutString);
+ return FALSE;
+diff --git svtools/source/numbers/zforscan.cxx svtools/source/numbers/zforscan.cxx
+index ab780cd..7bd764e 100644
+--- svtools/source/numbers/zforscan.cxx
++++ svtools/source/numbers/zforscan.cxx
+@@ -468,7 +468,7 @@ void ImpSvNumberformatScan::ChangeNullDate(USHORT nDay, USHORT nMonth, USHORT nY
+ pNullDate = new Date(nDay, nMonth, nYear);
+ }
+
+-void ImpSvNumberformatScan::ChangeStandardPrec(short nPrec)
++void ImpSvNumberformatScan::ChangeStandardPrec(sal_uInt16 nPrec)
+ {
+ nStandardPrec = nPrec;
+ }
+diff --git svtools/source/numbers/zforscan.hxx svtools/source/numbers/zforscan.hxx
+index df243f1..6a69675 100644
+--- svtools/source/numbers/zforscan.hxx
++++ svtools/source/numbers/zforscan.hxx
+@@ -57,7 +57,7 @@ public:
+
+ void ChangeNullDate(USHORT nDay, USHORT nMonth, USHORT nYear);
+ // tauscht Referenzdatum aus
+- void ChangeStandardPrec(short nPrec); // tauscht Standardprecision aus
++ void ChangeStandardPrec(sal_uInt16 nPrec); // tauscht Standardprecision aus
+
+ xub_StrLen ScanFormat( String& rString, String& rComment ); // Aufruf der Scan-Analyse
+
+@@ -96,7 +96,7 @@ public:
+ InitKeywords();
+ return sNameStandardFormat;
+ }
+- short GetStandardPrec() const { return nStandardPrec; }
++ sal_uInt16 GetStandardPrec() const { return nStandardPrec; }
+ const Color& GetRedColor() const { return StandardColor[4]; }
+ Color* GetColor(String& sStr); // Setzt Hauptfarben oder
+ // definierte Farben
+@@ -161,7 +161,7 @@ private: // ---- privater Teil
+ // Array der Standardfarben
+ Date* pNullDate; // 30Dec1899
+ String sNameStandardFormat; // "Standard"
+- short nStandardPrec; // default Precision fuer Standardformat (2)
++ sal_uInt16 nStandardPrec; // default Precision for Standardformat
+ SvNumberFormatter* pFormatter; // Pointer auf die Formatliste
+
+ String sStrArray[NF_MAX_FORMAT_SYMBOLS]; // Array der Symbole
More information about the ooo-build-commit
mailing list