1*38d50f7bSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*38d50f7bSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*38d50f7bSAndrew Rist * or more contributor license agreements. See the NOTICE file 5*38d50f7bSAndrew Rist * distributed with this work for additional information 6*38d50f7bSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*38d50f7bSAndrew Rist * to you under the Apache License, Version 2.0 (the 8*38d50f7bSAndrew Rist * "License"); you may not use this file except in compliance 9*38d50f7bSAndrew Rist * with the License. You may obtain a copy of the License at 10*38d50f7bSAndrew Rist * 11*38d50f7bSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*38d50f7bSAndrew Rist * 13*38d50f7bSAndrew Rist * Unless required by applicable law or agreed to in writing, 14*38d50f7bSAndrew Rist * software distributed under the License is distributed on an 15*38d50f7bSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*38d50f7bSAndrew Rist * KIND, either express or implied. See the License for the 17*38d50f7bSAndrew Rist * specific language governing permissions and limitations 18*38d50f7bSAndrew Rist * under the License. 19*38d50f7bSAndrew Rist * 20*38d50f7bSAndrew Rist *************************************************************/ 21*38d50f7bSAndrew Rist 22*38d50f7bSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #ifndef SC_EXTERNALREFMGR_HXX 25cdf0e10cSrcweir #define SC_EXTERNALREFMGR_HXX 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include "global.hxx" 28cdf0e10cSrcweir #include "address.hxx" 29cdf0e10cSrcweir #include "sfx2/objsh.hxx" 30cdf0e10cSrcweir #include "sfx2/lnkbase.hxx" 31cdf0e10cSrcweir #include "tools/time.hxx" 32cdf0e10cSrcweir #include "vcl/timer.hxx" 33cdf0e10cSrcweir #include "svl/zforlist.hxx" 34cdf0e10cSrcweir #include "scmatrix.hxx" 35cdf0e10cSrcweir #include "rangelst.hxx" 36cdf0e10cSrcweir 37cdf0e10cSrcweir #include <hash_map> 38cdf0e10cSrcweir #include <hash_set> 39cdf0e10cSrcweir #include <boost/shared_ptr.hpp> 40cdf0e10cSrcweir #include <vector> 41cdf0e10cSrcweir #include <list> 42cdf0e10cSrcweir #include <set> 43cdf0e10cSrcweir #include <formula/ExternalReferenceHelper.hxx> 44cdf0e10cSrcweir 45cdf0e10cSrcweir class ScDocument; 46cdf0e10cSrcweir namespace formula 47cdf0e10cSrcweir { 48cdf0e10cSrcweir class FormulaToken; 49cdf0e10cSrcweir } 50cdf0e10cSrcweir class ScToken; 51cdf0e10cSrcweir class ScMatrix; 52cdf0e10cSrcweir class ScTokenArray; 53cdf0e10cSrcweir class String; 54cdf0e10cSrcweir class SfxObjectShellRef; 55cdf0e10cSrcweir class Window; 56cdf0e10cSrcweir class ScFormulaCell; 57cdf0e10cSrcweir 58cdf0e10cSrcweir class ScExternalRefCache; 59cdf0e10cSrcweir 60cdf0e10cSrcweir class ScExternalRefLink : public ::sfx2::SvBaseLink 61cdf0e10cSrcweir { 62cdf0e10cSrcweir public: 63cdf0e10cSrcweir ScExternalRefLink(ScDocument* pDoc, sal_uInt16 nFileId, const String& rFilter); 64cdf0e10cSrcweir virtual ~ScExternalRefLink(); 65cdf0e10cSrcweir 66cdf0e10cSrcweir virtual void Closed(); 67cdf0e10cSrcweir virtual void DataChanged(const String& rMimeType, const ::com::sun::star::uno::Any & rValue); 68cdf0e10cSrcweir virtual void Edit(Window* pParent, const Link& rEndEditHdl); 69cdf0e10cSrcweir 70cdf0e10cSrcweir void SetDoReferesh(bool b); 71cdf0e10cSrcweir 72cdf0e10cSrcweir private: 73cdf0e10cSrcweir ScExternalRefLink(); // disabled 74cdf0e10cSrcweir ScExternalRefLink(const ScExternalRefLink&); // disabled 75cdf0e10cSrcweir 76cdf0e10cSrcweir DECL_LINK( ExternalRefEndEditHdl, ::sfx2::SvBaseLink* ); 77cdf0e10cSrcweir 78cdf0e10cSrcweir sal_uInt16 mnFileId; 79cdf0e10cSrcweir String maFilterName; 80cdf0e10cSrcweir ScDocument* mpDoc; 81cdf0e10cSrcweir bool mbDoRefresh; 82cdf0e10cSrcweir }; 83cdf0e10cSrcweir 84cdf0e10cSrcweir // ============================================================================ 85cdf0e10cSrcweir 86cdf0e10cSrcweir /** 87cdf0e10cSrcweir * Cache table for external reference data. 88cdf0e10cSrcweir */ 89cdf0e10cSrcweir class ScExternalRefCache 90cdf0e10cSrcweir { 91cdf0e10cSrcweir public: 92cdf0e10cSrcweir typedef ::boost::shared_ptr< formula::FormulaToken> TokenRef; 93cdf0e10cSrcweir typedef ::boost::shared_ptr<ScTokenArray> TokenArrayRef; 94cdf0e10cSrcweir 95cdf0e10cSrcweir struct TableName 96cdf0e10cSrcweir { 97cdf0e10cSrcweir String maUpperName; 98cdf0e10cSrcweir String maRealName; 99cdf0e10cSrcweir 100cdf0e10cSrcweir explicit TableName(const String& rUppper, const String& rReal); 101cdf0e10cSrcweir }; 102cdf0e10cSrcweir 103cdf0e10cSrcweir struct CellFormat 104cdf0e10cSrcweir { 105cdf0e10cSrcweir bool mbIsSet; 106cdf0e10cSrcweir short mnType; 107cdf0e10cSrcweir sal_uInt32 mnIndex; 108cdf0e10cSrcweir 109cdf0e10cSrcweir explicit CellFormat(); 110cdf0e10cSrcweir }; 111cdf0e10cSrcweir 112cdf0e10cSrcweir private: 113cdf0e10cSrcweir /** individual cell within cached external ref table. */ 114cdf0e10cSrcweir struct Cell 115cdf0e10cSrcweir { 116cdf0e10cSrcweir TokenRef mxToken; 117cdf0e10cSrcweir sal_uInt32 mnFmtIndex; 118cdf0e10cSrcweir }; 119cdf0e10cSrcweir typedef ::std::hash_map<SCCOL, Cell> RowDataType; 120cdf0e10cSrcweir typedef ::std::hash_map<SCROW, RowDataType> RowsDataType; 121cdf0e10cSrcweir 122cdf0e10cSrcweir public: 123cdf0e10cSrcweir // SUNWS needs a forward declared friend, otherwise types and members 124cdf0e10cSrcweir // of the outer class are not accessible. 125cdf0e10cSrcweir class Table; 126cdf0e10cSrcweir friend class ScExternalRefCache::Table; 127cdf0e10cSrcweir 128cdf0e10cSrcweir /** 129cdf0e10cSrcweir * Represents a single cached table in an external document. It only 130cdf0e10cSrcweir * stores non-empty cells; empty cells should never be stored in the data 131cdf0e10cSrcweir * cache. Instead, cached ranges should be used to determine whether or 132cdf0e10cSrcweir * not a cell is empty or needs fetching from the source document. If a 133cdf0e10cSrcweir * cell's value is not stored but its address is within the cached ranges, 134cdf0e10cSrcweir * that cell is already queried in the source document and we know it's 135cdf0e10cSrcweir * empty. 136cdf0e10cSrcweir */ 137cdf0e10cSrcweir class Table 138cdf0e10cSrcweir { 139cdf0e10cSrcweir public: 140cdf0e10cSrcweir 141cdf0e10cSrcweir enum ReferencedFlag 142cdf0e10cSrcweir { 143cdf0e10cSrcweir UNREFERENCED, 144cdf0e10cSrcweir REFERENCED_MARKED, // marked as referenced during store to file 145cdf0e10cSrcweir REFERENCED_PERMANENT // permanently marked, e.g. from within interpreter 146cdf0e10cSrcweir }; 147cdf0e10cSrcweir 148cdf0e10cSrcweir Table(); 149cdf0e10cSrcweir ~Table(); 150cdf0e10cSrcweir 151cdf0e10cSrcweir /** 152cdf0e10cSrcweir * Add cell value to the cache. 153cdf0e10cSrcweir * 154cdf0e10cSrcweir * @param bSetCacheRange if true, mark this cell 'cached'. This is 155cdf0e10cSrcweir * false _only when_ adding a range of cell 156cdf0e10cSrcweir * values, for performance reasons. 157cdf0e10cSrcweir */ 158cdf0e10cSrcweir SC_DLLPUBLIC void setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex = 0, bool bSetCacheRange = true); 159cdf0e10cSrcweir SC_DLLPUBLIC TokenRef getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex = NULL) const; 160cdf0e10cSrcweir bool hasRow( SCROW nRow ) const; 161cdf0e10cSrcweir /** Set/clear referenced status flag only if current status is not 162cdf0e10cSrcweir REFERENCED_PERMANENT. */ 163cdf0e10cSrcweir void setReferenced( bool bReferenced ); 164cdf0e10cSrcweir /// Unconditionally set the reference status flag. 165cdf0e10cSrcweir void setReferencedFlag( ReferencedFlag eFlag ); 166cdf0e10cSrcweir ReferencedFlag getReferencedFlag() const; 167cdf0e10cSrcweir bool isReferenced() const; 168cdf0e10cSrcweir /// Obtain a sorted vector of rows. 169cdf0e10cSrcweir void getAllRows(::std::vector<SCROW>& rRows, SCROW nLow = 0, SCROW nHigh = MAXROW) const; 170cdf0e10cSrcweir /// Returns the half-open range of used rows in this table. Returns [0,0) if table is empty. 171cdf0e10cSrcweir SC_DLLPUBLIC ::std::pair< SCROW, SCROW > getRowRange() const; 172cdf0e10cSrcweir /// Obtain a sorted vector of columns. 173cdf0e10cSrcweir void getAllCols(SCROW nRow, ::std::vector<SCCOL>& rCols, SCCOL nLow = 0, SCCOL nHigh = MAXCOL) const; 174cdf0e10cSrcweir /// Returns the half-open range of used columns in the specified row. Returns [0,0) if row is empty. 175cdf0e10cSrcweir SC_DLLPUBLIC ::std::pair< SCCOL, SCCOL > getColRange( SCROW nRow ) const; 176cdf0e10cSrcweir void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const; 177cdf0e10cSrcweir const ScRangeList& getCachedRanges() const; 178cdf0e10cSrcweir bool isRangeCached(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const; 179cdf0e10cSrcweir 180cdf0e10cSrcweir void setCachedCell(SCCOL nCol, SCROW nRow); 181cdf0e10cSrcweir void setCachedCellRange(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2); 182cdf0e10cSrcweir 183cdf0e10cSrcweir /** 184cdf0e10cSrcweir * Call this to mark the entire table "cached". This will prevent all 185cdf0e10cSrcweir * future attempts to access the source document even when non-cached 186cdf0e10cSrcweir * cells are queried. In such case, non-cached cells are treated as 187cdf0e10cSrcweir * empty cells. Useful when loading a document with own external data 188cdf0e10cSrcweir * cache. 189cdf0e10cSrcweir */ 190cdf0e10cSrcweir SC_DLLPUBLIC void setWholeTableCached(); 191cdf0e10cSrcweir private: 192cdf0e10cSrcweir bool isInCachedRanges(SCCOL nCol, SCROW nRow) const; 193cdf0e10cSrcweir TokenRef getEmptyOrNullToken(SCCOL nCol, SCROW nRow) const; 194cdf0e10cSrcweir 195cdf0e10cSrcweir private: 196cdf0e10cSrcweir /** Data cache */ 197cdf0e10cSrcweir RowsDataType maRows; 198cdf0e10cSrcweir /** Collection of individual cached ranges. The table ranges are 199cdf0e10cSrcweir * not used & always zero. */ 200cdf0e10cSrcweir ScRangeList maCachedRanges; 201cdf0e10cSrcweir ReferencedFlag meReferenced; 202cdf0e10cSrcweir }; 203cdf0e10cSrcweir 204cdf0e10cSrcweir typedef ::boost::shared_ptr<Table> TableTypeRef; 205cdf0e10cSrcweir typedef ::std::hash_map<String, size_t, ScStringHashCode> TableNameIndexMap; 206cdf0e10cSrcweir 207cdf0e10cSrcweir ScExternalRefCache(); 208cdf0e10cSrcweir ~ScExternalRefCache(); 209cdf0e10cSrcweir 210cdf0e10cSrcweir const String* getRealTableName(sal_uInt16 nFileId, const String& rTabName) const; 211cdf0e10cSrcweir const String* getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const; 212cdf0e10cSrcweir 213cdf0e10cSrcweir /** 214cdf0e10cSrcweir * Get a cached cell data at specified cell location. 215cdf0e10cSrcweir * 216cdf0e10cSrcweir * @param nFileId file ID of an external document 217cdf0e10cSrcweir * @param rTabName sheet name 218cdf0e10cSrcweir * @param nCol 219cdf0e10cSrcweir * @param nRow 220cdf0e10cSrcweir * 221cdf0e10cSrcweir * @return pointer to the token instance in the cache. 222cdf0e10cSrcweir */ 223cdf0e10cSrcweir ScExternalRefCache::TokenRef getCellData( 224cdf0e10cSrcweir sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex); 225cdf0e10cSrcweir 226cdf0e10cSrcweir /** 227cdf0e10cSrcweir * Get a cached cell range data. 228cdf0e10cSrcweir * 229cdf0e10cSrcweir * @return a new token array instance. Note that <i>the caller must 230cdf0e10cSrcweir * manage the life cycle of the returned instance</i>, which is 231cdf0e10cSrcweir * guaranteed if the TokenArrayRef is properly used.. 232cdf0e10cSrcweir */ 233cdf0e10cSrcweir ScExternalRefCache::TokenArrayRef getCellRangeData( 234cdf0e10cSrcweir sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange); 235cdf0e10cSrcweir 236cdf0e10cSrcweir ScExternalRefCache::TokenArrayRef getRangeNameTokens(sal_uInt16 nFileId, const String& rName); 237cdf0e10cSrcweir void setRangeNameTokens(sal_uInt16 nFileId, const String& rName, TokenArrayRef pArray); 238cdf0e10cSrcweir 239cdf0e10cSrcweir void setCellData(sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex); 240cdf0e10cSrcweir 241cdf0e10cSrcweir struct SingleRangeData 242cdf0e10cSrcweir { 243cdf0e10cSrcweir /** This name must be in upper-case. */ 244cdf0e10cSrcweir String maTableName; 245cdf0e10cSrcweir ScMatrixRef mpRangeData; 246cdf0e10cSrcweir }; 247cdf0e10cSrcweir void setCellRangeData(sal_uInt16 nFileId, const ScRange& rRange, const ::std::vector<SingleRangeData>& rData, 248cdf0e10cSrcweir TokenArrayRef pArray); 249cdf0e10cSrcweir 250cdf0e10cSrcweir bool isDocInitialized(sal_uInt16 nFileId); 251cdf0e10cSrcweir void initializeDoc(sal_uInt16 nFileId, const ::std::vector<String>& rTabNames); 252cdf0e10cSrcweir String getTableName(sal_uInt16 nFileId, size_t nCacheId) const; 253cdf0e10cSrcweir void getAllTableNames(sal_uInt16 nFileId, ::std::vector<String>& rTabNames) const; 254cdf0e10cSrcweir SCsTAB getTabSpan( sal_uInt16 nFileId, const String& rStartTabName, const String& rEndTabName ) const; 255cdf0e10cSrcweir void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const; 256cdf0e10cSrcweir 257cdf0e10cSrcweir /** 258cdf0e10cSrcweir * Set all tables of a document as referenced, used only during 259cdf0e10cSrcweir * store-to-file. 260cdf0e10cSrcweir * @returns <TRUE/> if ALL tables of ALL documents are marked. 261cdf0e10cSrcweir */ 262cdf0e10cSrcweir bool setCacheDocReferenced( sal_uInt16 nFileId ); 263cdf0e10cSrcweir 264cdf0e10cSrcweir /** 265cdf0e10cSrcweir * Set a table as referenced, used only during store-to-file. 266cdf0e10cSrcweir * @returns <TRUE/> if ALL tables of ALL documents are marked. 267cdf0e10cSrcweir */ 268cdf0e10cSrcweir bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets, bool bPermanent ); 269cdf0e10cSrcweir void setAllCacheTableReferencedStati( bool bReferenced ); 270cdf0e10cSrcweir bool areAllCacheTablesReferenced() const; 271cdf0e10cSrcweir 272cdf0e10cSrcweir /** 273cdf0e10cSrcweir * Set a table as permanently referenced, to be called if not in 274cdf0e10cSrcweir * mark-during-store-to-file cycle. 275cdf0e10cSrcweir */ 276cdf0e10cSrcweir void setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets ); 277cdf0e10cSrcweir 278cdf0e10cSrcweir private: 279cdf0e10cSrcweir struct ReferencedStatus 280cdf0e10cSrcweir { 281cdf0e10cSrcweir struct DocReferenced 282cdf0e10cSrcweir { 283cdf0e10cSrcweir ::std::vector<bool> maTables; 284cdf0e10cSrcweir bool mbAllTablesReferenced; 285cdf0e10cSrcweir // Initially, documents have no tables but all referenced. DocReferencedScExternalRefCache::ReferencedStatus::DocReferenced286cdf0e10cSrcweir DocReferenced() : mbAllTablesReferenced(true) {} 287cdf0e10cSrcweir }; 288cdf0e10cSrcweir typedef ::std::vector<DocReferenced> DocReferencedVec; 289cdf0e10cSrcweir 290cdf0e10cSrcweir DocReferencedVec maDocs; 291cdf0e10cSrcweir bool mbAllReferenced; 292cdf0e10cSrcweir 293cdf0e10cSrcweir ReferencedStatus(); 294cdf0e10cSrcweir explicit ReferencedStatus( size_t nDocs ); 295cdf0e10cSrcweir void reset( size_t nDocs ); 296cdf0e10cSrcweir void checkAllDocs(); 297cdf0e10cSrcweir 298cdf0e10cSrcweir } maReferenced; 299cdf0e10cSrcweir void addCacheTableToReferenced( sal_uInt16 nFileId, size_t nIndex ); 300cdf0e10cSrcweir void addCacheDocToReferenced( sal_uInt16 nFileId ); 301cdf0e10cSrcweir public: 302cdf0e10cSrcweir 303cdf0e10cSrcweir ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const; 304cdf0e10cSrcweir ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex); 305cdf0e10cSrcweir 306cdf0e10cSrcweir void clearCache(sal_uInt16 nFileId); 307cdf0e10cSrcweir 308cdf0e10cSrcweir private: 309cdf0e10cSrcweir struct RangeHash 310cdf0e10cSrcweir { operator ()ScExternalRefCache::RangeHash311cdf0e10cSrcweir size_t operator()(const ScRange& rRange) const 312cdf0e10cSrcweir { 313cdf0e10cSrcweir const ScAddress& s = rRange.aStart; 314cdf0e10cSrcweir const ScAddress& e = rRange.aEnd; 315cdf0e10cSrcweir return s.Tab() + s.Col() + s.Row() + e.Tab() + e.Col() + e.Row(); 316cdf0e10cSrcweir } 317cdf0e10cSrcweir }; 318cdf0e10cSrcweir 319cdf0e10cSrcweir typedef ::std::hash_map<String, TokenArrayRef, ScStringHashCode> RangeNameMap; 320cdf0e10cSrcweir typedef ::std::hash_map<ScRange, TokenArrayRef, RangeHash> RangeArrayMap; 321cdf0e10cSrcweir typedef ::std::hash_map<String, String, ScStringHashCode> NamePairMap; 322cdf0e10cSrcweir 323cdf0e10cSrcweir // SUNWS needs a forward declared friend, otherwise types and members 324cdf0e10cSrcweir // of the outer class are not accessible. 325cdf0e10cSrcweir struct DocItem; 326cdf0e10cSrcweir friend struct ScExternalRefCache::DocItem; 327cdf0e10cSrcweir 328cdf0e10cSrcweir /** Represents data cached for a single external document. */ 329cdf0e10cSrcweir struct DocItem 330cdf0e10cSrcweir { 331cdf0e10cSrcweir /** The raw cache tables. */ 332cdf0e10cSrcweir ::std::vector<TableTypeRef> maTables; 333cdf0e10cSrcweir /** Table name list in correct order, in both upper- and real-case. */ 334cdf0e10cSrcweir ::std::vector<TableName> maTableNames; 335cdf0e10cSrcweir /** Table name to index map. The names must be stored upper-case. */ 336cdf0e10cSrcweir TableNameIndexMap maTableNameIndex; 337cdf0e10cSrcweir /** Range name cache. */ 338cdf0e10cSrcweir RangeNameMap maRangeNames; 339cdf0e10cSrcweir /** Token array cache for cell ranges. */ 340cdf0e10cSrcweir RangeArrayMap maRangeArrays; 341cdf0e10cSrcweir /** Upper- to real-case mapping for range names. */ 342cdf0e10cSrcweir NamePairMap maRealRangeNameMap; 343cdf0e10cSrcweir 344cdf0e10cSrcweir bool mbInitFromSource; 345cdf0e10cSrcweir DocItemScExternalRefCache::DocItem346cdf0e10cSrcweir DocItem() : mbInitFromSource(false) {} 347cdf0e10cSrcweir }; 348cdf0e10cSrcweir typedef ::std::hash_map<sal_uInt16, DocItem> DocDataType; 349cdf0e10cSrcweir DocItem* getDocItem(sal_uInt16 nFileId) const; 350cdf0e10cSrcweir 351cdf0e10cSrcweir private: 352cdf0e10cSrcweir mutable DocDataType maDocs; 353cdf0e10cSrcweir }; 354cdf0e10cSrcweir 355cdf0e10cSrcweir // ============================================================================ 356cdf0e10cSrcweir 357cdf0e10cSrcweir class SC_DLLPUBLIC ScExternalRefManager : public formula::ExternalReferenceHelper 358cdf0e10cSrcweir { 359cdf0e10cSrcweir public: 360cdf0e10cSrcweir 361cdf0e10cSrcweir typedef ::std::set<ScFormulaCell*> RefCellSet; 362cdf0e10cSrcweir typedef ::std::hash_map<sal_uInt16, RefCellSet> RefCellMap; 363cdf0e10cSrcweir 364cdf0e10cSrcweir enum LinkUpdateType { LINK_MODIFIED, LINK_BROKEN }; 365cdf0e10cSrcweir 366cdf0e10cSrcweir /** 367cdf0e10cSrcweir * Base class for objects that need to listen to link updates. When a 368cdf0e10cSrcweir * link to a certain external file is updated, the notify() method gets 369cdf0e10cSrcweir * called. 370cdf0e10cSrcweir */ 371cdf0e10cSrcweir class LinkListener 372cdf0e10cSrcweir { 373cdf0e10cSrcweir public: 374cdf0e10cSrcweir LinkListener(); 375cdf0e10cSrcweir virtual ~LinkListener() = 0; 376cdf0e10cSrcweir virtual void notify(sal_uInt16 nFileId, LinkUpdateType eType) = 0; 377cdf0e10cSrcweir 378cdf0e10cSrcweir struct Hash 379cdf0e10cSrcweir { operator ()ScExternalRefManager::LinkListener::Hash380cdf0e10cSrcweir size_t operator() (const LinkListener* p) const 381cdf0e10cSrcweir { 382cdf0e10cSrcweir return reinterpret_cast<size_t>(p); 383cdf0e10cSrcweir } 384cdf0e10cSrcweir }; 385cdf0e10cSrcweir }; 386cdf0e10cSrcweir 387cdf0e10cSrcweir /** 388cdf0e10cSrcweir * Use this guard when performing something from the API that might query 389cdf0e10cSrcweir * values from external references. Interpreting formula strings is one 390cdf0e10cSrcweir * such example. 391cdf0e10cSrcweir */ 392cdf0e10cSrcweir class ApiGuard 393cdf0e10cSrcweir { 394cdf0e10cSrcweir public: 395cdf0e10cSrcweir ApiGuard(ScDocument* pDoc); 396cdf0e10cSrcweir ~ApiGuard(); 397cdf0e10cSrcweir private: 398cdf0e10cSrcweir ScExternalRefManager* mpMgr; 399cdf0e10cSrcweir bool mbOldInteractionEnabled; 400cdf0e10cSrcweir }; 401cdf0e10cSrcweir 402cdf0e10cSrcweir private: 403cdf0e10cSrcweir /** Shell instance for a source document. */ 404cdf0e10cSrcweir struct SrcShell 405cdf0e10cSrcweir { 406cdf0e10cSrcweir SfxObjectShellRef maShell; 407cdf0e10cSrcweir Time maLastAccess; 408cdf0e10cSrcweir }; 409cdf0e10cSrcweir 410cdf0e10cSrcweir typedef ::std::hash_map<sal_uInt16, SrcShell> DocShellMap; 411cdf0e10cSrcweir typedef ::std::hash_map<sal_uInt16, bool> LinkedDocMap; 412cdf0e10cSrcweir 413cdf0e10cSrcweir typedef ::std::hash_map<sal_uInt16, SvNumberFormatterMergeMap> NumFmtMap; 414cdf0e10cSrcweir 415cdf0e10cSrcweir 416cdf0e10cSrcweir typedef ::std::hash_set<LinkListener*, LinkListener::Hash> LinkListeners; 417cdf0e10cSrcweir typedef ::std::hash_map<sal_uInt16, LinkListeners> LinkListenerMap; 418cdf0e10cSrcweir 419cdf0e10cSrcweir public: 420cdf0e10cSrcweir /** Source document meta-data container. */ 421cdf0e10cSrcweir struct SrcFileData 422cdf0e10cSrcweir { 423cdf0e10cSrcweir String maFileName; /// original file name as loaded from the file. 424cdf0e10cSrcweir String maRealFileName; /// file name created from the relative name. 425cdf0e10cSrcweir String maRelativeName; 426cdf0e10cSrcweir String maFilterName; 427cdf0e10cSrcweir String maFilterOptions; 428cdf0e10cSrcweir 429cdf0e10cSrcweir void maybeCreateRealFileName(const String& rOwnDocName); 430cdf0e10cSrcweir }; 431cdf0e10cSrcweir 432cdf0e10cSrcweir public: 433cdf0e10cSrcweir explicit ScExternalRefManager(ScDocument* pDoc); 434cdf0e10cSrcweir virtual ~ScExternalRefManager(); 435cdf0e10cSrcweir 436cdf0e10cSrcweir virtual String getCacheTableName(sal_uInt16 nFileId, size_t nTabIndex) const; 437cdf0e10cSrcweir 438cdf0e10cSrcweir /** 439cdf0e10cSrcweir * Get a cache table instance for specified table and table index. Unlike 440cdf0e10cSrcweir * the other method that takes a table name, this method does not create a 441cdf0e10cSrcweir * new table when a table is not available for specified index. 442cdf0e10cSrcweir * 443cdf0e10cSrcweir * @param nFileId file ID 444cdf0e10cSrcweir * @param nTabIndex cache table index 445cdf0e10cSrcweir * 446cdf0e10cSrcweir * @return shared_ptr to the cache table instance 447cdf0e10cSrcweir */ 448cdf0e10cSrcweir ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const; 449cdf0e10cSrcweir 450cdf0e10cSrcweir /** 451cdf0e10cSrcweir * Get a cache table instance for specified file and table name. If the 452cdf0e10cSrcweir * table instance is not already present, it'll instantiate a new one and 453cdf0e10cSrcweir * append it to the end of the table array. <I>It's important to be 454cdf0e10cSrcweir * aware of this fact especially for multi-table ranges for which 455cdf0e10cSrcweir * table orders are critical.</I> 456cdf0e10cSrcweir * 457cdf0e10cSrcweir * Excel filter calls this method to populate the cache table from the 458cdf0e10cSrcweir * XCT/CRN records. 459cdf0e10cSrcweir * 460cdf0e10cSrcweir * @param nFileId file ID 461cdf0e10cSrcweir * @param rTabName table name 462cdf0e10cSrcweir * @param bCreateNew if true, create a new table instance if it's not 463cdf0e10cSrcweir * already present. If false, it returns NULL if the 464cdf0e10cSrcweir * specified table's cache doesn't exist. 465cdf0e10cSrcweir * @param pnIndex if non-NULL pointer is passed, it stores the internal 466cdf0e10cSrcweir * index of a cache table instance. 467cdf0e10cSrcweir * 468cdf0e10cSrcweir * @return shared_ptr to the cache table instance 469cdf0e10cSrcweir */ 470cdf0e10cSrcweir ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex = 0); 471cdf0e10cSrcweir 472cdf0e10cSrcweir /** Returns a vector containing all (real) table names and cache tables of 473cdf0e10cSrcweir the specified file. 474cdf0e10cSrcweir 475cdf0e10cSrcweir The index in the returned vector corresponds to the table index used to 476cdf0e10cSrcweir access the cache table, e.g. in getCacheTable(). 477cdf0e10cSrcweir */ 478cdf0e10cSrcweir void getAllCachedTableNames(sal_uInt16 nFileId, ::std::vector<String>& rTabNames) const; 479cdf0e10cSrcweir 480cdf0e10cSrcweir /** 481cdf0e10cSrcweir * Get the span (distance+sign(distance)) of two sheets of a specified 482cdf0e10cSrcweir * file. 483cdf0e10cSrcweir * 484cdf0e10cSrcweir * @param nFileId file ID 485cdf0e10cSrcweir * @param rStartTabName name of first sheet (sheet1) 486cdf0e10cSrcweir * @param rEndTabName name of second sheet (sheet2) 487cdf0e10cSrcweir * 488cdf0e10cSrcweir * @return span 489cdf0e10cSrcweir * 1 if sheet2 == sheet1 490cdf0e10cSrcweir * > 1 if sheet2 > sheet1 491cdf0e10cSrcweir * < -1 if sheet2 < sheet1 492cdf0e10cSrcweir * -1 if nFileId or rStartTabName not found 493cdf0e10cSrcweir * 0 if rEndTabName not found 494cdf0e10cSrcweir */ 495cdf0e10cSrcweir SCsTAB getCachedTabSpan( sal_uInt16 nFileId, const String& rStartTabName, const String& rEndTabName ) const; 496cdf0e10cSrcweir 497cdf0e10cSrcweir /** 498cdf0e10cSrcweir * Get all unique number format indices that are used in the cache tables. 499cdf0e10cSrcweir * The retrieved indices are sorted in ascending order. 500cdf0e10cSrcweir * 501cdf0e10cSrcweir * @param rNumFmts (reference) all unique number format indices. 502cdf0e10cSrcweir */ 503cdf0e10cSrcweir void getAllCachedNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const; 504cdf0e10cSrcweir 505cdf0e10cSrcweir sal_uInt16 getExternalFileCount() const; 506cdf0e10cSrcweir 507cdf0e10cSrcweir /** 508cdf0e10cSrcweir * Mark all tables as referenced that are used by any LinkListener, used 509cdf0e10cSrcweir * only during store-to-file. 510cdf0e10cSrcweir * @returns <TRUE/> if ALL tables of ALL external documents are marked. 511cdf0e10cSrcweir */ 512cdf0e10cSrcweir bool markUsedByLinkListeners(); 513cdf0e10cSrcweir 514cdf0e10cSrcweir bool markUsedExternalRefCells(); 515cdf0e10cSrcweir 516cdf0e10cSrcweir /** 517cdf0e10cSrcweir * Set a table as referenced, used only during store-to-file. 518cdf0e10cSrcweir * @returns <TRUE/> if ALL tables of ALL external documents are marked. 519cdf0e10cSrcweir */ 520cdf0e10cSrcweir bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets ); 521cdf0e10cSrcweir void setAllCacheTableReferencedStati( bool bReferenced ); 522cdf0e10cSrcweir 523cdf0e10cSrcweir /** 524cdf0e10cSrcweir * Set a table as permanently referenced, to be called if not in 525cdf0e10cSrcweir * mark-during-store-to-file cycle. 526cdf0e10cSrcweir */ 527cdf0e10cSrcweir void setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets ); 528cdf0e10cSrcweir 529cdf0e10cSrcweir /** 530cdf0e10cSrcweir * @returns <TRUE/> if setAllCacheTableReferencedStati(false) was called, 531cdf0e10cSrcweir * <FALSE/> if setAllCacheTableReferencedStati(true) was called. 532cdf0e10cSrcweir */ isInReferenceMarking() const533cdf0e10cSrcweir bool isInReferenceMarking() const { return mbInReferenceMarking; } 534cdf0e10cSrcweir 535cdf0e10cSrcweir void storeRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScTokenArray& rArray); 536cdf0e10cSrcweir 537cdf0e10cSrcweir ScExternalRefCache::TokenRef getSingleRefToken( 538cdf0e10cSrcweir sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell, 539cdf0e10cSrcweir const ScAddress* pCurPos, SCTAB* pTab, ScExternalRefCache::CellFormat* pFmt = NULL); 540cdf0e10cSrcweir 541cdf0e10cSrcweir /** 542cdf0e10cSrcweir * Get an array of tokens that consist of the specified external cell 543cdf0e10cSrcweir * range. 544cdf0e10cSrcweir * 545cdf0e10cSrcweir * @param nFileId file ID for an external document 546cdf0e10cSrcweir * @param rTabName referenced sheet name 547cdf0e10cSrcweir * @param rRange referenced cell range 548cdf0e10cSrcweir * @param pCurPos current cursor position to keep track of cells that 549cdf0e10cSrcweir * reference an external data. 550cdf0e10cSrcweir * 551cdf0e10cSrcweir * @return shared_ptr to a token array instance. <i>The caller must not 552cdf0e10cSrcweir * delete the instance returned by this method.</i> 553cdf0e10cSrcweir */ 554cdf0e10cSrcweir ScExternalRefCache::TokenArrayRef getDoubleRefTokens( 555cdf0e10cSrcweir sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos); 556cdf0e10cSrcweir 557cdf0e10cSrcweir /** 558cdf0e10cSrcweir * Get an array of tokens corresponding with a specified name in a 559cdf0e10cSrcweir * specified file. 560cdf0e10cSrcweir * 561cdf0e10cSrcweir * @param pCurPos currnet cell address where this name token is used. 562cdf0e10cSrcweir * This is purely to keep track of all cells containing 563cdf0e10cSrcweir * external names for refreshing purposes. If this is 564cdf0e10cSrcweir * NULL, then the cell will not be added to the list. 565cdf0e10cSrcweir * 566cdf0e10cSrcweir * @return shared_ptr to array of tokens composing the name 567cdf0e10cSrcweir */ 568cdf0e10cSrcweir ScExternalRefCache::TokenArrayRef getRangeNameTokens( 569cdf0e10cSrcweir sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos = NULL); 570cdf0e10cSrcweir 571cdf0e10cSrcweir const String& getOwnDocumentName() const; 572cdf0e10cSrcweir bool isOwnDocument(const String& rFile) const; 573cdf0e10cSrcweir 574cdf0e10cSrcweir /** 575cdf0e10cSrcweir * Takes a flat file name, and convert it to an absolute URL path. An 576cdf0e10cSrcweir * absolute URL path begines with 'file:///. 577cdf0e10cSrcweir * 578cdf0e10cSrcweir * @param rFile file name to convert 579cdf0e10cSrcweir */ 580cdf0e10cSrcweir void convertToAbsName(String& rFile) const; 581cdf0e10cSrcweir sal_uInt16 getExternalFileId(const String& rFile); 582cdf0e10cSrcweir 583cdf0e10cSrcweir /** 584cdf0e10cSrcweir * It returns a pointer to the name of the URI associated with a given 585cdf0e10cSrcweir * external file ID. In case the original document has moved, it returns 586cdf0e10cSrcweir * an URI adjusted for the relocation. 587cdf0e10cSrcweir * 588cdf0e10cSrcweir * @param nFileId file ID for an external document 589cdf0e10cSrcweir * @param bForceOriginal If true, it always returns the original document 590cdf0e10cSrcweir * URI even if the referring document has relocated. 591cdf0e10cSrcweir * If false, it returns an URI adjusted for 592cdf0e10cSrcweir * relocated document. 593cdf0e10cSrcweir * 594cdf0e10cSrcweir * @return const String* external document URI. 595cdf0e10cSrcweir */ 596cdf0e10cSrcweir const String* getExternalFileName(sal_uInt16 nFileId, bool bForceOriginal = false); 597cdf0e10cSrcweir bool hasExternalFile(sal_uInt16 nFileId) const; 598cdf0e10cSrcweir bool hasExternalFile(const String& rFile) const; 599cdf0e10cSrcweir const SrcFileData* getExternalFileData(sal_uInt16 nFileId) const; 600cdf0e10cSrcweir 601cdf0e10cSrcweir const String* getRealTableName(sal_uInt16 nFileId, const String& rTabName) const; 602cdf0e10cSrcweir const String* getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const; 603cdf0e10cSrcweir void refreshNames(sal_uInt16 nFileId); 604cdf0e10cSrcweir void breakLink(sal_uInt16 nFileId); 605cdf0e10cSrcweir void switchSrcFile(sal_uInt16 nFileId, const String& rNewFile, const String& rNewFilter); 606cdf0e10cSrcweir 607cdf0e10cSrcweir /** 608cdf0e10cSrcweir * Set a relative file path for the specified file ID. Note that the 609cdf0e10cSrcweir * caller must ensure that the passed URL is a valid relative URL. 610cdf0e10cSrcweir * 611cdf0e10cSrcweir * @param nFileId file ID for an external document 612cdf0e10cSrcweir * @param rRelUrl relative URL 613cdf0e10cSrcweir */ 614cdf0e10cSrcweir void setRelativeFileName(sal_uInt16 nFileId, const String& rRelUrl); 615cdf0e10cSrcweir 616cdf0e10cSrcweir /** 617cdf0e10cSrcweir * Set the filter name and options if any for a given source document. 618cdf0e10cSrcweir * These values get reset when the source document ever gets reloaded. 619cdf0e10cSrcweir * 620cdf0e10cSrcweir * @param nFileId 621cdf0e10cSrcweir * @param rFilterName 622cdf0e10cSrcweir * @param rOptions 623cdf0e10cSrcweir */ 624cdf0e10cSrcweir void setFilterData(sal_uInt16 nFileId, const String& rFilterName, const String& rOptions); 625cdf0e10cSrcweir 626cdf0e10cSrcweir void clear(); 627cdf0e10cSrcweir 628cdf0e10cSrcweir bool hasExternalData() const; 629cdf0e10cSrcweir 630cdf0e10cSrcweir /** 631cdf0e10cSrcweir * Re-generates relative names for all stored source files. This is 632cdf0e10cSrcweir * necessary when exporting to an ods document, to ensure that all source 633cdf0e10cSrcweir * files have their respective relative names for xlink:href export. 634cdf0e10cSrcweir * 635cdf0e10cSrcweir * @param rBaseFileUrl Absolute URL of the content.xml fragment of the 636cdf0e10cSrcweir * document being exported. 637cdf0e10cSrcweir */ 638cdf0e10cSrcweir void resetSrcFileData(const String& rBaseFileUrl); 639cdf0e10cSrcweir 640cdf0e10cSrcweir /** 641cdf0e10cSrcweir * Replace the original URL wirh the real URL that was generated from the relative URL. 642cdf0e10cSrcweir */ 643cdf0e10cSrcweir void updateAbsAfterLoad(); 644cdf0e10cSrcweir 645cdf0e10cSrcweir /** 646cdf0e10cSrcweir * Stop tracking a specific formula cell. 647cdf0e10cSrcweir * 648cdf0e10cSrcweir * @param pCell pointer to cell that formerly contained external 649cdf0e10cSrcweir * reference. 650cdf0e10cSrcweir */ 651cdf0e10cSrcweir void removeRefCell(ScFormulaCell* pCell); 652cdf0e10cSrcweir 653cdf0e10cSrcweir /** 654cdf0e10cSrcweir * Register a new link listener to a specified external document. Note 655cdf0e10cSrcweir * that the caller is responsible for managing the life cycle of the 656cdf0e10cSrcweir * listener object. 657cdf0e10cSrcweir */ 658cdf0e10cSrcweir void addLinkListener(sal_uInt16 nFileId, LinkListener* pListener); 659cdf0e10cSrcweir 660cdf0e10cSrcweir /** 661cdf0e10cSrcweir * Remove an existing link listener. Note that removing a listener 662cdf0e10cSrcweir * pointer here does not delete the listener object instance. 663cdf0e10cSrcweir */ 664cdf0e10cSrcweir void removeLinkListener(sal_uInt16 nFileId, LinkListener* pListener); 665cdf0e10cSrcweir 666cdf0e10cSrcweir void removeLinkListener(LinkListener* pListener); 667cdf0e10cSrcweir 668cdf0e10cSrcweir /** 669cdf0e10cSrcweir * Notify all listeners that are listening to a specified external 670cdf0e10cSrcweir * document. 671cdf0e10cSrcweir * 672cdf0e10cSrcweir * @param nFileId file ID for an external document. 673cdf0e10cSrcweir */ 674cdf0e10cSrcweir void notifyAllLinkListeners(sal_uInt16 nFileId, LinkUpdateType eType); 675cdf0e10cSrcweir 676cdf0e10cSrcweir private: 677cdf0e10cSrcweir ScExternalRefManager(); 678cdf0e10cSrcweir ScExternalRefManager(const ScExternalRefManager&); 679cdf0e10cSrcweir 680cdf0e10cSrcweir void refreshAllRefCells(sal_uInt16 nFileId); 681cdf0e10cSrcweir 682cdf0e10cSrcweir void insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell); 683cdf0e10cSrcweir 684cdf0e10cSrcweir ScDocument* getSrcDocument(sal_uInt16 nFileId); 685cdf0e10cSrcweir SfxObjectShellRef loadSrcDocument(sal_uInt16 nFileId, String& rFilter); 686cdf0e10cSrcweir bool isFileLoadable(const String& rFile) const; 687cdf0e10cSrcweir 688cdf0e10cSrcweir void maybeLinkExternalFile(sal_uInt16 nFileId); 689cdf0e10cSrcweir 690cdf0e10cSrcweir /** 691cdf0e10cSrcweir * Try to create a "real" file name from the relative path. The original 692cdf0e10cSrcweir * file name may not point to the real document when the referencing and 693cdf0e10cSrcweir * referenced documents have been moved. 694cdf0e10cSrcweir * 695cdf0e10cSrcweir * For the real file name to be created, the relative name should not be 696cdf0e10cSrcweir * empty before calling this method, or the real file name will not be 697cdf0e10cSrcweir * created. 698cdf0e10cSrcweir * 699cdf0e10cSrcweir * @param nFileId file ID for an external document 700cdf0e10cSrcweir */ 701cdf0e10cSrcweir void maybeCreateRealFileName(sal_uInt16 nFileId); 702cdf0e10cSrcweir 703cdf0e10cSrcweir /** 704cdf0e10cSrcweir * Purge those source document instances that have not been accessed for 705cdf0e10cSrcweir * the specified duration. 706cdf0e10cSrcweir * 707cdf0e10cSrcweir * @param nTimeOut time out value in 100th of a second 708cdf0e10cSrcweir */ 709cdf0e10cSrcweir void purgeStaleSrcDocument(sal_Int32 nTimeOut); 710cdf0e10cSrcweir 711cdf0e10cSrcweir sal_uInt32 getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, ScDocument* pSrcDoc); 712cdf0e10cSrcweir 713cdf0e10cSrcweir private: 714cdf0e10cSrcweir /** cache of referenced ranges and names from source documents. */ 715cdf0e10cSrcweir ScExternalRefCache maRefCache; 716cdf0e10cSrcweir 717cdf0e10cSrcweir ScDocument* mpDoc; 718cdf0e10cSrcweir 719cdf0e10cSrcweir /** 720cdf0e10cSrcweir * Source document cache. This stores the original source document shell 721cdf0e10cSrcweir * instances. They get purged after a certain period of time. 722cdf0e10cSrcweir */ 723cdf0e10cSrcweir DocShellMap maDocShells; 724cdf0e10cSrcweir 725cdf0e10cSrcweir /** list of source documents that are managed by the link manager. */ 726cdf0e10cSrcweir LinkedDocMap maLinkedDocs; 727cdf0e10cSrcweir 728cdf0e10cSrcweir /** 729cdf0e10cSrcweir * List of referencing cells that may contain external names. There is 730cdf0e10cSrcweir * one list per source document. 731cdf0e10cSrcweir */ 732cdf0e10cSrcweir RefCellMap maRefCells; 733cdf0e10cSrcweir 734cdf0e10cSrcweir LinkListenerMap maLinkListeners; 735cdf0e10cSrcweir 736cdf0e10cSrcweir NumFmtMap maNumFormatMap; 737cdf0e10cSrcweir 738cdf0e10cSrcweir /** original source file index. */ 739cdf0e10cSrcweir ::std::vector<SrcFileData> maSrcFiles; 740cdf0e10cSrcweir 741cdf0e10cSrcweir /** Status whether in reference marking state. See isInReferenceMarking(). */ 742cdf0e10cSrcweir bool mbInReferenceMarking:1; 743cdf0e10cSrcweir 744cdf0e10cSrcweir /** 745cdf0e10cSrcweir * Controls whether or not to allow user interaction. We don't want any 746cdf0e10cSrcweir * user interaction when calling from the API. 747cdf0e10cSrcweir */ 748cdf0e10cSrcweir bool mbUserInteractionEnabled:1; 749cdf0e10cSrcweir 750cdf0e10cSrcweir AutoTimer maSrcDocTimer; 751cdf0e10cSrcweir DECL_LINK(TimeOutHdl, AutoTimer*); 752cdf0e10cSrcweir }; 753cdf0e10cSrcweir 754cdf0e10cSrcweir 755cdf0e10cSrcweir #endif 756