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