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