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