diff options
author | Ivo Hinkelmann <ihi@openoffice.org> | 2009-04-02 15:00:15 +0000 |
---|---|---|
committer | Ivo Hinkelmann <ihi@openoffice.org> | 2009-04-02 15:00:15 +0000 |
commit | d847cf92cf4f2ee7927c3662f12e91ee84fb5331 (patch) | |
tree | 48f4071d5063581bf385fb87bbb904acf289b897 | |
parent | a08dbc2fa8f1a79555352d0b1693e6e3faa96516 (diff) |
CWS-TOOLING: integrate CWS calc31stopper4_DEV300
2009-03-25 11:52:59 +0100 nn r270010 : GetHTMLRangeNameList: call ScHTMLImport static method, not same method again (bug-id not available yet)
2009-03-20 14:24:51 +0100 er r269808 : #i100416# makeExternalRefStrImpl: don't care about a second sheet name if not needed
2009-03-20 13:14:30 +0100 er r269803 : carry along row position also for non-existing (empty) rows
2009-03-20 11:26:33 +0100 er r269790 : SUNWS12: declarator required in declaration; removed SC_DLLPRIVATE from inner class declaration
2009-03-19 19:40:09 +0100 er r269767 : #i100300# save only referenced tables of external data cache
2009-03-19 14:45:05 +0100 dr r269746 : #i100346# more places where checking docshell is needed
2009-03-19 14:13:20 +0100 fs r269744 : #i100349# do not delete the pool before all instances knowing it have been deleted
2009-03-19 11:35:45 +0100 dr r269735 : #i100346# always check docshell, is missing when pasting from clipboard
2009-03-19 09:39:49 +0100 dr r269728 : #i100332# remove debug statement, patch from kohei
26 files changed, 531 insertions, 48 deletions
diff --git a/sc/inc/cell.hxx b/sc/inc/cell.hxx index 708ddbe31ef0..b8a228ddfd09 100644 --- a/sc/inc/cell.hxx +++ b/sc/inc/cell.hxx @@ -381,6 +381,7 @@ public: void CompileTokenArray( BOOL bNoListening = FALSE ); void CompileXML( ScProgress& rProgress ); // compile temporary string tokens void CalcAfterLoad(); + bool MarkUsedExternalReferences(); void Interpret(); inline BOOL IsIterCell() const { return bIsIterCell; } inline USHORT GetSeenInIteration() const { return nSeenInIteration; } diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index fc73c858c69f..c66ecb960e7d 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -279,6 +279,7 @@ public: void CalcAfterLoad(); void CompileAll(); void CompileXML( ScProgress& rProgress ); + bool MarkUsedExternalReferences(); void ResetChanged( SCROW nStartRow, SCROW nEndRow ); diff --git a/sc/inc/conditio.hxx b/sc/inc/conditio.hxx index 90e10ed72cb3..2ec655585cd4 100644 --- a/sc/inc/conditio.hxx +++ b/sc/inc/conditio.hxx @@ -149,6 +149,8 @@ public: void SourceChanged( const ScAddress& rChanged ); + bool MarkUsedExternalReferences() const; + protected: virtual void DataChanged( const ScRange* pModified ) const; ScDocument* GetDocument() const { return pDoc; } @@ -240,6 +242,8 @@ public: void SetUsed(BOOL bSet) { bIsUsed = bSet; } BOOL IsUsed() const { return bIsUsed; } + bool MarkUsedExternalReferences() const; + // sortiert (per PTRARR) nach Index // operator== nur fuer die Sortierung BOOL operator ==( const ScConditionalFormat& r ) const { return nKey == r.nKey; } @@ -278,6 +282,10 @@ public: void SourceChanged( const ScAddress& rAddr ); + /** Temporarily during save, returns RefManager's decision whether ALL + * references are marked now. */ + bool MarkUsedExternalReferences() const; + BOOL operator==( const ScConditionalFormatList& r ) const; // fuer Ref-Undo }; diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 78bc75e318dd..e21b0af336f0 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -606,7 +606,11 @@ public: const String& aFileName, const String& aTabName ); + bool HasExternalRefManager() { return pExternalRefMgr.get(); } SC_DLLPUBLIC ScExternalRefManager* GetExternalRefManager(); + bool IsInExternalReferenceMarking() const; + void MarkUsedExternalReferences(); + bool MarkUsedExternalReferences( ScTokenArray & rArr ); BOOL HasDdeLinks() const; BOOL HasAreaLinks() const; diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx index 55d80751e957..b4c63101ec70 100644 --- a/sc/inc/externalrefmgr.hxx +++ b/sc/inc/externalrefmgr.hxx @@ -138,12 +138,18 @@ public: SC_DLLPUBLIC void setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex = 0); TokenRef getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex = NULL) const; bool hasRow( SCROW nRow ) const; + /// A temporary state used only during store to file. + bool isReferenced() const; + void setReferenced( bool bReferenced ); + /// Obtain a sorted vector of rows. void getAllRows(::std::vector<SCROW>& rRows) const; + /// Obtain a sorted vector of columns. void getAllCols(SCROW nRow, ::std::vector<SCCOL>& rCols) const; void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const; private: RowsDataType maRows; + bool mbReferenced; }; typedef ::boost::shared_ptr<Table> TableTypeRef; @@ -202,6 +208,45 @@ public: bool hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const; size_t getCacheTableCount(sal_uInt16 nFileId) const; + /** + * Set all tables of a document as referenced, used only during + * store-to-file. + * @returns <TRUE/> if ALL tables of ALL documents are marked. + */ + bool setCacheDocReferenced( sal_uInt16 nFileId ); + + /** + * Set a table as referenced, used only during store-to-file. + * @returns <TRUE/> if ALL tables of ALL documents are marked. + */ + bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName ); + void setAllCacheTableReferencedStati( bool bReferenced ); + bool areAllCacheTablesReferenced() const; +private: + struct ReferencedStatus + { + struct DocReferenced + { + ::std::vector<bool> maTables; + bool mbAllTablesReferenced; + // Initially, documents have no tables but all referenced. + DocReferenced() : mbAllTablesReferenced(true) {} + }; + typedef ::std::vector<DocReferenced> DocReferencedVec; + + DocReferencedVec maDocs; + bool mbAllReferenced; + + ReferencedStatus(); + explicit ReferencedStatus( size_t nDocs ); + void reset( size_t nDocs ); + void checkAllDocs(); + + } maReferenced; + void addCacheTableToReferenced( sal_uInt16 nFileId, size_t nIndex ); + void addCacheDocToReferenced( sal_uInt16 nFileId ); +public: + ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const; ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex); @@ -434,6 +479,33 @@ public: size_t getCacheTableCount(sal_uInt16 nFileId) const; sal_uInt16 getExternalFileCount() const; + /** + * Mark all tables as referenced that are used by any LinkListener, used + * only during store-to-file. + * @returns <TRUE/> if ALL tables of ALL external documents are marked. + */ + bool markUsedByLinkListeners(); + + /** + * Set all tables of a document as referenced, used only during + * store-to-file. + * @returns <TRUE/> if ALL tables of ALL external documents are marked. + */ + bool setCacheDocReferenced( sal_uInt16 nFileId ); + + /** + * Set a table as referenced, used only during store-to-file. + * @returns <TRUE/> if ALL tables of ALL external documents are marked. + */ + bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName ); + void setAllCacheTableReferencedStati( bool bReferenced ); + + /** + * @returns <TRUE/> if setAllCacheTableReferencedStati(false) was called, + * <FALSE/> if setAllCacheTableReferencedStati(true) was called. + */ + bool isInReferenceMarking() const { return bInReferenceMarking; } + void storeRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScTokenArray& rArray); ScExternalRefCache::TokenRef getSingleRefToken( @@ -618,6 +690,9 @@ private: /** original source file index. */ ::std::vector<SrcFileData> maSrcFiles; + /** Status whether in reference marking state. See isInReferenceMarking(). */ + bool bInReferenceMarking; + AutoTimer maSrcDocTimer; DECL_LINK(TimeOutHdl, AutoTimer*); }; diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 9a3b1746055d..e738ff5fbdb8 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -376,6 +376,7 @@ public: void CalcAfterLoad(); void CompileAll(); void CompileXML( ScProgress& rProgress ); + bool MarkUsedExternalReferences(); void UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, diff --git a/sc/inc/validat.hxx b/sc/inc/validat.hxx index 6aaa6f40d325..d3588c366a7c 100644 --- a/sc/inc/validat.hxx +++ b/sc/inc/validat.hxx @@ -205,6 +205,10 @@ public: const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz ); void UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos ); + /** Temporarily during save, returns RefManager's decision whether ALL + * references are marked now. */ + bool MarkUsedExternalReferences() const; + BOOL operator==( const ScValidationDataList& r ) const; // fuer Ref-Undo }; diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx index bba8b8b59703..0d71db3427b0 100644 --- a/sc/source/core/data/cell.cxx +++ b/sc/source/core/data/cell.cxx @@ -53,6 +53,7 @@ #include "editutil.hxx" #include "recursionhelper.hxx" #include "postit.hxx" +#include "externalrefmgr.hxx" #include <svx/editobj.hxx> #include <svtools/intitem.hxx> #include <svx/flditem.hxx> @@ -1120,6 +1121,12 @@ void ScFormulaCell::CalcAfterLoad() } +bool ScFormulaCell::MarkUsedExternalReferences() +{ + return pCode && pDocument->MarkUsedExternalReferences( *pCode); +} + + // FIXME: set to 0 #define erDEBUGDOT 0 // If set to 1, write output that's suitable for graphviz tools like dot. diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 67eb13b0c6c4..68d378994c14 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -2096,6 +2096,22 @@ void ScColumn::CalcAfterLoad() } +bool ScColumn::MarkUsedExternalReferences() +{ + bool bAllMarked = false; + if (pItems) + { + for (SCSIZE i = 0; i < nCount && !bAllMarked; ++i) + { + ScBaseCell* pCell = pItems[i].pCell; + if ( pCell->GetCellType() == CELLTYPE_FORMULA ) + bAllMarked = ((ScFormulaCell*)pCell)->MarkUsedExternalReferences(); + } + } + return bAllMarked; +} + + void ScColumn::ResetChanged( SCROW nStartRow, SCROW nEndRow ) { if (pItems) diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx index e5fd9776aa3e..b6b063002957 100644 --- a/sc/source/core/data/conditio.cxx +++ b/sc/source/core/data/conditio.cxx @@ -1111,6 +1111,18 @@ void ScConditionEntry::DataChanged( const ScRange* /* pModified */ ) const // nix } +bool ScConditionEntry::MarkUsedExternalReferences() const +{ + bool bAllMarked = false; + for (USHORT nPass = 0; !bAllMarked && nPass < 2; nPass++) + { + ScTokenArray* pFormula = nPass ? pFormula2 : pFormula1; + if (pFormula) + bAllMarked = pDoc->MarkUsedExternalReferences( *pFormula); + } + return bAllMarked; +} + //------------------------------------------------------------------------ ScCondFormatEntry::ScCondFormatEntry( ScConditionMode eOper, @@ -1458,6 +1470,14 @@ void ScConditionalFormat::SourceChanged( const ScAddress& rAddr ) ppEntries[i]->SourceChanged( rAddr ); } +bool ScConditionalFormat::MarkUsedExternalReferences() const +{ + bool bAllMarked = false; + for (USHORT i=0; !bAllMarked && i<nEntryCount; i++) + bAllMarked = ppEntries[i]->MarkUsedExternalReferences(); + return bAllMarked; +} + //------------------------------------------------------------------------ ScConditionalFormatList::ScConditionalFormatList(const ScConditionalFormatList& rList) : @@ -1555,5 +1575,11 @@ void ScConditionalFormatList::SourceChanged( const ScAddress& rAddr ) (*this)[i]->SourceChanged( rAddr ); } - - +bool ScConditionalFormatList::MarkUsedExternalReferences() const +{ + bool bAllMarked = false; + USHORT nCount = Count(); + for (USHORT i=0; !bAllMarked && i<nCount; i++) + bAllMarked = (*this)[i]->MarkUsedExternalReferences(); + return bAllMarked; +} diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx index 7b90b5f7738f..2b3fbb359988 100644 --- a/sc/source/core/data/documen3.cxx +++ b/sc/source/core/data/documen3.cxx @@ -484,6 +484,29 @@ ScExternalRefManager* ScDocument::GetExternalRefManager() return pExternalRefMgr.get(); } +bool ScDocument::IsInExternalReferenceMarking() const +{ + return pExternalRefMgr.get() && pExternalRefMgr->isInReferenceMarking(); +} + +void ScDocument::MarkUsedExternalReferences() +{ + if (!pExternalRefMgr.get()) + return; + if (!pExternalRefMgr->hasExternalData()) + return; + // Charts. + bool bAllMarked = pExternalRefMgr->markUsedByLinkListeners(); + // Formula cells. + for (SCTAB nTab = 0; !bAllMarked && nTab < nMaxTableNumber; ++nTab) + { + if (pTab[nTab]) + bAllMarked = pTab[nTab]->MarkUsedExternalReferences(); + } + /* NOTE: Conditional formats and validation objects are marked when + * collecting them during export. */ +} + ScOutlineTable* ScDocument::GetOutlineTable( SCTAB nTab, BOOL bCreate ) { ScOutlineTable* pVal = NULL; diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx index 0f3d31964679..204a1b2264af 100644 --- a/sc/source/core/data/documen4.cxx +++ b/sc/source/core/data/documen4.cxx @@ -38,6 +38,7 @@ #include <svtools/intitem.hxx> #include <svtools/zforlist.hxx> #include <vcl/sound.hxx> +#include <formula/token.hxx> #include "document.hxx" #include "table.hxx" @@ -56,6 +57,9 @@ #include "progress.hxx" #include "paramisc.hxx" #include "compiler.hxx" +#include "externalrefmgr.hxx" + +using namespace formula; // ----------------------------------------------------------------------- @@ -290,6 +294,40 @@ void ScDocument::InsertTableOp(const ScTabOpParam& rParam, // Mehrfachopera pTab[i]->PutCell( j, k, aRefCell.CloneWithoutNote( *this, ScAddress( j, k, i ), SC_CLONECELL_STARTLISTENING ) ); } +bool ScDocument::MarkUsedExternalReferences( ScTokenArray & rArr ) +{ + bool bAllMarked = false; + if (rArr.GetLen()) + { + ScExternalRefManager* pRefMgr = NULL; + rArr.Reset(); + ScToken* t; + while (!bAllMarked && (t = static_cast<ScToken*>(rArr.GetNextReferenceOrName())) != NULL) + { + if (t->GetOpCode() == ocExternalRef) + { + if (!pRefMgr) + pRefMgr = GetExternalRefManager(); + switch (t->GetType()) + { + case svExternalSingleRef: + case svExternalDoubleRef: + bAllMarked = pRefMgr->setCacheTableReferenced( + t->GetIndex(), t->GetString()); + break; + case svExternalName: + /* TODO: external names aren't supported yet, but would + * have to be marked as well, if so. Mechanism would be + * different. */ + DBG_ERRORFILE("ScDocument::MarkUsedExternalReferences: implement the svExternalName case!"); + break; + } + } + } + } + return bAllMarked; +} + BOOL ScDocument::GetNextSpellingCell(SCCOL& nCol, SCROW& nRow, SCTAB nTab, BOOL bInSel, const ScMarkData& rMark) const { diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 1cf195567661..6c1ecf660275 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -1072,13 +1072,23 @@ void ScTable::CompileXML( ScProgress& rProgress ) } } - void ScTable::CalcAfterLoad() { for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].CalcAfterLoad(); } +bool ScTable::MarkUsedExternalReferences() +{ + bool bAllMarked = false; + for (SCCOL i=0; i <= MAXCOL && !bAllMarked; ++i) + { + bAllMarked = aCol[i].MarkUsedExternalReferences(); + } + return bAllMarked; +} + + void ScTable::ResetChanged( const ScRange& rRange ) { SCCOL nStartCol = rRange.aStart.Col(); diff --git a/sc/source/core/data/validat.cxx b/sc/source/core/data/validat.cxx index ac01f84d291a..09c1db07c464 100644 --- a/sc/source/core/data/validat.cxx +++ b/sc/source/core/data/validat.cxx @@ -939,6 +939,15 @@ void ScValidationDataList::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos ) (*this)[i]->UpdateMoveTab( nOldPos, nNewPos ); } +bool ScValidationDataList::MarkUsedExternalReferences() const +{ + bool bAllMarked = false; + USHORT nCount = Count(); + for (USHORT i=0; !bAllMarked && i<nCount; i++) + bAllMarked = (*this)[i]->MarkUsedExternalReferences(); + return bAllMarked; +} + BOOL ScValidationDataList::operator==( const ScValidationDataList& r ) const { // fuer Ref-Undo - interne Variablen werden nicht verglichen diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 20c001f03b3c..90029b6ac0c1 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -1125,24 +1125,25 @@ struct ConventionOOO_A1 : public Convention_A1 rBuffer.append(sal_Unicode(':')); - // Get the name of the last table. - vector<String> aTabNames; - pRefMgr->getAllCachedTableNames(nFileId, aTabNames); - if (aTabNames.empty()) - { - DBG_ERROR1( "ConventionOOO_A1::makeExternalRefStrImpl: no sheet names for document ID %s", nFileId); - break; - } - String aLastTabName; - if (!lcl_getLastTabName(aLastTabName, rTabName, aTabNames, aRef)) + bool bDisplayTabName = (aRef.Ref1.nTab != aRef.Ref2.nTab); + if (bDisplayTabName) { - rBuffer.append(aLastTabName); - DBG_ERROR( "ConventionOOO_A1::makeExternalRefStrImpl: sheet name not found"); - break; + // Get the name of the last table. + vector<String> aTabNames; + pRefMgr->getAllCachedTableNames(nFileId, aTabNames); + if (aTabNames.empty()) + { + DBG_ERROR1( "ConventionOOO_A1::makeExternalRefStrImpl: no sheet names for document ID %s", nFileId); + } + + if (!lcl_getLastTabName(aLastTabName, rTabName, aTabNames, aRef)) + { + DBG_ERROR( "ConventionOOO_A1::makeExternalRefStrImpl: sheet name not found"); + // aLastTabName contains #REF!, proceed. + } } - bool bDisplayTabName = (aRef.Ref1.nTab != aRef.Ref2.nTab); - if (bODF && !bDisplayTabName) + else if (bODF) rBuffer.append( sal_Unicode('.')); // need at least the sheet separator in ODF makeExternalSingleRefStr( rBuffer, nFileId, aLastTabName, aRef.Ref2, pRefMgr, bDisplayTabName); diff --git a/sc/source/filter/excel/excform8.cxx b/sc/source/filter/excel/excform8.cxx index 6093ef5d8eeb..10fc15c633b6 100644 --- a/sc/source/filter/excel/excform8.cxx +++ b/sc/source/filter/excel/excform8.cxx @@ -68,7 +68,7 @@ ExcelToSc8::~ExcelToSc8() bool ExcelToSc8::GetExternalFileIdFromXti( UINT16 nIxti, sal_uInt16& rFileId ) const { const String* pFileUrl = rLinkMan.GetSupbookUrl(nIxti); - if (!pFileUrl || pFileUrl->Len() == 0) + if (!pFileUrl || pFileUrl->Len() == 0 || !GetDocShell()) return false; String aFileUrl = ScGlobal::GetAbsDocName(*pFileUrl, GetDocShell()); @@ -1222,6 +1222,9 @@ ConvErr ExcelToSc8::Convert( _ScRangeListTabs& rRangeList, XclImpStream& aIn, sa ConvErr ExcelToSc8::ConvertExternName( const ScTokenArray*& rpArray, XclImpStream& rStrm, sal_Size nFormulaLen, const String& rUrl, const vector<String>& rTabNames ) { + if( !GetDocShell() ) + return ConvErrNi; + String aFileUrl = ScGlobal::GetAbsDocName(rUrl, GetDocShell()); sal_uInt8 nOp, nByte; diff --git a/sc/source/filter/excel/xilink.cxx b/sc/source/filter/excel/xilink.cxx index c51dd5cf24e3..16a3edf46373 100644 --- a/sc/source/filter/excel/xilink.cxx +++ b/sc/source/filter/excel/xilink.cxx @@ -548,7 +548,7 @@ sal_uInt16 XclImpSupbook::GetTabCount() const void XclImpSupbook::LoadCachedValues() { - if (meType != EXC_SBTYPE_EXTERN || GetExtDocOptions().GetDocSettings().mnLinkCnt > 0) + if (meType != EXC_SBTYPE_EXTERN || GetExtDocOptions().GetDocSettings().mnLinkCnt > 0 || !GetDocShell()) return; String aAbsUrl( ScGlobal::GetAbsDocName(maXclUrl, GetDocShell()) ); diff --git a/sc/source/filter/ftools/ftools.cxx b/sc/source/filter/ftools/ftools.cxx index c92547b31b95..98faeb9f03d4 100644 --- a/sc/source/filter/ftools/ftools.cxx +++ b/sc/source/filter/ftools/ftools.cxx @@ -396,7 +396,6 @@ bool ScfTools::GetHTMLNameFromName( const String& rSource, String& rName ) ScFormatFilterPluginImpl::ScFormatFilterPluginImpl() { - fprintf (stderr, "loaded\n"); } ScFormatFilterPlugin * SAL_CALL ScFilterCreate(void) diff --git a/sc/source/filter/html/htmlimp.cxx b/sc/source/filter/html/htmlimp.cxx index 36491a4a12c7..abc7d2b21392 100644 --- a/sc/source/filter/html/htmlimp.cxx +++ b/sc/source/filter/html/htmlimp.cxx @@ -217,7 +217,7 @@ void ScHTMLImport::WriteToDocument( BOOL bSizeColsRows, double nOutputFactor ) String ScFormatFilterPluginImpl::GetHTMLRangeNameList( ScDocument* pDoc, const String& rOrigName ) { - return GetHTMLRangeNameList( pDoc, rOrigName ); + return ScHTMLImport::GetHTMLRangeNameList( pDoc, rOrigName ); } String ScHTMLImport::GetHTMLRangeNameList( ScDocument* pDoc, const String& rOrigName ) diff --git a/sc/source/filter/xml/XMLStylesExportHelper.cxx b/sc/source/filter/xml/XMLStylesExportHelper.cxx index 0e4c0431e144..9abb3339d01d 100644 --- a/sc/source/filter/xml/XMLStylesExportHelper.cxx +++ b/sc/source/filter/xml/XMLStylesExportHelper.cxx @@ -194,6 +194,10 @@ sal_Bool ScMyValidationsContainer::AddValidation(const uno::Any& aTempAny, rtl::OUString ScMyValidationsContainer::GetCondition(ScXMLExport& rExport, const ScMyValidation& aValidation) { + /* ATTENTION! Should the condition to not write sheet::ValidationType_ANY + * ever be changed, adapt the conditional call of + * MarkUsedExternalReferences() in + * ScTableValidationObj::ScTableValidationObj() accordingly! */ rtl::OUString sCondition; if (aValidation.aValidationType != sheet::ValidationType_ANY) { diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx index 5aba1809390f..8dda5e3c0eec 100644 --- a/sc/source/filter/xml/xmlexprt.cxx +++ b/sc/source/filter/xml/xmlexprt.cxx @@ -3325,7 +3325,7 @@ void ScXMLExport::WriteExternalRefCaches() itr != itrEnd; ++itr) { ScExternalRefCache::TableTypeRef pTable = pRefMgr->getCacheTable(nFileId, *itr, false); - if (!pTable.get()) + if (!pTable.get() || !pTable->isReferenced()) continue; OUStringBuffer aBuf; @@ -3368,10 +3368,9 @@ void ScXMLExport::WriteExternalRefCaches() SCROW nRow = *itrRow; vector<SCCOL> aCols; pTable->getAllCols(nRow, aCols); - for (vector<SCCOL>::const_iterator itrCol = aCols.begin(), itrColEnd = aCols.end(); - itrCol != itrColEnd; ++itrCol) + if (!aCols.empty()) { - SCCOL nCol = *itrCol; + SCCOL nCol = aCols.back(); if (nMaxColsUsed <= nCol) nMaxColsUsed = nCol + 1; } diff --git a/sc/source/filter/xml/xmlexternaltabi.cxx b/sc/source/filter/xml/xmlexternaltabi.cxx index 16378b3bea61..4eefbbc1a917 100644 --- a/sc/source/filter/xml/xmlexternaltabi.cxx +++ b/sc/source/filter/xml/xmlexternaltabi.cxx @@ -166,10 +166,13 @@ void ScXMLExternalRefRowContext::EndElement() for (sal_Int32 i = 1; i < mnRepeatRowCount; ++i) { // Performance: duplicates of a non-existent row will still not exist. - // Don't find that out that for every cell. + // Don't find that out for every cell. // External references often are a sparse matrix. if (i == 1 && !pTab->hasRow( mrExternalRefInfo.mnRow)) + { + mrExternalRefInfo.mnRow += mnRepeatRowCount; return; + } for (sal_Int32 j = 0; j < mrExternalRefInfo.mnCol; ++j) { diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index 7f1fb3b549cf..4545406ac3c9 100644 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -1265,22 +1265,51 @@ BOOL __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium ) } +ScDocShell::PrepareSaveGuard::PrepareSaveGuard( ScDocShell& rDocShell ) + : mrDocShell( rDocShell) +{ + // DoEnterHandler not here (because of AutoSave), is in ExecuteSave. + + ScChartListenerCollection* pCharts = mrDocShell.aDocument.GetChartListenerCollection(); + if (pCharts) + pCharts->UpdateDirtyCharts(); // Charts to be updated. + mrDocShell.aDocument.StopTemporaryChartLock(); + if (mrDocShell.pAutoStyleList) + mrDocShell.pAutoStyleList->ExecuteAllNow(); // Execute template timeouts now. + if (mrDocShell.aDocument.HasExternalRefManager()) + { + ScExternalRefManager* pRefMgr = mrDocShell.aDocument.GetExternalRefManager(); + if (pRefMgr && pRefMgr->hasExternalData()) + { + pRefMgr->setAllCacheTableReferencedStati( false); + mrDocShell.aDocument.MarkUsedExternalReferences(); // Mark tables of external references to be written. + } + } + if (mrDocShell.GetCreateMode()== SFX_CREATE_MODE_STANDARD) + mrDocShell.SfxObjectShell::SetVisArea( Rectangle() ); // "Normally" worked on => no VisArea. +} + +ScDocShell::PrepareSaveGuard::~PrepareSaveGuard() +{ + if (mrDocShell.aDocument.HasExternalRefManager()) + { + ScExternalRefManager* pRefMgr = mrDocShell.aDocument.GetExternalRefManager(); + if (pRefMgr && pRefMgr->hasExternalData()) + { + // Prevent accidental data loss due to lack of knowledge. + pRefMgr->setAllCacheTableReferencedStati( true); + } + } +} + + BOOL __EXPORT ScDocShell::Save() { RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::Save" ); ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() ); - // DoEnterHandler hier nicht (wegen AutoSave), ist im ExecuteSave - - ScChartListenerCollection* pCharts = aDocument.GetChartListenerCollection(); - if (pCharts) - pCharts->UpdateDirtyCharts(); // Charts, die noch upgedated werden muessen - aDocument.StopTemporaryChartLock(); - if (pAutoStyleList) - pAutoStyleList->ExecuteAllNow(); // Vorlagen-Timeouts jetzt ausfuehren - if (GetCreateMode()== SFX_CREATE_MODE_STANDARD) - SfxObjectShell::SetVisArea( Rectangle() ); // normal bearbeitet -> keine VisArea + PrepareSaveGuard aPrepareGuard( *this); // wait cursor is handled with progress bar BOOL bRet = SfxObjectShell::Save(); @@ -1296,16 +1325,7 @@ BOOL __EXPORT ScDocShell::SaveAs( SfxMedium& rMedium ) ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() ); - // DoEnterHandler hier nicht (wegen AutoSave), ist im ExecuteSave - - ScChartListenerCollection* pCharts = aDocument.GetChartListenerCollection(); - if (pCharts) - pCharts->UpdateDirtyCharts(); // Charts, die noch upgedated werden muessen - aDocument.StopTemporaryChartLock(); - if (pAutoStyleList) - pAutoStyleList->ExecuteAllNow(); // Vorlagen-Timeouts jetzt ausfuehren - if (GetCreateMode()== SFX_CREATE_MODE_STANDARD) - SfxObjectShell::SetVisArea( Rectangle() ); // normal bearbeitet -> keine VisArea + PrepareSaveGuard aPrepareGuard( *this); // wait cursor is handled with progress bar BOOL bRet = SfxObjectShell::SaveAs( rMedium ); diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx index 913ad89f8cab..d78aa6fe3d84 100644 --- a/sc/source/ui/docshell/externalrefmgr.cxx +++ b/sc/source/ui/docshell/externalrefmgr.cxx @@ -143,6 +143,7 @@ private: // ============================================================================ ScExternalRefCache::Table::Table() + : mbReferenced( true) // Prevent accidental data loss due to lack of knowledge. { } @@ -150,6 +151,16 @@ ScExternalRefCache::Table::~Table() { } +void ScExternalRefCache::Table::setReferenced( bool bReferenced ) +{ + mbReferenced = bReferenced; +} + +bool ScExternalRefCache::Table::isReferenced() const +{ + return mbReferenced; +} + void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex) { using ::std::pair; @@ -702,6 +713,168 @@ size_t ScExternalRefCache::getCacheTableCount(sal_uInt16 nFileId) const return pDoc ? pDoc->maTables.size() : 0; } +bool ScExternalRefCache::setCacheDocReferenced( sal_uInt16 nFileId ) +{ + DocItem* pDocItem = getDocItem(nFileId); + if (!pDocItem) + return areAllCacheTablesReferenced(); + + for (::std::vector<TableTypeRef>::iterator itrTab = pDocItem->maTables.begin(); + itrTab != pDocItem->maTables.end(); ++itrTab) + { + if ((*itrTab).get()) + (*itrTab)->setReferenced( true); + } + addCacheDocToReferenced( nFileId); + return areAllCacheTablesReferenced(); +} + +bool ScExternalRefCache::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName ) +{ + size_t nIndex = 0; + TableTypeRef pTab = getCacheTable( nFileId, rTabName, false, &nIndex); + if (pTab.get()) + { + if (!pTab->isReferenced()) + { + pTab->setReferenced( true); + addCacheTableToReferenced( nFileId, nIndex); + } + } + return areAllCacheTablesReferenced(); +} + +void ScExternalRefCache::setAllCacheTableReferencedStati( bool bReferenced ) +{ + if (bReferenced) + { + maReferenced.reset(0); + for (DocDataType::iterator itrDoc = maDocs.begin(); itrDoc != maDocs.end(); ++itrDoc) + { + ScExternalRefCache::DocItem& rDocItem = (*itrDoc).second; + for (::std::vector<TableTypeRef>::iterator itrTab = rDocItem.maTables.begin(); + itrTab != rDocItem.maTables.end(); ++itrTab) + { + if ((*itrTab).get()) + (*itrTab)->setReferenced( true); + } + } + } + else + { + size_t nDocs = 0; + for (DocDataType::const_iterator itrDoc = maDocs.begin(); itrDoc != maDocs.end(); ++itrDoc) + { + if (nDocs <= (*itrDoc).first) + nDocs = (*itrDoc).first + 1; + } + maReferenced.reset( nDocs); + + for (DocDataType::iterator itrDoc = maDocs.begin(); itrDoc != maDocs.end(); ++itrDoc) + { + ScExternalRefCache::DocItem& rDocItem = (*itrDoc).second; + sal_uInt16 nFileId = (*itrDoc).first; + size_t nTables = rDocItem.maTables.size(); + ReferencedStatus::DocReferenced & rDocReferenced = maReferenced.maDocs[nFileId]; + // All referenced => non-existing tables evaluate as completed. + rDocReferenced.maTables.resize( nTables, true); + for (size_t i=0; i < nTables; ++i) + { + TableTypeRef & xTab = rDocItem.maTables[i]; + if (xTab.get()) + { + xTab->setReferenced( false); + rDocReferenced.maTables[i] = false; + rDocReferenced.mbAllTablesReferenced = false; + } + } + } + } +} + +void ScExternalRefCache::addCacheTableToReferenced( sal_uInt16 nFileId, size_t nIndex ) +{ + if (nFileId >= maReferenced.maDocs.size()) + return; + + ::std::vector<bool> & rTables = maReferenced.maDocs[nFileId].maTables; + size_t nTables = rTables.size(); + if (nIndex >= nTables) + return; + + if (!rTables[nIndex]) + { + rTables[nIndex] = true; + size_t i = 0; + while (i < nTables && rTables[i]) + ++i; + if (i == nTables) + { + maReferenced.maDocs[nFileId].mbAllTablesReferenced = true; + maReferenced.checkAllDocs(); + } + } +} + +void ScExternalRefCache::addCacheDocToReferenced( sal_uInt16 nFileId ) +{ + if (nFileId >= maReferenced.maDocs.size()) + return; + + if (!maReferenced.maDocs[nFileId].mbAllTablesReferenced) + { + ::std::vector<bool> & rTables = maReferenced.maDocs[nFileId].maTables; + size_t nSize = rTables.size(); + for (size_t i=0; i < nSize; ++i) + rTables[i] = true; + maReferenced.maDocs[nFileId].mbAllTablesReferenced = true; + maReferenced.checkAllDocs(); + } +} + +bool ScExternalRefCache::areAllCacheTablesReferenced() const +{ + return maReferenced.mbAllReferenced; +} + +ScExternalRefCache::ReferencedStatus::ReferencedStatus() : + mbAllReferenced(false) +{ + reset(0); +} + +ScExternalRefCache::ReferencedStatus::ReferencedStatus( size_t nDocs ) : + mbAllReferenced(false) +{ + reset( nDocs); +} + +void ScExternalRefCache::ReferencedStatus::reset( size_t nDocs ) +{ + if (nDocs) + { + mbAllReferenced = false; + DocReferencedVec aRefs( nDocs); + maDocs.swap( aRefs); + } + else + { + mbAllReferenced = true; + DocReferencedVec aRefs; + maDocs.swap( aRefs); + } +} + +void ScExternalRefCache::ReferencedStatus::checkAllDocs() +{ + for (DocReferencedVec::const_iterator itr = maDocs.begin(); itr != maDocs.end(); ++itr) + { + if (!(*itr).mbAllTablesReferenced) + return; + } + mbAllReferenced = true; +} + ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const { DocItem* pDoc = getDocItem(nFileId); @@ -987,7 +1160,8 @@ static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, const ScRange& } ScExternalRefManager::ScExternalRefManager(ScDocument* pDoc) : - mpDoc(pDoc) + mpDoc(pDoc), + bInReferenceMarking(false) { maSrcDocTimer.SetTimeoutHdl( LINK(this, ScExternalRefManager, TimeOutHdl) ); maSrcDocTimer.SetTimeout(SRCDOC_SCAN_INTERVAL); @@ -1278,6 +1452,37 @@ sal_uInt16 ScExternalRefManager::getExternalFileCount() const return static_cast< sal_uInt16 >( maSrcFiles.size() ); } +bool ScExternalRefManager::markUsedByLinkListeners() +{ + bool bAllMarked = false; + for (LinkListenerMap::const_iterator itr = maLinkListeners.begin(); + itr != maLinkListeners.end() && !bAllMarked; ++itr) + { + if (!(*itr).second.empty()) + bAllMarked = maRefCache.setCacheDocReferenced( (*itr).first); + /* TODO: LinkListeners should remember the table they're listening to. + * As is, listening to one table will mark all tables of the document + * being referenced. */ + } + return bAllMarked; +} + +bool ScExternalRefManager::setCacheDocReferenced( sal_uInt16 nFileId ) +{ + return maRefCache.setCacheDocReferenced( nFileId); +} + +bool ScExternalRefManager::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName ) +{ + return maRefCache.setCacheTableReferenced( nFileId, rTabName); +} + +void ScExternalRefManager::setAllCacheTableReferencedStati( bool bReferenced ) +{ + bInReferenceMarking = !bReferenced; + maRefCache.setAllCacheTableReferencedStati( bReferenced ); +} + void ScExternalRefManager::storeRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScTokenArray& rArray) { ScExternalRefCache::TokenArrayRef pArray(rArray.Clone()); diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx index 8a9dd449686d..f8bfc53ddf44 100644 --- a/sc/source/ui/inc/docsh.hxx +++ b/sc/source/ui/inc/docsh.hxx @@ -135,6 +135,21 @@ class SC_DLLPUBLIC ScDocShell: public SfxObjectShell, public SfxListener SC_DLLPRIVATE void InitOptions(); SC_DLLPRIVATE void ResetDrawObjectShell(); + // SUNWS needs a forward declared friend, otherwise types and members + // of the outer class are not accessible. + class PrepareSaveGuard; + friend class ScDocShell::PrepareSaveGuard; + /** Do things that need to be done before saving to our own format and + necessary clean ups in dtor. */ + class PrepareSaveGuard + { + public: + explicit PrepareSaveGuard( ScDocShell & rDocShell ); + ~PrepareSaveGuard(); + private: + ScDocShell & mrDocShell; + }; + SC_DLLPRIVATE BOOL LoadXML( SfxMedium* pMedium, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& ); SC_DLLPRIVATE BOOL SaveXML( SfxMedium* pMedium, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& ); SC_DLLPRIVATE SCTAB GetSaveTab(); diff --git a/sc/source/ui/unoobj/fmtuno.cxx b/sc/source/ui/unoobj/fmtuno.cxx index 759d723aa020..79221cb153a0 100644 --- a/sc/source/ui/unoobj/fmtuno.cxx +++ b/sc/source/ui/unoobj/fmtuno.cxx @@ -147,6 +147,10 @@ ScTableConditionalFormat::ScTableConditionalFormat(ScDocument* pDoc, ULONG nKey, const ScConditionalFormat* pFormat = pList->GetFormat( nKey ); if (pFormat) { + // During save to XML. + if (pDoc->IsInExternalReferenceMarking()) + pFormat->MarkUsedExternalReferences(); + USHORT nEntryCount = pFormat->Count(); for (USHORT i=0; i<nEntryCount; i++) { @@ -624,6 +628,13 @@ ScTableValidationObj::ScTableValidationObj(ScDocument* pDoc, ULONG nKey, bShowError = pData->GetErrMsg( aErrorTitle, aErrorMessage, eStyle ); nErrorStyle = sal::static_int_cast<USHORT>( eStyle ); + // During save to XML, sheet::ValidationType_ANY formulas are not + // saved, even if in the list, see + // ScMyValidationsContainer::GetCondition(), so shall not mark + // anything in use. + if (nValMode != SC_VALID_ANY && pDoc->IsInExternalReferenceMarking()) + pData->MarkUsedExternalReferences(); + bFound = TRUE; } } |