[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