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