Kaydet (Commit) 37f6e5de authored tarafından Dennis Francis's avatar Dennis Francis Kaydeden (comit) Eike Rathke

tdf#114710 : Fixes crash when pasting as GDI metafile

The bug document has a formula cell (at O7) that depends on cells with
non-default number formats, but this cell's number format was force
set by the user to the default. So the mbNeedsNumberFormat for this
ScFormulaCell object is now false. But when a copy to clip
and paste as GDI metafile is made, this subtle information about
the "user forced default number format" is lost.
ScColumn::SetFormulaCell() is used while making the copies of the
original formula cell to clipdoc and then to another document, where
it sets the field mbNeedsNumberFormat of the formulacell to true if the
number-format of the target cell is default. Note that the
number-formats along with all attributes of the target cells are
copied from the source before copying the actual cell contents.
As a result, after copy pasting, the formulacell at O7 of the new
document will have mbNeedsNumberFormat = true. This causes the
attribute modification (in ScAttrArray of corresponding column)
while Interpret()'ing the cell. Unfortunately this Interpret() happens
while in a call to ScRefCellValue::hasNumeric() while in the middle of
rendering the cell of the new document (in ScOutputData::LayoutStrings()),
and naturally this messes up the ScPatternAttr references the view has been
caching, hence the crash.

The steps involved in the fix are :-
1. Carry around the state of mbNeedsNumberFormat in
   the copy-constructor of ScFormulaCell, in case the src formula-cell
   is not yet Interpret()'ed. Note that after Interpret() is done, the
   mbNeedsNumberFormat is set back to false and inherited numfmt is
   applied to attributes data structure.

2. In ScColumn::SetFormulaCell(), allow an optional param
   bInheritNumFormatIfNeeded (default = true). In that method,
   the mbNeedNumberFormat is set to true only if this flag is true
   and the cell format is default. So when the copy/paste operation
   is going on, we pass the mbNeedNumberFormat of the source
   formula-cell for the new parameter to SetFormulaCell().

Change-Id: I535e413d4bde4c33a5f6ad3ce01536d0e94e7074
Reviewed-on: https://gerrit.libreoffice.org/55555Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarEike Rathke <erack@redhat.com>
üst e1ea52fa
......@@ -331,10 +331,12 @@ public:
*/
ScFormulaCell* SetFormulaCell(
SCROW nRow, ScFormulaCell* pCell,
sc::StartListeningType eListenType = sc::SingleCellListening );
sc::StartListeningType eListenType = sc::SingleCellListening,
bool bInheritNumFormatIfNeeded = true);
void SetFormulaCell(
sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScFormulaCell* pCell,
sc::StartListeningType eListenType = sc::SingleCellListening );
sc::StartListeningType eListenType = sc::SingleCellListening,
bool bInheritNumFormatIfNeeded = true);
bool SetFormulaCells( SCROW nRow, std::vector<ScFormulaCell*>& rCells );
......
......@@ -1003,7 +1003,9 @@ public:
{
mrDestCol.SetFormulaCell(
maDestBlockPos, nSrcRow + mnRowOffset,
new ScFormulaCell(rSrcCell, *mrDestCol.GetDoc(), aDestPos));
new ScFormulaCell(rSrcCell, *mrDestCol.GetDoc(), aDestPos),
sc::SingleCellListening,
rSrcCell.NeedsNumberFormat());
}
}
else if (bNumeric || bDateTime || bString)
......@@ -1969,11 +1971,12 @@ void ScColumn::SetFormula( SCROW nRow, const OUString& rFormula, formula::Formul
}
ScFormulaCell* ScColumn::SetFormulaCell(
SCROW nRow, ScFormulaCell* pCell, sc::StartListeningType eListenType )
SCROW nRow, ScFormulaCell* pCell, sc::StartListeningType eListenType,
bool bInheritNumFormatIfNeeded )
{
sc::CellStoreType::iterator it = GetPositionToInsert(nRow);
sal_uInt32 nCellFormat = GetNumberFormat(GetDoc()->GetNonThreadedContext(), nRow);
if( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
if( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 && bInheritNumFormatIfNeeded )
pCell->SetNeedNumberFormat(true);
it = maCells.set(it, nRow, pCell);
maCellTextAttrs.set(nRow, sc::CellTextAttr());
......@@ -1986,11 +1989,12 @@ ScFormulaCell* ScColumn::SetFormulaCell(
void ScColumn::SetFormulaCell(
sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScFormulaCell* pCell,
sc::StartListeningType eListenType )
sc::StartListeningType eListenType,
bool bInheritNumFormatIfNeeded )
{
rBlockPos.miCellPos = GetPositionToInsert(rBlockPos.miCellPos, nRow);
sal_uInt32 nCellFormat = GetNumberFormat(GetDoc()->GetNonThreadedContext(), nRow);
if( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
if( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 && bInheritNumFormatIfNeeded )
pCell->SetNeedNumberFormat(true);
rBlockPos.miCellPos = maCells.set(rBlockPos.miCellPos, nRow, pCell);
rBlockPos.miCellTextAttrPos = maCellTextAttrs.set(
......
......@@ -817,7 +817,7 @@ ScFormulaCell::ScFormulaCell(const ScFormulaCell& rCell, ScDocument& rDoc, const
bInChangeTrack( false ),
bTableOpDirty( false ),
bNeedListening( false ),
mbNeedsNumberFormat( false ),
mbNeedsNumberFormat( rCell.mbNeedsNumberFormat ),
mbAllowNumberFormatChange(false),
mbPostponedDirty(false),
mbIsExtRef(false),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment