sc/inc/address.hxx | 6 ++ sc/inc/compiler.hxx | 8 +-- sc/inc/document.hxx | 44 ++++++++++++---- sc/inc/token.hxx | 7 +- sc/inc/tokenarray.hxx | 8 ++- sc/qa/unit/ucalc.hxx | 2 sc/qa/unit/ucalc_formula.cxx | 20 +++++++ sc/source/core/data/documen2.cxx | 8 +-- sc/source/core/tool/compiler.cxx | 66 ++++++++++++------------- sc/source/core/tool/interpr2.cxx | 6 +- sc/source/core/tool/interpr4.cxx | 14 ++--- sc/source/core/tool/reftokenhelper.cxx | 8 +-- sc/source/core/tool/token.cxx | 86 ++++++++++++++++++--------------- sc/source/ui/unoobj/chart2uno.cxx | 10 +-- 14 files changed, 177 insertions(+), 116 deletions(-)
New commits: commit 113444f59dc7690850919155b9b164b1a686bbe7 Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Fri Dec 13 15:59:51 2019 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Fri Dec 13 19:41:59 2019 +0100 sc: rowcol: tdf#50916 create ScSheetLimits to hold by rtl::Reference ScTokenArray sometimes outlives the ScDocument that created it, which means it accesses dead data when it tries to validate columns and rows. So create the ScSheetLimits class, which ScTokenArray can hold by reference counted pointer. Change-Id: Ic5771734fe4962d12f024fc1b29232124c14208a Reviewed-on: https://gerrit.libreoffice.org/85117 Tested-by: Jenkins Reviewed-by: Michael Meeks <michael.me...@collabora.com> diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx index 1d6680cb8ebf..5a1f7d91f2ab 100644 --- a/sc/inc/address.hxx +++ b/sc/inc/address.hxx @@ -90,11 +90,13 @@ const SCROW MAXROW_30 = 8191; [[nodiscard]] inline bool ValidCol( SCCOL nCol, SCCOL nMaxCol = MAXCOL ) { + assert(nMaxCol == MAXCOL); // temporary to debug jumbo sheets work return nCol >= 0 && nCol <= nMaxCol; } [[nodiscard]] inline bool ValidRow( SCROW nRow, SCROW nMaxRow = MAXROW) { + assert(nMaxRow == MAXROW); // temporary to debug jumbo sheets work return nRow >= 0 && nRow <= nMaxRow; } @@ -110,21 +112,25 @@ const SCROW MAXROW_30 = 8191; [[nodiscard]] inline bool ValidColRow( SCCOL nCol, SCROW nRow, SCCOL nMaxCol = MAXCOL, SCROW nMaxRow = MAXROW ) { + assert(nMaxRow == MAXROW); // temporary to debug jumbo sheets work return ValidCol(nCol,nMaxCol) && ValidRow(nRow,nMaxRow); } [[nodiscard]] inline bool ValidColRowTab( SCCOL nCol, SCROW nRow, SCTAB nTab, SCCOL nMaxCol = MAXCOL, SCROW nMaxRow = MAXROW ) { + assert(nMaxRow == MAXROW); // temporary to debug jumbo sheets work return ValidCol(nCol,nMaxCol) && ValidRow(nRow,nMaxRow) && ValidTab( nTab); } [[nodiscard]] inline SCCOL SanitizeCol( SCCOL nCol, SCCOL nMaxCol = MAXCOL ) { + assert(nMaxCol == MAXCOL); // temporary to debug jumbo sheets work return nCol < 0 ? 0 : (nCol > nMaxCol ? nMaxCol : nCol); } [[nodiscard]] inline SCROW SanitizeRow( SCROW nRow, SCROW nMaxRow = MAXROW ) { + assert(nMaxRow == MAXROW); // temporary to debug jumbo sheets work return nRow < 0 ? 0 : (nRow > nMaxRow ? nMaxRow : nRow); } diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx index dce569c2b68a..623f94945943 100644 --- a/sc/inc/compiler.hxx +++ b/sc/inc/compiler.hxx @@ -39,6 +39,8 @@ #include <formula/FormulaCompiler.hxx> +struct ScSheetLimits; + // constants and data types also for external modules (ScInterpreter et al) #define MAXSTRLEN 1024 /* maximum length of input string of one symbol */ @@ -167,7 +169,7 @@ public: */ bool IsValidReference(const ScDocument* pDoc) const; - formula::FormulaToken* CreateToken(const ScDocument* pDoc) const; // create typified token + formula::FormulaToken* CreateToken(ScSheetLimits& rLimits) const; // create typified token }; class SC_DLLPUBLIC ScCompiler : public formula::FormulaCompiler @@ -189,7 +191,7 @@ public: virtual ~Convention(); virtual void makeRefStr( - const ScDocument* pDoc, + ScSheetLimits& rLimits, OUStringBuffer& rBuffer, formula::FormulaGrammar::Grammar eGram, const ScAddress& rPos, @@ -220,7 +222,7 @@ public: const OUString& rTabName, const ScSingleRefData& rRef ) const = 0; virtual void makeExternalRefStr( - const ScDocument* pDoc, + ScSheetLimits& rLimits, OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 nFileId, const OUString& rFileName, const std::vector<OUString>& rTabNames, const OUString& rTabName, const ScComplexRefData& rRef ) const = 0; diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index e160c8d4b735..94c9b2820c17 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -20,6 +20,7 @@ #ifndef INCLUDED_SC_INC_DOCUMENT_HXX #define INCLUDED_SC_INC_DOCUMENT_HXX +#include <salhelper/simplereferenceobject.hxx> #include <vcl/idle.hxx> #include <vcl/errcode.hxx> #include <com/sun/star/uno/Reference.hxx> @@ -280,6 +281,25 @@ const sal_uInt8 SC_DDE_ENGLISH = 1; const sal_uInt8 SC_DDE_TEXT = 2; const sal_uInt8 SC_DDE_IGNOREMODE = 255; /// For usage in FindDdeLink() only! +// Because some stuff needs this info, and those objects lifetimes sometimes exceeds the lifetime +// of the ScDocument. +struct ScSheetLimits : public salhelper::SimpleReferenceObject +{ + const SCCOL mnMaxCol; /// Maximum addressable column + const SCROW mnMaxRow; /// Maximum addressable row + + ScSheetLimits(SCCOL nMaxCol, SCROW nMaxRow) : mnMaxCol(nMaxCol), mnMaxRow(nMaxRow) {} + + [[nodiscard]] bool ValidCol(SCCOL nCol) const { return ::ValidCol(nCol, mnMaxCol); } + [[nodiscard]] bool ValidRow(SCROW nRow) const { return ::ValidRow(nRow, mnMaxRow); } + [[nodiscard]] bool ValidColRow(SCCOL nCol, SCROW nRow) const { return ::ValidColRow(nCol, nRow, mnMaxCol, mnMaxRow); } + [[nodiscard]] bool ValidColRowTab(SCCOL nCol, SCROW nRow, SCTAB nTab) const { return ::ValidColRowTab(nCol, nRow, nTab, mnMaxCol, mnMaxRow); } + [[nodiscard]] bool ValidRange(const ScRange& rRange) const { return ::ValidRange(rRange, mnMaxCol, mnMaxRow); } + [[nodiscard]] bool ValidAddress(const ScAddress& rAddress) const { return ::ValidAddress(rAddress, mnMaxCol, mnMaxRow); } + [[nodiscard]] SCCOL SanitizeCol( SCCOL nCol ) const { return ::SanitizeCol(nCol, mnMaxCol); } + [[nodiscard]] SCROW SanitizeRow( SCROW nRow ) const { return ::SanitizeRow(nRow, mnMaxRow); } +}; + // During threaded calculation fields being mutated are kept in this struct struct ScDocumentThreadSpecific { @@ -371,8 +391,7 @@ private: std::unique_ptr<ScValidationDataList> pValidationList; // validity SvNumberFormatterIndexTable* pFormatExchangeList; // for application of number formats TableContainer maTabs; - SCCOL mnMaxCol; /// Maximum addressable column - SCROW mnMaxRow; /// Maximum addressable row + rtl::Reference<ScSheetLimits> mxSheetLimits; std::vector<OUString> maTabNames; // for undo document, we need the information tab name <-> index mutable std::unique_ptr<ScRangeName> pRangeName; std::unique_ptr<ScDBCollection> pDBCollection; @@ -856,16 +875,17 @@ public: SC_DLLPUBLIC bool GetCodeName( SCTAB nTab, OUString& rName ) const; SC_DLLPUBLIC bool SetCodeName( SCTAB nTab, const OUString& rName ); SC_DLLPUBLIC bool GetTable( const OUString& rName, SCTAB& rTab ) const; - SC_DLLPUBLIC SCCOL MaxCol() const { return mnMaxCol; } - SC_DLLPUBLIC SCROW MaxRow() const { return mnMaxRow; } - [[nodiscard]] bool ValidCol(SCCOL nCol) const { return ::ValidCol(nCol, mnMaxCol); } - [[nodiscard]] bool ValidRow(SCROW nRow) const { return ::ValidRow(nRow, mnMaxRow); } - [[nodiscard]] bool ValidColRow(SCCOL nCol, SCROW nRow) const { return ::ValidColRow(nCol, nRow, mnMaxCol, mnMaxRow); } - [[nodiscard]] bool ValidColRowTab(SCCOL nCol, SCROW nRow, SCTAB nTab) const { return ::ValidColRowTab(nCol, nRow, nTab, mnMaxCol, mnMaxRow); } - [[nodiscard]] bool ValidRange(const ScRange& rRange) const { return ::ValidRange(rRange, mnMaxCol, mnMaxRow); } - [[nodiscard]] bool ValidAddress(const ScAddress& rAddress) const { return ::ValidAddress(rAddress, mnMaxCol, mnMaxRow); } - [[nodiscard]] SCCOL SanitizeCol( SCCOL nCol ) const { return ::SanitizeCol(nCol, mnMaxCol); } - [[nodiscard]] SCROW SanitizeRow( SCROW nRow ) const { return ::SanitizeRow(nRow, mnMaxRow); } + SC_DLLPUBLIC SCCOL MaxCol() const { return mxSheetLimits->mnMaxCol; } + SC_DLLPUBLIC SCROW MaxRow() const { return mxSheetLimits->mnMaxRow; } + ScSheetLimits& GetSheetLimits() const { return *mxSheetLimits; } + [[nodiscard]] bool ValidCol(SCCOL nCol) const { return ::ValidCol(nCol, mxSheetLimits->mnMaxCol); } + [[nodiscard]] bool ValidRow(SCROW nRow) const { return ::ValidRow(nRow, mxSheetLimits->mnMaxRow); } + [[nodiscard]] bool ValidColRow(SCCOL nCol, SCROW nRow) const { return ::ValidColRow(nCol, nRow, MaxCol(), MaxRow()); } + [[nodiscard]] bool ValidColRowTab(SCCOL nCol, SCROW nRow, SCTAB nTab) const { return ::ValidColRowTab(nCol, nRow, nTab, MaxCol(), MaxRow()); } + [[nodiscard]] bool ValidRange(const ScRange& rRange) const { return ::ValidRange(rRange, MaxCol(), MaxRow()); } + [[nodiscard]] bool ValidAddress(const ScAddress& rAddress) const { return ::ValidAddress(rAddress, MaxCol(), MaxRow()); } + [[nodiscard]] SCCOL SanitizeCol( SCCOL nCol ) const { return ::SanitizeCol(nCol, MaxCol()); } + [[nodiscard]] SCROW SanitizeRow( SCROW nRow ) const { return ::SanitizeRow(nRow, MaxRow()); } SC_DLLPUBLIC std::vector<OUString> GetAllTableNames() const; diff --git a/sc/inc/token.hxx b/sc/inc/token.hxx index 58adad226284..ff52adac2031 100644 --- a/sc/inc/token.hxx +++ b/sc/inc/token.hxx @@ -35,6 +35,7 @@ class ScJumpMatrix; class ScMatrix; +struct ScSheetLimits; typedef ::std::vector< ScComplexRefData > ScRefList; @@ -54,14 +55,14 @@ void DumpToken(formula::FormulaToken const & rToken); A reused or new'ed ScDoubleRefToken, or a NULL TokenRef if rTok1 or rTok2 are not of sv(Single|Double)Ref */ -formula::FormulaTokenRef extendRangeReference( const ScDocument* pDoc, formula::FormulaToken & rTok1, formula::FormulaToken & rTok2, const ScAddress & rPos, bool bReuseDoubleRef ); +formula::FormulaTokenRef extendRangeReference( ScSheetLimits& rLimits, formula::FormulaToken & rTok1, formula::FormulaToken & rTok2, const ScAddress & rPos, bool bReuseDoubleRef ); class ScSingleRefToken final : public formula::FormulaToken { private: ScSingleRefData aSingleRef; public: - ScSingleRefToken( const ScDocument* /*pDoc*/, const ScSingleRefData& r, OpCode e = ocPush ) : + ScSingleRefToken( ScSheetLimits& , const ScSingleRefData& r, OpCode e = ocPush ) : FormulaToken( formula::svSingleRef, e ), aSingleRef( r ) {} virtual const ScSingleRefData* GetSingleRef() const override; virtual ScSingleRefData* GetSingleRef() override; @@ -75,7 +76,7 @@ class ScDoubleRefToken final : public formula::FormulaToken private: ScComplexRefData aDoubleRef; public: - ScDoubleRefToken( const ScDocument* /*pDoc*/, const ScComplexRefData& r, OpCode e = ocPush ) : + ScDoubleRefToken( ScSheetLimits&, const ScComplexRefData& r, OpCode e = ocPush ) : FormulaToken( formula::svDoubleRef, e ), aDoubleRef( r ) {} virtual const ScSingleRefData* GetSingleRef() const override; virtual ScSingleRefData* GetSingleRef() override; diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx index ae6eb22a593f..37ccf6b67c06 100644 --- a/sc/inc/tokenarray.hxx +++ b/sc/inc/tokenarray.hxx @@ -21,6 +21,7 @@ #define INCLUDED_SC_INC_TOKENARRAY_HXX #include <formula/token.hxx> +#include <rtl/ref.hxx> #include "scdllapi.h" #include "types.hxx" #include "calcmacros.hxx" @@ -43,14 +44,16 @@ class ColRowReorderMapType; struct ScRawToken; struct ScSingleRefData; struct ScComplexRefData; +struct ScSheetLimits; class SAL_WARN_UNUSED SC_DLLPUBLIC ScTokenArray final : public formula::FormulaTokenArray { friend class ScCompiler; - bool ImplGetReference( const ScDocument* pDoc, ScRange& rRange, const ScAddress& rPos, bool bValidOnly ) const; + bool ImplGetReference( ScRange& rRange, const ScAddress& rPos, bool bValidOnly ) const; - const ScDocument* mpDoc; + // hold a reference to the limits because sometimes our lifetime exceeds the lifetime of the associated ScDocument + rtl::Reference<ScSheetLimits> mxSheetLimits; size_t mnHashValue; ScFormulaVectorState meVectorState : 4; // Only 4 bits bool mbOpenCLEnabled : 1; @@ -60,6 +63,7 @@ class SAL_WARN_UNUSED SC_DLLPUBLIC ScTokenArray final : public formula::FormulaT public: ScTokenArray(const ScDocument* pDoc); + ScTokenArray(ScSheetLimits&); /** Assignment with incrementing references of FormulaToken entries (not copied!) */ ScTokenArray( const ScTokenArray& ) = default; diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index a779371f83b7..af09ab3f21c7 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -100,8 +100,7 @@ ScDocument::ScDocument( ScDocumentMode eMode, SfxObjectShell* pDocShell ) : mpPrinter( nullptr ), mpVirtualDevice_100th_mm( nullptr ), pFormatExchangeList( nullptr ), - mnMaxCol(MAXCOL), - mnMaxRow(MAXROW), + mxSheetLimits(new ScSheetLimits(MAXCOL, MAXROW)), pFormulaTree( nullptr ), pEOFormulaTree( nullptr ), pFormulaTrack( nullptr ), @@ -173,10 +172,9 @@ ScDocument::ScDocument( ScDocumentMode eMode, SfxObjectShell* pDocShell ) : const ScDefaultsOptions& rOpt = SC_MOD()->GetDefaultsOptions(); if (rOpt.GetInitJumboSheets()) { - mnMaxCol = 16384; - mnMaxRow = 16 * 1000 * 1000; + mxSheetLimits = new ScSheetLimits(16384, 16 * 1000 * 1000); } - maPreviewSelection = { mnMaxRow, mnMaxCol }; + maPreviewSelection = { MaxRow(), MaxCol() }; aCurTextWidthCalcPos = { MaxCol(), 0, 0 }; SetStorageGrammar( formula::FormulaGrammar::GRAM_STORAGE_DEFAULT); diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 3d4a2def3552..7f1460db8f51 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -832,7 +832,7 @@ struct ConventionOOO_A1 : public Convention_A1 } } - static SingletonDisplay getSingletonDisplay( const ScDocument* pDoc, const ScAddress& rAbs1, const ScAddress& rAbs2, + static SingletonDisplay getSingletonDisplay( ScSheetLimits& rLimits, const ScAddress& rAbs1, const ScAddress& rAbs2, const ScComplexRefData& rRef, bool bFromRangeName ) { // If any part is error, display as such. @@ -846,7 +846,7 @@ struct ConventionOOO_A1 : public Convention_A1 // Same if not in named expression and both rows of entire columns are // relative references. - if (!bFromRangeName && rAbs1.Row() == 0 && rAbs2.Row() == pDoc->MaxRow() && + if (!bFromRangeName && rAbs1.Row() == 0 && rAbs2.Row() == rLimits.mnMaxRow && rRef.Ref1.IsRowRel() && rRef.Ref2.IsRowRel()) return SINGLETON_COL; @@ -856,7 +856,7 @@ struct ConventionOOO_A1 : public Convention_A1 // Same if not in named expression and both columns of entire rows are // relative references. - if (!bFromRangeName && rAbs1.Col() == 0 && rAbs2.Col() == pDoc->MaxCol() && + if (!bFromRangeName && rAbs1.Col() == 0 && rAbs2.Col() == rLimits.mnMaxCol && rRef.Ref1.IsColRel() && rRef.Ref2.IsColRel()) return SINGLETON_ROW; @@ -864,7 +864,7 @@ struct ConventionOOO_A1 : public Convention_A1 } virtual void makeRefStr( - const ScDocument* pDoc, + ScSheetLimits& rLimits, OUStringBuffer& rBuffer, formula::FormulaGrammar::Grammar /*eGram*/, const ScAddress& rPos, @@ -880,7 +880,7 @@ struct ConventionOOO_A1 : public Convention_A1 aAbs2 = rRef.Ref2.toAbs(rPos); SingletonDisplay eSingleton = bSingleRef ? SINGLETON_NONE : - getSingletonDisplay( pDoc, aAbs1, aAbs2, rRef, bFromRangeName); + getSingletonDisplay( rLimits, aAbs1, aAbs2, rRef, bFromRangeName); MakeOneRefStrImpl(rBuffer, rErrRef, rTabNames, rRef.Ref1, aAbs1, false, false, eSingleton); if (!bSingleRef) { @@ -1009,7 +1009,7 @@ struct ConventionOOO_A1 : public Convention_A1 } virtual void makeExternalRefStr( - const ScDocument* /*pDoc*/, + ScSheetLimits&, OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 /*nFileId*/, const OUString& rFileName, const std::vector<OUString>& rTabNames, const OUString& rTabName, const ScComplexRefData& rRef ) const override @@ -1023,7 +1023,7 @@ struct ConventionOOO_A1_ODF : public ConventionOOO_A1 ConventionOOO_A1_ODF() : ConventionOOO_A1 (FormulaGrammar::CONV_ODF) { } virtual void makeRefStr( - const ScDocument* pDoc, + ScSheetLimits& rLimits, OUStringBuffer& rBuffer, formula::FormulaGrammar::Grammar eGram, const ScAddress& rPos, @@ -1050,7 +1050,7 @@ struct ConventionOOO_A1_ODF : public ConventionOOO_A1 else { SingletonDisplay eSingleton = bSingleRef ? SINGLETON_NONE : - getSingletonDisplay( pDoc, aAbs1, aAbs2, rRef, bFromRangeName); + getSingletonDisplay( rLimits, aAbs1, aAbs2, rRef, bFromRangeName); MakeOneRefStrImpl(rBuffer, rErrRef, rTabNames, rRef.Ref1, aAbs1, false, true, eSingleton); if (!bSingleRef) { @@ -1076,7 +1076,7 @@ struct ConventionOOO_A1_ODF : public ConventionOOO_A1 } virtual void makeExternalRefStr( - const ScDocument* /*pDoc*/, + ScSheetLimits& , OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 /*nFileId*/, const OUString& rFileName, const std::vector<OUString>& rTabNames, const OUString& rTabName, const ScComplexRefData& rRef ) const override @@ -1271,7 +1271,7 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL } virtual void makeRefStr( - const ScDocument* pDoc, + ScSheetLimits& rLimits, OUStringBuffer& rBuf, formula::FormulaGrammar::Grammar /*eGram*/, const ScAddress& rPos, @@ -1303,7 +1303,7 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL return; } - if (aAbs1.Col() == 0 && aAbs2.Col() >= pDoc->MaxCol()) + if (aAbs1.Col() == 0 && aAbs2.Col() >= rLimits.mnMaxCol) { if (!aRef.Ref1.IsRowRel()) rBuf.append( '$' ); @@ -1315,7 +1315,7 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL return; } - if (aAbs1.Row() == 0 && aAbs2.Row() >= pDoc->MaxRow()) + if (aAbs1.Row() == 0 && aAbs2.Row() >= rLimits.mnMaxRow) { if (!aRef.Ref1.IsColRel()) rBuf.append( '$' ); @@ -1394,7 +1394,7 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL } virtual void makeExternalRefStr( - const ScDocument* /*pDoc*/, + ScSheetLimits&, OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 /*nFileId*/, const OUString& rFileName, const std::vector<OUString>& rTabNames, const OUString& rTabName, const ScComplexRefData& rRef ) const override @@ -1418,7 +1418,7 @@ struct ConventionXL_OOX : public ConventionXL_A1 { ConventionXL_OOX() : ConventionXL_A1( FormulaGrammar::CONV_XL_OOX ) { } - virtual void makeRefStr( const ScDocument* pDoc, + virtual void makeRefStr( ScSheetLimits& rLimits, OUStringBuffer& rBuf, formula::FormulaGrammar::Grammar eGram, const ScAddress& rPos, @@ -1450,7 +1450,7 @@ struct ConventionXL_OOX : public ConventionXL_A1 return; } - ConventionXL_A1::makeRefStr( pDoc, rBuf, eGram, aPos, rErrRef, rTabNames, rRef, bSingleRef, bFromRangeName); + ConventionXL_A1::makeRefStr( rLimits, rBuf, eGram, aPos, rErrRef, rTabNames, rRef, bSingleRef, bFromRangeName); } virtual OUString makeExternalNameStr( sal_uInt16 nFileId, const OUString& /*rFile*/, @@ -1513,7 +1513,7 @@ struct ConventionXL_OOX : public ConventionXL_A1 } virtual void makeExternalRefStr( - const ScDocument* /*pDoc*/, + ScSheetLimits& , OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 nFileId, const OUString& /*rFileName*/, const std::vector<OUString>& rTabNames, const OUString& rTabName, const ScComplexRefData& rRef ) const override @@ -1591,7 +1591,7 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL { ConventionXL_R1C1() : ScCompiler::Convention( FormulaGrammar::CONV_XL_R1C1 ) { } - virtual void makeRefStr( const ScDocument* pDoc, + virtual void makeRefStr( ScSheetLimits& rLimits, OUStringBuffer& rBuf, formula::FormulaGrammar::Grammar /*eGram*/, const ScAddress& rPos, @@ -1621,7 +1621,7 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL return; } - if (aAbsRef.aStart.Col() == 0 && aAbsRef.aEnd.Col() >= pDoc->MaxCol()) + if (aAbsRef.aStart.Col() == 0 && aAbsRef.aEnd.Col() >= rLimits.mnMaxCol) { r1c1_add_row(rBuf, rRef.Ref1, aAbsRef.aStart); if (aAbsRef.aStart.Row() != aAbsRef.aEnd.Row() || @@ -1634,7 +1634,7 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL } - if (aAbsRef.aStart.Row() == 0 && aAbsRef.aEnd.Row() >= pDoc->MaxRow()) + if (aAbsRef.aStart.Row() == 0 && aAbsRef.aEnd.Row() >= rLimits.mnMaxRow) { r1c1_add_col(rBuf, rRef.Ref1, aAbsRef.aStart); if (aAbsRef.aStart.Col() != aAbsRef.aEnd.Col() || @@ -1718,7 +1718,7 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL } virtual void makeExternalRefStr( - const ScDocument* pDoc, + ScSheetLimits& rLimits, OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 /*nFileId*/, const OUString& rFileName, const std::vector<OUString>& rTabNames, const OUString& rTabName, const ScComplexRefData& rRef ) const override @@ -1735,7 +1735,7 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL return; } - if (aAbsRef.aStart.Col() == 0 && aAbsRef.aEnd.Col() >= pDoc->MaxCol()) + if (aAbsRef.aStart.Col() == 0 && aAbsRef.aEnd.Col() >= rLimits.mnMaxCol) { r1c1_add_row(rBuffer, rRef.Ref1, aAbsRef.aStart); if (aAbsRef.aStart.Row() != aAbsRef.aEnd.Row() || rRef.Ref1.IsRowRel() != rRef.Ref2.IsRowRel()) @@ -1746,7 +1746,7 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL return; } - if (aAbsRef.aStart.Row() == 0 && aAbsRef.aEnd.Row() >= pDoc->MaxRow()) + if (aAbsRef.aStart.Row() == 0 && aAbsRef.aEnd.Row() >= rLimits.mnMaxRow) { r1c1_add_col(rBuffer, rRef.Ref1, aAbsRef.aStart); if (aAbsRef.aStart.Col() != aAbsRef.aEnd.Col() || rRef.Ref1.IsColRel() != rRef.Ref2.IsColRel()) @@ -4658,7 +4658,7 @@ std::unique_ptr<ScTokenArray> ScCompiler::CompileString( const OUString& rFormul ++pFunctionStack[ nFunction ].nSep; } } - FormulaToken* pNewToken = static_cast<ScTokenArray*>(pArr)->Add( maRawToken.CreateToken(pDoc)); + FormulaToken* pNewToken = static_cast<ScTokenArray*>(pArr)->Add( maRawToken.CreateToken(pDoc->GetSheetLimits())); if (!pNewToken && eOp == ocArrayClose && pArr->OpCodeBefore( pArr->GetLen()) == ocArrayClose) { // Nested inline array or non-value/non-string in array. The @@ -5026,7 +5026,7 @@ void ScCompiler::CreateStringFromExternal( OUStringBuffer& rBuffer, const Formul *pFileName << "' '" << t->GetString().getString() << "'"); pConv->makeExternalRefStr( - pDoc, rBuffer, GetPos(), nFileId, *pFileName, aTabNames, t->GetString().getString(), + pDoc->GetSheetLimits(), rBuffer, GetPos(), nFileId, *pFileName, aTabNames, t->GetString().getString(), *t->GetDoubleRef()); } break; @@ -5128,7 +5128,7 @@ void ScCompiler::CreateStringFromSingleRef( OUStringBuffer& rBuffer, const Formu else { rBuffer.append(ScCompiler::GetNativeSymbol(ocErrName)); - pConv->makeRefStr(pDoc, rBuffer, meGrammar, aPos, aErrRef, + pConv->makeRefStr(pDoc->GetSheetLimits(), rBuffer, meGrammar, aPos, aErrRef, GetSetupTabNames(), aRef, true, (pArr && pArr->IsFromRangeName())); } } @@ -5160,14 +5160,14 @@ void ScCompiler::CreateStringFromSingleRef( OUStringBuffer& rBuffer, const Formu rBuffer.append(aStr); } else - pConv->makeRefStr(pDoc, rBuffer, meGrammar, aPos, aErrRef, + pConv->makeRefStr(pDoc->GetSheetLimits(), rBuffer, meGrammar, aPos, aErrRef, GetSetupTabNames(), aRef, true, (pArr && pArr->IsFromRangeName())); } void ScCompiler::CreateStringFromDoubleRef( OUStringBuffer& rBuffer, const FormulaToken* _pTokenP ) const { OUString aErrRef = GetCurrentOpCodeMap()->getSymbol(ocErrRef); - pConv->makeRefStr(pDoc, rBuffer, meGrammar, aPos, aErrRef, GetSetupTabNames(), + pConv->makeRefStr(pDoc->GetSheetLimits(), rBuffer, meGrammar, aPos, aErrRef, GetSetupTabNames(), *_pTokenP->GetDoubleRef(), false, (pArr && pArr->IsFromRangeName())); } @@ -5287,7 +5287,7 @@ sal_Unicode ScCompiler::GetNativeAddressSymbol( Convention::SpecialSymbolType eT FormulaTokenRef ScCompiler::ExtendRangeReference( FormulaToken & rTok1, FormulaToken & rTok2 ) { - return extendRangeReference( pDoc, rTok1, rTok2, aPos, true/*bReuseDoubleRef*/ ); + return extendRangeReference( pDoc->GetSheetLimits(), rTok1, rTok2, aPos, true/*bReuseDoubleRef*/ ); } void ScCompiler::fillAddInToken(::std::vector< css::sheet::FormulaOpCodeMapEntry >& _rVec,bool _bIsEnglish) const @@ -5519,7 +5519,7 @@ bool ScCompiler::HandleColRowName() pNew->AddDoubleReference( aRefData ); else { // automagically - pNew->Add( new ScDoubleRefToken( pDoc, aRefData, ocColRowNameAuto ) ); + pNew->Add( new ScDoubleRefToken( pDoc->GetSheetLimits(), aRefData, ocColRowNameAuto ) ); } } PushTokenArray( pNew, true ); @@ -5808,7 +5808,7 @@ bool ScCompiler::HandleTableRef() if (nError != FormulaError::NONE) { aRefData.SetAddress( aRange.aStart, aRange.aStart); - pTR->SetAreaRefRPN( new ScSingleRefToken(pDoc, aRefData)); // set reference at TableRef + pTR->SetAreaRefRPN( new ScSingleRefToken(pDoc->GetSheetLimits(), aRefData)); // set reference at TableRef pNew->Add( new FormulaErrorToken( nError)); // set error in RPN } else @@ -5837,7 +5837,7 @@ bool ScCompiler::HandleTableRef() if (nError != FormulaError::NONE) { aRefData.SetRange( aRange, aRange.aStart); - pTR->SetAreaRefRPN( new ScDoubleRefToken(pDoc, aRefData)); // set reference at TableRef + pTR->SetAreaRefRPN( new ScDoubleRefToken(pDoc->GetSheetLimits(), aRefData)); // set reference at TableRef pNew->Add( new FormulaErrorToken( nError)); // set error in RPN } else @@ -6095,7 +6095,7 @@ void ScCompiler::ReplaceDoubleRefII(FormulaToken** ppDoubleRefTok) aSingleRef.SetAddress(aAddr, aPos); // Replace the original doubleref token with computed singleref token - FormulaToken* pNewSingleRefTok = new ScSingleRefToken(pDoc, aSingleRef); + FormulaToken* pNewSingleRefTok = new ScSingleRefToken(pDoc->GetSheetLimits(), aSingleRef); (*ppDoubleRefTok)->DecRef(); *ppDoubleRefTok = pNewSingleRefTok; pNewSingleRefTok->IncRef(); @@ -6226,7 +6226,7 @@ void ScCompiler::CorrectSumRange(const ScComplexRefData& rBaseRange, return; // Replace sum-range token - FormulaToken* pNewSumRangeTok = new ScDoubleRefToken(pDoc, rSumRange); + FormulaToken* pNewSumRangeTok = new ScDoubleRefToken(pDoc->GetSheetLimits(), rSumRange); (*ppSumRangeToken)->DecRef(); *ppSumRangeToken = pNewSumRangeTok; pNewSumRangeTok->IncRef(); diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx index e20af82a4f4b..43bf4f75da07 100644 --- a/sc/source/core/tool/interpr2.cxx +++ b/sc/source/core/tool/interpr2.cxx @@ -2494,9 +2494,9 @@ void ScInterpreter::ScIntersect() { const ScComplexRefData& rRef = (*pRefList)[0]; if (rRef.Ref1 == rRef.Ref2) - PushTempToken( new ScSingleRefToken(pDok, rRef.Ref1)); + PushTempToken( new ScSingleRefToken(pDok->GetSheetLimits(), rRef.Ref1)); else - PushTempToken( new ScDoubleRefToken(pDok, rRef)); + PushTempToken( new ScDoubleRefToken(pDok->GetSheetLimits(), rRef)); } else PushTokenRef( xRes); @@ -2568,7 +2568,7 @@ void ScInterpreter::ScRangeFunc() // We explicitly tell extendRangeReference() to not reuse the token, // casting const away spares two clones. FormulaTokenRef xRes = extendRangeReference( - pDok, const_cast<FormulaToken&>(*x1), const_cast<FormulaToken&>(*x2), aPos, false); + pDok->GetSheetLimits(), const_cast<FormulaToken&>(*x1), const_cast<FormulaToken&>(*x2), aPos, false); if (!xRes) PushIllegalArgument(); else diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 55d6b715c2f4..8a7143fb94ef 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -1367,7 +1367,7 @@ void ScInterpreter::PopRefListPushMatrixOrRef() if (nEntries == 1) { --sp; - PushTempTokenWithoutError( new ScDoubleRefToken( pDok, (*pv)[0] )); + PushTempTokenWithoutError( new ScDoubleRefToken( pDok->GetSheetLimits(), (*pv)[0] )); } else if (bMatrixFormula) { @@ -1813,7 +1813,7 @@ void ScInterpreter::PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab) { ScSingleRefData aRef; aRef.InitAddress(ScAddress(nCol,nRow,nTab)); - PushTempTokenWithoutError( new ScSingleRefToken( pDok, aRef ) ); + PushTempTokenWithoutError( new ScSingleRefToken( pDok->GetSheetLimits(), aRef ) ); } } @@ -1824,7 +1824,7 @@ void ScInterpreter::PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, { ScComplexRefData aRef; aRef.InitRange(ScRange(nCol1,nRow1,nTab1,nCol2,nRow2,nTab2)); - PushTempTokenWithoutError( new ScDoubleRefToken( pDok, aRef ) ); + PushTempTokenWithoutError( new ScDoubleRefToken( pDok->GetSheetLimits(), aRef ) ); } } @@ -1859,7 +1859,7 @@ void ScInterpreter::PushSingleRef( const ScRefAddress& rRef ) { ScSingleRefData aRef; aRef.InitFromRefAddress( rRef, aPos); - PushTempTokenWithoutError( new ScSingleRefToken( pDok, aRef ) ); + PushTempTokenWithoutError( new ScSingleRefToken( pDok->GetSheetLimits(), aRef ) ); } } @@ -1869,7 +1869,7 @@ void ScInterpreter::PushDoubleRef( const ScRefAddress& rRef1, const ScRefAddress { ScComplexRefData aRef; aRef.InitFromRefAddresses( rRef1, rRef2, aPos); - PushTempTokenWithoutError( new ScDoubleRefToken( pDok, aRef ) ); + PushTempTokenWithoutError( new ScDoubleRefToken( pDok->GetSheetLimits(), aRef ) ); } } @@ -3666,7 +3666,7 @@ void ScInterpreter::ScDBArea() pDBData->GetArea(aRange); aRange.aEnd.SetTab(aRange.aStart.Tab()); aRefData.SetRange(aRange, aPos); - PushTempToken( new ScDoubleRefToken( pDok, aRefData ) ); + PushTempToken( new ScDoubleRefToken( pDok->GetSheetLimits(), aRefData ) ); } else PushError( FormulaError::NoName); @@ -3750,7 +3750,7 @@ void ScInterpreter::ScColRowNameAuto() } } aRefData.SetRange(aAbs, aPos); - PushTempToken( new ScDoubleRefToken( pDok, aRefData ) ); + PushTempToken( new ScDoubleRefToken( pDok->GetSheetLimits(), aRefData ) ); } // --- internals ------------------------------------------------------------ diff --git a/sc/source/core/tool/reftokenhelper.cxx b/sc/source/core/tool/reftokenhelper.cxx index 135b544fcdac..15341e92f930 100644 --- a/sc/source/core/tool/reftokenhelper.cxx +++ b/sc/source/core/tool/reftokenhelper.cxx @@ -176,7 +176,7 @@ void ScRefTokenHelper::getTokenFromRange(const ScDocument* pDoc, ScTokenRef& pTo // different sheets. aData.Ref2.SetFlag3D(rRange.aStart.Tab() != rRange.aEnd.Tab()); - pToken.reset(new ScDoubleRefToken(pDoc, aData)); + pToken.reset(new ScDoubleRefToken(pDoc->GetSheetLimits(), aData)); } void ScRefTokenHelper::getTokensFromRangeList(const ScDocument* pDoc, vector<ScTokenRef>& pTokens, const ScRangeList& rRanges) @@ -389,7 +389,7 @@ private: if (bExternal) pOldToken.reset(new ScExternalDoubleRefToken(nFileId, aTabName, aNewData)); else - pOldToken.reset(new ScDoubleRefToken(pDoc, aNewData)); + pOldToken.reset(new ScDoubleRefToken(pDoc->GetSheetLimits(), aNewData)); bJoined = true; break; @@ -449,7 +449,7 @@ ScTokenRef ScRefTokenHelper::createRefToken(const ScDocument* pDoc, const ScAddr { ScSingleRefData aRefData; aRefData.InitAddress(rAddr); - ScTokenRef pRef(new ScSingleRefToken(pDoc, aRefData)); + ScTokenRef pRef(new ScSingleRefToken(pDoc->GetSheetLimits(), aRefData)); return pRef; } @@ -457,7 +457,7 @@ ScTokenRef ScRefTokenHelper::createRefToken(const ScDocument* pDoc, const ScRang { ScComplexRefData aRefData; aRefData.InitRange(rRange); - ScTokenRef pRef(new ScDoubleRefToken(pDoc, aRefData)); + ScTokenRef pRef(new ScDoubleRefToken(pDoc->GetSheetLimits(), aRefData)); return pRef; } diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index 332debee8d10..6fd70a6eaf23 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -350,7 +350,7 @@ bool ScRawToken::IsValidReference(const ScDocument* pDoc) const return false; } -FormulaToken* ScRawToken::CreateToken(const ScDocument* pDoc) const +FormulaToken* ScRawToken::CreateToken(ScSheetLimits& rLimits) const { #define IF_NOT_OPCODE_ERROR(o,c) SAL_WARN_IF((eOp!=o), "sc.core", #c "::ctor: OpCode " << static_cast<int>(eOp) << " lost, converted to " #o "; maybe inherit from FormulaToken instead!") switch ( GetType() ) @@ -370,14 +370,14 @@ FormulaToken* ScRawToken::CreateToken(const ScDocument* pDoc) const } case svSingleRef : if (eOp == ocPush) - return new ScSingleRefToken(pDoc, aRef.Ref1 ); + return new ScSingleRefToken(rLimits, aRef.Ref1 ); else - return new ScSingleRefToken(pDoc, aRef.Ref1, eOp ); + return new ScSingleRefToken(rLimits, aRef.Ref1, eOp ); case svDoubleRef : if (eOp == ocPush) - return new ScDoubleRefToken(pDoc, aRef ); + return new ScDoubleRefToken(rLimits, aRef ); else - return new ScDoubleRefToken(pDoc, aRef, eOp ); + return new ScDoubleRefToken(rLimits, aRef, eOp ); case svMatrix : IF_NOT_OPCODE_ERROR( ocPush, ScMatrixToken); return new ScMatrixToken( pMat ); @@ -499,7 +499,7 @@ void DumpToken(formula::FormulaToken const & rToken) } #endif -FormulaTokenRef extendRangeReference( const ScDocument* pDoc, FormulaToken & rTok1, FormulaToken & rTok2, +FormulaTokenRef extendRangeReference( ScSheetLimits& rLimits, FormulaToken & rTok1, FormulaToken & rTok2, const ScAddress & rPos, bool bReuseDoubleRef ) { @@ -549,7 +549,7 @@ FormulaTokenRef extendRangeReference( const ScDocument* pDoc, FormulaToken & rTo if (bExternal) xRes = new ScExternalDoubleRefToken( rTok1.GetIndex(), rTok1.GetString(), aRef); else - xRes = new ScDoubleRefToken(pDoc, aRef); + xRes = new ScDoubleRefToken(rLimits, aRef); } else { @@ -575,7 +575,7 @@ FormulaTokenRef extendRangeReference( const ScDocument* pDoc, FormulaToken & rTo return nullptr; if (bExternal) return nullptr; // external reference list not possible - xRes = new ScDoubleRefToken(pDoc, (*pRefList)[0] ); + xRes = new ScDoubleRefToken(rLimits, (*pRefList)[0] ); } if (!xRes) return nullptr; // shouldn't happen... @@ -1678,7 +1678,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r ) } } -bool ScTokenArray::ImplGetReference( const ScDocument* pDoc, ScRange& rRange, const ScAddress& rPos, bool bValidOnly ) const +bool ScTokenArray::ImplGetReference( ScRange& rRange, const ScAddress& rPos, bool bValidOnly ) const { bool bIs = false; if ( pCode && nLen == 1 ) @@ -1690,7 +1690,7 @@ bool ScTokenArray::ImplGetReference( const ScDocument* pDoc, ScRange& rRange, co { const ScSingleRefData& rRef = *static_cast<const ScSingleRefToken*>(pToken)->GetSingleRef(); rRange.aStart = rRange.aEnd = rRef.toAbs(rPos); - bIs = !bValidOnly || pDoc->ValidAddress(rRange.aStart); + bIs = !bValidOnly || mxSheetLimits->ValidAddress(rRange.aStart); } else if ( pToken->GetType() == svDoubleRef ) { @@ -1699,7 +1699,7 @@ bool ScTokenArray::ImplGetReference( const ScDocument* pDoc, ScRange& rRange, co const ScSingleRefData& rRef2 = rCompl.Ref2; rRange.aStart = rRef1.toAbs(rPos); rRange.aEnd = rRef2.toAbs(rPos); - bIs = !bValidOnly || pDoc->ValidRange(rRange); + bIs = !bValidOnly || mxSheetLimits->ValidRange(rRange); } } } @@ -1852,17 +1852,25 @@ bool ScTokenArray::IsInvariant() const bool ScTokenArray::IsReference( ScRange& rRange, const ScAddress& rPos ) const { - return ImplGetReference(mpDoc, rRange, rPos, false); + return ImplGetReference(rRange, rPos, false); } bool ScTokenArray::IsValidReference( ScRange& rRange, const ScAddress& rPos ) const { - return ImplGetReference(mpDoc, rRange, rPos, true); + return ImplGetReference(rRange, rPos, true); } ScTokenArray::ScTokenArray(const ScDocument* pDoc) : FormulaTokenArray(), - mpDoc(pDoc), + mxSheetLimits(&pDoc->GetSheetLimits()), + mnHashValue(0) +{ + ResetVectorState(); +} + +ScTokenArray::ScTokenArray(ScSheetLimits& rLimits) : + FormulaTokenArray(), + mxSheetLimits(&rLimits), mnHashValue(0) { ResetVectorState(); @@ -1909,7 +1917,7 @@ void ScTokenArray::Clear() std::unique_ptr<ScTokenArray> ScTokenArray::Clone() const { - std::unique_ptr<ScTokenArray> p(new ScTokenArray(mpDoc)); + std::unique_ptr<ScTokenArray> p(new ScTokenArray(*mxSheetLimits)); p->nLen = nLen; p->nRPN = nRPN; p->nMode = nMode; @@ -1967,7 +1975,7 @@ std::unique_ptr<ScTokenArray> ScTokenArray::Clone() const FormulaToken* ScTokenArray::AddRawToken( const ScRawToken& r ) { - return Add( r.CreateToken(mpDoc) ); + return Add( r.CreateToken(*mxSheetLimits) ); } // Utility function to ensure that there is strict alternation of values and @@ -2165,7 +2173,7 @@ void ScTokenArray::MergeRangeReference( const ScAddress & rPos ) (((p2 = PeekPrev(nIdx)) != nullptr) && p2->GetOpCode() == ocRange) && ((p1 = PeekPrev(nIdx)) != nullptr)) { - FormulaTokenRef p = extendRangeReference( mpDoc, *p1, *p3, rPos, true); + FormulaTokenRef p = extendRangeReference( *mxSheetLimits, *p1, *p3, rPos, true); if (p) { p->IncRef(); @@ -2187,17 +2195,17 @@ FormulaToken* ScTokenArray::AddOpCode( OpCode e ) FormulaToken* ScTokenArray::AddSingleReference( const ScSingleRefData& rRef ) { - return Add( new ScSingleRefToken(mpDoc, rRef ) ); + return Add( new ScSingleRefToken( *mxSheetLimits, rRef ) ); } FormulaToken* ScTokenArray::AddMatrixSingleReference( const ScSingleRefData& rRef ) { - return Add( new ScSingleRefToken(mpDoc, rRef, ocMatRef ) ); + return Add( new ScSingleRefToken(*mxSheetLimits, rRef, ocMatRef ) ); } FormulaToken* ScTokenArray::AddDoubleReference( const ScComplexRefData& rRef ) { - return Add( new ScDoubleRefToken(mpDoc, rRef ) ); + return Add( new ScDoubleRefToken(*mxSheetLimits, rRef ) ); } FormulaToken* ScTokenArray::AddMatrix( const ScMatrixRef& p ) @@ -2234,7 +2242,7 @@ FormulaToken* ScTokenArray::AddExternalDoubleReference( sal_uInt16 nFileId, cons FormulaToken* ScTokenArray::AddColRowName( const ScSingleRefData& rRef ) { - return Add( new ScSingleRefToken(mpDoc, rRef, ocColRowName ) ); + return Add( new ScSingleRefToken(*mxSheetLimits, rRef, ocColRowName ) ); } void ScTokenArray::AssignXMLString( const OUString &rText, const OUString &rFormulaNmsp ) @@ -2258,13 +2266,13 @@ bool ScTokenArray::GetAdjacentExtendOfOuterFuncRefs( SCCOLROW& nExtend, switch ( eDir ) { case DIR_BOTTOM : - if ( rPos.Row() < mpDoc->MaxRow() ) + if ( rPos.Row() < mxSheetLimits->mnMaxRow ) nRow = (nExtend = rPos.Row()) + 1; else return false; break; case DIR_RIGHT : - if ( rPos.Col() < mpDoc->MaxCol() ) + if ( rPos.Col() < mxSheetLimits->mnMaxCol ) nCol = static_cast<SCCOL>(nExtend = rPos.Col()) + 1; else return false; @@ -4513,7 +4521,7 @@ void ScTokenArray::ClearTabDeleted( const ScAddress& rPos, SCTAB nStartTab, SCTA namespace { void checkBounds( - const ScDocument* pDoc, + ScSheetLimits& rLimits, const ScAddress& rPos, SCROW nGroupLen, const ScRange& rCheckRange, const ScSingleRefData& rRef, std::vector<SCROW>& rBounds, const ScRange* pDeletedRange ) { @@ -4549,7 +4557,7 @@ void checkBounds( SCROW nOffset = pDeletedRange->aStart.Row() - aAbs.aStart.Row(); SCROW nRow = rPos.Row() + nOffset; // Unlike for rCheckRange, for pDeletedRange nRow can be anywhere>=0. - if (pDoc->ValidRow(nRow)) + if (rLimits.ValidRow(nRow)) rBounds.push_back(nRow); } @@ -4574,7 +4582,7 @@ void checkBounds( SCROW nOffset = pDeletedRange->aEnd.Row() + 1 - aAbs.aStart.Row(); SCROW nRow = rPos.Row() + nOffset; // Unlike for rCheckRange, for pDeletedRange nRow can be ~anywhere. - if (pDoc->ValidRow(nRow)) + if (rLimits.ValidRow(nRow)) rBounds.push_back(nRow); } } @@ -4612,7 +4620,7 @@ void checkBounds( pDeletedRange = &aDeletedRange; } - checkBounds(&rCxt.mrDoc, rPos, nGroupLen, aCheckRange, rRef, rBounds, pDeletedRange); + checkBounds(rCxt.mrDoc.GetSheetLimits(), rPos, nGroupLen, aCheckRange, rRef, rBounds, pDeletedRange); } } @@ -4671,14 +4679,14 @@ void ScTokenArray::CheckRelativeReferenceBounds( case svSingleRef: { const ScSingleRefData& rRef = *p->GetSingleRef(); - checkBounds(mpDoc, rPos, nGroupLen, rRange, rRef, rBounds, nullptr); + checkBounds(*mxSheetLimits, rPos, nGroupLen, rRange, rRef, rBounds, nullptr); } break; case svDoubleRef: { const ScComplexRefData& rRef = *p->GetDoubleRef(); - checkBounds(mpDoc, rPos, nGroupLen, rRange, rRef.Ref1, rBounds, nullptr); - checkBounds(mpDoc, rPos, nGroupLen, rRange, rRef.Ref2, rBounds, nullptr); + checkBounds(*mxSheetLimits, rPos, nGroupLen, rRange, rRef.Ref1, rBounds, nullptr); + checkBounds(*mxSheetLimits, rPos, nGroupLen, rRange, rRef.Ref2, rBounds, nullptr); } break; default: @@ -4814,7 +4822,7 @@ void appendString( OUStringBuffer& rBuf, const OUString& rStr ) rBuf.append('"'); } -void appendTokenByType( const ScDocument* pDoc, sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, const FormulaToken& rToken, +void appendTokenByType( ScSheetLimits& rLimits, sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, const FormulaToken& rToken, const ScAddress& rPos, bool bFromRangeName ) { if (rToken.IsExternalRef()) @@ -4845,7 +4853,7 @@ void appendTokenByType( const ScDocument* pDoc, sc::TokenStringContext& rCxt, OU return; rCxt.mpRefConv->makeExternalRefStr( - pDoc, rBuf, rPos, nFileId, aFileName, it->second, aTabName, + rLimits, rBuf, rPos, nFileId, aFileName, it->second, aTabName, *rToken.GetDoubleRef()); } break; @@ -4883,7 +4891,7 @@ void appendTokenByType( const ScDocument* pDoc, sc::TokenStringContext& rCxt, OU ScComplexRefData aRef; aRef.Ref1 = rRef; aRef.Ref2 = rRef; - rCxt.mpRefConv->makeRefStr(pDoc, rBuf, rCxt.meGram, rPos, rCxt.maErrRef, rCxt.maTabNames, aRef, true, + rCxt.mpRefConv->makeRefStr(rLimits, rBuf, rCxt.meGram, rPos, rCxt.maErrRef, rCxt.maTabNames, aRef, true, bFromRangeName); } else @@ -4895,7 +4903,7 @@ void appendTokenByType( const ScDocument* pDoc, sc::TokenStringContext& rCxt, OU if (rCxt.mpRefConv) { const ScComplexRefData& rRef = *rToken.GetDoubleRef(); - rCxt.mpRefConv->makeRefStr(pDoc, rBuf, rCxt.meGram, rPos, rCxt.maErrRef, rCxt.maTabNames, rRef, false, + rCxt.mpRefConv->makeRefStr(rLimits, rBuf, rCxt.meGram, rPos, rCxt.maErrRef, rCxt.maTabNames, rRef, false, bFromRangeName); } else @@ -5115,7 +5123,7 @@ OUString ScTokenArray::CreateString( sc::TokenStringContext& rCxt, const ScAddre if (eOp < rCxt.mxOpCodeMap->getSymbolCount()) aBuf.append(rCxt.mxOpCodeMap->getSymbol(eOp)); - appendTokenByType(mpDoc, rCxt, aBuf, *pToken, rPos, IsFromRangeName()); + appendTokenByType(*mxSheetLimits, rCxt, aBuf, *pToken, rPos, IsFromRangeName()); } return aBuf.makeStringAndClear(); diff --git a/sc/source/ui/unoobj/chart2uno.cxx b/sc/source/ui/unoobj/chart2uno.cxx index 658ad00c7b91..b7c11adfedba 100644 --- a/sc/source/ui/unoobj/chart2uno.cxx +++ b/sc/source/ui/unoobj/chart2uno.cxx @@ -762,7 +762,7 @@ void Chart2Positioner::createPositionMap() if (bExternal) rCol[ nInsRow ].reset(new ScExternalSingleRefToken(nFileId, aTabName, aCellData)); else - rCol[ nInsRow ].reset(new ScSingleRefToken(mpDoc, aCellData)); + rCol[ nInsRow ].reset(new ScSingleRefToken(mpDoc->GetSheetLimits(), aCellData)); } } } @@ -921,12 +921,12 @@ private: if (bExternal) rStart.reset(new ScExternalSingleRefToken(nFileId, aTabName, aData.Ref1)); else - rStart.reset(new ScSingleRefToken(pDoc, aData.Ref1)); + rStart.reset(new ScSingleRefToken(pDoc->GetSheetLimits(), aData.Ref1)); if (bExternal) rEnd.reset(new ScExternalSingleRefToken(nFileId, aTabName, aData.Ref2)); else - rEnd.reset(new ScSingleRefToken(pDoc, aData.Ref2)); + rEnd.reset(new ScSingleRefToken(pDoc->GetSheetLimits(), aData.Ref2)); return true; } @@ -1292,7 +1292,7 @@ bool lcl_addUpperLeftCornerIfMissing(const ScDocument* pDoc, vector<ScTokenRef>& } else { - ScTokenRef pCorner(new ScSingleRefToken(pDoc, aData)); + ScTokenRef pCorner(new ScSingleRefToken(pDoc->GetSheetLimits(), aData)); ScRefTokenHelper::join(pDoc, rRefTokens, pCorner, ScAddress()); } } @@ -1312,7 +1312,7 @@ bool lcl_addUpperLeftCornerIfMissing(const ScDocument* pDoc, vector<ScTokenRef>& } else { - ScTokenRef pCorner(new ScDoubleRefToken(pDoc, r)); + ScTokenRef pCorner(new ScDoubleRefToken(pDoc->GetSheetLimits(), r)); ScRefTokenHelper::join(pDoc, rRefTokens, pCorner, ScAddress()); } } commit 3b8e554b69de349a20d10ec90b27ab71a013b464 Author: Deena Francis <deena.fran...@gmail.com> AuthorDate: Fri Dec 13 19:49:36 2019 +0530 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Fri Dec 13 19:41:49 2019 +0100 tdf#120948: row deltas should be stored as SCROW... instead of SCCOL, else it may cause overflows. Also included a unit test for protecting the fix. Change-Id: I8f735b23b7f95ecf34ccae86f00c76b82b0d668f Reviewed-on: https://gerrit.libreoffice.org/85118 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx index d5b0bdf7ab28..777dc4a51389 100644 --- a/sc/qa/unit/ucalc.hxx +++ b/sc/qa/unit/ucalc.hxx @@ -562,6 +562,7 @@ public: void testProtectedSheetEditByColumn(); void testFuncRowsHidden(); void testInsertColCellStoreEventSwap(); + void testFormulaAfterDeleteRows(); CPPUNIT_TEST_SUITE(Test); CPPUNIT_TEST(testCollator); @@ -862,6 +863,7 @@ public: CPPUNIT_TEST(testProtectedSheetEditByColumn); CPPUNIT_TEST(testFuncRowsHidden); CPPUNIT_TEST(testInsertColCellStoreEventSwap); + CPPUNIT_TEST(testFormulaAfterDeleteRows); CPPUNIT_TEST_SUITE_END(); private: diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx index b90db089d8ed..5c93d3083111 100644 --- a/sc/qa/unit/ucalc_formula.cxx +++ b/sc/qa/unit/ucalc_formula.cxx @@ -8996,4 +8996,24 @@ void Test::testInsertColCellStoreEventSwap() m_pDoc->DeleteTab(0); } +void Test::testFormulaAfterDeleteRows() +{ + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on. + m_pDoc->InsertTab(0, "Test"); + + // Fill A1:A70000 with 1.0 + std::vector<double> aVals(70000, 1.0); + m_pDoc->SetValues(ScAddress(0, 0, 0), aVals); + // Set A70001 with formula "=SUM(A1:A70000)" + m_pDoc->SetString(0, 70000, 0, "=SUM(A1:A70000)"); + + // Delete rows 2:69998 + m_pDoc->DeleteRow(ScRange(0, 1, 0, m_pDoc->MaxCol(), 69997, 0)); + + const ScAddress aPos(0, 3, 0); // A4 + ASSERT_FORMULA_EQUAL(*m_pDoc, aPos, "SUM(A1:A3)", "Wrong formula in A4."); + + ASSERT_DOUBLES_EQUAL_MESSAGE("Wrong value at A4", 3.0, m_pDoc->GetValue(aPos)); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index a70c68842273..332debee8d10 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -2838,8 +2838,8 @@ ShrinkResult shrinkRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, else { // The reference range is truncated on the top. - SCCOL nOffset = rDeletedRange.aStart.Row() - rRefRange.aStart.Row(); - SCCOL nDelta = rRefRange.aStart.Row() - rDeletedRange.aEnd.Row() - 1; + SCROW nOffset = rDeletedRange.aStart.Row() - rRefRange.aStart.Row(); + SCROW nDelta = rRefRange.aStart.Row() - rDeletedRange.aEnd.Row() - 1; rRefRange.IncEndRowSticky(&rCxt.mrDoc, nDelta+nOffset); rRefRange.aStart.IncRow(nOffset); } @@ -2852,7 +2852,7 @@ ShrinkResult shrinkRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, // Reference is deleted in the middle. Move the last row // position upward. - SCCOL nDelta = rDeletedRange.aStart.Row() - rDeletedRange.aEnd.Row() - 1; + SCROW nDelta = rDeletedRange.aStart.Row() - rDeletedRange.aEnd.Row() - 1; rRefRange.IncEndRowSticky(&rCxt.mrDoc, nDelta); } else @@ -2862,7 +2862,7 @@ ShrinkResult shrinkRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, return STICKY; // The reference range is truncated on the bottom. - SCCOL nDelta = rDeletedRange.aStart.Row() - rRefRange.aEnd.Row() - 1; + SCROW nDelta = rDeletedRange.aStart.Row() - rRefRange.aEnd.Row() - 1; rRefRange.IncEndRowSticky(&rCxt.mrDoc, nDelta); } return SHRUNK; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits