summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2014-05-27 01:34:37 +0200
committerEike Rathke <erack@redhat.com>2014-05-27 01:47:01 +0200
commit1baac7f17b024b15d79bbb9e89e68b2863c150e9 (patch)
treea1ab397d52a73e934b065586e39e7d49c9790de2
parent6c0956030e7ee9a2329ad303042186918603418d (diff)
resolved fdo#79228 resync ScPatternAttr if changed in GetNeededSize()
Change-Id: Ida47df6223a20939ad5971dc00b8f3462a92dd3e (cherry picked from commit a1dedadbf0d87a1db24e9b336257678e059882f0)
-rw-r--r--sc/inc/attarray.hxx21
-rw-r--r--sc/inc/column.hxx2
-rw-r--r--sc/source/core/data/column2.cxx45
-rw-r--r--sc/source/core/data/table1.cxx4
4 files changed, 62 insertions, 10 deletions
diff --git a/sc/inc/attarray.hxx b/sc/inc/attarray.hxx
index 08e3c5a2d90c..9b6464b37247 100644
--- a/sc/inc/attarray.hxx
+++ b/sc/inc/attarray.hxx
@@ -206,6 +206,7 @@ class ScAttrIterator
public:
inline ScAttrIterator( const ScAttrArray* pNewArray, SCROW nStart, SCROW nEnd );
inline const ScPatternAttr* Next( SCROW& rTop, SCROW& rBottom );
+ inline const ScPatternAttr* Resync( SCROW nRow, SCROW& rTop, SCROW& rBottom );
SCROW GetNextRow() const { return nRow; }
};
@@ -236,6 +237,26 @@ inline const ScPatternAttr* ScAttrIterator::Next( SCROW& rTop, SCROW& rBottom )
return pRet;
}
+inline const ScPatternAttr* ScAttrIterator::Resync( SCROW nRowP, SCROW& rTop, SCROW& rBottom )
+{
+ nRow = nRowP;
+ // Chances are high that the pattern changed on nRowP introduced a span
+ // starting right there. Assume that Next() was called so nPos already
+ // advanced. Another high chance is that the change extended a previous or
+ // next pattern. In all these cases we don't need to search.
+ if (3 <= nPos && nPos <= pArray->nCount && pArray->pData[nPos-3].nRow < nRowP &&
+ nRowP <= pArray->pData[nPos-2].nRow)
+ nPos -= 2;
+ else if (2 <= nPos && nPos <= pArray->nCount && pArray->pData[nPos-2].nRow < nRowP &&
+ nRowP <= pArray->pData[nPos-1].nRow)
+ --nPos;
+ else if (pArray->nCount > 0 && nRowP <= pArray->pData[0].nRow)
+ nPos = 0;
+ else
+ pArray->Search( nRowP, nPos );
+ return Next( rTop, rBottom);
+}
+
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 421205650886..547fd147b3ca 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -445,7 +445,7 @@ public:
long GetNeededSize(
SCROW nRow, OutputDevice* pDev, double nPPTX, double nPPTY,
const Fraction& rZoomX, const Fraction& rZoomY,
- bool bWidth, const ScNeededSizeOptions& rOptions) const;
+ bool bWidth, const ScNeededSizeOptions& rOptions, const ScPatternAttr** pPatternChange ) const;
sal_uInt16 GetOptimalColWidth(
OutputDevice* pDev, double nPPTX, double nPPTY,
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 7e5a4a67ca3e..763e6584e494 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -86,7 +86,8 @@ inline bool IsAmbiguousScript( sal_uInt8 nScript )
long ScColumn::GetNeededSize(
SCROW nRow, OutputDevice* pDev, double nPPTX, double nPPTY,
const Fraction& rZoomX, const Fraction& rZoomY,
- bool bWidth, const ScNeededSizeOptions& rOptions ) const
+ bool bWidth, const ScNeededSizeOptions& rOptions,
+ const ScPatternAttr** ppPatternChange ) const
{
std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
sc::CellStoreType::const_iterator it = aPos.first;
@@ -148,9 +149,32 @@ long ScColumn::GetNeededSize(
SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
sal_uLong nFormat = pPattern->GetNumberFormat( pFormatter, pCondSet );
// #i111387# disable automatic line breaks only for "General" number format
- if (bBreak && aCell.hasNumeric() && ( nFormat % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 )
+ if (bBreak && ( nFormat % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 )
{
- bBreak = false;
+ // If a formula cell needs to be interpreted during aCell.hasNumeric()
+ // to determine the type, the pattern may get invalidated because the
+ // result may set a number format. In which case there's also the
+ // General format not set anymore..
+ bool bMayInvalidatePattern = (aCell.meType == CELLTYPE_FORMULA);
+ const ScPatternAttr* pOldPattern = pPattern;
+ bool bNumeric = aCell.hasNumeric();
+ if (bMayInvalidatePattern)
+ {
+ pPattern = pAttrArray->GetPattern( nRow );
+ if (ppPatternChange)
+ *ppPatternChange = pPattern; // XXX caller may have to check for change!
+ }
+ if (bNumeric)
+ {
+ if (!bMayInvalidatePattern || pPattern == pOldPattern)
+ bBreak = false;
+ else
+ {
+ nFormat = pPattern->GetNumberFormat( pFormatter, pCondSet );
+ if ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
+ bBreak = false;
+ }
+ }
}
// get other attributes from pattern and conditional formatting
@@ -689,9 +713,9 @@ sal_uInt16 ScColumn::GetOptimalColWidth(
const ScPatternAttr* pPattern = GetPattern(nRow);
aOptions.pPattern = pPattern;
aOptions.bGetFont = (pPattern != pOldPattern || nScript != nOldScript);
- sal_uInt16 nThis = (sal_uInt16) GetNeededSize(
- nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, true, aOptions);
pOldPattern = pPattern;
+ sal_uInt16 nThis = (sal_uInt16) GetNeededSize(
+ nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, true, aOptions, &pOldPattern);
if (nThis)
{
if (nThis > nWidth || !bFound)
@@ -763,7 +787,6 @@ void ScColumn::GetOptimalHeight(
// with conditional formatting, always consider the individual cells
const ScPatternAttr* pPattern = aIter.Next(nStart,nEnd);
- ::boost::ptr_vector<ScPatternAttr> aAltPatterns;
while ( pPattern )
{
const ScMergeAttr* pMerge = (const ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
@@ -902,11 +925,19 @@ void ScColumn::GetOptimalHeight(
if (rCxt.isForceAutoSize() || !(pDocument->GetRowFlags(nRow, nTab) & CR_MANUALSIZE) )
{
aOptions.pPattern = pPattern;
+ const ScPatternAttr* pOldPattern = pPattern;
sal_uInt16 nHeight = (sal_uInt16)
( GetNeededSize( nRow, rCxt.getOutputDevice(), rCxt.getPPTX(), rCxt.getPPTY(),
- rCxt.getZoomX(), rCxt.getZoomY(), false, aOptions ) / rCxt.getPPTY() );
+ rCxt.getZoomX(), rCxt.getZoomY(), false, aOptions,
+ &pPattern) / rCxt.getPPTY() );
if (nHeight > pHeight[nRow-nStartRow])
pHeight[nRow-nStartRow] = nHeight;
+ // Pattern changed due to calculation? => sync.
+ if (pPattern != pOldPattern)
+ {
+ pPattern = aIter.Resync( nRow, nStart, nEnd);
+ nNextEnd = 0;
+ }
}
}
}
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index e6033373765d..b7e020f5a04b 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -451,7 +451,7 @@ long ScTable::GetNeededSize( SCCOL nCol, SCROW nRow,
aOptions.bTotalSize = bTotalSize;
return aCol[nCol].GetNeededSize
- ( nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, aOptions );
+ ( nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, aOptions, NULL );
}
bool ScTable::SetOptimalHeight(
@@ -1802,7 +1802,7 @@ void ScTable::MaybeAddExtraColumn(SCCOL& rCol, SCROW nRow, OutputDevice* pDev, d
Fraction aZoom(1,1);
nPixel = aCol[rCol].GetNeededSize(
- nRow, pDev, nPPTX, nPPTY, aZoom, aZoom, true, aOptions );
+ nRow, pDev, nPPTX, nPPTY, aZoom, aZoom, true, aOptions, NULL );
aCol[rCol].SetTextWidth(nRow, static_cast<sal_uInt16>(nPixel));
}