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 : : #include "externalrefmgr.hxx"
30 : : #include "document.hxx"
31 : : #include "token.hxx"
32 : : #include "tokenarray.hxx"
33 : : #include "address.hxx"
34 : : #include "tablink.hxx"
35 : : #include "docsh.hxx"
36 : : #include "scextopt.hxx"
37 : : #include "rangenam.hxx"
38 : : #include "cell.hxx"
39 : : #include "viewdata.hxx"
40 : : #include "tabvwsh.hxx"
41 : : #include "sc.hrc"
42 : : #include "globstr.hrc"
43 : :
44 : : #include "sfx2/app.hxx"
45 : : #include "sfx2/docfilt.hxx"
46 : : #include "sfx2/docfile.hxx"
47 : : #include "sfx2/fcontnr.hxx"
48 : : #include "sfx2/sfxsids.hrc"
49 : : #include "sfx2/objsh.hxx"
50 : : #include "svl/broadcast.hxx"
51 : : #include "svl/smplhint.hxx"
52 : : #include "svl/itemset.hxx"
53 : : #include "svl/stritem.hxx"
54 : : #include "svl/urihelper.hxx"
55 : : #include "svl/zformat.hxx"
56 : : #include "sfx2/linkmgr.hxx"
57 : : #include "tools/urlobj.hxx"
58 : : #include "unotools/ucbhelper.hxx"
59 : : #include "unotools/localfilehelper.hxx"
60 : : #include "vcl/msgbox.hxx"
61 : :
62 : : #include <memory>
63 : : #include <algorithm>
64 : :
65 : : #include <boost/scoped_ptr.hpp>
66 : :
67 : : using ::std::auto_ptr;
68 : : using ::com::sun::star::uno::Any;
69 : : using ::rtl::OUString;
70 : : using ::std::vector;
71 : : using ::std::find;
72 : : using ::std::find_if;
73 : : using ::std::remove_if;
74 : : using ::std::distance;
75 : : using ::std::pair;
76 : : using ::std::list;
77 : : using ::std::unary_function;
78 : : using namespace formula;
79 : :
80 : : #define SRCDOC_LIFE_SPAN 6000 // 1 minute (in 100th of a sec)
81 : : #define SRCDOC_SCAN_INTERVAL 1000*5 // every 5 seconds (in msec)
82 : :
83 : : namespace {
84 : :
85 : 0 : class TabNameSearchPredicate : public unary_function<ScExternalRefCache::TableName, bool>
86 : : {
87 : : public:
88 : 0 : explicit TabNameSearchPredicate(const OUString& rSearchName) :
89 : 0 : maSearchName(ScGlobal::pCharClass->uppercase(rSearchName))
90 : : {
91 : 0 : }
92 : :
93 : 0 : bool operator()(const ScExternalRefCache::TableName& rTabNameSet) const
94 : : {
95 : : // Ok, I'm doing case insensitive search here.
96 : 0 : return rTabNameSet.maUpperName.equals(maSearchName);
97 : : }
98 : :
99 : : private:
100 : : OUString maSearchName;
101 : : };
102 : :
103 : : class FindSrcFileByName : public unary_function<ScExternalRefManager::SrcFileData, bool>
104 : : {
105 : : public:
106 : 122 : FindSrcFileByName(const OUString& rMatchName) :
107 : 122 : mrMatchName(rMatchName)
108 : : {
109 : 122 : }
110 : :
111 : 111 : bool operator()(const ScExternalRefManager::SrcFileData& rSrcData) const
112 : : {
113 : 111 : return rSrcData.maFileName.equals(mrMatchName);
114 : : }
115 : :
116 : : private:
117 : : const OUString& mrMatchName;
118 : : };
119 : :
120 : : class NotifyLinkListener : public unary_function<ScExternalRefManager::LinkListener*, void>
121 : : {
122 : : public:
123 : 0 : NotifyLinkListener(sal_uInt16 nFileId, ScExternalRefManager::LinkUpdateType eType) :
124 : 0 : mnFileId(nFileId), meType(eType) {}
125 : :
126 : 0 : NotifyLinkListener(const NotifyLinkListener& r) :
127 : 0 : mnFileId(r.mnFileId), meType(r.meType) {}
128 : :
129 : 0 : void operator() (ScExternalRefManager::LinkListener* p) const
130 : : {
131 : 0 : p->notify(mnFileId, meType);
132 : 0 : }
133 : : private:
134 : : sal_uInt16 mnFileId;
135 : : ScExternalRefManager::LinkUpdateType meType;
136 : : };
137 : :
138 : : struct UpdateFormulaCell : public unary_function<ScFormulaCell*, void>
139 : : {
140 : 0 : void operator() (ScFormulaCell* pCell) const
141 : : {
142 : : // Check to make sure the cell really contains ocExternalRef.
143 : : // External names, external cell and range references all have a
144 : : // ocExternalRef token.
145 : 0 : const ScTokenArray* pCode = pCell->GetCode();
146 [ # # ]: 0 : if (!pCode->HasExternalRef())
147 : 0 : return;
148 : :
149 : 0 : ScTokenArray* pArray = pCell->GetCode();
150 [ # # ]: 0 : if (pArray)
151 : : // Clear the error code, or a cell with error won't get re-compiled.
152 : 0 : pArray->SetCodeError(0);
153 : :
154 : 0 : pCell->SetCompile(true);
155 : 0 : pCell->CompileTokenArray();
156 : 0 : pCell->SetDirty();
157 : : }
158 : : };
159 : :
160 : : class RemoveFormulaCell : public unary_function<pair<const sal_uInt16, ScExternalRefManager::RefCellSet>, void>
161 : : {
162 : : public:
163 : 229 : explicit RemoveFormulaCell(ScFormulaCell* p) : mpCell(p) {}
164 : 18 : void operator() (pair<const sal_uInt16, ScExternalRefManager::RefCellSet>& r) const
165 : : {
166 : 18 : r.second.erase(mpCell);
167 : 18 : }
168 : : private:
169 : : ScFormulaCell* mpCell;
170 : : };
171 : :
172 : : class ConvertFormulaToStatic : public unary_function<ScFormulaCell*, void>
173 : : {
174 : : public:
175 : 0 : explicit ConvertFormulaToStatic(ScDocument* pDoc) : mpDoc(pDoc) {}
176 : 0 : void operator() (ScFormulaCell* pCell) const
177 : : {
178 : 0 : ScAddress aPos = pCell->aPos;
179 : :
180 : : // We don't check for empty cells because empty external cells are
181 : : // treated as having a value of 0.
182 : :
183 [ # # ][ # # ]: 0 : if (pCell->IsValue())
184 : : {
185 : : // Turn this into value cell.
186 [ # # ]: 0 : double fVal = pCell->GetValue();
187 [ # # ][ # # ]: 0 : mpDoc->PutCell(aPos, new ScValueCell(fVal));
[ # # ]
188 : : }
189 : : else
190 : : {
191 : : // string cell otherwise.
192 [ # # ]: 0 : rtl::OUString aVal = pCell->GetString();
193 [ # # ][ # # ]: 0 : mpDoc->PutCell(aPos, new ScStringCell(aVal));
[ # # ]
194 : : }
195 : 0 : }
196 : : private:
197 : : ScDocument* mpDoc;
198 : : };
199 : :
200 : : /**
201 : : * Check whether a named range contains an external reference to a
202 : : * particular document.
203 : : */
204 : 0 : bool hasRefsToSrcDoc(ScRangeData& rData, sal_uInt16 nFileId)
205 : : {
206 : 0 : ScTokenArray* pArray = rData.GetCode();
207 [ # # ]: 0 : if (!pArray)
208 : 0 : return false;
209 : :
210 : 0 : pArray->Reset();
211 : 0 : ScToken* p = static_cast<ScToken*>(pArray->GetNextReference());
212 [ # # ]: 0 : for (; p; p = static_cast<ScToken*>(pArray->GetNextReference()))
213 : : {
214 [ # # ]: 0 : if (!p->IsExternalRef())
215 : 0 : continue;
216 : :
217 [ # # ]: 0 : if (p->GetIndex() == nFileId)
218 : 0 : return true;
219 : : }
220 : 0 : return false;
221 : : }
222 : :
223 : : class EraseRangeByIterator : unary_function<ScRangeName::iterator, void>
224 : : {
225 : : ScRangeName& mrRanges;
226 : : public:
227 : 0 : EraseRangeByIterator(ScRangeName& rRanges) : mrRanges(rRanges) {}
228 : 0 : void operator() (const ScRangeName::iterator& itr)
229 : : {
230 : 0 : mrRanges.erase(itr);
231 : 0 : }
232 : : };
233 : :
234 : : /**
235 : : * Remove all named ranges that contain references to specified source
236 : : * document.
237 : : */
238 : 0 : void removeRangeNamesBySrcDoc(ScRangeName& rRanges, sal_uInt16 nFileId)
239 : : {
240 [ # # ][ # # ]: 0 : ScRangeName::iterator itr = rRanges.begin(), itrEnd = rRanges.end();
241 [ # # ]: 0 : vector<ScRangeName::iterator> v;
242 [ # # ][ # # ]: 0 : for (; itr != itrEnd; ++itr)
[ # # ]
243 : : {
244 [ # # ][ # # ]: 0 : if (hasRefsToSrcDoc(*itr->second, nFileId))
[ # # ]
245 [ # # ]: 0 : v.push_back(itr);
246 : : }
247 [ # # ]: 0 : for_each(v.begin(), v.end(), EraseRangeByIterator(rRanges));
248 : 0 : }
249 : :
250 : : }
251 : :
252 : : // ============================================================================
253 : :
254 : 12 : ScExternalRefCache::Table::Table()
255 [ + - ][ + - ]: 12 : : meReferenced( REFERENCED_MARKED )
256 : : // Prevent accidental data loss due to lack of knowledge.
257 : : {
258 : 12 : }
259 : :
260 [ + - ]: 3 : ScExternalRefCache::Table::~Table()
261 : : {
262 : 3 : }
263 : :
264 : 0 : void ScExternalRefCache::Table::setReferencedFlag( ScExternalRefCache::Table::ReferencedFlag eFlag )
265 : : {
266 : 0 : meReferenced = eFlag;
267 : 0 : }
268 : :
269 : 0 : void ScExternalRefCache::Table::setReferenced( bool bReferenced )
270 : : {
271 [ # # ]: 0 : if (meReferenced != REFERENCED_PERMANENT)
272 [ # # ]: 0 : meReferenced = (bReferenced ? REFERENCED_MARKED : UNREFERENCED);
273 : 0 : }
274 : :
275 : 0 : ScExternalRefCache::Table::ReferencedFlag ScExternalRefCache::Table::getReferencedFlag() const
276 : : {
277 : 0 : return meReferenced;
278 : : }
279 : :
280 : 0 : bool ScExternalRefCache::Table::isReferenced() const
281 : : {
282 : 0 : return meReferenced != UNREFERENCED;
283 : : }
284 : :
285 : 189 : void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uLong nFmtIndex, bool bSetCacheRange)
286 : : {
287 : : using ::std::pair;
288 [ + - ]: 189 : RowsDataType::iterator itrRow = maRows.find(nRow);
289 [ + - ][ + + ]: 189 : if (itrRow == maRows.end())
290 : : {
291 : : // This row does not exist yet.
292 : : pair<RowsDataType::iterator, bool> res = maRows.insert(
293 [ + - ][ + - ]: 48 : RowsDataType::value_type(nRow, RowDataType()));
[ + - ][ + - ]
[ + - ]
294 : :
295 [ + - ]: 48 : if (!res.second)
296 : 189 : return;
297 : :
298 : 48 : itrRow = res.first;
299 : : }
300 : :
301 : : // Insert this token into the specified column location. I don't need to
302 : : // check for existing data. Just overwrite it.
303 [ + - ]: 189 : RowDataType& rRow = itrRow->second;
304 [ + - ]: 189 : ScExternalRefCache::Cell aCell;
305 [ + - ]: 189 : aCell.mxToken = pToken;
306 : 189 : aCell.mnFmtIndex = nFmtIndex;
307 [ + - ][ + - ]: 189 : rRow.insert(RowDataType::value_type(nCol, aCell));
[ + - ]
308 [ + + ]: 189 : if (bSetCacheRange)
309 [ + - ][ + - ]: 189 : setCachedCell(nCol, nRow);
310 : : }
311 : :
312 : 0 : ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex) const
313 : : {
314 [ # # ]: 0 : RowsDataType::const_iterator itrTable = maRows.find(nRow);
315 [ # # ][ # # ]: 0 : if (itrTable == maRows.end())
316 : : {
317 : : // this table doesn't have the specified row.
318 [ # # ]: 0 : return getEmptyOrNullToken(nCol, nRow);
319 : : }
320 : :
321 [ # # ]: 0 : const RowDataType& rRowData = itrTable->second;
322 [ # # ]: 0 : RowDataType::const_iterator itrRow = rRowData.find(nCol);
323 [ # # ][ # # ]: 0 : if (itrRow == rRowData.end())
324 : : {
325 : : // this row doesn't have the specified column.
326 [ # # ]: 0 : return getEmptyOrNullToken(nCol, nRow);
327 : : }
328 : :
329 [ # # ]: 0 : const Cell& rCell = itrRow->second;
330 [ # # ]: 0 : if (pnFmtIndex)
331 : 0 : *pnFmtIndex = rCell.mnFmtIndex;
332 : :
333 : 0 : return rCell.mxToken;
334 : : }
335 : :
336 : 0 : bool ScExternalRefCache::Table::hasRow( SCROW nRow ) const
337 : : {
338 [ # # ]: 0 : RowsDataType::const_iterator itrRow = maRows.find(nRow);
339 [ # # ]: 0 : return itrRow != maRows.end();
340 : : }
341 : :
342 : 6 : void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows, SCROW nLow, SCROW nHigh) const
343 : : {
344 [ + - ]: 6 : vector<SCROW> aRows;
345 [ + - ]: 6 : aRows.reserve(maRows.size());
346 [ + - ][ + - ]: 6 : RowsDataType::const_iterator itr = maRows.begin(), itrEnd = maRows.end();
347 [ + + ]: 33 : for (; itr != itrEnd; ++itr)
348 [ + - ][ + - ]: 27 : if (nLow <= itr->first && itr->first <= nHigh)
[ + - ][ + - ]
[ + - ]
349 [ + - ][ + - ]: 27 : aRows.push_back(itr->first);
350 : :
351 : : // hash map is not ordered, so we need to explicitly sort it.
352 [ + - ]: 6 : ::std::sort(aRows.begin(), aRows.end());
353 : 6 : rRows.swap(aRows);
354 : 6 : }
355 : :
356 : 0 : ::std::pair< SCROW, SCROW > ScExternalRefCache::Table::getRowRange() const
357 : : {
358 : 0 : ::std::pair< SCROW, SCROW > aRange( 0, 0 );
359 [ # # ]: 0 : if( !maRows.empty() )
360 : : {
361 : : // iterate over entire container (hash map is not sorted by key)
362 [ # # ][ # # ]: 0 : RowsDataType::const_iterator itr = maRows.begin(), itrEnd = maRows.end();
363 [ # # ]: 0 : aRange.first = itr->first;
364 [ # # ]: 0 : aRange.second = itr->first + 1;
365 [ # # ]: 0 : while( ++itr != itrEnd )
366 : : {
367 [ # # ][ # # ]: 0 : if( itr->first < aRange.first )
368 [ # # ]: 0 : aRange.first = itr->first;
369 [ # # ][ # # ]: 0 : else if( itr->first >= aRange.second )
370 [ # # ]: 0 : aRange.second = itr->first + 1;
371 : : }
372 : : }
373 : 0 : return aRange;
374 : : }
375 : :
376 : 27 : void ScExternalRefCache::Table::getAllCols(SCROW nRow, vector<SCCOL>& rCols, SCCOL nLow, SCCOL nHigh) const
377 : : {
378 [ + - ]: 27 : RowsDataType::const_iterator itrRow = maRows.find(nRow);
379 [ + - ][ + - ]: 27 : if (itrRow == maRows.end())
380 : : // this table doesn't have the specified row.
381 : 27 : return;
382 : :
383 [ + - ]: 27 : const RowDataType& rRowData = itrRow->second;
384 [ + - ]: 27 : vector<SCCOL> aCols;
385 [ + - ]: 27 : aCols.reserve(rRowData.size());
386 [ + - ][ + - ]: 27 : RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end();
387 [ + + ]: 81 : for (; itrCol != itrColEnd; ++itrCol)
388 [ + - ][ + - ]: 54 : if (nLow <= itrCol->first && itrCol->first <= nHigh)
[ + - ][ + - ]
[ + - ]
389 [ + - ][ + - ]: 54 : aCols.push_back(itrCol->first);
390 : :
391 : : // hash map is not ordered, so we need to explicitly sort it.
392 [ + - ]: 27 : ::std::sort(aCols.begin(), aCols.end());
393 : 27 : rCols.swap(aCols);
394 : : }
395 : :
396 : 0 : ::std::pair< SCCOL, SCCOL > ScExternalRefCache::Table::getColRange( SCROW nRow ) const
397 : : {
398 : 0 : ::std::pair< SCCOL, SCCOL > aRange( 0, 0 );
399 : :
400 [ # # ]: 0 : RowsDataType::const_iterator itrRow = maRows.find( nRow );
401 [ # # ][ # # ]: 0 : if (itrRow == maRows.end())
402 : : // this table doesn't have the specified row.
403 : : return aRange;
404 : :
405 [ # # ]: 0 : const RowDataType& rRowData = itrRow->second;
406 [ # # ]: 0 : if( !rRowData.empty() )
407 : : {
408 : : // iterate over entire container (hash map is not sorted by key)
409 [ # # ][ # # ]: 0 : RowDataType::const_iterator itr = rRowData.begin(), itrEnd = rRowData.end();
410 [ # # ]: 0 : aRange.first = itr->first;
411 [ # # ]: 0 : aRange.second = itr->first + 1;
412 [ # # ]: 0 : while( ++itr != itrEnd )
413 : : {
414 [ # # ][ # # ]: 0 : if( itr->first < aRange.first )
415 [ # # ]: 0 : aRange.first = itr->first;
416 [ # # ][ # # ]: 0 : else if( itr->first >= aRange.second )
417 [ # # ]: 0 : aRange.second = itr->first + 1;
418 : : }
419 : : }
420 : : return aRange;
421 : : }
422 : :
423 : 0 : void ScExternalRefCache::Table::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const
424 : : {
425 [ # # ][ # # ]: 0 : RowsDataType::const_iterator itrRow = maRows.begin(), itrRowEnd = maRows.end();
426 [ # # ]: 0 : for (; itrRow != itrRowEnd; ++itrRow)
427 : : {
428 [ # # ]: 0 : const RowDataType& rRowData = itrRow->second;
429 [ # # ][ # # ]: 0 : RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end();
430 [ # # ]: 0 : for (; itrCol != itrColEnd; ++itrCol)
431 : : {
432 [ # # ]: 0 : const Cell& rCell = itrCol->second;
433 [ # # ]: 0 : rNumFmts.push_back(rCell.mnFmtIndex);
434 : : }
435 : : }
436 : 0 : }
437 : :
438 : 0 : bool ScExternalRefCache::Table::isRangeCached(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
439 : : {
440 [ # # ]: 0 : return maCachedRanges.In(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0));
441 : : }
442 : :
443 : 270 : void ScExternalRefCache::Table::setCachedCell(SCCOL nCol, SCROW nRow)
444 : : {
445 : 270 : setCachedCellRange(nCol, nRow, nCol, nRow);
446 : 270 : }
447 : :
448 : 288 : void ScExternalRefCache::Table::setCachedCellRange(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
449 : : {
450 : 288 : ScRange aRange(nCol1, nRow1, 0, nCol2, nRow2, 0);
451 [ + + ][ + - ]: 288 : if ( maCachedRanges.empty() )
452 [ + - ]: 12 : maCachedRanges.Append(aRange);
453 : : else
454 [ + - ]: 276 : maCachedRanges.Join(aRange);
455 : :
456 [ + - ]: 288 : String aStr;
457 [ + - ][ + - ]: 288 : maCachedRanges.Format(aStr, SCA_VALID);
458 : 288 : }
459 : :
460 : 0 : void ScExternalRefCache::Table::setWholeTableCached()
461 : : {
462 : 0 : setCachedCellRange(0, 0, MAXCOL, MAXROW);
463 : 0 : }
464 : :
465 : 0 : bool ScExternalRefCache::Table::isInCachedRanges(SCCOL nCol, SCROW nRow) const
466 : : {
467 [ # # ]: 0 : return maCachedRanges.In(ScRange(nCol, nRow, 0, nCol, nRow, 0));
468 : : }
469 : :
470 : 0 : ScExternalRefCache::TokenRef ScExternalRefCache::Table::getEmptyOrNullToken(
471 : : SCCOL nCol, SCROW nRow) const
472 : : {
473 [ # # ]: 0 : if (isInCachedRanges(nCol, nRow))
474 : : {
475 [ # # ][ # # ]: 0 : TokenRef p(new ScEmptyCellToken(false, false));
476 [ # # ]: 0 : return p;
477 : : }
478 : 0 : return TokenRef();
479 : : }
480 : :
481 : : // ----------------------------------------------------------------------------
482 : :
483 : 24 : ScExternalRefCache::TableName::TableName(const OUString& rUpper, const OUString& rReal) :
484 : 24 : maUpperName(rUpper), maRealName(rReal)
485 : : {
486 : 24 : }
487 : :
488 : : // ----------------------------------------------------------------------------
489 : :
490 : 129 : ScExternalRefCache::CellFormat::CellFormat() :
491 : 129 : mbIsSet(false), mnType(NUMBERFORMAT_ALL), mnIndex(0)
492 : : {
493 : 129 : }
494 : :
495 : : // ----------------------------------------------------------------------------
496 : :
497 [ + - ]: 275 : ScExternalRefCache::ScExternalRefCache()
498 : : {
499 : 275 : }
500 [ + - ]: 262 : ScExternalRefCache::~ScExternalRefCache()
501 : : {
502 : 262 : }
503 : :
504 : 87 : const OUString* ScExternalRefCache::getRealTableName(sal_uInt16 nFileId, const OUString& rTabName) const
505 : : {
506 [ + - ]: 87 : DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
507 [ - + ][ + - ]: 87 : if (itrDoc == maDocs.end())
508 : : {
509 : : // specified document is not cached.
510 : 0 : return NULL;
511 : : }
512 : :
513 [ + - ]: 87 : const DocItem& rDoc = itrDoc->second;
514 : : TableNameIndexMap::const_iterator itrTabId = rDoc.maTableNameIndex.find(
515 [ + - ][ + - ]: 87 : ScGlobal::pCharClass->uppercase(rTabName));
516 [ - + ][ + - ]: 87 : if (itrTabId == rDoc.maTableNameIndex.end())
517 : : {
518 : : // the specified table is not in cache.
519 : 0 : return NULL;
520 : : }
521 : :
522 [ + - ]: 87 : return &rDoc.maTableNames[itrTabId->second].maRealName;
523 : : }
524 : :
525 : 0 : const OUString* ScExternalRefCache::getRealRangeName(sal_uInt16 nFileId, const OUString& rRangeName) const
526 : : {
527 [ # # ]: 0 : DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
528 [ # # ][ # # ]: 0 : if (itrDoc == maDocs.end())
529 : : {
530 : : // specified document is not cached.
531 : 0 : return NULL;
532 : : }
533 : :
534 [ # # ]: 0 : const DocItem& rDoc = itrDoc->second;
535 : : NamePairMap::const_iterator itr = rDoc.maRealRangeNameMap.find(
536 [ # # ][ # # ]: 0 : ScGlobal::pCharClass->uppercase(rRangeName));
537 [ # # ][ # # ]: 0 : if (itr == rDoc.maRealRangeNameMap.end())
538 : : // range name not found.
539 : 0 : return NULL;
540 : :
541 [ # # ]: 0 : return &itr->second;
542 : : }
543 : :
544 : 0 : ScExternalRefCache::TokenRef ScExternalRefCache::getCellData(
545 : : sal_uInt16 nFileId, const OUString& rTabName, SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex)
546 : : {
547 [ # # ]: 0 : DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
548 [ # # ][ # # ]: 0 : if (itrDoc == maDocs.end())
549 : : {
550 : : // specified document is not cached.
551 : 0 : return TokenRef();
552 : : }
553 : :
554 [ # # ]: 0 : const DocItem& rDoc = itrDoc->second;
555 : : TableNameIndexMap::const_iterator itrTabId = rDoc.maTableNameIndex.find(
556 [ # # ][ # # ]: 0 : ScGlobal::pCharClass->uppercase(rTabName));
557 [ # # ][ # # ]: 0 : if (itrTabId == rDoc.maTableNameIndex.end())
558 : : {
559 : : // the specified table is not in cache.
560 : 0 : return TokenRef();
561 : : }
562 : :
563 [ # # ]: 0 : const TableTypeRef& pTableData = rDoc.maTables[itrTabId->second];
564 [ # # ]: 0 : if (!pTableData.get())
565 : : {
566 : : // the table data is not instantiated yet.
567 : 0 : return TokenRef();
568 : : }
569 : :
570 [ # # ]: 0 : return pTableData->getCell(nCol, nRow, pnFmtIndex);
571 : : }
572 : :
573 : 0 : ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData(
574 : : sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange)
575 : : {
576 [ # # ]: 0 : DocDataType::iterator itrDoc = maDocs.find(nFileId);
577 [ # # ][ # # ]: 0 : if (itrDoc == maDocs.end())
578 : : // specified document is not cached.
579 [ # # ]: 0 : return TokenArrayRef();
580 : :
581 [ # # ]: 0 : DocItem& rDoc = itrDoc->second;
582 : :
583 : : TableNameIndexMap::iterator itrTabId = rDoc.maTableNameIndex.find(
584 [ # # ][ # # ]: 0 : ScGlobal::pCharClass->uppercase(rTabName));
585 [ # # ][ # # ]: 0 : if (itrTabId == rDoc.maTableNameIndex.end())
586 : : // the specified table is not in cache.
587 [ # # ]: 0 : return TokenArrayRef();
588 : :
589 : 0 : const ScAddress& s = rRange.aStart;
590 : 0 : const ScAddress& e = rRange.aEnd;
591 : :
592 : 0 : SCTAB nTab1 = s.Tab(), nTab2 = e.Tab();
593 : 0 : SCCOL nCol1 = s.Col(), nCol2 = e.Col();
594 : 0 : SCROW nRow1 = s.Row(), nRow2 = e.Row();
595 : :
596 : : // Make sure I have all the tables cached.
597 [ # # ]: 0 : size_t nTabFirstId = itrTabId->second;
598 : 0 : size_t nTabLastId = nTabFirstId + nTab2 - nTab1;
599 [ # # ]: 0 : if (nTabLastId >= rDoc.maTables.size())
600 : : // not all tables are cached.
601 [ # # ]: 0 : return TokenArrayRef();
602 : :
603 : 0 : ScRange aCacheRange( nCol1, nRow1, static_cast<SCTAB>(nTabFirstId), nCol2, nRow2, static_cast<SCTAB>(nTabLastId));
604 : :
605 [ # # ]: 0 : RangeArrayMap::const_iterator itrRange = rDoc.maRangeArrays.find( aCacheRange);
606 [ # # ][ # # ]: 0 : if (itrRange != rDoc.maRangeArrays.end())
607 : : // Cache hit!
608 [ # # ][ # # ]: 0 : return itrRange->second;
609 : :
610 : 0 : ::boost::scoped_ptr<ScRange> pNewRange;
611 [ # # ]: 0 : TokenArrayRef pArray;
612 : 0 : bool bFirstTab = true;
613 [ # # ]: 0 : for (size_t nTab = nTabFirstId; nTab <= nTabLastId; ++nTab)
614 : : {
615 [ # # ]: 0 : TableTypeRef pTab = rDoc.maTables[nTab];
616 [ # # ]: 0 : if (!pTab.get())
617 [ # # ]: 0 : return TokenArrayRef();
618 : :
619 : 0 : SCCOL nDataCol1 = nCol1, nDataCol2 = nCol2;
620 : 0 : SCROW nDataRow1 = nRow1, nDataRow2 = nRow2;
621 : :
622 [ # # ][ # # ]: 0 : if (!pTab->isRangeCached(nDataCol1, nDataRow1, nDataCol2, nDataRow2))
623 : : {
624 : : // specified range is not entirely within cached ranges.
625 [ # # ]: 0 : return TokenArrayRef();
626 : : }
627 : :
628 : : ScMatrixRef xMat = new ScMatrix(
629 [ # # ][ # # ]: 0 : static_cast<SCSIZE>(nDataCol2-nDataCol1+1), static_cast<SCSIZE>(nDataRow2-nDataRow1+1));
630 : :
631 : : // Only fill non-empty cells, for better performance.
632 [ # # ]: 0 : vector<SCROW> aRows;
633 [ # # ]: 0 : pTab->getAllRows(aRows, nDataRow1, nDataRow2);
634 [ # # ][ # # ]: 0 : for (vector<SCROW>::const_iterator itr = aRows.begin(), itrEnd = aRows.end(); itr != itrEnd; ++itr)
[ # # ][ # # ]
[ # # ]
635 : : {
636 [ # # ]: 0 : SCROW nRow = *itr;
637 [ # # ]: 0 : vector<SCCOL> aCols;
638 [ # # ]: 0 : pTab->getAllCols(nRow, aCols, nDataCol1, nDataCol2);
639 [ # # ][ # # ]: 0 : for (vector<SCCOL>::const_iterator itrCol = aCols.begin(), itrColEnd = aCols.end(); itrCol != itrColEnd; ++itrCol)
[ # # ][ # # ]
[ # # ]
640 : : {
641 [ # # ]: 0 : SCCOL nCol = *itrCol;
642 [ # # ]: 0 : TokenRef pToken = pTab->getCell(nCol, nRow);
643 [ # # ]: 0 : if (!pToken)
644 : : // This should never happen!
645 [ # # ]: 0 : return TokenArrayRef();
646 : :
647 : 0 : SCSIZE nC = nCol - nDataCol1, nR = nRow - nDataRow1;
648 [ # # # ]: 0 : switch (pToken->GetType())
649 : : {
650 : : case svDouble:
651 [ # # ][ # # ]: 0 : xMat->PutDouble(pToken->GetDouble(), nC, nR);
652 : 0 : break;
653 : : case svString:
654 [ # # ][ # # ]: 0 : xMat->PutString(pToken->GetString(), nC, nR);
[ # # ]
655 : 0 : break;
656 : : default:
657 : : ;
658 : : }
659 [ # # ][ # # ]: 0 : }
660 [ # # ]: 0 : }
661 : :
662 [ # # ]: 0 : if (!bFirstTab)
663 [ # # ]: 0 : pArray->AddOpCode(ocSep);
664 : :
665 [ # # ][ # # ]: 0 : ScMatrixToken aToken(xMat);
666 [ # # ]: 0 : if (!pArray)
667 [ # # ][ # # ]: 0 : pArray.reset(new ScTokenArray);
[ # # ]
668 [ # # ]: 0 : pArray->AddToken(aToken);
669 : :
670 : 0 : bFirstTab = false;
671 : :
672 [ # # ]: 0 : if (!pNewRange)
673 [ # # ][ # # ]: 0 : pNewRange.reset(new ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0));
674 : : else
675 [ # # ]: 0 : pNewRange->ExtendTo(ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0));
676 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
[ # # ][ # # ]
677 : :
678 [ # # ]: 0 : if (pNewRange)
679 [ # # ][ # # ]: 0 : rDoc.maRangeArrays.insert( RangeArrayMap::value_type(*pNewRange, pArray));
[ # # ]
680 [ # # ][ # # ]: 0 : return pArray;
[ # # ]
681 : : }
682 : :
683 : 0 : ScExternalRefCache::TokenArrayRef ScExternalRefCache::getRangeNameTokens(sal_uInt16 nFileId, const OUString& rName)
684 : : {
685 [ # # ]: 0 : DocItem* pDoc = getDocItem(nFileId);
686 [ # # ]: 0 : if (!pDoc)
687 [ # # ]: 0 : return TokenArrayRef();
688 : :
689 : 0 : RangeNameMap& rMap = pDoc->maRangeNames;
690 : : RangeNameMap::const_iterator itr = rMap.find(
691 [ # # ][ # # ]: 0 : ScGlobal::pCharClass->uppercase(rName));
692 [ # # ][ # # ]: 0 : if (itr == rMap.end())
693 [ # # ]: 0 : return TokenArrayRef();
694 : :
695 [ # # ][ # # ]: 0 : return itr->second;
696 : : }
697 : :
698 : 0 : void ScExternalRefCache::setRangeNameTokens(sal_uInt16 nFileId, const OUString& rName, TokenArrayRef pArray)
699 : : {
700 [ # # ]: 0 : DocItem* pDoc = getDocItem(nFileId);
701 [ # # ]: 0 : if (!pDoc)
702 : 0 : return;
703 : :
704 [ # # ][ # # ]: 0 : String aUpperName = ScGlobal::pCharClass->uppercase(rName);
705 : 0 : RangeNameMap& rMap = pDoc->maRangeNames;
706 [ # # ][ # # ]: 0 : rMap.insert(RangeNameMap::value_type(aUpperName, pArray));
[ # # ]
707 [ # # ][ # # ]: 0 : pDoc->maRealRangeNameMap.insert(NamePairMap::value_type(aUpperName, rName));
[ # # ]
708 : : }
709 : :
710 : 135 : void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const OUString& rTabName, SCCOL nCol, SCROW nRow,
711 : : TokenRef pToken, sal_uLong nFmtIndex)
712 : : {
713 [ + - ][ + - ]: 135 : if (!isDocInitialized(nFileId))
714 : : return;
715 : :
716 : : using ::std::pair;
717 [ + - ]: 135 : DocItem* pDocItem = getDocItem(nFileId);
718 [ + - ]: 135 : if (!pDocItem)
719 : : return;
720 : :
721 : 135 : DocItem& rDoc = *pDocItem;
722 : :
723 : : // See if the table by this name already exists.
724 : : TableNameIndexMap::iterator itrTabName = rDoc.maTableNameIndex.find(
725 [ + - ][ + - ]: 135 : ScGlobal::pCharClass->uppercase(rTabName));
726 [ + - ][ + - ]: 135 : if (itrTabName == rDoc.maTableNameIndex.end())
727 : : // Table not found. Maybe the table name or the file id is wrong ???
728 : : return;
729 : :
730 [ + - ]: 135 : TableTypeRef& pTableData = rDoc.maTables[itrTabName->second];
731 [ + + ]: 135 : if (!pTableData.get())
732 [ + - ][ + - ]: 12 : pTableData.reset(new Table);
[ + - ]
733 : :
734 [ + - ][ + - ]: 135 : pTableData->setCell(nCol, nRow, pToken, nFmtIndex);
735 [ + - ]: 135 : pTableData->setCachedCell(nCol, nRow);
736 : : }
737 : :
738 : 18 : void ScExternalRefCache::setCellRangeData(sal_uInt16 nFileId, const ScRange& rRange, const vector<SingleRangeData>& rData,
739 : : const TokenArrayRef& pArray)
740 : : {
741 : : using ::std::pair;
742 [ + - ][ + - ]: 18 : if (rData.empty() || !isDocInitialized(nFileId))
[ - + ][ + - ]
743 : : // nothing to cache
744 : : return;
745 : :
746 : : // First, get the document item for the given file ID.
747 [ + - ]: 18 : DocItem* pDocItem = getDocItem(nFileId);
748 [ + - ]: 18 : if (!pDocItem)
749 : : return;
750 : :
751 : 18 : DocItem& rDoc = *pDocItem;
752 : :
753 : : // Now, find the table position of the first table to cache.
754 [ + - ][ + - ]: 18 : const String& rFirstTabName = rData.front().maTableName;
755 : : TableNameIndexMap::iterator itrTabName = rDoc.maTableNameIndex.find(
756 [ + - ][ + - ]: 18 : ScGlobal::pCharClass->uppercase(rFirstTabName));
[ + - ]
757 [ - + ][ + - ]: 18 : if (itrTabName == rDoc.maTableNameIndex.end())
758 : : {
759 : : // table index not found.
760 : : return;
761 : : }
762 : :
763 [ + - ]: 18 : size_t nTabFirstId = itrTabName->second;
764 : 18 : SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
765 : 18 : SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
766 : 18 : vector<SingleRangeData>::const_iterator itrDataBeg = rData.begin(), itrDataEnd = rData.end();
767 [ + - ][ + + ]: 36 : for (vector<SingleRangeData>::const_iterator itrData = itrDataBeg; itrData != itrDataEnd; ++itrData)
768 : : {
769 [ + - ]: 18 : size_t i = nTabFirstId + ::std::distance(itrDataBeg, itrData);
770 : 18 : TableTypeRef& pTabData = rDoc.maTables[i];
771 [ - + ]: 18 : if (!pTabData.get())
772 [ # # ][ # # ]: 0 : pTabData.reset(new Table);
[ # # ]
773 : :
774 [ + + ]: 81 : for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
775 : : {
776 [ + + ]: 126 : for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
777 : : {
778 : 63 : SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
779 : 63 : TokenRef pToken;
780 : 63 : const ScMatrixRef& pMat = itrData->mpRangeData;
781 [ + + ][ + - ]: 63 : if (pMat->IsEmpty(nC, nR))
782 : : // Don't cache empty cells.
783 : 9 : continue;
784 : :
785 [ + - ][ + - ]: 54 : if (pMat->IsValue(nC, nR))
786 [ + - ][ + - ]: 54 : pToken.reset(new formula::FormulaDoubleToken(pMat->GetDouble(nC, nR)));
[ + - ][ + - ]
787 [ # # ][ # # ]: 0 : else if (pMat->IsString(nC, nR))
788 [ # # ][ # # ]: 0 : pToken.reset(new formula::FormulaStringToken(pMat->GetString(nC, nR)));
[ # # ][ # # ]
[ # # ][ # # ]
789 : :
790 [ + - ]: 54 : if (pToken)
791 : : // Don't mark this cell 'cached' here, for better performance.
792 [ + - ][ + - ]: 54 : pTabData->setCell(nCol, nRow, pToken, 0, false);
793 [ + - ][ + + ]: 63 : }
794 : : }
795 : : // Mark the whole range 'cached'.
796 [ + - ]: 18 : pTabData->setCachedCellRange(nCol1, nRow1, nCol2, nRow2);
797 : : }
798 : :
799 : 18 : size_t nTabLastId = nTabFirstId + rRange.aEnd.Tab() - rRange.aStart.Tab();
800 : 18 : ScRange aCacheRange( nCol1, nRow1, static_cast<SCTAB>(nTabFirstId), nCol2, nRow2, static_cast<SCTAB>(nTabLastId));
801 : :
802 [ + - ][ + - ]: 18 : rDoc.maRangeArrays.insert( RangeArrayMap::value_type( aCacheRange, pArray));
[ + - ][ + - ]
[ + - ]
803 : : }
804 : :
805 : 327 : bool ScExternalRefCache::isDocInitialized(sal_uInt16 nFileId)
806 : : {
807 : 327 : DocItem* pDoc = getDocItem(nFileId);
808 [ - + ]: 327 : if (!pDoc)
809 : 0 : return false;
810 : :
811 : 327 : return pDoc->mbInitFromSource;
812 : : }
813 : :
814 : 33 : static bool lcl_getTableDataIndex(const ScExternalRefCache::TableNameIndexMap& rMap, const String& rName, size_t& rIndex)
815 : : {
816 [ + - ][ + - ]: 33 : ScExternalRefCache::TableNameIndexMap::const_iterator itr = rMap.find(rName);
817 [ + + ][ + - ]: 33 : if (itr == rMap.end())
818 : 24 : return false;
819 : :
820 [ + - ]: 9 : rIndex = itr->second;
821 : 33 : return true;
822 : : }
823 : :
824 : 9 : void ScExternalRefCache::initializeDoc(sal_uInt16 nFileId, const vector<OUString>& rTabNames)
825 : : {
826 [ + - ]: 9 : DocItem* pDoc = getDocItem(nFileId);
827 [ + - ]: 9 : if (!pDoc)
828 : 9 : return;
829 : :
830 : 9 : size_t n = rTabNames.size();
831 : :
832 : : // table name list - the list must include all table names in the source
833 : : // document and only to be populated when loading the source document, not
834 : : // when loading cached data from, say, Excel XCT/CRN records.
835 [ + - ]: 9 : vector<TableName> aNewTabNames;
836 [ + - ]: 9 : aNewTabNames.reserve(n);
837 [ + - ][ + + ]: 33 : for (vector<OUString>::const_iterator itr = rTabNames.begin(), itrEnd = rTabNames.end();
838 : : itr != itrEnd; ++itr)
839 : : {
840 [ + - ]: 24 : TableName aNameItem(ScGlobal::pCharClass->uppercase(*itr), *itr);
841 [ + - ]: 24 : aNewTabNames.push_back(aNameItem);
842 : 24 : }
843 : 9 : pDoc->maTableNames.swap(aNewTabNames);
844 : :
845 : : // data tables - preserve any existing data that may have been set during
846 : : // file import.
847 [ + - ]: 9 : vector<TableTypeRef> aNewTables(n);
848 [ + + ]: 33 : for (size_t i = 0; i < n; ++i)
849 : : {
850 : : size_t nIndex;
851 [ + - ][ + - ]: 24 : if (lcl_getTableDataIndex(pDoc->maTableNameIndex, pDoc->maTableNames[i].maUpperName, nIndex))
[ + - ][ - + ]
852 : : {
853 [ # # ]: 0 : aNewTables[i] = pDoc->maTables[nIndex];
854 : : }
855 : : }
856 : 9 : pDoc->maTables.swap(aNewTables);
857 : :
858 : : // name index map
859 [ + - ]: 9 : TableNameIndexMap aNewNameIndex;
860 [ + + ]: 33 : for (size_t i = 0; i < n; ++i)
861 [ + - ]: 24 : aNewNameIndex.insert(TableNameIndexMap::value_type(pDoc->maTableNames[i].maUpperName, i));
862 [ + - ]: 9 : pDoc->maTableNameIndex.swap(aNewNameIndex);
863 : :
864 [ + - ]: 9 : pDoc->mbInitFromSource = true;
865 : : }
866 : :
867 : 0 : String ScExternalRefCache::getTableName(sal_uInt16 nFileId, size_t nCacheId) const
868 : : {
869 [ # # ]: 0 : if( DocItem* pDoc = getDocItem( nFileId ) )
870 [ # # ]: 0 : if( nCacheId < pDoc->maTableNames.size() )
871 : 0 : return pDoc->maTableNames[ nCacheId ].maRealName;
872 : 0 : return EMPTY_STRING;
873 : : }
874 : :
875 : 3 : void ScExternalRefCache::getAllTableNames(sal_uInt16 nFileId, vector<OUString>& rTabNames) const
876 : : {
877 : 3 : rTabNames.clear();
878 : 3 : DocItem* pDoc = getDocItem(nFileId);
879 [ - + ]: 3 : if (!pDoc)
880 : 3 : return;
881 : :
882 : 3 : size_t n = pDoc->maTableNames.size();
883 : 3 : rTabNames.reserve(n);
884 [ + - ][ + - ]: 15 : for (vector<TableName>::const_iterator itr = pDoc->maTableNames.begin(), itrEnd = pDoc->maTableNames.end();
[ + + ][ + - ]
885 : : itr != itrEnd; ++itr)
886 [ + - ]: 12 : rTabNames.push_back(itr->maRealName);
887 : : }
888 : :
889 : 0 : SCsTAB ScExternalRefCache::getTabSpan( sal_uInt16 nFileId, const OUString& rStartTabName, const OUString& rEndTabName ) const
890 : : {
891 [ # # ]: 0 : DocItem* pDoc = getDocItem(nFileId);
892 [ # # ]: 0 : if (!pDoc)
893 : 0 : return -1;
894 : :
895 [ # # ]: 0 : vector<TableName>::const_iterator itrBeg = pDoc->maTableNames.begin();
896 [ # # ]: 0 : vector<TableName>::const_iterator itrEnd = pDoc->maTableNames.end();
897 : :
898 : : vector<TableName>::const_iterator itrStartTab = ::std::find_if( itrBeg, itrEnd,
899 [ # # ][ # # ]: 0 : TabNameSearchPredicate( rStartTabName));
900 [ # # ][ # # ]: 0 : if (itrStartTab == itrEnd)
901 : 0 : return -1;
902 : :
903 : : vector<TableName>::const_iterator itrEndTab = ::std::find_if( itrBeg, itrEnd,
904 [ # # ][ # # ]: 0 : TabNameSearchPredicate( rEndTabName));
905 [ # # ][ # # ]: 0 : if (itrEndTab == itrEnd)
906 : 0 : return 0;
907 : :
908 [ # # ]: 0 : size_t nStartDist = ::std::distance( itrBeg, itrStartTab);
909 [ # # ]: 0 : size_t nEndDist = ::std::distance( itrBeg, itrEndTab);
910 [ # # ]: 0 : return nStartDist <= nEndDist ? static_cast<SCsTAB>(nEndDist - nStartDist + 1) : -static_cast<SCsTAB>(nStartDist - nEndDist + 1);
911 : : }
912 : :
913 : 0 : void ScExternalRefCache::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const
914 : : {
915 : : using ::std::sort;
916 : : using ::std::unique;
917 : :
918 [ # # ]: 0 : vector<sal_uInt32> aNumFmts;
919 [ # # ][ # # ]: 0 : for (DocDataType::const_iterator itrDoc = maDocs.begin(), itrDocEnd = maDocs.end();
[ # # ]
920 : : itrDoc != itrDocEnd; ++itrDoc)
921 : : {
922 [ # # ]: 0 : const vector<TableTypeRef>& rTables = itrDoc->second.maTables;
923 [ # # ][ # # ]: 0 : for (vector<TableTypeRef>::const_iterator itrTab = rTables.begin(), itrTabEnd = rTables.end();
924 : : itrTab != itrTabEnd; ++itrTab)
925 : : {
926 [ # # ]: 0 : TableTypeRef pTab = *itrTab;
927 [ # # ]: 0 : if (!pTab)
928 : 0 : continue;
929 : :
930 [ # # ][ # # ]: 0 : pTab->getAllNumberFormats(aNumFmts);
931 [ # # ]: 0 : }
932 : : }
933 : :
934 : : // remove duplicates.
935 [ # # ]: 0 : sort(aNumFmts.begin(), aNumFmts.end());
936 [ # # ][ # # ]: 0 : aNumFmts.erase(unique(aNumFmts.begin(), aNumFmts.end()), aNumFmts.end());
937 : 0 : rNumFmts.swap(aNumFmts);
938 : 0 : }
939 : :
940 : 0 : bool ScExternalRefCache::hasCacheTable(sal_uInt16 nFileId, const OUString& rTabName) const
941 : : {
942 [ # # ]: 0 : DocItem* pDoc = getDocItem(nFileId);
943 [ # # ]: 0 : if (!pDoc)
944 : 0 : return false;
945 : :
946 [ # # ][ # # ]: 0 : String aUpperName = ScGlobal::pCharClass->uppercase(rTabName);
947 [ # # ][ # # ]: 0 : vector<TableName>::const_iterator itrBeg = pDoc->maTableNames.begin(), itrEnd = pDoc->maTableNames.end();
948 : : vector<TableName>::const_iterator itr = ::std::find_if(
949 [ # # ][ # # ]: 0 : itrBeg, itrEnd, TabNameSearchPredicate(aUpperName));
[ # # ]
950 : :
951 [ # # ][ # # ]: 0 : return itr != itrEnd;
952 : : }
953 : :
954 : 0 : size_t ScExternalRefCache::getCacheTableCount(sal_uInt16 nFileId) const
955 : : {
956 : 0 : DocItem* pDoc = getDocItem(nFileId);
957 [ # # ]: 0 : return pDoc ? pDoc->maTables.size() : 0;
958 : : }
959 : :
960 : 0 : bool ScExternalRefCache::setCacheDocReferenced( sal_uInt16 nFileId )
961 : : {
962 : 0 : DocItem* pDocItem = getDocItem(nFileId);
963 [ # # ]: 0 : if (!pDocItem)
964 : 0 : return areAllCacheTablesReferenced();
965 : :
966 [ # # ][ # # ]: 0 : for (::std::vector<TableTypeRef>::iterator itrTab = pDocItem->maTables.begin();
967 : 0 : itrTab != pDocItem->maTables.end(); ++itrTab)
968 : : {
969 [ # # ]: 0 : if ((*itrTab).get())
970 : 0 : (*itrTab)->setReferenced( true);
971 : : }
972 : 0 : addCacheDocToReferenced( nFileId);
973 : 0 : return areAllCacheTablesReferenced();
974 : : }
975 : :
976 : 0 : bool ScExternalRefCache::setCacheTableReferenced( sal_uInt16 nFileId, const OUString& rTabName, size_t nSheets, bool bPermanent )
977 : : {
978 : 0 : DocItem* pDoc = getDocItem(nFileId);
979 [ # # ]: 0 : if (pDoc)
980 : : {
981 : 0 : size_t nIndex = 0;
982 [ # # ][ # # ]: 0 : String aTabNameUpper = ScGlobal::pCharClass->uppercase( rTabName);
983 [ # # ][ # # ]: 0 : if (lcl_getTableDataIndex( pDoc->maTableNameIndex, aTabNameUpper, nIndex))
984 : : {
985 [ # # ]: 0 : size_t nStop = ::std::min( nIndex + nSheets, pDoc->maTables.size());
986 [ # # ]: 0 : for (size_t i = nIndex; i < nStop; ++i)
987 : : {
988 [ # # ]: 0 : TableTypeRef pTab = pDoc->maTables[i];
989 [ # # ]: 0 : if (pTab.get())
990 : : {
991 : : Table::ReferencedFlag eNewFlag = (bPermanent ?
992 : : Table::REFERENCED_PERMANENT :
993 [ # # ]: 0 : Table::REFERENCED_MARKED);
994 : 0 : Table::ReferencedFlag eOldFlag = pTab->getReferencedFlag();
995 [ # # ][ # # ]: 0 : if (eOldFlag != Table::REFERENCED_PERMANENT && eNewFlag != eOldFlag)
996 : : {
997 : 0 : pTab->setReferencedFlag( eNewFlag);
998 [ # # ]: 0 : addCacheTableToReferenced( nFileId, i);
999 : : }
1000 : : }
1001 [ # # ]: 0 : }
1002 [ # # ]: 0 : }
1003 : : }
1004 : 0 : return areAllCacheTablesReferenced();
1005 : : }
1006 : :
1007 : 0 : void ScExternalRefCache::setAllCacheTableReferencedStati( bool bReferenced )
1008 : : {
1009 [ # # ]: 0 : if (bReferenced)
1010 : : {
1011 : 0 : maReferenced.reset(0);
1012 [ # # ][ # # ]: 0 : for (DocDataType::iterator itrDoc = maDocs.begin(); itrDoc != maDocs.end(); ++itrDoc)
[ # # ]
1013 : : {
1014 [ # # ]: 0 : ScExternalRefCache::DocItem& rDocItem = (*itrDoc).second;
1015 [ # # ][ # # ]: 0 : for (::std::vector<TableTypeRef>::iterator itrTab = rDocItem.maTables.begin();
1016 : 0 : itrTab != rDocItem.maTables.end(); ++itrTab)
1017 : : {
1018 [ # # ]: 0 : if ((*itrTab).get())
1019 : 0 : (*itrTab)->setReferenced( true);
1020 : : }
1021 : : }
1022 : : }
1023 : : else
1024 : : {
1025 : 0 : size_t nDocs = 0;
1026 [ # # ][ # # ]: 0 : for (DocDataType::const_iterator itrDoc = maDocs.begin(); itrDoc != maDocs.end(); ++itrDoc)
[ # # ]
1027 : : {
1028 [ # # ][ # # ]: 0 : if (nDocs <= (*itrDoc).first)
1029 [ # # ]: 0 : nDocs = (*itrDoc).first + 1;
1030 : : }
1031 : 0 : maReferenced.reset( nDocs);
1032 : :
1033 [ # # ][ # # ]: 0 : for (DocDataType::iterator itrDoc = maDocs.begin(); itrDoc != maDocs.end(); ++itrDoc)
[ # # ]
1034 : : {
1035 [ # # ]: 0 : ScExternalRefCache::DocItem& rDocItem = (*itrDoc).second;
1036 [ # # ]: 0 : sal_uInt16 nFileId = (*itrDoc).first;
1037 : 0 : size_t nTables = rDocItem.maTables.size();
1038 : 0 : ReferencedStatus::DocReferenced & rDocReferenced = maReferenced.maDocs[nFileId];
1039 : : // All referenced => non-existing tables evaluate as completed.
1040 [ # # ]: 0 : rDocReferenced.maTables.resize( nTables, true);
1041 [ # # ]: 0 : for (size_t i=0; i < nTables; ++i)
1042 : : {
1043 : 0 : TableTypeRef & xTab = rDocItem.maTables[i];
1044 [ # # ]: 0 : if (xTab.get())
1045 : : {
1046 [ # # ]: 0 : if (xTab->getReferencedFlag() == Table::REFERENCED_PERMANENT)
1047 [ # # ]: 0 : addCacheTableToReferenced( nFileId, i);
1048 : : else
1049 : : {
1050 : 0 : xTab->setReferencedFlag( Table::UNREFERENCED);
1051 [ # # ]: 0 : rDocReferenced.maTables[i] = false;
1052 : 0 : rDocReferenced.mbAllTablesReferenced = false;
1053 : : // An addCacheTableToReferenced() actually may have
1054 : : // resulted in mbAllReferenced been set. Clear it.
1055 : 0 : maReferenced.mbAllReferenced = false;
1056 : : }
1057 : : }
1058 : : }
1059 : : }
1060 : : }
1061 : 0 : }
1062 : :
1063 : 0 : void ScExternalRefCache::addCacheTableToReferenced( sal_uInt16 nFileId, size_t nIndex )
1064 : : {
1065 [ # # ]: 0 : if (nFileId >= maReferenced.maDocs.size())
1066 : 0 : return;
1067 : :
1068 : 0 : ::std::vector<bool> & rTables = maReferenced.maDocs[nFileId].maTables;
1069 : 0 : size_t nTables = rTables.size();
1070 [ # # ]: 0 : if (nIndex >= nTables)
1071 : 0 : return;
1072 : :
1073 [ # # ]: 0 : if (!rTables[nIndex])
1074 : : {
1075 : 0 : rTables[nIndex] = true;
1076 : 0 : size_t i = 0;
1077 [ # # ][ # # ]: 0 : while (i < nTables && rTables[i])
[ # # ][ # # ]
[ # # # # ]
1078 : 0 : ++i;
1079 [ # # ]: 0 : if (i == nTables)
1080 : : {
1081 : 0 : maReferenced.maDocs[nFileId].mbAllTablesReferenced = true;
1082 : 0 : maReferenced.checkAllDocs();
1083 : : }
1084 : : }
1085 : : }
1086 : :
1087 : 0 : void ScExternalRefCache::addCacheDocToReferenced( sal_uInt16 nFileId )
1088 : : {
1089 [ # # ]: 0 : if (nFileId >= maReferenced.maDocs.size())
1090 : 0 : return;
1091 : :
1092 [ # # ]: 0 : if (!maReferenced.maDocs[nFileId].mbAllTablesReferenced)
1093 : : {
1094 : 0 : ::std::vector<bool> & rTables = maReferenced.maDocs[nFileId].maTables;
1095 : 0 : size_t nSize = rTables.size();
1096 [ # # ]: 0 : for (size_t i=0; i < nSize; ++i)
1097 : 0 : rTables[i] = true;
1098 : 0 : maReferenced.maDocs[nFileId].mbAllTablesReferenced = true;
1099 : 0 : maReferenced.checkAllDocs();
1100 : : }
1101 : : }
1102 : :
1103 : 0 : bool ScExternalRefCache::areAllCacheTablesReferenced() const
1104 : : {
1105 : 0 : return maReferenced.mbAllReferenced;
1106 : : }
1107 : :
1108 : 275 : ScExternalRefCache::ReferencedStatus::ReferencedStatus() :
1109 : 275 : mbAllReferenced(false)
1110 : : {
1111 [ + - ]: 275 : reset(0);
1112 : 275 : }
1113 : :
1114 : 275 : void ScExternalRefCache::ReferencedStatus::reset( size_t nDocs )
1115 : : {
1116 [ - + ]: 275 : if (nDocs)
1117 : : {
1118 : 0 : mbAllReferenced = false;
1119 [ # # ]: 0 : DocReferencedVec aRefs( nDocs);
1120 : 0 : maDocs.swap( aRefs);
1121 : : }
1122 : : else
1123 : : {
1124 : 275 : mbAllReferenced = true;
1125 [ + - ]: 275 : DocReferencedVec aRefs;
1126 : 275 : maDocs.swap( aRefs);
1127 : : }
1128 : 275 : }
1129 : :
1130 : 0 : void ScExternalRefCache::ReferencedStatus::checkAllDocs()
1131 : : {
1132 [ # # ][ # # ]: 0 : for (DocReferencedVec::const_iterator itr = maDocs.begin(); itr != maDocs.end(); ++itr)
[ # # ]
1133 : : {
1134 [ # # ]: 0 : if (!(*itr).mbAllTablesReferenced)
1135 : 0 : return;
1136 : : }
1137 : 0 : mbAllReferenced = true;
1138 : : }
1139 : :
1140 : 0 : ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const
1141 : : {
1142 : 0 : DocItem* pDoc = getDocItem(nFileId);
1143 [ # # ][ # # ]: 0 : if (!pDoc || nTabIndex >= pDoc->maTables.size())
[ # # ]
1144 : 0 : return TableTypeRef();
1145 : :
1146 : 0 : return pDoc->maTables[nTabIndex];
1147 : : }
1148 : :
1149 : 9 : ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, const OUString& rTabName, bool bCreateNew, size_t* pnIndex)
1150 : : {
1151 : : // In API, the index is transported as cached sheet ID of type sal_Int32 in
1152 : : // sheet::SingleReference.Sheet or sheet::ComplexReference.Reference1.Sheet
1153 : : // in a sheet::FormulaToken, choose a sensible value for N/A. Effectively
1154 : : // being 0xffffffff
1155 : 9 : const size_t nNotAvailable = static_cast<size_t>( static_cast<sal_Int32>( -1));
1156 : :
1157 [ + - ]: 9 : DocItem* pDoc = getDocItem(nFileId);
1158 [ - + ]: 9 : if (!pDoc)
1159 : : {
1160 [ # # ]: 0 : if (pnIndex) *pnIndex = nNotAvailable;
1161 [ # # ]: 0 : return TableTypeRef();
1162 : : }
1163 : :
1164 : 9 : DocItem& rDoc = *pDoc;
1165 : :
1166 : : size_t nIndex;
1167 [ + - ][ + - ]: 9 : String aTabNameUpper = ScGlobal::pCharClass->uppercase(rTabName);
1168 [ + - ][ + - ]: 9 : if (lcl_getTableDataIndex(rDoc.maTableNameIndex, aTabNameUpper, nIndex))
1169 : : {
1170 : : // specified table found.
1171 [ - + ]: 9 : if( pnIndex ) *pnIndex = nIndex;
1172 [ - + ][ # # ]: 9 : if (bCreateNew && !rDoc.maTables[nIndex])
[ - + ]
1173 [ # # ][ # # ]: 0 : rDoc.maTables[nIndex].reset(new Table);
[ # # ]
1174 : :
1175 [ + - ]: 9 : return rDoc.maTables[nIndex];
1176 : : }
1177 : :
1178 [ # # ]: 0 : if (!bCreateNew)
1179 : : {
1180 [ # # ]: 0 : if (pnIndex) *pnIndex = nNotAvailable;
1181 [ # # ]: 0 : return TableTypeRef();
1182 : : }
1183 : :
1184 : : // Specified table doesn't exist yet. Create one.
1185 : 0 : nIndex = rDoc.maTables.size();
1186 [ # # ]: 0 : if( pnIndex ) *pnIndex = nIndex;
1187 [ # # ][ # # ]: 0 : TableTypeRef pTab(new Table);
[ # # ]
1188 [ # # ]: 0 : rDoc.maTables.push_back(pTab);
1189 [ # # ][ # # ]: 0 : rDoc.maTableNames.push_back(TableName(aTabNameUpper, rTabName));
1190 : : rDoc.maTableNameIndex.insert(
1191 [ # # ][ # # ]: 0 : TableNameIndexMap::value_type(aTabNameUpper, nIndex));
1192 [ # # ][ + - ]: 9 : return pTab;
[ # # ]
1193 : : }
1194 : :
1195 : 3 : void ScExternalRefCache::clearCache(sal_uInt16 nFileId)
1196 : : {
1197 : 3 : maDocs.erase(nFileId);
1198 : 3 : }
1199 : :
1200 : 501 : ScExternalRefCache::DocItem* ScExternalRefCache::getDocItem(sal_uInt16 nFileId) const
1201 : : {
1202 : : using ::std::pair;
1203 [ + - ]: 501 : DocDataType::iterator itrDoc = maDocs.find(nFileId);
1204 [ + - ][ + + ]: 501 : if (itrDoc == maDocs.end())
1205 : : {
1206 : : // specified document is not cached.
1207 : : pair<DocDataType::iterator, bool> res = maDocs.insert(
1208 [ + - ][ + - ]: 9 : DocDataType::value_type(nFileId, DocItem()));
[ + - ][ + - ]
[ + - ]
1209 : :
1210 [ - + ]: 9 : if (!res.second)
1211 : : // insertion failed.
1212 : 0 : return NULL;
1213 : :
1214 : 9 : itrDoc = res.first;
1215 : : }
1216 : :
1217 [ + - ]: 501 : return &itrDoc->second;
1218 : : }
1219 : :
1220 : : // ============================================================================
1221 : :
1222 : 6 : ScExternalRefLink::ScExternalRefLink(ScDocument* pDoc, sal_uInt16 nFileId, const String& rFilter) :
1223 : : ::sfx2::SvBaseLink(::sfx2::LINKUPDATE_ONCALL, FORMAT_FILE),
1224 : : mnFileId(nFileId),
1225 : : maFilterName(rFilter),
1226 : : mpDoc(pDoc),
1227 [ + - ]: 6 : mbDoRefresh(true)
1228 : : {
1229 : 6 : }
1230 : :
1231 [ # # ]: 0 : ScExternalRefLink::~ScExternalRefLink()
1232 : : {
1233 [ # # ]: 0 : }
1234 : :
1235 : 0 : void ScExternalRefLink::Closed()
1236 : : {
1237 : 0 : ScExternalRefManager* pMgr = mpDoc->GetExternalRefManager();
1238 : 0 : pMgr->breakLink(mnFileId);
1239 : 0 : }
1240 : :
1241 : 6 : ::sfx2::SvBaseLink::UpdateResult ScExternalRefLink::DataChanged(const String& /*rMimeType*/, const Any& /*rValue*/)
1242 : : {
1243 [ + - ]: 6 : if (!mbDoRefresh)
1244 : 6 : return SUCCESS;
1245 : :
1246 : 0 : rtl::OUString aFile, aFilter;
1247 [ # # ][ # # ]: 0 : mpDoc->GetLinkManager()->GetDisplayNames(this, NULL, &aFile, NULL, &aFilter);
1248 [ # # ]: 0 : ScExternalRefManager* pMgr = mpDoc->GetExternalRefManager();
1249 : :
1250 [ # # ][ # # ]: 0 : if (!pMgr->isFileLoadable(aFile))
1251 : 0 : return ERROR_GENERAL;
1252 : :
1253 [ # # ]: 0 : const OUString* pCurFile = pMgr->getExternalFileName(mnFileId);
1254 [ # # ]: 0 : if (!pCurFile)
1255 : 0 : return ERROR_GENERAL;
1256 : :
1257 [ # # ]: 0 : if (pCurFile->equals(aFile))
1258 : : {
1259 : : // Refresh the current source document.
1260 [ # # ]: 0 : pMgr->refreshNames(mnFileId);
1261 : : }
1262 : : else
1263 : : {
1264 : : // The source document has changed.
1265 [ # # ]: 0 : ScDocShell* pDocShell = ScDocShell::GetViewData()->GetDocShell();
1266 [ # # ]: 0 : ScDocShellModificator aMod(*pDocShell);
1267 [ # # ]: 0 : pMgr->switchSrcFile(mnFileId, aFile, aFilter);
1268 [ # # ]: 0 : maFilterName = aFilter;
1269 [ # # ][ # # ]: 0 : aMod.SetDocumentModified();
1270 : : }
1271 : :
1272 : 6 : return SUCCESS;
1273 : : }
1274 : :
1275 : 0 : void ScExternalRefLink::Edit(Window* pParent, const Link& /*rEndEditHdl*/)
1276 : : {
1277 [ # # ]: 0 : SvBaseLink::Edit(pParent, LINK(this, ScExternalRefLink, ExternalRefEndEditHdl));
1278 : 0 : }
1279 : :
1280 : 12 : void ScExternalRefLink::SetDoReferesh(bool b)
1281 : : {
1282 : 12 : mbDoRefresh = b;
1283 : 12 : }
1284 : :
1285 : 0 : IMPL_LINK_NOARG(ScExternalRefLink, ExternalRefEndEditHdl)
1286 : : {
1287 : 0 : return 0;
1288 : : }
1289 : :
1290 : : // ============================================================================
1291 : :
1292 : 156 : static FormulaToken* lcl_convertToToken(ScBaseCell* pCell)
1293 : : {
1294 [ + + ][ - + ]: 156 : if (!pCell || pCell->HasEmptyData())
[ + + ]
1295 : : {
1296 [ - + ][ # # ]: 21 : bool bInherited = (pCell && pCell->GetCellType() == CELLTYPE_FORMULA);
1297 [ + - ]: 21 : return new ScEmptyCellToken( bInherited, false);
1298 : : }
1299 : :
1300 [ - + + - : 135 : switch (pCell->GetCellType())
- ]
1301 : : {
1302 : : case CELLTYPE_EDIT:
1303 : : {
1304 [ # # ]: 0 : rtl::OUString aStr = static_cast<ScEditCell*>(pCell)->GetString();
1305 [ # # ][ # # ]: 0 : return new formula::FormulaStringToken(aStr);
[ # # ][ # # ]
1306 : : }
1307 : : case CELLTYPE_STRING:
1308 : : {
1309 : 78 : rtl::OUString aStr = static_cast<ScStringCell*>(pCell)->GetString();
1310 [ + - ][ + - ]: 78 : return new formula::FormulaStringToken(aStr);
[ + - ][ + - ]
1311 : : }
1312 : : case CELLTYPE_VALUE:
1313 : : {
1314 : 57 : double fVal = static_cast<ScValueCell*>(pCell)->GetValue();
1315 [ + - ]: 57 : return new formula::FormulaDoubleToken(fVal);
1316 : : }
1317 : : case CELLTYPE_FORMULA:
1318 : : {
1319 [ # # ]: 0 : ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
1320 : 0 : sal_uInt16 nError = pFCell->GetErrCode();
1321 [ # # ]: 0 : if (nError)
1322 [ # # ]: 0 : return new FormulaErrorToken( nError);
1323 [ # # ]: 0 : else if (pFCell->IsValue())
1324 : : {
1325 : 0 : double fVal = pFCell->GetValue();
1326 [ # # ]: 0 : return new formula::FormulaDoubleToken(fVal);
1327 : : }
1328 : : else
1329 : : {
1330 [ # # ]: 0 : rtl::OUString aStr = pFCell->GetString();
1331 [ # # ][ # # ]: 0 : return new formula::FormulaStringToken(aStr);
[ # # ][ # # ]
1332 : : }
1333 : : }
1334 : : default:
1335 : : OSL_FAIL("attempted to convert an unknown cell type.");
1336 : : }
1337 : :
1338 : 156 : return NULL;
1339 : : }
1340 : :
1341 : 18 : static ScTokenArray* lcl_convertToTokenArray(const ScDocument* pSrcDoc, ScRange& rRange,
1342 : : vector<ScExternalRefCache::SingleRangeData>& rCacheData)
1343 : : {
1344 : 18 : ScAddress& s = rRange.aStart;
1345 : 18 : ScAddress& e = rRange.aEnd;
1346 : :
1347 : 18 : SCTAB nTab1 = s.Tab(), nTab2 = e.Tab();
1348 : 18 : SCCOL nCol1 = s.Col(), nCol2 = e.Col();
1349 : 18 : SCROW nRow1 = s.Row(), nRow2 = e.Row();
1350 : :
1351 [ - + ]: 18 : if (nTab2 != nTab1)
1352 : : // For now, we don't support multi-sheet ranges intentionally because
1353 : : // we don't have a way to express them in a single token. In the
1354 : : // future we can introduce a new stack variable type svMatrixList with
1355 : : // a new token type that can store a 3D matrix value and convert a 3D
1356 : : // range to it.
1357 : 0 : return NULL;
1358 : :
1359 : 18 : ::boost::scoped_ptr<ScRange> pUsedRange;
1360 : :
1361 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
1362 [ + - ][ + - ]: 18 : auto_ptr<ScTokenArray> pArray(new ScTokenArray);
1363 : : SAL_WNODEPRECATED_DECLARATIONS_POP
1364 : 18 : bool bFirstTab = true;
1365 : : vector<ScExternalRefCache::SingleRangeData>::iterator
1366 : 18 : itrCache = rCacheData.begin(), itrCacheEnd = rCacheData.end();
1367 : :
1368 [ + + ][ + - ]: 36 : for (SCTAB nTab = nTab1; nTab <= nTab2 && itrCache != itrCacheEnd; ++nTab, ++itrCache)
[ + - ][ + + ]
1369 : : {
1370 : : // Only loop within the data area.
1371 : 18 : SCCOL nDataCol1 = nCol1, nDataCol2 = nCol2;
1372 : 18 : SCROW nDataRow1 = nRow1, nDataRow2 = nRow2;
1373 : : bool bShrunk;
1374 [ + - ][ - + ]: 18 : if (!pSrcDoc->ShrinkToUsedDataArea( bShrunk, nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2, false))
1375 : : // no data within specified range.
1376 : 0 : continue;
1377 : :
1378 [ - + ]: 18 : if (pUsedRange.get())
1379 : : // Make sure the used area only grows, not shrinks.
1380 [ # # ]: 0 : pUsedRange->ExtendTo(ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0));
1381 : : else
1382 [ + - ][ + - ]: 18 : pUsedRange.reset(new ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0));
1383 : :
1384 : : ScMatrixRef xMat = new ScMatrix(
1385 [ + - ][ + - ]: 18 : static_cast<SCSIZE>(nCol2-nCol1+1), static_cast<SCSIZE>(nRow2-nRow1+1));
1386 : :
1387 [ + + ]: 36 : for (SCCOL nCol = nDataCol1; nCol <= nDataCol2; ++nCol)
1388 : : {
1389 [ + + ]: 81 : for (SCROW nRow = nDataRow1; nRow <= nDataRow2; ++nRow)
1390 : : {
1391 : 63 : SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
1392 : : ScBaseCell* pCell;
1393 [ + - ]: 63 : pSrcDoc->GetCell(nCol, nRow, nTab, pCell);
1394 [ + - ][ + - ]: 63 : if (!pCell || pCell->HasEmptyData())
[ - + ][ - + ]
1395 : : // Skip empty cells. Matrix's default values are empty elements.
1396 : 0 : continue;
1397 : :
1398 [ - - + - : 63 : switch (pCell->GetCellType())
- ]
1399 : : {
1400 : : case CELLTYPE_EDIT:
1401 : : {
1402 [ # # ]: 0 : rtl::OUString aStr = static_cast<ScEditCell*>(pCell)->GetString();
1403 [ # # ]: 0 : xMat->PutString(aStr, nC, nR);
1404 : : }
1405 : 0 : break;
1406 : : case CELLTYPE_STRING:
1407 : : {
1408 : 0 : rtl::OUString aStr = static_cast<ScStringCell*>(pCell)->GetString();
1409 [ # # ]: 0 : xMat->PutString(aStr, nC, nR);
1410 : : }
1411 : 0 : break;
1412 : : case CELLTYPE_VALUE:
1413 : : {
1414 : 63 : double fVal = static_cast<ScValueCell*>(pCell)->GetValue();
1415 [ + - ]: 63 : xMat->PutDouble(fVal, nC, nR);
1416 : : }
1417 : 63 : break;
1418 : : case CELLTYPE_FORMULA:
1419 : : {
1420 [ # # ]: 0 : ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
1421 [ # # ]: 0 : sal_uInt16 nError = pFCell->GetErrCode();
1422 [ # # ]: 0 : if (nError)
1423 [ # # ]: 0 : xMat->PutDouble( CreateDoubleError( nError), nC, nR);
1424 [ # # ][ # # ]: 0 : else if (pFCell->IsValue())
1425 : : {
1426 [ # # ]: 0 : double fVal = pFCell->GetValue();
1427 [ # # ]: 0 : xMat->PutDouble(fVal, nC, nR);
1428 : : }
1429 : : else
1430 : : {
1431 [ # # ]: 0 : rtl::OUString aStr = pFCell->GetString();
1432 [ # # ]: 0 : xMat->PutString(aStr, nC, nR);
1433 : : }
1434 : : }
1435 : 63 : break;
1436 : : default:
1437 : : OSL_FAIL("attempted to convert an unknown cell type.");
1438 : : }
1439 : : }
1440 : : }
1441 [ - + ]: 18 : if (!bFirstTab)
1442 [ # # ]: 0 : pArray->AddOpCode(ocSep);
1443 : :
1444 [ + - ][ + - ]: 18 : ScMatrixToken aToken(xMat);
1445 [ + - ]: 18 : pArray->AddToken(aToken);
1446 : :
1447 [ + - ]: 18 : itrCache->mpRangeData = xMat;
1448 : :
1449 : 18 : bFirstTab = false;
1450 [ + - ][ + - ]: 18 : }
1451 : :
1452 [ - + ]: 18 : if (!pUsedRange.get())
1453 : 0 : return NULL;
1454 : :
1455 : 18 : s.SetCol(pUsedRange->aStart.Col());
1456 : 18 : s.SetRow(pUsedRange->aStart.Row());
1457 : 18 : e.SetCol(pUsedRange->aEnd.Col());
1458 : 18 : e.SetRow(pUsedRange->aEnd.Row());
1459 : :
1460 [ + - ][ + - ]: 18 : return pArray.release();
1461 : : }
1462 : :
1463 : 0 : static ScTokenArray* lcl_fillEmptyMatrix(const ScRange& rRange)
1464 : : {
1465 : 0 : SCSIZE nC = static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1);
1466 : 0 : SCSIZE nR = static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1);
1467 [ # # ][ # # ]: 0 : ScMatrixRef xMat = new ScMatrix(nC, nR);
1468 : :
1469 [ # # ][ # # ]: 0 : ScMatrixToken aToken(xMat);
1470 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
1471 [ # # ][ # # ]: 0 : auto_ptr<ScTokenArray> pArray(new ScTokenArray);
1472 : : SAL_WNODEPRECATED_DECLARATIONS_POP
1473 [ # # ]: 0 : pArray->AddToken(aToken);
1474 [ # # ][ # # ]: 0 : return pArray.release();
[ # # ]
1475 : : }
1476 : :
1477 : 275 : ScExternalRefManager::ScExternalRefManager(ScDocument* pDoc) :
1478 : : mpDoc(pDoc),
1479 : : mbInReferenceMarking(false),
1480 [ + - ][ + - ]: 275 : mbUserInteractionEnabled(true)
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1481 : : {
1482 [ + - ]: 275 : maSrcDocTimer.SetTimeoutHdl( LINK(this, ScExternalRefManager, TimeOutHdl) );
1483 [ + - ]: 275 : maSrcDocTimer.SetTimeout(SRCDOC_SCAN_INTERVAL);
1484 : 275 : }
1485 : :
1486 [ + - ][ + - ]: 262 : ScExternalRefManager::~ScExternalRefManager()
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1487 : : {
1488 [ + - ]: 262 : clear();
1489 [ - + ]: 524 : }
1490 : :
1491 : 0 : OUString ScExternalRefManager::getCacheTableName(sal_uInt16 nFileId, size_t nTabIndex) const
1492 : : {
1493 [ # # ]: 0 : return maRefCache.getTableName(nFileId, nTabIndex);
1494 : : }
1495 : :
1496 : 0 : ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const
1497 : : {
1498 : 0 : return maRefCache.getCacheTable(nFileId, nTabIndex);
1499 : : }
1500 : :
1501 : 9 : ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(
1502 : : sal_uInt16 nFileId, const OUString& rTabName, bool bCreateNew, size_t* pnIndex)
1503 : : {
1504 : 9 : return maRefCache.getCacheTable(nFileId, rTabName, bCreateNew, pnIndex);
1505 : : }
1506 : :
1507 : : // ============================================================================
1508 : :
1509 : 0 : ScExternalRefManager::LinkListener::LinkListener()
1510 : : {
1511 : 0 : }
1512 : :
1513 : 0 : ScExternalRefManager::LinkListener::~LinkListener()
1514 : : {
1515 [ # # ]: 0 : }
1516 : :
1517 : : // ----------------------------------------------------------------------------
1518 : :
1519 : 2048 : ScExternalRefManager::ApiGuard::ApiGuard(ScDocument* pDoc) :
1520 : 2048 : mpMgr(pDoc->GetExternalRefManager()),
1521 : 2048 : mbOldInteractionEnabled(mpMgr->mbUserInteractionEnabled)
1522 : : {
1523 : : // We don't want user interaction handled in the API.
1524 : 2048 : mpMgr->mbUserInteractionEnabled = false;
1525 : 2048 : }
1526 : :
1527 : 2048 : ScExternalRefManager::ApiGuard::~ApiGuard()
1528 : : {
1529 : : // Restore old value.
1530 : 2048 : mpMgr->mbUserInteractionEnabled = mbOldInteractionEnabled;
1531 : 2048 : }
1532 : :
1533 : : // ----------------------------------------------------------------------------
1534 : :
1535 : 3 : void ScExternalRefManager::getAllCachedTableNames(sal_uInt16 nFileId, vector<OUString>& rTabNames) const
1536 : : {
1537 : 3 : maRefCache.getAllTableNames(nFileId, rTabNames);
1538 : 3 : }
1539 : :
1540 : 0 : SCsTAB ScExternalRefManager::getCachedTabSpan( sal_uInt16 nFileId, const OUString& rStartTabName, const OUString& rEndTabName ) const
1541 : : {
1542 : 0 : return maRefCache.getTabSpan( nFileId, rStartTabName, rEndTabName);
1543 : : }
1544 : :
1545 : 0 : void ScExternalRefManager::getAllCachedNumberFormats(vector<sal_uInt32>& rNumFmts) const
1546 : : {
1547 : 0 : maRefCache.getAllNumberFormats(rNumFmts);
1548 : 0 : }
1549 : :
1550 : 0 : bool ScExternalRefManager::hasCacheTable(sal_uInt16 nFileId, const OUString& rTabName) const
1551 : : {
1552 : 0 : return maRefCache.hasCacheTable(nFileId, rTabName);
1553 : : }
1554 : :
1555 : 0 : size_t ScExternalRefManager::getCacheTableCount(sal_uInt16 nFileId) const
1556 : : {
1557 : 0 : return maRefCache.getCacheTableCount(nFileId);
1558 : : }
1559 : :
1560 : 4 : sal_uInt16 ScExternalRefManager::getExternalFileCount() const
1561 : : {
1562 : 4 : return static_cast< sal_uInt16 >( maSrcFiles.size() );
1563 : : }
1564 : :
1565 : 0 : bool ScExternalRefManager::markUsedByLinkListeners()
1566 : : {
1567 : 0 : bool bAllMarked = false;
1568 [ # # ][ # # ]: 0 : for (LinkListenerMap::const_iterator itr = maLinkListeners.begin();
[ # # ][ # # ]
1569 [ # # ][ # # ]: 0 : itr != maLinkListeners.end() && !bAllMarked; ++itr)
[ # # ]
[ # # # # ]
1570 : : {
1571 [ # # ][ # # ]: 0 : if (!(*itr).second.empty())
1572 [ # # ][ # # ]: 0 : bAllMarked = maRefCache.setCacheDocReferenced( (*itr).first);
1573 : : /* TODO: LinkListeners should remember the table they're listening to.
1574 : : * As is, listening to one table will mark all tables of the document
1575 : : * being referenced. */
1576 : : }
1577 : 0 : return bAllMarked;
1578 : : }
1579 : :
1580 : 0 : bool ScExternalRefManager::markUsedExternalRefCells()
1581 : : {
1582 [ # # ][ # # ]: 0 : RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end();
1583 [ # # ]: 0 : for (; itr != itrEnd; ++itr)
1584 : : {
1585 [ # # ][ # # ]: 0 : RefCellSet::iterator itrCell = itr->second.begin(), itrCellEnd = itr->second.end();
1586 [ # # ][ # # ]: 0 : for (; itrCell != itrCellEnd; ++itrCell)
[ # # ]
1587 : : {
1588 [ # # ]: 0 : ScFormulaCell* pCell = *itrCell;
1589 [ # # ]: 0 : bool bUsed = pCell->MarkUsedExternalReferences();
1590 [ # # ]: 0 : if (bUsed)
1591 : : // Return true when at least one cell references external docs.
1592 : 0 : return true;
1593 : : }
1594 : : }
1595 : 0 : return false;
1596 : : }
1597 : :
1598 : 0 : bool ScExternalRefManager::setCacheTableReferenced( sal_uInt16 nFileId, const OUString& rTabName, size_t nSheets )
1599 : : {
1600 : 0 : return maRefCache.setCacheTableReferenced( nFileId, rTabName, nSheets, false);
1601 : : }
1602 : :
1603 : 0 : void ScExternalRefManager::setAllCacheTableReferencedStati( bool bReferenced )
1604 : : {
1605 : 0 : mbInReferenceMarking = !bReferenced;
1606 : 0 : maRefCache.setAllCacheTableReferencedStati( bReferenced );
1607 : 0 : }
1608 : :
1609 : 0 : void ScExternalRefManager::storeRangeNameTokens(sal_uInt16 nFileId, const OUString& rName, const ScTokenArray& rArray)
1610 : : {
1611 [ # # ][ # # ]: 0 : ScExternalRefCache::TokenArrayRef pArray(rArray.Clone());
1612 [ # # ][ # # ]: 0 : maRefCache.setRangeNameTokens(nFileId, rName, pArray);
[ # # ][ # # ]
1613 : 0 : }
1614 : :
1615 : : namespace {
1616 : :
1617 : : /**
1618 : : * Put a single cell data into internal cache table.
1619 : : *
1620 : : * @param pFmt optional cell format index that may need to be stored with
1621 : : * the cell value.
1622 : : */
1623 : 156 : void putCellDataIntoCache(
1624 : : ScExternalRefCache& rRefCache, const ScExternalRefCache::TokenRef& pToken,
1625 : : sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell,
1626 : : const ScExternalRefCache::CellFormat* pFmt)
1627 : : {
1628 : : // Now, insert the token into cache table but don't cache empty cells.
1629 [ + + ]: 156 : if (pToken->GetType() != formula::svEmptyCell)
1630 : : {
1631 [ + + ][ + - ]: 135 : sal_uLong nFmtIndex = (pFmt && pFmt->mbIsSet) ? pFmt->mnIndex : 0;
1632 [ + - ][ + - ]: 135 : rRefCache.setCellData(nFileId, rTabName, rCell.Col(), rCell.Row(), pToken, nFmtIndex);
1633 : : }
1634 : 156 : }
1635 : :
1636 : : /**
1637 : : * Put the data into our internal cache table.
1638 : : *
1639 : : * @param rRefCache cache table set.
1640 : : * @param pArray single range data to be returned.
1641 : : * @param nFileId external file ID
1642 : : * @param rTabName name of the table where the data should be cached.
1643 : : * @param rCacheData range data to be cached.
1644 : : * @param rCacheRange original cache range, including the empty region if
1645 : : * any.
1646 : : * @param rDataRange reduced cache range that includes only the non-empty
1647 : : * data area.
1648 : : */
1649 : 18 : void putRangeDataIntoCache(
1650 : : ScExternalRefCache& rRefCache, ScExternalRefCache::TokenArrayRef& pArray,
1651 : : sal_uInt16 nFileId, const String& rTabName,
1652 : : const vector<ScExternalRefCache::SingleRangeData>& rCacheData,
1653 : : const ScRange& rCacheRange, const ScRange& rDataRange)
1654 : : {
1655 [ + - ]: 18 : if (pArray)
1656 : : // Cache these values.
1657 : 18 : rRefCache.setCellRangeData(nFileId, rDataRange, rCacheData, pArray);
1658 : : else
1659 : : {
1660 : : // Array is empty. Fill it with an empty matrix of the required size.
1661 [ # # ][ # # ]: 0 : pArray.reset(lcl_fillEmptyMatrix(rCacheRange));
1662 : :
1663 : : // Make sure to set this range 'cached', to prevent unnecessarily
1664 : : // accessing the src document time and time again.
1665 : : ScExternalRefCache::TableTypeRef pCacheTab =
1666 [ # # ][ # # ]: 0 : rRefCache.getCacheTable(nFileId, rTabName, true, NULL);
1667 [ # # ]: 0 : if (pCacheTab)
1668 : : pCacheTab->setCachedCellRange(
1669 [ # # ][ # # ]: 0 : rCacheRange.aStart.Col(), rCacheRange.aStart.Row(), rCacheRange.aEnd.Col(), rCacheRange.aEnd.Row());
1670 : : }
1671 : 18 : }
1672 : :
1673 : : /**
1674 : : * When accessing an external document for the first time, we need to
1675 : : * populate the cache with all its sheet names (whether they are referenced
1676 : : * or not) in the correct order. Many client codes that use external
1677 : : * references make this assumption.
1678 : : *
1679 : : * @param rRefCache cache table set.
1680 : : * @param pSrcDoc source document instance.
1681 : : * @param nFileId external file ID associated with the source document.
1682 : : */
1683 : 174 : void initDocInCache(ScExternalRefCache& rRefCache, const ScDocument* pSrcDoc, sal_uInt16 nFileId)
1684 : : {
1685 [ - + ]: 174 : if (!pSrcDoc)
1686 : 0 : return;
1687 : :
1688 [ + + ]: 174 : if (rRefCache.isDocInitialized(nFileId))
1689 : : // Already initialized. No need to do this twice.
1690 : 165 : return;
1691 : :
1692 : 9 : SCTAB nTabCount = pSrcDoc->GetTableCount();
1693 [ + - ]: 9 : if (nTabCount)
1694 : : {
1695 : : // Populate the cache with all table names in the source document.
1696 [ + - ]: 9 : vector<OUString> aTabNames;
1697 [ + - ]: 9 : aTabNames.reserve(nTabCount);
1698 [ + + ]: 33 : for (SCTAB i = 0; i < nTabCount; ++i)
1699 : : {
1700 : 24 : OUString aName;
1701 [ + - ]: 24 : pSrcDoc->GetName(i, aName);
1702 [ + - ]: 24 : aTabNames.push_back(aName);
1703 : 24 : }
1704 [ + - ]: 174 : rRefCache.initializeDoc(nFileId, aTabNames);
1705 : : }
1706 : : }
1707 : :
1708 : : }
1709 : :
1710 : 156 : ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
1711 : : sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rCell,
1712 : : const ScAddress* pCurPos, SCTAB* pTab, ScExternalRefCache::CellFormat* pFmt)
1713 : : {
1714 [ + + ]: 156 : if (pCurPos)
1715 [ + - ]: 69 : insertRefCell(nFileId, *pCurPos);
1716 : :
1717 [ + - ]: 156 : maybeLinkExternalFile(nFileId);
1718 : :
1719 [ + + ]: 156 : if (pTab)
1720 : 87 : *pTab = -1;
1721 : :
1722 [ + + ]: 156 : if (pFmt)
1723 : 69 : pFmt->mbIsSet = false;
1724 : :
1725 [ + - ]: 156 : const ScDocument* pSrcDoc = getInMemorySrcDocument(nFileId);
1726 [ + - ]: 156 : if (pSrcDoc)
1727 : : {
1728 : : // source document already loaded in memory. Re-use this instance.
1729 : : SCTAB nTab;
1730 [ + - ][ - + ]: 156 : if (!pSrcDoc->GetTable(rTabName, nTab))
1731 : : {
1732 : : // specified table name doesn't exist in the source document.
1733 [ # # ][ # # ]: 0 : ScExternalRefCache::TokenRef pToken(new FormulaErrorToken(errNoRef));
1734 [ # # ]: 0 : return pToken;
1735 : : }
1736 : :
1737 [ + + ]: 156 : if (pTab)
1738 : 87 : *pTab = nTab;
1739 : :
1740 : : ScExternalRefCache::TokenRef pToken =
1741 : : getSingleRefTokenFromSrcDoc(
1742 [ + - ]: 156 : nFileId, pSrcDoc, ScAddress(rCell.Col(),rCell.Row(),nTab), pFmt);
1743 : :
1744 [ + - ][ + - ]: 156 : putCellDataIntoCache(maRefCache, pToken, nFileId, rTabName, rCell, pFmt);
[ + - ]
1745 [ + - ]: 156 : return pToken;
1746 : : }
1747 : :
1748 : : // Check if the given table name and the cell position is cached.
1749 : 0 : sal_uInt32 nFmtIndex = 0;
1750 : : ScExternalRefCache::TokenRef pToken = maRefCache.getCellData(
1751 [ # # ]: 0 : nFileId, rTabName, rCell.Col(), rCell.Row(), &nFmtIndex);
1752 [ # # ]: 0 : if (pToken)
1753 : : {
1754 : : // Cache hit !
1755 [ # # ]: 0 : fillCellFormat(nFmtIndex, pFmt);
1756 : 0 : return pToken;
1757 : : }
1758 : :
1759 : : // reference not cached. read from the source document.
1760 [ # # ]: 0 : pSrcDoc = getSrcDocument(nFileId);
1761 [ # # ]: 0 : if (!pSrcDoc)
1762 : : {
1763 : : // Source document not reachable. Throw a reference error.
1764 [ # # ][ # # ]: 0 : pToken.reset(new FormulaErrorToken(errNoRef));
[ # # ]
1765 : 0 : return pToken;
1766 : : }
1767 : :
1768 : : SCTAB nTab;
1769 [ # # ][ # # ]: 0 : if (!pSrcDoc->GetTable(rTabName, nTab))
1770 : : {
1771 : : // specified table name doesn't exist in the source document.
1772 [ # # ][ # # ]: 0 : pToken.reset(new FormulaErrorToken(errNoRef));
[ # # ]
1773 : 0 : return pToken;
1774 : : }
1775 : :
1776 [ # # ]: 0 : if (pTab)
1777 : 0 : *pTab = nTab;
1778 : :
1779 : 0 : SCCOL nDataCol1 = 0, nDataCol2 = MAXCOL;
1780 : 0 : SCROW nDataRow1 = 0, nDataRow2 = MAXROW;
1781 [ # # ]: 0 : bool bData = pSrcDoc->ShrinkToDataArea(nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2);
1782 [ # # ][ # # ]: 0 : if (!bData || rCell.Col() < nDataCol1 || nDataCol2 < rCell.Col() || rCell.Row() < nDataRow1 || nDataRow2 < rCell.Row())
[ # # ][ # # ]
[ # # ][ # # ]
1783 : : {
1784 : : // requested cell is outside the data area. Don't even bother caching
1785 : : // this data, but add it to the cached range to prevent accessing the
1786 : : // source document time and time again.
1787 : : ScExternalRefCache::TableTypeRef pCacheTab =
1788 [ # # ]: 0 : maRefCache.getCacheTable(nFileId, rTabName, true, NULL);
1789 [ # # ]: 0 : if (pCacheTab)
1790 [ # # ]: 0 : pCacheTab->setCachedCell(rCell.Col(), rCell.Row());
1791 : :
1792 [ # # ][ # # ]: 0 : pToken.reset(new ScEmptyCellToken(false, false));
[ # # ]
1793 [ # # ]: 0 : return pToken;
1794 : : }
1795 : :
1796 : : pToken = getSingleRefTokenFromSrcDoc(
1797 [ # # ][ # # ]: 0 : nFileId, pSrcDoc, ScAddress(rCell.Col(),rCell.Row(),nTab), pFmt);
[ # # ]
1798 : :
1799 [ # # ][ # # ]: 0 : putCellDataIntoCache(maRefCache, pToken, nFileId, rTabName, rCell, pFmt);
[ # # ]
1800 [ # # ]: 156 : return pToken;
1801 : : }
1802 : :
1803 : 18 : ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(
1804 : : sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange, const ScAddress* pCurPos)
1805 : : {
1806 [ + - ]: 18 : if (pCurPos)
1807 [ + - ]: 18 : insertRefCell(nFileId, *pCurPos);
1808 : :
1809 [ + - ]: 18 : maybeLinkExternalFile(nFileId);
1810 : :
1811 : 18 : ScRange aDataRange(rRange);
1812 [ + - ]: 18 : const ScDocument* pSrcDoc = getInMemorySrcDocument(nFileId);
1813 [ + - ]: 18 : if (pSrcDoc)
1814 : : {
1815 : : // Document already loaded in memory.
1816 [ + - ]: 18 : vector<ScExternalRefCache::SingleRangeData> aCacheData;
1817 : : ScExternalRefCache::TokenArrayRef pArray =
1818 [ + - ]: 18 : getDoubleRefTokensFromSrcDoc(pSrcDoc, rTabName, aDataRange, aCacheData);
1819 : :
1820 : : // Put the data into cache.
1821 [ + - ][ + - ]: 18 : putRangeDataIntoCache(maRefCache, pArray, nFileId, rTabName, aCacheData, rRange, aDataRange);
[ + - ]
1822 [ + - ][ + - ]: 18 : return pArray;
1823 : : }
1824 : :
1825 : : // Check if the given table name and the cell position is cached.
1826 : : ScExternalRefCache::TokenArrayRef pArray =
1827 [ # # ]: 0 : maRefCache.getCellRangeData(nFileId, rTabName, rRange);
1828 [ # # ]: 0 : if (pArray)
1829 : : // Cache hit !
1830 [ # # ]: 0 : return pArray;
1831 : :
1832 [ # # ]: 0 : pSrcDoc = getSrcDocument(nFileId);
1833 [ # # ]: 0 : if (!pSrcDoc)
1834 : : {
1835 : : // Source document is not reachable. Throw a reference error.
1836 [ # # ][ # # ]: 0 : pArray.reset(new ScTokenArray);
[ # # ]
1837 [ # # ][ # # ]: 0 : pArray->AddToken(FormulaErrorToken(errNoRef));
[ # # ]
1838 [ # # ]: 0 : return pArray;
1839 : : }
1840 : :
1841 [ # # ]: 0 : vector<ScExternalRefCache::SingleRangeData> aCacheData;
1842 [ # # ][ # # ]: 0 : pArray = getDoubleRefTokensFromSrcDoc(pSrcDoc, rTabName, aDataRange, aCacheData);
[ # # ]
1843 : :
1844 : : // Put the data into cache.
1845 [ # # ][ # # ]: 0 : putRangeDataIntoCache(maRefCache, pArray, nFileId, rTabName, aCacheData, rRange, aDataRange);
[ # # ]
1846 [ # # ][ # # ]: 18 : return pArray;
1847 : : }
1848 : :
1849 : 0 : ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokens(
1850 : : sal_uInt16 nFileId, const OUString& rName, const ScAddress* pCurPos)
1851 : : {
1852 [ # # ]: 0 : if (pCurPos)
1853 [ # # ]: 0 : insertRefCell(nFileId, *pCurPos);
1854 : :
1855 [ # # ]: 0 : maybeLinkExternalFile(nFileId);
1856 : :
1857 : 0 : OUString aName = rName; // make a copy to have the casing corrected.
1858 [ # # ]: 0 : const ScDocument* pSrcDoc = getInMemorySrcDocument(nFileId);
1859 [ # # ]: 0 : if (pSrcDoc)
1860 : : {
1861 : : // Document already loaded in memory.
1862 : : ScExternalRefCache::TokenArrayRef pArray =
1863 [ # # ]: 0 : getRangeNameTokensFromSrcDoc(nFileId, pSrcDoc, aName);
1864 : :
1865 [ # # ]: 0 : if (pArray)
1866 : : // Cache this range name array.
1867 [ # # ][ # # ]: 0 : maRefCache.setRangeNameTokens(nFileId, aName, pArray);
[ # # ]
1868 : :
1869 [ # # ][ # # ]: 0 : return pArray;
1870 : : }
1871 : :
1872 [ # # ]: 0 : ScExternalRefCache::TokenArrayRef pArray = maRefCache.getRangeNameTokens(nFileId, rName);
1873 [ # # ]: 0 : if (pArray.get())
1874 : : // This range name is cached.
1875 [ # # ]: 0 : return pArray;
1876 : :
1877 [ # # ]: 0 : pSrcDoc = getSrcDocument(nFileId);
1878 [ # # ]: 0 : if (!pSrcDoc)
1879 : : // failed to load document from disk.
1880 [ # # ]: 0 : return ScExternalRefCache::TokenArrayRef();
1881 : :
1882 [ # # ][ # # ]: 0 : pArray = getRangeNameTokensFromSrcDoc(nFileId, pSrcDoc, aName);
[ # # ]
1883 : :
1884 [ # # ]: 0 : if (pArray)
1885 : : // Cache this range name array.
1886 [ # # ][ # # ]: 0 : maRefCache.setRangeNameTokens(nFileId, aName, pArray);
[ # # ]
1887 : :
1888 [ # # ][ # # ]: 0 : return pArray;
1889 : : }
1890 : :
1891 : 0 : void ScExternalRefManager::refreshAllRefCells(sal_uInt16 nFileId)
1892 : : {
1893 [ # # ]: 0 : RefCellMap::iterator itrFile = maRefCells.find(nFileId);
1894 [ # # ][ # # ]: 0 : if (itrFile == maRefCells.end())
1895 : : return;
1896 : :
1897 [ # # ]: 0 : RefCellSet& rRefCells = itrFile->second;
1898 [ # # ]: 0 : for_each(rRefCells.begin(), rRefCells.end(), UpdateFormulaCell());
1899 : :
1900 [ # # ]: 0 : ScViewData* pViewData = ScDocShell::GetViewData();
1901 [ # # ]: 0 : if (!pViewData)
1902 : : return;
1903 : :
1904 : 0 : ScTabViewShell* pVShell = pViewData->GetViewShell();
1905 [ # # ]: 0 : if (!pVShell)
1906 : : return;
1907 : :
1908 : : // Repainting the grid also repaints the texts, but is there a better way
1909 : : // to refresh texts?
1910 [ # # ]: 0 : pVShell->Invalidate(FID_REPAINT);
1911 [ # # ]: 0 : pVShell->PaintGrid();
1912 : : }
1913 : :
1914 : 87 : void ScExternalRefManager::insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell)
1915 : : {
1916 [ + - ]: 87 : RefCellMap::iterator itr = maRefCells.find(nFileId);
1917 [ + - ][ + + ]: 87 : if (itr == maRefCells.end())
1918 : : {
1919 [ + - ]: 6 : RefCellSet aRefCells;
1920 : : pair<RefCellMap::iterator, bool> r = maRefCells.insert(
1921 [ + - ][ + - ]: 6 : RefCellMap::value_type(nFileId, aRefCells));
1922 [ - + ]: 6 : if (!r.second)
1923 : : // insertion failed.
1924 : 87 : return;
1925 : :
1926 [ + - ]: 6 : itr = r.first;
1927 : : }
1928 : :
1929 [ + - ]: 87 : ScBaseCell* pCell = mpDoc->GetCell(rCell);
1930 [ + - ][ + - ]: 87 : if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
[ + - ]
1931 [ + - ][ + - ]: 87 : itr->second.insert(static_cast<ScFormulaCell*>(pCell));
[ + - ]
1932 : : }
1933 : :
1934 : 156 : void ScExternalRefManager::fillCellFormat(sal_uLong nFmtIndex, ScExternalRefCache::CellFormat* pFmt) const
1935 : : {
1936 [ + + ]: 156 : if (!pFmt)
1937 : 156 : return;
1938 : :
1939 : 69 : short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex);
1940 [ + - ]: 69 : if (nFmtType != NUMBERFORMAT_UNDEFINED)
1941 : : {
1942 : 69 : pFmt->mbIsSet = true;
1943 : 69 : pFmt->mnIndex = nFmtIndex;
1944 : 69 : pFmt->mnType = nFmtType;
1945 : : }
1946 : : }
1947 : :
1948 : 156 : ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefTokenFromSrcDoc(
1949 : : sal_uInt16 nFileId, const ScDocument* pSrcDoc, const ScAddress& rCell,
1950 : : ScExternalRefCache::CellFormat* pFmt)
1951 : : {
1952 : : // Get the cell from src doc, and convert it into a token.
1953 : 156 : ScBaseCell* pCell = NULL;
1954 [ + - ]: 156 : pSrcDoc->GetCell(rCell.Col(), rCell.Row(), rCell.Tab(), pCell);
1955 [ + - ]: 156 : ScExternalRefCache::TokenRef pToken(lcl_convertToToken(pCell));
1956 : :
1957 [ - + ]: 156 : if (!pToken.get())
1958 : : {
1959 : : // Generate an error for unresolvable cells.
1960 [ # # ][ # # ]: 0 : pToken.reset( new FormulaErrorToken( errNoValue));
[ # # ]
1961 : : }
1962 : :
1963 : : // Get number format information.
1964 : 156 : sal_uInt32 nFmtIndex = 0;
1965 [ + - ]: 156 : pSrcDoc->GetNumberFormat(rCell.Col(), rCell.Row(), rCell.Tab(), nFmtIndex);
1966 [ + - ]: 156 : nFmtIndex = getMappedNumberFormat(nFileId, nFmtIndex, pSrcDoc);
1967 [ + - ]: 156 : fillCellFormat(nFmtIndex, pFmt);
1968 : 156 : return pToken;
1969 : : }
1970 : :
1971 : 18 : ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokensFromSrcDoc(
1972 : : const ScDocument* pSrcDoc, const OUString& rTabName, ScRange& rRange,
1973 : : vector<ScExternalRefCache::SingleRangeData>& rCacheData)
1974 : : {
1975 [ + - ]: 18 : ScExternalRefCache::TokenArrayRef pArray;
1976 : : SCTAB nTab1;
1977 : :
1978 [ + - ][ - + ]: 18 : if (!pSrcDoc->GetTable(rTabName, nTab1))
1979 : : {
1980 : : // specified table name doesn't exist in the source document.
1981 [ # # ][ # # ]: 0 : pArray.reset(new ScTokenArray);
[ # # ]
1982 [ # # ][ # # ]: 0 : pArray->AddToken(FormulaErrorToken(errNoRef));
[ # # ]
1983 : : return pArray;
1984 : : }
1985 : :
1986 : 18 : ScRange aRange(rRange);
1987 : 18 : SCTAB nTabSpan = aRange.aEnd.Tab() - aRange.aStart.Tab();
1988 : :
1989 [ + - ]: 18 : vector<ScExternalRefCache::SingleRangeData> aCacheData;
1990 [ + - ]: 18 : aCacheData.reserve(nTabSpan+1);
1991 [ + - ][ + - ]: 18 : aCacheData.push_back(ScExternalRefCache::SingleRangeData());
[ + - ]
1992 [ + - ][ + - ]: 18 : aCacheData.back().maTableName = ScGlobal::pCharClass->uppercase(rTabName);
1993 : :
1994 [ - + ]: 18 : for (SCTAB i = 1; i < nTabSpan + 1; ++i)
1995 : : {
1996 : 0 : OUString aTabName;
1997 [ # # ][ # # ]: 0 : if (!pSrcDoc->GetName(nTab1 + 1, aTabName))
1998 : : // source document doesn't have any table by the specified name.
1999 : : break;
2000 : :
2001 [ # # ][ # # ]: 0 : aCacheData.push_back(ScExternalRefCache::SingleRangeData());
[ # # ]
2002 [ # # ][ # # ]: 0 : aCacheData.back().maTableName = ScGlobal::pCharClass->uppercase(aTabName);
[ # # ]
2003 : 0 : }
2004 : :
2005 : 18 : aRange.aStart.SetTab(nTab1);
2006 : 18 : aRange.aEnd.SetTab(nTab1 + nTabSpan);
2007 : :
2008 [ + - ][ + - ]: 18 : pArray.reset(lcl_convertToTokenArray(pSrcDoc, aRange, aCacheData));
2009 : 18 : rRange = aRange;
2010 : 18 : rCacheData.swap(aCacheData);
2011 : 18 : return pArray;
2012 : : }
2013 : :
2014 : 0 : ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokensFromSrcDoc(
2015 : : sal_uInt16 nFileId, const ScDocument* pSrcDoc, OUString& rName)
2016 : : {
2017 [ # # ]: 0 : ScRangeName* pExtNames = pSrcDoc->GetRangeName();
2018 [ # # ][ # # ]: 0 : String aUpperName = ScGlobal::pCharClass->uppercase(rName);
2019 [ # # ][ # # ]: 0 : const ScRangeData* pRangeData = pExtNames->findByUpperName(aUpperName);
2020 [ # # ]: 0 : if (!pRangeData)
2021 [ # # ]: 0 : return ScExternalRefCache::TokenArrayRef();
2022 : :
2023 : : // Parse all tokens in this external range data, and replace each absolute
2024 : : // reference token with an external reference token, and cache them. Also
2025 : : // register the source document with the link manager if it's a new
2026 : : // source.
2027 : :
2028 [ # # ][ # # ]: 0 : ScExternalRefCache::TokenArrayRef pNew(new ScTokenArray);
[ # # ]
2029 : :
2030 [ # # ]: 0 : ScTokenArray aCode(*pRangeData->GetCode());
2031 [ # # ][ # # ]: 0 : for (const FormulaToken* pToken = aCode.First(); pToken; pToken = aCode.Next())
[ # # ]
2032 : : {
2033 : 0 : bool bTokenAdded = false;
2034 [ # # # ]: 0 : switch (pToken->GetType())
2035 : : {
2036 : : case svSingleRef:
2037 : : {
2038 [ # # ]: 0 : const ScSingleRefData& rRef = static_cast<const ScToken*>(pToken)->GetSingleRef();
2039 : 0 : OUString aTabName;
2040 [ # # ]: 0 : pSrcDoc->GetName(rRef.nTab, aTabName);
2041 [ # # ][ # # ]: 0 : ScExternalSingleRefToken aNewToken(nFileId, aTabName, static_cast<const ScToken*>(pToken)->GetSingleRef());
[ # # ][ # # ]
2042 [ # # ]: 0 : pNew->AddToken(aNewToken);
2043 [ # # ]: 0 : bTokenAdded = true;
2044 : : }
2045 : 0 : break;
2046 : : case svDoubleRef:
2047 : : {
2048 [ # # ]: 0 : const ScSingleRefData& rRef = static_cast<const ScToken*>(pToken)->GetSingleRef();
2049 : 0 : OUString aTabName;
2050 [ # # ]: 0 : pSrcDoc->GetName(rRef.nTab, aTabName);
2051 [ # # ][ # # ]: 0 : ScExternalDoubleRefToken aNewToken(nFileId, aTabName, static_cast<const ScToken*>(pToken)->GetDoubleRef());
[ # # ][ # # ]
2052 [ # # ]: 0 : pNew->AddToken(aNewToken);
2053 [ # # ]: 0 : bTokenAdded = true;
2054 : : }
2055 : 0 : break;
2056 : : default:
2057 : : ; // nothing
2058 : : }
2059 : :
2060 [ # # ]: 0 : if (!bTokenAdded)
2061 [ # # ]: 0 : pNew->AddToken(*pToken);
2062 : : }
2063 : :
2064 : 0 : rName = pRangeData->GetName(); // Get the correctly-cased name.
2065 [ # # ][ # # ]: 0 : return pNew;
[ # # ][ # # ]
2066 : : }
2067 : :
2068 : 174 : const ScDocument* ScExternalRefManager::getInMemorySrcDocument(sal_uInt16 nFileId)
2069 : : {
2070 [ + - ]: 174 : const OUString* pFileName = getExternalFileName(nFileId);
2071 [ - + ]: 174 : if (!pFileName)
2072 : 0 : return NULL;
2073 : :
2074 : 174 : ScDocument* pSrcDoc = NULL;
2075 [ + - ]: 174 : TypeId aType(TYPE(ScDocShell));
2076 [ + - ]: 174 : ScDocShell* pShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType, false));
2077 [ + - ]: 4578 : while (pShell)
2078 : : {
2079 : 4578 : SfxMedium* pMedium = pShell->GetMedium();
2080 [ + - ][ + - ]: 4578 : if (pMedium && !pMedium->GetName().isEmpty())
[ + + ][ + + ]
2081 : : {
2082 : : // TODO: We should make the case sensitivity platform dependent.
2083 [ + - ][ + - ]: 174 : if (pFileName->equalsIgnoreAsciiCase(pMedium->GetName()))
2084 : : {
2085 : : // Found !
2086 : 174 : pSrcDoc = pShell->GetDocument();
2087 : 174 : break;
2088 : : }
2089 : : }
2090 : : else
2091 : : {
2092 : : // handle unsaved documents here
2093 [ + - ][ + - ]: 4404 : OUString aName = pShell->GetName();
2094 [ - + ]: 4404 : if (pFileName->equalsIgnoreAsciiCase(aName))
2095 : : {
2096 : : // Found !
2097 [ # # ]: 0 : SrcShell aSrcDoc;
2098 [ # # ]: 0 : aSrcDoc.maShell = pShell;
2099 [ # # ][ # # ]: 0 : maUnsavedDocShells.insert(DocShellMap::value_type(nFileId, aSrcDoc));
[ # # ]
2100 [ # # ]: 0 : StartListening(*pShell);
2101 : 0 : pSrcDoc = pShell->GetDocument();
2102 [ # # ]: 4404 : break;
2103 [ + - ]: 4404 : }
2104 : : }
2105 [ + - ]: 4404 : pShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pShell, &aType, false));
2106 : : }
2107 : :
2108 [ + - ]: 174 : initDocInCache(maRefCache, pSrcDoc, nFileId);
2109 : 174 : return pSrcDoc;
2110 : : }
2111 : :
2112 : 0 : const ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId)
2113 : : {
2114 [ # # ]: 0 : if (!mpDoc->IsExecuteLinkEnabled())
2115 : 0 : return NULL;
2116 : :
2117 [ # # ]: 0 : DocShellMap::iterator itrEnd = maDocShells.end();
2118 [ # # ]: 0 : DocShellMap::iterator itr = maDocShells.find(nFileId);
2119 : :
2120 [ # # ]: 0 : if (itr != itrEnd)
2121 : : {
2122 : : // document already loaded.
2123 : :
2124 [ # # ]: 0 : SfxObjectShell* p = itr->second.maShell;
2125 [ # # ][ # # ]: 0 : itr->second.maLastAccess = Time( Time::SYSTEM );
[ # # ]
2126 : 0 : return static_cast<ScDocShell*>(p)->GetDocument();
2127 : : }
2128 : :
2129 [ # # ]: 0 : itrEnd = maUnsavedDocShells.end();
2130 [ # # ]: 0 : itr = maUnsavedDocShells.find(nFileId);
2131 [ # # ]: 0 : if (itr != itrEnd)
2132 : : {
2133 : : //document is unsaved document
2134 : :
2135 [ # # ]: 0 : SfxObjectShell* p = itr->second.maShell;
2136 [ # # ][ # # ]: 0 : itr->second.maLastAccess = Time( Time::SYSTEM );
[ # # ]
2137 : 0 : return static_cast<ScDocShell*>(p)->GetDocument();
2138 : : }
2139 : :
2140 [ # # ]: 0 : const OUString* pFile = getExternalFileName(nFileId);
2141 [ # # ]: 0 : if (!pFile)
2142 : : // no file name associated with this ID.
2143 : 0 : return NULL;
2144 : :
2145 : 0 : OUString aFilter;
2146 [ # # ]: 0 : SrcShell aSrcDoc;
2147 [ # # ][ # # ]: 0 : aSrcDoc.maShell = loadSrcDocument(nFileId, aFilter);
[ # # ]
2148 [ # # ]: 0 : if (!aSrcDoc.maShell.Is())
2149 : : {
2150 : : // source document could not be loaded.
2151 : 0 : return NULL;
2152 : : }
2153 : :
2154 [ # # ]: 0 : if (maDocShells.empty())
2155 : : {
2156 : : // If this is the first source document insertion, start up the timer.
2157 [ # # ]: 0 : maSrcDocTimer.Start();
2158 : : }
2159 : :
2160 [ # # ][ # # ]: 0 : maDocShells.insert(DocShellMap::value_type(nFileId, aSrcDoc));
[ # # ]
2161 : 0 : SfxObjectShell* p = aSrcDoc.maShell;
2162 : 0 : ScDocument* pSrcDoc = static_cast<ScDocShell*>(p)->GetDocument();
2163 [ # # ]: 0 : initDocInCache(maRefCache, pSrcDoc, nFileId);
2164 [ # # ]: 0 : return pSrcDoc;
2165 : : }
2166 : :
2167 : 0 : SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, OUString& rFilter)
2168 : : {
2169 [ # # ]: 0 : const SrcFileData* pFileData = getExternalFileData(nFileId);
2170 [ # # ]: 0 : if (!pFileData)
2171 : 0 : return NULL;
2172 : :
2173 : : // Always load the document by using the path created from the relative
2174 : : // path. If the referenced document is not there, simply exit. The
2175 : : // original file name should be used only when the relative path is not
2176 : : // given.
2177 : 0 : OUString aFile = pFileData->maFileName;
2178 [ # # ]: 0 : maybeCreateRealFileName(nFileId);
2179 [ # # ]: 0 : if (!pFileData->maRealFileName.isEmpty())
2180 : 0 : aFile = pFileData->maRealFileName;
2181 : :
2182 [ # # ][ # # ]: 0 : if (!isFileLoadable(aFile))
2183 : 0 : return NULL;
2184 : :
2185 : 0 : OUString aOptions = pFileData->maFilterOptions;
2186 [ # # ]: 0 : if ( !pFileData->maFilterName.isEmpty() )
2187 : 0 : rFilter = pFileData->maFilterName; // don't overwrite stored filter with guessed filter
2188 : : else
2189 [ # # ]: 0 : ScDocumentLoader::GetFilterName(aFile, rFilter, aOptions, true, false);;
2190 [ # # ]: 0 : ScDocumentLoader::GetFilterName(aFile, rFilter, aOptions, true, false);
2191 [ # # ][ # # ]: 0 : const SfxFilter* pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName(rFilter);
[ # # ][ # # ]
[ # # ]
2192 : :
2193 [ # # ]: 0 : if (pFileData->maRelativeName.isEmpty())
2194 : : {
2195 : : // Generate a relative file path.
2196 [ # # ][ # # ]: 0 : INetURLObject aBaseURL(getOwnDocumentName());
2197 [ # # ][ # # ]: 0 : aBaseURL.insertName(OUString(RTL_CONSTASCII_USTRINGPARAM("content.xml")));
2198 : :
2199 : : OUString aStr = URIHelper::simpleNormalizedMakeRelative(
2200 [ # # ][ # # ]: 0 : aBaseURL.GetMainURL(INetURLObject::NO_DECODE), aFile);
2201 : :
2202 [ # # ][ # # ]: 0 : setRelativeFileName(nFileId, aStr);
2203 : : }
2204 : :
2205 [ # # ][ # # ]: 0 : SfxItemSet* pSet = new SfxAllItemSet(SFX_APP()->GetPool());
[ # # ]
2206 [ # # ]: 0 : if (!aOptions.isEmpty())
2207 [ # # ][ # # ]: 0 : pSet->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions));
[ # # ][ # # ]
[ # # ]
2208 : :
2209 : : // make medium hidden to prevent assertion from progress bar
2210 [ # # ][ # # ]: 0 : pSet->Put( SfxBoolItem(SID_HIDDEN, true) );
[ # # ]
2211 : :
2212 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
2213 [ # # ][ # # ]: 0 : auto_ptr<SfxMedium> pMedium(new SfxMedium(aFile, STREAM_STD_READ, pFilter, pSet));
[ # # ][ # # ]
2214 : : SAL_WNODEPRECATED_DECLARATIONS_POP
2215 [ # # ][ # # ]: 0 : if (pMedium->GetError() != ERRCODE_NONE)
2216 : 0 : return NULL;
2217 : :
2218 : : // To load encrypted documents with password, user interaction needs to be enabled.
2219 [ # # ]: 0 : pMedium->UseInteractionHandler(mbUserInteractionEnabled);
2220 : :
2221 [ # # ][ # # ]: 0 : ScDocShell* pNewShell = new ScDocShell(SFX_CREATE_MODE_INTERNAL);
2222 : 0 : SfxObjectShellRef aRef = pNewShell;
2223 : :
2224 : : // increment the recursive link count of the source document.
2225 : 0 : ScExtDocOptions* pExtOpt = mpDoc->GetExtDocOptions();
2226 [ # # ][ # # ]: 0 : sal_uInt32 nLinkCount = pExtOpt ? pExtOpt->GetDocSettings().mnLinkCnt : 0;
2227 : 0 : ScDocument* pSrcDoc = pNewShell->GetDocument();
2228 : 0 : pSrcDoc->EnableExecuteLink(false); // to prevent circular access of external references.
2229 [ # # ]: 0 : pSrcDoc->EnableUndo(false);
2230 : 0 : pSrcDoc->EnableAdjustHeight(false);
2231 : :
2232 : 0 : ScExtDocOptions* pExtOptNew = pSrcDoc->GetExtDocOptions();
2233 [ # # ]: 0 : if (!pExtOptNew)
2234 : : {
2235 [ # # ][ # # ]: 0 : pExtOptNew = new ScExtDocOptions;
2236 [ # # ]: 0 : pSrcDoc->SetExtDocOptions(pExtOptNew);
2237 : : }
2238 [ # # ]: 0 : pExtOptNew->GetDocSettings().mnLinkCnt = nLinkCount + 1;
2239 : :
2240 [ # # ]: 0 : pNewShell->DoLoad(pMedium.release());
2241 : :
2242 : : // with UseInteractionHandler, options may be set by dialog during DoLoad
2243 [ # # ]: 0 : OUString aNew = ScDocumentLoader::GetOptions(*pNewShell->GetMedium());
2244 [ # # ][ # # ]: 0 : if (!aNew.isEmpty() && aNew != aOptions)
[ # # ]
2245 : 0 : aOptions = aNew;
2246 [ # # ]: 0 : setFilterData(nFileId, rFilter, aOptions); // update the filter data, including the new options
2247 : :
2248 [ # # ][ # # ]: 0 : return aRef;
2249 : : }
2250 : :
2251 : 0 : bool ScExternalRefManager::isFileLoadable(const OUString& rFile) const
2252 : : {
2253 [ # # ]: 0 : if (rFile.isEmpty())
2254 : 0 : return false;
2255 : :
2256 [ # # ][ # # ]: 0 : if (isOwnDocument(rFile))
2257 : 0 : return false;
2258 : 0 : rtl::OUString aPhysical;
2259 [ # # ][ # # ]: 0 : if (utl::LocalFileHelper::ConvertURLToPhysicalName(rFile, aPhysical) && !aPhysical.isEmpty())
[ # # ][ # # ]
2260 : : {
2261 : : // #i114504# try IsFolder/Exists only for file URLs
2262 : :
2263 [ # # ][ # # ]: 0 : if (utl::UCBContentHelper::IsFolder(rFile))
2264 : 0 : return false;
2265 : :
2266 [ # # ]: 0 : return utl::UCBContentHelper::Exists(rFile);
2267 : : }
2268 : : else
2269 : 0 : return true; // for http and others, Exists doesn't work, but the URL can still be opened
2270 : : }
2271 : :
2272 : 174 : void ScExternalRefManager::maybeLinkExternalFile(sal_uInt16 nFileId)
2273 : : {
2274 [ + - ][ + + ]: 174 : if (maLinkedDocs.count(nFileId))
2275 : : // file alerady linked, or the link has been broken.
2276 : : return;
2277 : :
2278 : : // Source document not linked yet. Link it now.
2279 [ + - ]: 6 : const OUString* pFileName = getExternalFileName(nFileId);
2280 [ + - ]: 6 : if (!pFileName)
2281 : : return;
2282 : :
2283 : 6 : OUString aFilter, aOptions;
2284 [ + - ]: 6 : const SrcFileData* pFileData = getExternalFileData(nFileId);
2285 [ + - ]: 6 : if (pFileData)
2286 : : {
2287 : 6 : aFilter = pFileData->maFilterName;
2288 : 6 : aOptions = pFileData->maFilterOptions;
2289 : : }
2290 : : // If a filter was already set (for example, loading the cached table),
2291 : : // don't call GetFilterName which has to access the source file.
2292 [ + - ]: 6 : if (aFilter.isEmpty())
2293 [ + - ]: 6 : ScDocumentLoader::GetFilterName(*pFileName, aFilter, aOptions, true, false);
2294 [ + - ]: 6 : sfx2::LinkManager* pLinkMgr = mpDoc->GetLinkManager();
2295 [ + - ][ + - ]: 6 : ScExternalRefLink* pLink = new ScExternalRefLink(mpDoc, nFileId, aFilter);
[ + - ][ + - ]
2296 : : OSL_ENSURE(pFileName, "ScExternalRefManager::insertExternalFileLink: file name pointer is NULL");
2297 [ + - ]: 6 : String aTmp = aFilter;
2298 [ + - ][ + - ]: 6 : pLinkMgr->InsertFileLink(*pLink, OBJECT_CLIENT_FILE, *pFileName, &aTmp);
[ + - ]
2299 : :
2300 : 6 : pLink->SetDoReferesh(false);
2301 [ + - ]: 6 : pLink->Update();
2302 : 6 : pLink->SetDoReferesh(true);
2303 : :
2304 [ + - ][ + - ]: 174 : maLinkedDocs.insert(LinkedDocMap::value_type(nFileId, true));
[ + - ]
2305 : : }
2306 : :
2307 : 299 : void ScExternalRefManager::SrcFileData::maybeCreateRealFileName(const String& rOwnDocName)
2308 : : {
2309 [ - + ]: 299 : if (maRelativeName.isEmpty())
2310 : : // No relative path given. Nothing to do.
2311 : : return;
2312 : :
2313 [ # # ]: 0 : if (!maRealFileName.isEmpty())
2314 : : // Real file name already created. Nothing to do.
2315 : : return;
2316 : :
2317 : : // Formulate the absolute file path from the relative path.
2318 : 0 : const OUString& rRelPath = maRelativeName;
2319 [ # # ][ # # ]: 0 : INetURLObject aBaseURL(rOwnDocName);
2320 [ # # ][ # # ]: 0 : aBaseURL.insertName(OUString(RTL_CONSTASCII_USTRINGPARAM("content.xml")));
2321 : 0 : bool bWasAbs = false;
2322 [ # # ][ # # ]: 299 : maRealFileName = aBaseURL.smartRel2Abs(rRelPath, bWasAbs).GetMainURL(INetURLObject::NO_DECODE);
[ # # ][ # # ]
2323 : : }
2324 : :
2325 : 299 : void ScExternalRefManager::maybeCreateRealFileName(sal_uInt16 nFileId)
2326 : : {
2327 [ - + ]: 299 : if (nFileId >= maSrcFiles.size())
2328 : 299 : return;
2329 : :
2330 [ + - ][ + - ]: 299 : maSrcFiles[nFileId].maybeCreateRealFileName(getOwnDocumentName());
[ + - ][ + - ]
2331 : : }
2332 : :
2333 : 404 : OUString ScExternalRefManager::getOwnDocumentName() const
2334 : : {
2335 : 404 : SfxObjectShell* pShell = mpDoc->GetDocumentShell();
2336 [ - + ]: 404 : if (!pShell)
2337 : : // This should not happen!
2338 : 0 : return OUString();
2339 : :
2340 : 404 : SfxMedium* pMed = pShell->GetMedium();
2341 [ + + ]: 404 : if (!pMed)
2342 : 393 : return OUString();
2343 : :
2344 : 404 : return pMed->GetName();
2345 : : }
2346 : :
2347 : 105 : bool ScExternalRefManager::isOwnDocument(const OUString& rFile) const
2348 : : {
2349 : 105 : return getOwnDocumentName().equals(rFile);
2350 : : }
2351 : :
2352 : 105 : void ScExternalRefManager::convertToAbsName(OUString& rFile) const
2353 : : {
2354 : : // unsaved documents have no AbsName
2355 [ + - ]: 105 : TypeId aType(TYPE(ScDocShell));
2356 [ + - ]: 105 : ScDocShell* pShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType, false));
2357 [ + + ]: 2880 : while (pShell)
2358 : : {
2359 [ + - ][ + - ]: 2775 : if (rFile == rtl::OUString(pShell->GetName()))
[ + - ]
2360 : 105 : return;
2361 : :
2362 [ + - ]: 2775 : pShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pShell, &aType, false));
2363 : : }
2364 : :
2365 : 105 : SfxObjectShell* pDocShell = mpDoc->GetDocumentShell();
2366 [ + - ][ + - ]: 105 : rFile = ScGlobal::GetAbsDocName(rFile, pDocShell);
[ + - ][ + - ]
[ + - ]
2367 : : }
2368 : :
2369 : 122 : sal_uInt16 ScExternalRefManager::getExternalFileId(const OUString& rFile)
2370 : : {
2371 [ + - ][ + - ]: 122 : vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
2372 [ + - ]: 122 : vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
2373 [ + - ][ + + ]: 122 : if (itr != itrEnd)
2374 : : {
2375 [ + - ]: 111 : size_t nId = distance(itrBeg, itr);
2376 : 111 : return static_cast<sal_uInt16>(nId);
2377 : : }
2378 : :
2379 [ + - ]: 11 : SrcFileData aData;
2380 : 11 : aData.maFileName = rFile;
2381 [ + - ]: 11 : maSrcFiles.push_back(aData);
2382 [ + - ]: 122 : return static_cast<sal_uInt16>(maSrcFiles.size() - 1);
2383 : : }
2384 : :
2385 : 299 : const OUString* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId, bool bForceOriginal)
2386 : : {
2387 [ - + ]: 299 : if (nFileId >= maSrcFiles.size())
2388 : 0 : return NULL;
2389 : :
2390 [ - + ]: 299 : if (bForceOriginal)
2391 : 0 : return &maSrcFiles[nFileId].maFileName;
2392 : :
2393 : 299 : maybeCreateRealFileName(nFileId);
2394 : :
2395 [ - + ]: 299 : if (!maSrcFiles[nFileId].maRealFileName.isEmpty())
2396 : 0 : return &maSrcFiles[nFileId].maRealFileName;
2397 : :
2398 : 299 : return &maSrcFiles[nFileId].maFileName;
2399 : : }
2400 : :
2401 : 0 : bool ScExternalRefManager::hasExternalFile(sal_uInt16 nFileId) const
2402 : : {
2403 : 0 : return nFileId < maSrcFiles.size();
2404 : : }
2405 : :
2406 : 0 : bool ScExternalRefManager::hasExternalFile(const OUString& rFile) const
2407 : : {
2408 : 0 : vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
2409 [ # # ]: 0 : vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
2410 [ # # ]: 0 : return itr != itrEnd;
2411 : : }
2412 : :
2413 : 6 : const ScExternalRefManager::SrcFileData* ScExternalRefManager::getExternalFileData(sal_uInt16 nFileId) const
2414 : : {
2415 [ - + ]: 6 : if (nFileId >= maSrcFiles.size())
2416 : 0 : return NULL;
2417 : :
2418 : 6 : return &maSrcFiles[nFileId];
2419 : : }
2420 : :
2421 : 87 : const OUString* ScExternalRefManager::getRealTableName(sal_uInt16 nFileId, const OUString& rTabName) const
2422 : : {
2423 : 87 : return maRefCache.getRealTableName(nFileId, rTabName);
2424 : : }
2425 : :
2426 : 0 : const OUString* ScExternalRefManager::getRealRangeName(sal_uInt16 nFileId, const OUString& rRangeName) const
2427 : : {
2428 : 0 : return maRefCache.getRealRangeName(nFileId, rRangeName);
2429 : : }
2430 : :
2431 : : template<typename MapContainer>
2432 : 0 : void lcl_removeByFileId(sal_uInt16 nFileId, MapContainer& rMap)
2433 : : {
2434 [ # # ]: 0 : typename MapContainer::iterator itr = rMap.find(nFileId);
2435 [ # # ][ # # ]: 0 : if (itr != rMap.end())
2436 : : {
2437 : : // Close this document shell.
2438 [ # # ][ # # ]: 0 : itr->second.maShell->DoClose();
2439 [ # # ]: 0 : rMap.erase(itr);
2440 : : }
2441 : 0 : }
2442 : :
2443 : 3 : void ScExternalRefManager::clearCache(sal_uInt16 nFileId)
2444 : : {
2445 : 3 : maRefCache.clearCache(nFileId);
2446 : 3 : }
2447 : :
2448 : 0 : void ScExternalRefManager::refreshNames(sal_uInt16 nFileId)
2449 : : {
2450 : 0 : clearCache(nFileId);
2451 : 0 : lcl_removeByFileId(nFileId, maDocShells);
2452 : :
2453 [ # # ]: 0 : if (maDocShells.empty())
2454 : 0 : maSrcDocTimer.Stop();
2455 : :
2456 : : // Update all cells containing names from this source document.
2457 : 0 : refreshAllRefCells(nFileId);
2458 : :
2459 : 0 : notifyAllLinkListeners(nFileId, LINK_MODIFIED);
2460 : 0 : }
2461 : :
2462 : 0 : void ScExternalRefManager::breakLink(sal_uInt16 nFileId)
2463 : : {
2464 : : // Turn all formula cells referencing this external document into static
2465 : : // cells.
2466 [ # # ]: 0 : RefCellMap::iterator itrRefs = maRefCells.find(nFileId);
2467 [ # # ][ # # ]: 0 : if (itrRefs != maRefCells.end())
2468 : : {
2469 : : // Make a copy because removing the formula cells below will modify
2470 : : // the original container.
2471 [ # # ][ # # ]: 0 : RefCellSet aSet = itrRefs->second;
2472 [ # # ]: 0 : for_each(aSet.begin(), aSet.end(), ConvertFormulaToStatic(mpDoc));
2473 [ # # ]: 0 : maRefCells.erase(nFileId);
2474 : : }
2475 : :
2476 : : // Remove all named ranges that reference this document.
2477 : :
2478 : : // Global named ranges.
2479 [ # # ]: 0 : ScRangeName* pRanges = mpDoc->GetRangeName();
2480 [ # # ]: 0 : if (pRanges)
2481 [ # # ]: 0 : removeRangeNamesBySrcDoc(*pRanges, nFileId);
2482 : :
2483 : : // Sheet-local named ranges.
2484 [ # # ][ # # ]: 0 : for (SCTAB i = 0, n = mpDoc->GetTableCount(); i < n; ++i)
2485 : : {
2486 [ # # ]: 0 : pRanges = mpDoc->GetRangeName(i);
2487 [ # # ]: 0 : if (pRanges)
2488 [ # # ]: 0 : removeRangeNamesBySrcDoc(*pRanges, nFileId);
2489 : : }
2490 : :
2491 [ # # ]: 0 : clearCache(nFileId);
2492 [ # # ]: 0 : lcl_removeByFileId(nFileId, maDocShells);
2493 : :
2494 [ # # ]: 0 : if (maDocShells.empty())
2495 [ # # ]: 0 : maSrcDocTimer.Stop();
2496 : :
2497 [ # # ]: 0 : LinkedDocMap::iterator itr = maLinkedDocs.find(nFileId);
2498 [ # # ][ # # ]: 0 : if (itr != maLinkedDocs.end())
2499 [ # # ]: 0 : itr->second = false;
2500 : :
2501 [ # # ]: 0 : notifyAllLinkListeners(nFileId, LINK_BROKEN);
2502 : 0 : }
2503 : :
2504 : 0 : void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const OUString& rNewFile, const OUString& rNewFilter)
2505 : : {
2506 : 0 : maSrcFiles[nFileId].maFileName = rNewFile;
2507 [ # # ]: 0 : maSrcFiles[nFileId].maRelativeName = OUString();
2508 [ # # ]: 0 : maSrcFiles[nFileId].maRealFileName = OUString();
2509 [ # # ]: 0 : if (!maSrcFiles[nFileId].maFilterName.equals(rNewFilter))
2510 : : {
2511 : : // Filter type has changed.
2512 : 0 : maSrcFiles[nFileId].maFilterName = rNewFilter;
2513 [ # # ]: 0 : maSrcFiles[nFileId].maFilterOptions = OUString();
2514 : : }
2515 : 0 : refreshNames(nFileId);
2516 : 0 : }
2517 : :
2518 : 0 : void ScExternalRefManager::setRelativeFileName(sal_uInt16 nFileId, const OUString& rRelUrl)
2519 : : {
2520 [ # # ]: 0 : if (nFileId >= maSrcFiles.size())
2521 : 0 : return;
2522 : 0 : maSrcFiles[nFileId].maRelativeName = rRelUrl;
2523 : : }
2524 : :
2525 : 0 : void ScExternalRefManager::setFilterData(sal_uInt16 nFileId, const OUString& rFilterName, const OUString& rOptions)
2526 : : {
2527 [ # # ]: 0 : if (nFileId >= maSrcFiles.size())
2528 : 0 : return;
2529 : 0 : maSrcFiles[nFileId].maFilterName = rFilterName;
2530 : 0 : maSrcFiles[nFileId].maFilterOptions = rOptions;
2531 : : }
2532 : :
2533 : 262 : void ScExternalRefManager::clear()
2534 : : {
2535 [ + - ]: 262 : DocShellMap::iterator itrEnd = maDocShells.end();
2536 [ + - ][ - + ]: 262 : for (DocShellMap::iterator itr = maDocShells.begin(); itr != itrEnd; ++itr)
2537 [ # # ][ # # ]: 0 : itr->second.maShell->DoClose();
2538 : :
2539 [ + - ]: 262 : maDocShells.clear();
2540 [ + - ]: 262 : maSrcDocTimer.Stop();
2541 : 262 : }
2542 : :
2543 : 243 : bool ScExternalRefManager::hasExternalData() const
2544 : : {
2545 : 243 : return !maSrcFiles.empty();
2546 : : }
2547 : :
2548 : 4 : void ScExternalRefManager::resetSrcFileData(const OUString& rBaseFileUrl)
2549 : : {
2550 [ # # ][ + - ]: 4 : for (vector<SrcFileData>::iterator itr = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
[ - + ]
2551 : : itr != itrEnd; ++itr)
2552 : : {
2553 : : // Re-generate relative file name from the absolute file name.
2554 [ # # ]: 0 : OUString aAbsName = itr->maRealFileName;
2555 [ # # ]: 0 : if (aAbsName.isEmpty())
2556 [ # # ]: 0 : aAbsName = itr->maFileName;
2557 : :
2558 [ # # ]: 0 : itr->maRelativeName = URIHelper::simpleNormalizedMakeRelative(
2559 [ # # ]: 0 : rBaseFileUrl, aAbsName);
2560 : 0 : }
2561 : 4 : }
2562 : :
2563 : 229 : void ScExternalRefManager::removeRefCell(ScFormulaCell* pCell)
2564 : : {
2565 [ + - ][ + - ]: 229 : for_each(maRefCells.begin(), maRefCells.end(), RemoveFormulaCell(pCell));
[ + - ]
2566 : 229 : }
2567 : :
2568 : 0 : void ScExternalRefManager::addLinkListener(sal_uInt16 nFileId, LinkListener* pListener)
2569 : : {
2570 [ # # ]: 0 : LinkListenerMap::iterator itr = maLinkListeners.find(nFileId);
2571 [ # # ][ # # ]: 0 : if (itr == maLinkListeners.end())
2572 : : {
2573 : : pair<LinkListenerMap::iterator, bool> r = maLinkListeners.insert(
2574 [ # # ][ # # ]: 0 : LinkListenerMap::value_type(nFileId, LinkListeners()));
[ # # ][ # # ]
[ # # ]
2575 [ # # ]: 0 : if (!r.second)
2576 : : {
2577 : : OSL_FAIL("insertion of new link listener list failed");
2578 : 0 : return;
2579 : : }
2580 : :
2581 : 0 : itr = r.first;
2582 : : }
2583 : :
2584 [ # # ]: 0 : LinkListeners& rList = itr->second;
2585 [ # # ]: 0 : rList.insert(pListener);
2586 : : }
2587 : :
2588 : 0 : void ScExternalRefManager::removeLinkListener(sal_uInt16 nFileId, LinkListener* pListener)
2589 : : {
2590 [ # # ]: 0 : LinkListenerMap::iterator itr = maLinkListeners.find(nFileId);
2591 [ # # ][ # # ]: 0 : if (itr == maLinkListeners.end())
2592 : : // no listeners for a specified file.
2593 : 0 : return;
2594 : :
2595 [ # # ]: 0 : LinkListeners& rList = itr->second;
2596 [ # # ]: 0 : rList.erase(pListener);
2597 : :
2598 [ # # ]: 0 : if (rList.empty())
2599 : : // No more listeners for this file. Remove its entry.
2600 [ # # ]: 0 : maLinkListeners.erase(itr);
2601 : : }
2602 : :
2603 : 0 : void ScExternalRefManager::removeLinkListener(LinkListener* pListener)
2604 : : {
2605 [ # # ][ # # ]: 0 : LinkListenerMap::iterator itr = maLinkListeners.begin(), itrEnd = maLinkListeners.end();
2606 [ # # ]: 0 : for (; itr != itrEnd; ++itr)
2607 [ # # ][ # # ]: 0 : itr->second.erase(pListener);
2608 : 0 : }
2609 : :
2610 : 0 : void ScExternalRefManager::notifyAllLinkListeners(sal_uInt16 nFileId, LinkUpdateType eType)
2611 : : {
2612 [ # # ]: 0 : LinkListenerMap::iterator itr = maLinkListeners.find(nFileId);
2613 [ # # ][ # # ]: 0 : if (itr == maLinkListeners.end())
2614 : : // no listeners for a specified file.
2615 : 0 : return;
2616 : :
2617 [ # # ]: 0 : LinkListeners& rList = itr->second;
2618 [ # # ][ # # ]: 0 : for_each(rList.begin(), rList.end(), NotifyLinkListener(nFileId, eType));
[ # # ]
2619 : : }
2620 : :
2621 : 0 : void ScExternalRefManager::purgeStaleSrcDocument(sal_Int32 nTimeOut)
2622 : : {
2623 [ # # ]: 0 : DocShellMap aNewDocShells;
2624 [ # # ][ # # ]: 0 : DocShellMap::iterator itr = maDocShells.begin(), itrEnd = maDocShells.end();
2625 [ # # ]: 0 : for (; itr != itrEnd; ++itr)
2626 : : {
2627 : : // in 100th of a second.
2628 [ # # ][ # # ]: 0 : sal_Int32 nSinceLastAccess = (Time( Time::SYSTEM ) - itr->second.maLastAccess).GetTime();
[ # # ]
2629 [ # # ]: 0 : if (nSinceLastAccess < nTimeOut)
2630 [ # # ][ # # ]: 0 : aNewDocShells.insert(*itr);
2631 : : else
2632 : : // Timed out. Let's close this.
2633 [ # # ][ # # ]: 0 : itr->second.maShell->DoClose();
2634 : : }
2635 [ # # ]: 0 : maDocShells.swap(aNewDocShells);
2636 : :
2637 [ # # ]: 0 : if (maDocShells.empty())
2638 [ # # ][ # # ]: 0 : maSrcDocTimer.Stop();
2639 : 0 : }
2640 : :
2641 : 156 : sal_uInt32 ScExternalRefManager::getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, const ScDocument* pSrcDoc)
2642 : : {
2643 [ + - ]: 156 : NumFmtMap::iterator itr = maNumFormatMap.find(nFileId);
2644 [ + - ][ + + ]: 156 : if (itr == maNumFormatMap.end())
2645 : : {
2646 : : // Number formatter map is not initialized for this external document.
2647 : : pair<NumFmtMap::iterator, bool> r = maNumFormatMap.insert(
2648 [ + - ][ + - ]: 6 : NumFmtMap::value_type(nFileId, SvNumberFormatterMergeMap()));
2649 : :
2650 [ - + ]: 6 : if (!r.second)
2651 : : // insertion failed.
2652 : 0 : return nNumFmt;
2653 : :
2654 : 6 : itr = r.first;
2655 [ + - ][ + - ]: 6 : mpDoc->GetFormatTable()->MergeFormatter( *pSrcDoc->GetFormatTable());
[ + - ]
2656 [ + - ][ + - ]: 6 : SvNumberFormatterMergeMap aMap = mpDoc->GetFormatTable()->ConvertMergeTableToMap();
2657 [ + - ][ + - ]: 6 : itr->second.swap(aMap);
2658 : : }
2659 [ + - ]: 156 : const SvNumberFormatterMergeMap& rMap = itr->second;
2660 [ + - ]: 156 : SvNumberFormatterMergeMap::const_iterator itrNumFmt = rMap.find(nNumFmt);
2661 [ + - ][ - + ]: 156 : if (itrNumFmt != rMap.end())
2662 : : // mapped value found.
2663 [ # # ]: 0 : return itrNumFmt->second;
2664 : :
2665 : 156 : return nNumFmt;
2666 : : }
2667 : :
2668 : 0 : void ScExternalRefManager::transformUnsavedRefToSavedRef( SfxObjectShell* pShell )
2669 : : {
2670 [ # # ]: 0 : DocShellMap::iterator itr = maUnsavedDocShells.begin();
2671 [ # # ][ # # ]: 0 : while( itr != maUnsavedDocShells.end() )
2672 : : {
2673 [ # # ][ # # ]: 0 : if (&(itr->second.maShell) == pShell)
2674 : : {
2675 : : // found that the shell is marked as unsaved
2676 [ # # ][ # # ]: 0 : rtl::OUString aFileURL = pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
2677 [ # # ][ # # ]: 0 : switchSrcFile(itr->first, aFileURL, rtl::OUString());
2678 [ # # ]: 0 : EndListening(*pShell);
2679 [ # # ][ # # ]: 0 : maUnsavedDocShells.erase(itr++);
2680 : : }
2681 : : }
2682 : 0 : }
2683 : :
2684 : 0 : void ScExternalRefManager::Notify( SfxBroadcaster&, const SfxHint& rHint )
2685 : : {
2686 [ # # ]: 0 : if ( rHint.ISA( SfxEventHint ) )
2687 : : {
2688 : 0 : sal_uLong nEventId = ((SfxEventHint&)rHint).GetEventId();
2689 [ # # # ]: 0 : switch ( nEventId )
2690 : : {
2691 : : case SFX_EVENT_PREPARECLOSEDOC:
2692 : : {
2693 : 0 : SfxObjectShell* pObjShell = static_cast<const SfxEventHint&>( rHint ).GetObjShell();
2694 : 0 : ScDocShell* pDocShell = static_cast< ScDocShell* >( pObjShell );
2695 : : WarningBox aBox( pDocShell->GetActiveDialogParent(), WinBits( WB_OK ),
2696 [ # # ][ # # ]: 0 : ScGlobal::GetRscString( STR_CLOSE_WITH_UNSAVED_REFS ) );
[ # # ]
2697 [ # # ][ # # ]: 0 : aBox.Execute();
2698 : : }
2699 : 0 : break;
2700 : : case SFX_EVENT_SAVEDOCDONE:
2701 : : case SFX_EVENT_SAVEASDOCDONE:
2702 : : {
2703 : 0 : SfxObjectShell* pObjShell = static_cast<const SfxEventHint&>( rHint ).GetObjShell();
2704 : 0 : transformUnsavedRefToSavedRef(pObjShell);
2705 : : }
2706 : 0 : break;
2707 : : default:
2708 : 0 : break;
2709 : : }
2710 : : }
2711 : 0 : }
2712 : :
2713 : 0 : IMPL_LINK(ScExternalRefManager, TimeOutHdl, AutoTimer*, pTimer)
2714 : : {
2715 [ # # ]: 0 : if (pTimer == &maSrcDocTimer)
2716 : 0 : purgeStaleSrcDocument(SRCDOC_LIFE_SPAN);
2717 : :
2718 : 0 : return 0;
2719 : : }
2720 : :
2721 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|