diff options
author | Rüdiger Timm <rt@openoffice.org> | 2008-12-12 09:38:47 +0000 |
---|---|---|
committer | Rüdiger Timm <rt@openoffice.org> | 2008-12-12 09:38:47 +0000 |
commit | 47b1cc26c2697d81b44be5fb53598321cbc5d827 (patch) | |
tree | 38848d46028498de77cf271535fffac1954ad237 /sc/inc/externalrefmgr.hxx | |
parent | a190965485508c4493ee33228dae68e12cd858f9 (diff) |
CWS-TOOLING: integrate CWS mooxlsc
2008-12-12 09:32:19 +0100 dr r265390 : #i10000# warning
2008-12-11 14:54:26 +0100 dr r265301 : add strings from dr66 to meet ui freeze
2008-12-11 14:53:20 +0100 dr r265300 : add strings from dr66 to meet ui freeze
2008-12-08 14:43:25 +0100 er r264997 : DBG_... need semicolon
2008-12-04 19:16:50 +0100 er r264872 : DBG_... needs semicolon
2008-12-04 11:09:27 +0100 er r264824 : DBG_ERROR needs semicolon
2008-12-03 13:29:46 +0100 er r264770 : CWS-TOOLING: rebase CWS mooxlsc to trunk@264325 (milestone: DEV300:m36)
2008-12-02 16:49:09 +0100 er r264722 : disable code for named references #i4385# import as long as #i3740# isn't fully implemented
2008-12-02 16:45:04 +0100 er r264721 : some compilers attempt to be too smart; persuade them it's really meant what was written
2008-12-02 16:04:56 +0100 er r264715 : #i3740# no storage in ODF for external name references
2008-11-29 02:20:50 +0100 er r264575 : some huge performance improvement when reading repeated empty rows for the external references cache from ODF, as they often occur in the sparse matrix
2008-11-29 01:14:55 +0100 er r264574 : WriteExternalRefCaches: for table:number-columns-repeated write used columns instead of MAXCOLCOUNT
2008-11-28 18:30:04 +0100 er r264570 : #i3740# write/read external name references as bracketed references, as proposed on the ODFF list
2008-11-27 20:36:54 +0100 er r264521 : merge i95068 from cws calc46 for code correctness
2008-11-21 20:39:34 +0100 kohei r264174 : fixed a crash when importing a BIFF8 document with per-sheet external names.
For now, we don't support per-sheet external names. Let's throw in NoName
error until they are supported.
2008-11-21 18:47:27 +0100 kohei r264168 : I forgot to process cached range references in the EXTERNNAME record, which
prevented cached external names with range references from being imported
correctly.
P.S. I swear I thought I had covered this....
2008-11-20 23:07:22 +0100 er r264104 : #i4385# parse external defined names in MOOXML import
2008-11-14 23:18:54 +0100 er r263700 : #i92797# parse external sheet references under aspects of MOOXML import and new ScExternalRefManager
2008-11-14 18:49:48 +0100 er r263696 : remove infinity assertion, leftover from binary file format; coded double error may occur via filter import
2008-11-12 13:29:44 +0100 er r263593 : make references to entire rows/columns, such as A:A or 3:3, actually work in MOOXML import
2008-11-03 12:35:11 +0100 er r263282 : a struct is a struct is a ...
2008-10-31 00:30:59 +0100 er r262843 : aTableRowCellAttrTokenMap needed
2008-10-31 00:26:07 +0100 er r262842 : GetTableRowCellAttrTokenMap() is not unused
2008-10-31 00:13:53 +0100 er r262841 : merge error
2008-10-31 00:05:39 +0100 er r262840 : merge error
2008-10-30 23:17:48 +0100 er r262839 : unresolved merge conflict!?!
2008-10-30 22:59:11 +0100 er r262838 : merge error
2008-10-30 16:31:04 +0100 hr r262833 : CWS-TOOLING: rebase CWS mooxlsc to trunk@262620 (milestone: DEV300:m34)
2008-10-16 21:57:51 +0200 er r262272 : migrate CWS mooxlsc to SVN
Diffstat (limited to 'sc/inc/externalrefmgr.hxx')
-rw-r--r-- | sc/inc/externalrefmgr.hxx | 565 |
1 files changed, 565 insertions, 0 deletions
diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx new file mode 100644 index 000000000000..859a916e07e2 --- /dev/null +++ b/sc/inc/externalrefmgr.hxx @@ -0,0 +1,565 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: externalrefmgr.hxx,v $ + * $Revision: 1.1.2.23 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SC_EXTERNALREFMGR_HXX +#define SC_EXTERNALREFMGR_HXX + +#include "global.hxx" +#include "address.hxx" +#include "sfx2/objsh.hxx" +#include "sfx2/lnkbase.hxx" +#include "tools/time.hxx" +#include "vcl/timer.hxx" +#include "svtools/zforlist.hxx" +#include "scmatrix.hxx" + +#include <hash_map> +#include <hash_set> +#include <boost/shared_ptr.hpp> +#include <vector> +#include <list> + +class ScDocument; +class ScToken; +class ScMatrix; +class ScTokenArray; +class String; +class SfxObjectShellRef; +class Window; + +class ScExternalRefCache; + +class ScExternalRefLink : public ::sfx2::SvBaseLink +{ +public: + ScExternalRefLink(ScDocument* pDoc, sal_uInt16 nFileId, const String& rFilter); + virtual ~ScExternalRefLink(); + + virtual void Closed(); + virtual void DataChanged(const String& rMimeType, const ::com::sun::star::uno::Any & rValue); + virtual void Edit(Window* pParent, const Link& rEndEditHdl); + + void SetDoReferesh(bool b); + +private: + ScExternalRefLink(); // disabled + ScExternalRefLink(const ScExternalRefLink&); // disabled + + DECL_LINK( ExternalRefEndEditHdl, ::sfx2::SvBaseLink* ); + + sal_uInt16 mnFileId; + String maFilterName; + ScDocument* mpDoc; + bool mbDoRefresh; +}; + +// ============================================================================ + +/** + * Cache table for external reference data. + */ +class ScExternalRefCache +{ +public: + typedef ::boost::shared_ptr<ScToken> TokenRef; + typedef ::boost::shared_ptr<ScTokenArray> TokenArrayRef; + + struct TableName + { + String maUpperName; + String maRealName; + + explicit TableName(const String& rUppper, const String& rReal); + }; + + struct CellFormat + { + bool mbIsSet; + short mnType; + sal_uInt32 mnIndex; + + explicit CellFormat(); + }; + +private: + /** individual cell within cached external ref table. */ + struct Cell + { + TokenRef mxToken; + sal_uInt32 mnFmtIndex; + }; + typedef ::std::hash_map<SCCOL, Cell> RowDataType; + typedef ::std::hash_map<SCROW, RowDataType> RowsDataType; + +public: + // SUNWS needs a forward declared friend, otherwise types and members + // of the outer class are not accessible. + class Table; + friend class ScExternalRefCache::Table; + + class Table + { + public: + Table(); + ~Table(); + + 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; + void getAllRows(::std::vector<SCROW>& rRows) const; + void getAllCols(SCROW nRow, ::std::vector<SCCOL>& rCols) const; + void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const; + + private: + RowsDataType maRows; + }; + + typedef ::boost::shared_ptr<Table> TableTypeRef; + typedef ::std::hash_map<String, size_t, ScStringHashCode> TableNameIndexMap; + + ScExternalRefCache(); + ~ScExternalRefCache(); + + const String* getRealTableName(sal_uInt16 nFileId, const String& rTabName) const; + const String* getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const; + + /** + * Get a cached cell data at specified cell location. + * + * @param nFileId file ID of an external document + * @param rTabName sheet name + * @param nRow + * @param nCol + * + * @return pointer to the token instance in the cache. <i>The caller does + * not need to delete this instance since its life cycle is + * managed by this class.</i> + */ + ScExternalRefCache::TokenRef getCellData( + sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, + sal_uInt32* pnFmtIndex = NULL); + + /** + * Get a cached cell range data. + * + * @return a new token array instance. Note that <i>the caller must + * manage the life cycle of the returned instance</i>, which is + * guaranteed if the TokenArrayRef is properly used.. + */ + ScExternalRefCache::TokenArrayRef getCellRangeData(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange); + + ScExternalRefCache::TokenArrayRef getRangeNameTokens(sal_uInt16 nFileId, const String& rName); + void setRangeNameTokens(sal_uInt16 nFileId, const String& rName, TokenArrayRef pArray); + + void setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, TokenRef pToken, sal_uInt32 nFmtIndex); + + struct SingleRangeData + { + /** This name must be in upper-case. */ + String maTableName; + ScMatrixRef mpRangeData; + }; + void setCellRangeData(sal_uInt16 nFileId, const ScRange& rRange, const ::std::vector<SingleRangeData>& rData, + TokenArrayRef pArray); + + bool isDocInitialized(sal_uInt16 nFileId); + void initializeDoc(sal_uInt16 nFileId, const ::std::vector<String>& rTabNames); + String getTableName(sal_uInt16 nFileId, size_t nCacheId) const; + void getAllTableNames(sal_uInt16 nFileId, ::std::vector<String>& rTabNames) const; + SCsTAB getTabSpan( sal_uInt16 nFileId, const String& rStartTabName, const String& rEndTabName ) const; + void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const; + bool hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const; + size_t getCacheTableCount(sal_uInt16 nFileId) const; + + ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const; + ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex); + + void clearCache(sal_uInt16 nFileId); + +private: + struct RangeHash + { + size_t operator()(const ScRange& rRange) const + { + const ScAddress& s = rRange.aStart; + const ScAddress& e = rRange.aEnd; + return s.Tab() + s.Col() + s.Row() + e.Tab() + e.Col() + e.Row(); + } + }; + + typedef ::std::hash_map<String, TokenArrayRef, ScStringHashCode> RangeNameMap; + typedef ::std::hash_map<ScRange, TokenArrayRef, RangeHash> RangeArrayMap; + typedef ::std::hash_map<String, String, ScStringHashCode> NamePairMap; + + // SUNWS needs a forward declared friend, otherwise types and members + // of the outer class are not accessible. + struct DocItem; + friend struct ScExternalRefCache::DocItem; + + /** Represents data cached for a single external document. */ + struct DocItem + { + /** The raw cache tables. */ + ::std::vector<TableTypeRef> maTables; + /** Table name list in correct order, in both upper- and real-case. */ + ::std::vector<TableName> maTableNames; + /** Table name to index map. The names must be stored upper-case. */ + TableNameIndexMap maTableNameIndex; + /** Range name cache. */ + RangeNameMap maRangeNames; + /** Token array cache for cell ranges. */ + RangeArrayMap maRangeArrays; + /** Upper- to real-case mapping for range names. */ + NamePairMap maRealRangeNameMap; + + bool mbInitFromSource; + + DocItem() : mbInitFromSource(false) {} + }; + typedef ::std::hash_map<sal_uInt16, DocItem> DocDataType; + DocItem* getDocItem(sal_uInt16 nFileId) const; + +private: + mutable DocDataType maDocs; +}; + +// ============================================================================ + +class ScExternalRefManager +{ +public: + + // SUNWS needs a forward declared friend, otherwise types and members + // of the outer class are not accessible. + class RefCells; + friend class ScExternalRefManager::RefCells; + + /** + * Collection of cell addresses that contain external references. This + * data is used for link updates. + */ + class RefCells + { + public: + RefCells(); + ~RefCells(); + + void insertCell(const ScAddress& rAddr); + void removeCell(const ScAddress& rAddr); + void moveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy); + void insertTable(SCTAB nPos); + void removeTable(SCTAB nPos); + void refreshAllCells(ScExternalRefManager& rRefMgr); + private: + + typedef ::std::hash_set<SCROW> RowSet; + typedef ::std::hash_map<SCCOL, RowSet> ColSet; + + // SUNWS needs a forward declared friend, otherwise types and members + // of the outer class are not accessible. + struct TabItem; + friend struct ScExternalRefManager::RefCells::TabItem; + + struct TabItem + { + SCTAB mnIndex; + ColSet maCols; + explicit TabItem(SCTAB nIndex); + explicit TabItem(const TabItem& r); + }; + typedef ::boost::shared_ptr<TabItem> TabItemRef; + + /** + * Return the position that points either to the specified table + * position or to the position where a new table would be inserted in + * case the specified table is not present. + * + * @param nTab index of the desired table + */ + ::std::list<TabItemRef>::iterator getTabPos(SCTAB nTab); + + // This list must be sorted by the table index at all times. + ::std::list<TabItemRef> maTables; + }; + +private: + /** Shell instance for a source document. */ + struct SrcShell + { + SfxObjectShellRef maShell; + Time maLastAccess; + }; + + typedef ::std::hash_map<sal_uInt16, SrcShell> DocShellMap; + typedef ::std::hash_set<sal_uInt16> LinkedDocSet; + + typedef ::std::hash_map<sal_uInt16, RefCells> RefCellMap; + typedef ::std::hash_map<sal_uInt16, SvNumberFormatterMergeMap> NumFmtMap; + +public: + /** Source document meta-data container. */ + struct SrcFileData + { + String maFileName; + String maRelativeName; + String maFilterName; + String maFilterOptions; + }; + +public: + explicit ScExternalRefManager(ScDocument* pDoc); + ~ScExternalRefManager(); + + String getCacheTableName(sal_uInt16 nFileId, size_t nTabIndex) const; + + /** + * Get a cache table instance for specified table and table index. Unlike + * the other method that takes a table name, this method does not create a + * new table when a table is not available for specified index. + * + * @param nFileId file ID + * @param nTabIndex cache table index + * + * @return shared_ptr to the cache table instance + */ + ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const; + + /** + * Get a cache table instance for specified file and table name. If the + * table instance is not already present, it'll instantiate a new one and + * append it to the end of the table array. <I>It's important to be + * aware of this fact especially for multi-table ranges for which + * table orders are critical.</I> + * + * Excel filter calls this method to populate the cache table from the + * XCT/CRN records. + * + * @param nFileId file ID + * @param rTabName table name + * + * @return shared_ptr to the cache table instance + */ + ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex = 0); + void getAllCachedTableNames(sal_uInt16 nFileId, ::std::vector<String>& rTabNames) const; + + /** + * Get the span (distance+sign(distance)) of two sheets of a specified + * file. + * + * @param nFileId file ID + * @param rStartTabName name of first sheet (sheet1) + * @param rEndTabName name of second sheet (sheet2) + * + * @return span + * 1 if sheet2 == sheet1 + * > 1 if sheet2 > sheet1 + * < -1 if sheet2 < sheet1 + * -1 if nFileId or rStartTabName not found + * 0 if rEndTabName not found + */ + SCsTAB getCachedTabSpan( sal_uInt16 nFileId, const String& rStartTabName, const String& rEndTabName ) const; + + /** + * Get all unique number format indices that are used in the cache tables. + * The retrieved indices are sorted in ascending order. + * + * @param rNumFmts (reference) all unique number format indices. + */ + void getAllCachedNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const; + + bool hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const; + size_t getCacheTableCount(sal_uInt16 nFileId) const; + sal_uInt16 getExternalFileCount() const; + + void storeRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScTokenArray& rArray); + + ScExternalRefCache::TokenRef getSingleRefToken( + sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell, + const ScAddress* pCurPos, SCTAB* pTab, ScExternalRefCache::CellFormat* pFmt = NULL); + + /** + * Get an array of tokens that consist of the specified external cell + * range. + * + * @param nFileId file ID for an external document + * @param rTabName referenced sheet name + * @param rRange referenced cell range + * @param pCurPos current cursor position to keep track of cells that + * reference an external data. + * + * @return shared_ptr to a token array instance. <i>The caller must not + * delete the instance returned by this method.</i> + */ + ScExternalRefCache::TokenArrayRef getDoubleRefTokens(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos); + + /** + * Get an array of tokens corresponding with a specified name in a + * specified file. + * + * @param pCurPos currnet cell address where this name token is used. + * This is purely to keep track of all cells containing + * external names for refreshing purposes. If this is + * NULL, then the cell will not be added to the list. + * + * @return shared_ptr to array of tokens composing the name + */ + ScExternalRefCache::TokenArrayRef getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos = NULL); + + const String& getOwnDocumentName() const; + bool isOwnDocument(const String& rFile) const; + + /** + * Takes a flat file name, and convert it to an absolute URL path. An + * absolute URL path begines with 'file:///. + * + * @param rFile file name to convert + */ + void convertToAbsName(String& rFile) const; + sal_uInt16 getExternalFileId(const String& rFile); + const String* getExternalFileName(sal_uInt16 nFileId) const; + bool hasExternalFile(sal_uInt16 nFileId) const; + bool hasExternalFile(const String& rFile) const; + const SrcFileData* getExternalFileData(sal_uInt16 nFileId) const; + + const String* getRealTableName(sal_uInt16 nFileId, const String& rTabName) const; + const String* getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const; + void refreshNames(sal_uInt16 nFileId); + void switchSrcFile(sal_uInt16 nFileId, const String& rNewFile); + + void setRelativeFileName(sal_uInt16 nFileId, const String& rRelUrl); + + /** + * Set the filter name and options if any for a given source document. + * These values get reset when the source document ever gets reloaded. + * + * @param nFileId + * @param rFilterName + * @param rOptions + */ + void setFilterData(sal_uInt16 nFileId, const String& rFilterName, const String& rOptions); + + void removeSrcDocument(sal_uInt16 nFileId, bool bBreakLink); + void clear(); + + bool hasExternalData() const; + + /** + * Re-generates relative names for all stored source files. This is + * necessary when exporting to an ods document, to ensure that all source + * files have their respective relative names for xlink:href export. + */ + void resetSrcFileData(); + + /** + * Update a single referencing cell position. + * + * @param rOldPos old position + * @param rNewPos new position + */ + void updateRefCell(const ScAddress& rOldPos, const ScAddress& rNewPos, bool bCopy); + + /** + * Update referencing cells affected by sheet movement. + * + * @param nOldTab old sheet position + * @param nNewTab new sheet position + * @param bCopy whether this is a sheet move (false) or sheet copy (true) + */ + void updateRefMoveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy); + + /** + * Update referencing cells affected by sheet insertion. + * + * @param nPos sheet insertion position. All sheets to the right + * including the one at the insertion poistion shift to the + * right by one. + */ + void updateRefInsertTable(SCTAB nPos); + + void updateRefDeleteTable(SCTAB nPos); + +private: + ScExternalRefManager(); + ScExternalRefManager(const ScExternalRefManager&); + + void refreshAllRefCells(sal_uInt16 nFileId); + + void insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell); + + ScDocument* getSrcDocument(sal_uInt16 nFileId); + SfxObjectShellRef loadSrcDocument(sal_uInt16 nFileId, String& rFilter); + bool isFileLoadable(const String& rFile) const; + + void maybeLinkExternalFile(sal_uInt16 nFileId); + + bool compileTokensByCell(const ScAddress& rCell); + + /** + * Purge those source document instances that have not been accessed for + * the specified duration. + * + * @param nTimeOut time out value in 100th of a second + */ + void purgeStaleSrcDocument(sal_Int32 nTimeOut); + + sal_uInt32 getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, ScDocument* pSrcDoc); + +private: + /** cache of referenced ranges and names from source documents. */ + ScExternalRefCache maRefCache; + + ScDocument* mpDoc; + + /** + * Source document cache. This stores the original source document shell + * instances. They get purged after a certain period of time. + */ + DocShellMap maDocShells; + + /** list of source documents that are managed by the link manager. */ + LinkedDocSet maLinkedDocs; + + /** + * List of referencing cells that may contain external names. There is + * one list per source document. + */ + RefCellMap maRefCells; + + NumFmtMap maNumFormatMap; + + /** original source file index. */ + ::std::vector<SrcFileData> maSrcFiles; + + AutoTimer maSrcDocTimer; + DECL_LINK(TimeOutHdl, AutoTimer*); +}; + + +#endif |