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