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