[ooo-build-commit] patches/test
Kohei Yoshida
kohei at kemper.freedesktop.org
Tue Oct 13 22:28:36 PDT 2009
patches/test/calc-general-type-auto-decimal-sc.diff | 658 +++++++++++++++
patches/test/calc-general-type-auto-decimal-svtools.diff | 111 ++
2 files changed, 769 insertions(+)
New commits:
commit d6857c96fbad51259c884d804de6d70868de5bab
Author: Kohei Yoshida <kyoshida at novell.com>
Date: Wed Oct 14 01:30:35 2009 -0400
[wip] Re-implementing Calc's auto-decimal adjustment.
Re-implementing it based on comments gathered in i#46511.
I'm not entirely done yet.
* patches/test/calc-general-type-auto-decimal-sc.diff:
* patches/test/calc-general-type-auto-decimal-svtools.diff:
diff --git a/patches/test/calc-general-type-auto-decimal-sc.diff b/patches/test/calc-general-type-auto-decimal-sc.diff
new file mode 100644
index 0000000..d2d9ef4
--- /dev/null
+++ b/patches/test/calc-general-type-auto-decimal-sc.diff
@@ -0,0 +1,658 @@
+diff --git sc/source/ui/inc/output.hxx sc/source/ui/inc/output.hxx
+index ea2aadc..62c0609 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
+@@ -163,6 +172,13 @@ private:
+ Rectangle& rAlignRect, Rectangle& rClipRect,
+ BOOL& rLeftClip, BOOL& rRightClip );
+
++ 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,
++ 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,
+diff --git sc/source/ui/view/output2.cxx sc/source/ui/view/output2.cxx
+index ef7f0c9..6e48034 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
+ }
+
+- 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,49 @@ 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);
++
++ pNumFormat->GetOutputString(fVal, nNumDigits, aString);
++ 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 +573,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[] =
+@@ -1152,6 +1225,232 @@ void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY
+ #endif
+ }
+
++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,
++ OutputAreaParam& rParam )
++{
++ // 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
++ SCCOL nCompCol = nX;
++ while ( nCellX > nCompCol )
++ {
++ //! extra member function for width?
++ long nColWidth = ( nCompCol <= nX2 ) ?
++ pRowInfo[0].pCellInfo[nCompCol+1].nWidth :
++ (long) ( pDoc->GetColWidth( nCompCol, nTab ) * nPPTX );
++ nCellPosX += nColWidth * nLayoutSign;
++ ++nCompCol;
++ }
++ while ( nCellX < nCompCol )
++ {
++ --nCompCol;
++ long nColWidth = ( nCompCol <= nX2 ) ?
++ pRowInfo[0].pCellInfo[nCompCol+1].nWidth :
++ (long) ( pDoc->GetColWidth( nCompCol, nTab ) * nPPTX );
++ nCellPosX -= nColWidth * nLayoutSign;
++ }
++
++ long nCellPosY = nPosY; // find nCellY position, starting at nArrY/nPosY
++ SCSIZE nCompArr = nArrY;
++ SCROW nCompRow = pRowInfo[nCompArr].nRowNo;
++ while ( nCellY > nCompRow )
++ {
++ if ( nCompArr + 1 < nArrCount )
++ {
++ nCellPosY += pRowInfo[nCompArr].nHeight;
++ ++nCompArr;
++ nCompRow = pRowInfo[nCompArr].nRowNo;
++ }
++ else
++ {
++ USHORT nDocHeight = pDoc->GetRowHeight( nCompRow, nTab );
++ if ( nDocHeight )
++ nCellPosY += (long) ( nDocHeight * nPPTY );
++ ++nCompRow;
++ }
++ }
++ nCellPosY -= (long) pDoc->GetScaledRowHeight( nCellY, nCompRow-1, nTab, nPPTY );
++
++ const ScMergeAttr* pMerge = (const ScMergeAttr*)&rPattern.GetItem( ATTR_MERGE );
++ BOOL bMerged = pMerge->IsMerged();
++ long nMergeCols = pMerge->GetColMerge();
++ if ( nMergeCols == 0 )
++ nMergeCols = 1;
++ long nMergeRows = pMerge->GetRowMerge();
++ if ( nMergeRows == 0 )
++ nMergeRows = 1;
++
++ long i;
++ long nMergeSizeX = 0;
++ for ( i=0; i<nMergeCols; i++ )
++ {
++ long nColWidth = ( nCellX+i <= nX2 ) ?
++ pRowInfo[0].pCellInfo[nCellX+i+1].nWidth :
++ (long) ( pDoc->GetColWidth( sal::static_int_cast<SCCOL>(nCellX+i), nTab ) * nPPTX );
++ nMergeSizeX += nColWidth;
++ }
++ long nMergeSizeY = 0;
++ short nDirect = 0;
++ if ( rThisRowInfo.nRowNo == nCellY )
++ {
++ // take first row's height from row info
++ nMergeSizeY += rThisRowInfo.nHeight;
++ 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)
++
++ 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.
++
++ 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.
++
++ rParam.maClipRect = rParam.maAlignRect;
++ if ( nNeeded > nMergeSizeX )
++ {
++ SvxCellHorJustify eHorJust = (SvxCellHorJustify)nHorJustify;
++
++ long nMissing = nNeeded - nMergeSizeX;
++ long nLeftMissing = 0;
++ long nRightMissing = 0;
++ switch ( eHorJust )
++ {
++ case SVX_HOR_JUSTIFY_LEFT:
++ nRightMissing = nMissing;
++ break;
++ case SVX_HOR_JUSTIFY_RIGHT:
++ nLeftMissing = nMissing;
++ break;
++ case SVX_HOR_JUSTIFY_CENTER:
++ nLeftMissing = nMissing / 2;
++ nRightMissing = nMissing - nLeftMissing;
++ break;
++ default:
++ {
++ // added to avoid warnings
++ }
++ }
++
++ // nLeftMissing, nRightMissing are logical, eHorJust values are visual
++ if ( bLayoutRTL )
++ ::std::swap( nLeftMissing, nRightMissing );
++
++ SCCOL nRightX = nCellX;
++ SCCOL nLeftX = nCellX;
++ if ( !bMerged && !bCellIsValue && !bBreak )
++ {
++ // look for empty cells into which the text can be extended
++
++ while ( nRightMissing > 0 && nRightX < MAXCOL && ( bOverwrite || IsAvailable( nRightX+1, nCellY ) ) )
++ {
++ ++nRightX;
++ long nAdd = (long) ( pDoc->GetColWidth( nRightX, nTab ) * nPPTX );
++ nRightMissing -= nAdd;
++ rParam.maClipRect.Right() += nAdd * nLayoutSign;
++
++ if ( rThisRowInfo.nRowNo == nCellY && nRightX >= nX1 && nRightX <= nX2 )
++ rThisRowInfo.pCellInfo[nRightX].bHideGrid = TRUE;
++ }
++
++ while ( nLeftMissing > 0 && nLeftX > 0 && ( bOverwrite || IsAvailable( nLeftX-1, nCellY ) ) )
++ {
++ if ( rThisRowInfo.nRowNo == nCellY && nLeftX >= nX1 && nLeftX <= nX2 )
++ rThisRowInfo.pCellInfo[nLeftX].bHideGrid = TRUE;
++
++ --nLeftX;
++ long nAdd = (long) ( pDoc->GetColWidth( nLeftX, nTab ) * nPPTX );
++ nLeftMissing -= nAdd;
++ rParam.maClipRect.Left() -= nAdd * nLayoutSign;
++ }
++ }
++
++ // 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 );
++ 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 );
++ rParam.maClipRect.Left() += nMarkPixel * nLayoutSign;
++ }
++
++ rParam.mbLeftClip = ( nLeftMissing > 0 );
++ rParam.mbRightClip = ( nRightMissing > 0 );
++ }
++ else
++ {
++ 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)
++
++ if ( eType==OUTTYPE_WINDOW &&
++ ( static_cast<const ScMergeFlagAttr&>(rPattern.GetItem(ATTR_MERGE_FLAG)).GetValue() & SC_MF_AUTO ) &&
++ ( !bBreak || pRefDevice == pFmtDevice ) )
++ {
++ long nFilter = Min( nMergeSizeY, (long) DROPDOWN_BITMAP_SIZE );
++ BOOL bFit = ( nNeeded + nFilter <= nMergeSizeX );
++ if ( bFit || bCellIsValue )
++ {
++ // content fits even in the remaining area without the filter button
++ // -> align within that remaining area
++
++ 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 )
++ rParam.mbLeftClip = rParam.mbRightClip = TRUE;
++ }
++ }
++ }
++
++ // justify both rectangles for alignment calculation, use with DrawText etc.
++
++ rParam.maAlignRect.Justify();
++ rParam.maClipRect.Justify();
++
++#if 0
++ //! Test !!!
++ pDev->Push();
++ pDev->SetLineColor();
++ pDev->SetFillColor( COL_LIGHTGREEN );
++ pDev->DrawRect( pDev->PixelToLogic(rParam.maClipRect) );
++ pDev->DrawRect( rParam.maClipRect ); // print preview
++ pDev->Pop();
++ //! Test !!!
++#endif
++}
++
+ void ScOutputData::DrawStrings( BOOL bPixelToLogic )
+ {
+ DBG_ASSERT( pDev == pRefDevice ||
+@@ -1187,12 +1486,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 +1659,7 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic )
+ bNeedEdit = aVars.HasEditCharacters() ||
+ (bFormulaCell && ((ScFormulaCell*)pCell)->IsMultilineResult());
+ }
++ long nTotalMargin = 0;
+ if (bDoCell && !bNeedEdit)
+ {
+ CellType eCellType = pCell->GetCellType();
+@@ -1384,14 +1681,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 +1701,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 +1727,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 +1760,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 +1782,49 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic )
+ }
+ if ( bDoCell )
+ {
+- 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 +1907,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
diff --git a/patches/test/calc-general-type-auto-decimal-svtools.diff b/patches/test/calc-general-type-auto-decimal-svtools.diff
new file mode 100644
index 0000000..5ec9850
--- /dev/null
+++ b/patches/test/calc-general-type-auto-decimal-svtools.diff
@@ -0,0 +1,111 @@
+diff --git svtools/inc/svtools/zformat.hxx svtools/inc/svtools/zformat.hxx
+index 4c52b10..4037a73 100644
+--- svtools/inc/svtools/zformat.hxx
++++ svtools/inc/svtools/zformat.hxx
+@@ -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 );
+
+@@ -490,6 +496,7 @@ private:
+
+ // standard number output
+ SVT_DLLPRIVATE void ImpGetOutputStandard( double& fNumber, String& OutString );
++ SVT_DLLPRIVATE void ImpGetOutputStdToPrecision( double& rNumber, String& rOutString, USHORT nPrecision ) const;
+ // numbers in input line
+ SVT_DLLPRIVATE void ImpGetOutputInputLine( double fNumber, String& OutString );
+
+diff --git svtools/source/numbers/zformat.cxx svtools/source/numbers/zformat.cxx
+index 368fb16..831e999 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 {
+@@ -1778,9 +1781,14 @@ void SvNumberformat::Build50Formatstring( String& rStr ) const
+ void SvNumberformat::ImpGetOutputStandard(double& fNumber, String& OutString)
+ {
+ USHORT nStandardPrec = rScan.GetStandardPrec();
+- if ( fabs(fNumber) > 1.0E15 ) // #58531# war E16
+- OutString = ::rtl::math::doubleToUString( fNumber,
+- rtl_math_StringFormat_E, nStandardPrec /*2*/,
++ ImpGetOutputStdToPrecision(fNumber, OutString, nStandardPrec);
++}
++
++void SvNumberformat::ImpGetOutputStdToPrecision(double& rNumber, String& rOutString, USHORT nPrecision) const
++{
++ if ( fabs(rNumber) > 1.0E15 ) // #58531# war E16
++ rOutString = ::rtl::math::doubleToUString( rNumber,
++ rtl_math_StringFormat_E, nPrecision /*2*/,
+ GetFormatter().GetNumDecimalSep().GetChar(0));
+ else
+ {
+@@ -1809,15 +1817,14 @@ void SvNumberformat::ImpGetOutputStandard(double& fNumber, String& OutString)
+ }
+ #endif
+
+- OutString = ::rtl::math::doubleToUString( fNumber,
+- rtl_math_StringFormat_F, nStandardPrec /*2*/,
++ rOutString = ::rtl::math::doubleToUString( rNumber,
++ rtl_math_StringFormat_F, nPrecision /*2*/,
+ GetFormatter().GetNumDecimalSep().GetChar(0), sal_True );
+- if (OutString.GetChar(0) == '-' &&
+- OutString.GetTokenCount('0') == OutString.Len())
+- OutString.EraseLeadingChars('-'); // nicht -0
++ if (rOutString.GetChar(0) == '-' &&
++ rOutString.GetTokenCount('0') == rOutString.Len())
++ rOutString.EraseLeadingChars('-'); // nicht -0
+ }
+- ImpTransliterate( OutString, NumFor[0].GetNatNum() );
+- return;
++ ImpTransliterate( rOutString, NumFor[0].GetNatNum() );
+ }
+
+ void SvNumberformat::ImpGetOutputInputLine(double fNumber, String& OutString)
+@@ -1958,6 +1965,31 @@ ULONG SvNumberformat::ImpGGTRound(ULONG x, ULONG y)
+ }
+ }
+
++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 = fTestNum < 0;
++ if (bSign)
++ fTestNum = -fTestNum;
++
++ double nDigitPre = ceil(log10(fTestNum));
++ 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);
++ return true;
++}
++
+ BOOL SvNumberformat::GetOutputString(double fNumber,
+ String& OutString,
+ Color** ppColor)
More information about the ooo-build-commit
mailing list