ooo-build r13258 - in trunk: . patches/test
- From: kyoshida svn gnome org
- To: svn-commits-list gnome org
- Subject: ooo-build r13258 - in trunk: . patches/test
- Date: Thu, 17 Jul 2008 00:28:29 +0000 (UTC)
Author: kyoshida
Date: Thu Jul 17 00:28:28 2008
New Revision: 13258
URL: http://svn.gnome.org/viewvc/ooo-build?rev=13258&view=rev
Log:
2008-07-16 Kohei Yoshida <kyoshida novell com>
* patches/test/calc-external-defined-names.diff: more progress - support
for true external single & double ref tokens & Excel export filter.
Modified:
trunk/ChangeLog
trunk/patches/test/calc-external-defined-names.diff
Modified: trunk/patches/test/calc-external-defined-names.diff
==============================================================================
--- trunk/patches/test/calc-external-defined-names.diff (original)
+++ trunk/patches/test/calc-external-defined-names.diff Thu Jul 17 00:28:28 2008
@@ -135,10 +135,10 @@
@return TRUE = Sheet created, rnTab contains valid sheet index. */
diff --git sc/inc/externalrefmgr.hxx sc/inc/externalrefmgr.hxx
new file mode 100644
-index 0000000..303d90b
+index 0000000..2af580a
--- /dev/null
+++ sc/inc/externalrefmgr.hxx
-@@ -0,0 +1,210 @@
+@@ -0,0 +1,217 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -248,11 +248,11 @@
+ typedef ::boost::shared_ptr<ScToken> TokenRef;
+ typedef ::boost::shared_ptr<ScTokenArray> TokenArrayRef;
+
-+ typedef ::std::hash_map<sal_uInt16, SrcDoc > DocShellMap;
-+ typedef ::std::hash_map<ScAddress, TokenRef, AddressHash, ::std::equal_to<ScAddress> > SingleTokenMap;
-+ typedef ::std::hash_map<ScRange, TokenArrayRef, RangeHash, ::std::equal_to<ScRange> > DoubleTokenMap;
-+ typedef ::std::hash_map<String, TokenArrayRef, ScStringHashCode, ::std::equal_to<String> > RangeNameMap;
-+ typedef ::std::hash_set<sal_uInt16, ScStringHashCode, ::std::equal_to<String> > LinkedDocSet;
++ typedef ::std::hash_map<sal_uInt16, SrcDoc> DocShellMap;
++ typedef ::std::hash_map<ScAddress, TokenRef, AddressHash, ::std::equal_to<ScAddress> > SingleTokenMap;
++ typedef ::std::hash_map<ScRange, TokenArrayRef, RangeHash, ::std::equal_to<ScRange> > DoubleTokenMap;
++ typedef ::std::hash_map<String, TokenArrayRef, ScStringHashCode, ::std::equal_to<String> > RangeNameMap;
++ typedef ::std::hash_set<sal_uInt16, ScStringHashCode> LinkedDocSet;
+
+ typedef ::std::hash_set<ScAddress, AddressHash, ::std::equal_to<ScAddress> > RefCellSet;
+ typedef ::std::hash_map<sal_uInt16, RefCellSet> RefCellMap;
@@ -265,6 +265,7 @@
+ SingleTokenMap maSingleTokens;
+ DoubleTokenMap maDoubleTokens;
+ RangeNameMap maRangeNames;
++ ::std::vector<String> maTableNames;
+ };
+ typedef ::boost::shared_ptr<DocCache> DocCacheRef;
+ typedef ::std::hash_map<sal_uInt16, DocCacheRef> DocCacheMap;
@@ -273,19 +274,25 @@
+ explicit ScExternalRefManager(ScDocument* pDoc);
+ ~ScExternalRefManager();
+
-+ ScToken* getSingleRefToken(sal_uInt16 nFileId, const ScAddress& rCell, const ScAddress& rCurPos);
-+ ScTokenArray* getDoubleRefTokens(sal_uInt16 nFileId, const ScRange& rRange, const ScAddress& rCurPos);
++ ScToken* getSingleRefToken(sal_uInt16 nFileId, const ScAddress& rCell, const ScAddress* pCurPos);
++ ScTokenArray* getDoubleRefTokens(sal_uInt16 nFileId, const ScRange& rRange, const ScAddress* pCurPos);
+
+ /**
+ * Get an array of tokens corresponding with a specified name in a
+ * specified file.
++ *
++ * @param pCurPos currnet cell address where this name token is used.
++ * This is purely to keep track of all cells containing
++ * external names for refreshing purposes. If this is
++ * NULL, then the cell will not be added to the list.
+ *
-+ * @return ScTokenArray instance
++ * @return array of tokens composing the name
+ */
-+ ScTokenArray* getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress& rCurPos);
++ ScTokenArray* getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos = NULL);
+
+ sal_uInt16 getExternalFileId(const String& rFile);
-+ const String* getExternalFileName(sal_uInt16 nIndex) const;
++ const String* getExternalFileName(sal_uInt16 nFileId) const;
++ const String* getExternalTableName(sal_uInt16 nFileId, SCTAB nTabId);
+
+ void refreshNames(sal_uInt16 nFileId);
+ void switchSrcFile(sal_uInt16 nFileId, const String& rNewFile);
@@ -362,7 +369,7 @@
ocIf = SC_OPCODE_IF,
ocChose = SC_OPCODE_CHOSE,
diff --git sc/inc/token.hxx sc/inc/token.hxx
-index 23decd6..01e67ca 100644
+index 23decd6..1181360 100644
--- sc/inc/token.hxx
+++ sc/inc/token.hxx
@@ -64,7 +64,7 @@ enum StackVarEnum
@@ -374,15 +381,55 @@
svError, // error token
svMissing = 0x70, // 0 or ""
svUnknown // unknown StackType
-@@ -447,6 +447,21 @@ public:
+@@ -447,6 +447,61 @@ public:
};
++class ScExternalSingleRefToken : public ScOpToken
++{
++private:
++ sal_uInt16 mnFileId;
++ SingleRefData maSingleRef;
++
++ ScExternalSingleRefToken(); // disabled
++public:
++ ScExternalSingleRefToken( sal_uInt16 nFileId, const SingleRefData& r );
++ ScExternalSingleRefToken( const ScExternalSingleRefToken& r );
++ virtual ~ScExternalSingleRefToken();
++
++ virtual USHORT GetIndex() const;
++ virtual const SingleRefData& GetSingleRef() const;
++ virtual SingleRefData& GetSingleRef();
++ virtual BOOL operator==( const ScToken& rToken ) const;
++};
++
++
++class ScExternalDoubleRefToken : public ScOpToken
++{
++private:
++ sal_uInt16 mnFileId;
++ ComplRefData maDoubleRef;
++
++ ScExternalDoubleRefToken(); // disabled
++public:
++ ScExternalDoubleRefToken( sal_uInt16 nFileId, const ComplRefData& r );
++ ScExternalDoubleRefToken( const ScExternalDoubleRefToken& r );
++ virtual ~ScExternalDoubleRefToken();
++
++ virtual USHORT GetIndex() const;
++ virtual const ComplRefData& GetDoubleRef() const;
++ virtual ComplRefData& GetDoubleRef();
++ virtual BOOL operator==( const ScToken& rToken ) const;
++};
++
++
+class ScExternalNameToken : public ScOpToken
+{
+private:
+ sal_uInt16 mnFileId;
+ String maName;
++private:
++ ScExternalNameToken(); // disabled
+public:
+ ScExternalNameToken( sal_uInt16 nFileId, const String& rName );
+ ScExternalNameToken( const ScExternalNameToken& r );
@@ -479,7 +526,7 @@
const String& rFilterName, const String& rFilterOpt, const String& rTabName )
{
diff --git sc/source/core/tool/compiler.cxx sc/source/core/tool/compiler.cxx
-index 7caea76..10e0ccb 100644
+index 7caea76..c2d36c4 100644
--- sc/source/core/tool/compiler.cxx
+++ sc/source/core/tool/compiler.cxx
@@ -73,9 +73,13 @@
@@ -655,30 +702,77 @@
&& !IsDBRange( aUpper )
&& !IsColRowName( aUpper )
&& !(bMayBeFuncName && IsMacro( aUpper ))
-@@ -3452,6 +3567,22 @@ BOOL ScCompiler::GetToken()
+@@ -3452,6 +3567,69 @@ BOOL ScCompiler::GetToken()
}
if( pToken->GetOpCode() == ocSubTotal )
glSubTotal = TRUE;
+ else if ( pToken->GetOpCode() == ocExternalName )
+ {
++ // Handle external single and double references, or names.
++
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ const String* pFile = pRefMgr->getExternalFileName(pToken->GetIndex());
+ if (!pFile)
+ SetError(errNoName);
+
-+ const String& rName = pToken->GetString();
-+ ScTokenArray* pNew = pRefMgr->getRangeNameTokens(pToken->GetIndex(), rName, aPos);
-+ if (pNew)
++ switch (pToken->GetType())
+ {
-+ PushTokenArray(pNew->Clone(), true);
-+ return GetToken();
++ case svExternalName:
++ {
++ fprintf(stdout, "ScCompiler::GetToken: external name token\n");
++ const String& rName = pToken->GetString();
++ ScTokenArray* pNew = pRefMgr->getRangeNameTokens(pToken->GetIndex(), rName, &aPos);
++ if (pNew)
++ {
++ PushTokenArray(pNew->Clone(), true);
++ return GetToken();
++ }
++ }
++ break;
++ case svSingleRef:
++ {
++ fprintf(stdout, "ScCompiler::GetToken: external single ref (file id = %d)\n", pToken->GetIndex());
++ SingleRefData aData(pToken->GetSingleRef());
++ if (aData.IsTabRel())
++ // external single reference must have an absolute table reference!
++ break;
++
++ aData.CalcAbsIfRel(aPos);
++ ScAddress aAddr(aData.nCol, aData.nRow, aData.nTab);
++ ScToken* pNew = pRefMgr->getSingleRefToken(pToken->GetIndex(), aAddr, &aPos);
++ if (pNew)
++ {
++ pToken = pNew->Clone();
++ return false;
++ }
++ }
++ break;
++ case svDoubleRef:
++ {
++ fprintf(stdout, "ScCompiler::GetToken: external double ref (file id = %d)\n", pToken->GetIndex());
++ ComplRefData aData(pToken->GetDoubleRef());
++ if (aData.Ref1.IsTabRel() || aData.Ref2.IsTabRel())
++ // external double reference must have an absolute table reference!
++ break;
++
++ aData.CalcAbsIfRel(aPos);
++ ScRange aRange(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab,
++ aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab);
++ ScTokenArray* pNew = pRefMgr->getDoubleRefTokens(pToken->GetIndex(), aRange, &aPos);
++ if (pNew)
++ {
++ PushTokenArray(pNew->Clone(), true);
++ return GetToken();
++ }
++ }
++ break;
+ }
+ SetError(errNoName);
+ }
else if( pToken->GetOpCode() == ocName )
{
ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( pToken->GetIndex() );
-@@ -5402,6 +5533,15 @@ ScToken* ScCompiler::CreateStringFromToken( rtl::OUStringBuffer& rBuffer, ScToke
+@@ -5402,6 +5580,15 @@ ScToken* ScCompiler::CreateStringFromToken( rtl::OUStringBuffer& rBuffer, ScToke
BOOL bSpaces = FALSE;
ScToken* t = pTokenP;
OpCode eOp = t->GetOpCode();
@@ -695,7 +789,7 @@
{
// AND, OR infix?
diff --git sc/source/core/tool/token.cxx sc/source/core/tool/token.cxx
-index 7312257..8ccba56 100644
+index 7312257..5d1f006 100644
--- sc/source/core/tool/token.cxx
+++ sc/source/core/tool/token.cxx
@@ -52,6 +52,8 @@
@@ -750,7 +844,43 @@
case svJump :
return new ScJumpToken( eOp, (short*) nJump );
//break;
-@@ -505,6 +527,9 @@ ScToken* ScToken::Clone() const
+@@ -461,6 +483,7 @@ BOOL ScToken::IsMatrixFunction() const
+
+ ScToken* ScToken::Clone() const
+ {
++ OpCode nOp = GetOpCode();
+ switch ( GetType() )
+ {
+ case svByte :
+@@ -470,20 +493,24 @@ ScToken* ScToken::Clone() const
+ return new ScDoubleToken( *static_cast<const ScDoubleToken*>(this) );
+ //break;
+ case svString :
+- if (GetOpCode() == ocPush)
++ if (nOp == ocPush)
+ return new ScStringToken( *static_cast<const ScStringToken*>(this) );
+ else
+ return new ScStringOpToken( *static_cast<const ScStringOpToken*>(this) );
+ //break;
+ case svSingleRef :
+- if (GetOpCode() == ocPush)
++ if (nOp == ocPush)
+ return new ScSingleRefToken( *static_cast<const ScSingleRefToken*>(this) );
++ else if (nOp == ocExternalName)
++ return new ScExternalSingleRefToken( *static_cast<const ScExternalSingleRefToken*>(this) );
+ else
+ return new ScSingleRefOpToken( *static_cast<const ScSingleRefOpToken*>(this) );
+ //break;
+ case svDoubleRef :
+- if (GetOpCode() == ocPush)
++ if (nOp == ocPush)
+ return new ScDoubleRefToken( *static_cast<const ScDoubleRefToken*>(this) );
++ else if (nOp == ocExternalName)
++ return new ScExternalDoubleRefToken( *static_cast<const ScExternalDoubleRefToken*>(this) );
+ else
+ return new ScDoubleRefOpToken( *static_cast<const ScDoubleRefOpToken*>(this) );
+ //break;
+@@ -505,6 +532,9 @@ ScToken* ScToken::Clone() const
case svExternal :
return new ScExternalToken( *static_cast<const ScExternalToken*>(this) );
//break;
@@ -760,19 +890,113 @@
case svFAP :
return new ScFAPToken( *static_cast<const ScFAPToken*>(this) );
//break;
-@@ -1016,6 +1041,56 @@ BOOL ScIndexToken::operator==( const ScToken& r ) const
+@@ -1015,6 +1045,150 @@ BOOL ScIndexToken::operator==( const ScToken& r ) const
+ return ScToken::operator==( r ) && nIndex == r.GetIndex();
}
-
++// ============================================================================
++
++ScExternalSingleRefToken::ScExternalSingleRefToken( sal_uInt16 nFileId, const SingleRefData& r ) :
++ ScOpToken(ocExternalName, svSingleRef),
++ mnFileId(nFileId),
++ maSingleRef(r)
++{
++}
++
++ScExternalSingleRefToken::ScExternalSingleRefToken( const ScExternalSingleRefToken& r ) :
++ ScOpToken(r),
++ mnFileId(r.mnFileId),
++ maSingleRef(r.maSingleRef)
++{
++}
++
++ScExternalSingleRefToken::~ScExternalSingleRefToken()
++{
++}
++
++USHORT ScExternalSingleRefToken::GetIndex() const
++{
++ return mnFileId;
++}
++
++const SingleRefData& ScExternalSingleRefToken::GetSingleRef() const
++{
++ return maSingleRef;
++}
++
++SingleRefData& ScExternalSingleRefToken::GetSingleRef()
++{
++ return maSingleRef;
++}
++
++BOOL ScExternalSingleRefToken::operator ==( const ScToken& r ) const
++{
++ if (!ScToken::operator==(r))
++ return false;
++
++ if (mnFileId != r.GetIndex())
++ return false;
++
++ return maSingleRef == r.GetSingleRef();
++}
++
++// ============================================================================
++
++ScExternalDoubleRefToken::ScExternalDoubleRefToken( sal_uInt16 nFileId, const ComplRefData& r ) :
++ ScOpToken(ocExternalName, svDoubleRef),
++ mnFileId(nFileId),
++ maDoubleRef(r)
++{
++}
++
++ScExternalDoubleRefToken::ScExternalDoubleRefToken( const ScExternalDoubleRefToken& r ) :
++ ScOpToken(r),
++ mnFileId(r.mnFileId),
++ maDoubleRef(r.maDoubleRef)
++{
++}
++
++ScExternalDoubleRefToken::~ScExternalDoubleRefToken()
++{
++}
++
++USHORT ScExternalDoubleRefToken::GetIndex() const
++{
++ return mnFileId;
++}
++
++const ComplRefData& ScExternalDoubleRefToken::GetDoubleRef() const
++{
++ return maDoubleRef;
++}
++
++ComplRefData& ScExternalDoubleRefToken::GetDoubleRef()
++{
++ return maDoubleRef;
++}
++
++BOOL ScExternalDoubleRefToken::operator ==( const ScToken& r ) const
++{
++ if (!ScToken::operator==(r))
++ return false;
++
++ if (mnFileId != r.GetIndex())
++ return false;
++
++ return maDoubleRef == r.GetDoubleRef();
++}
++
++// ============================================================================
++
+ScExternalNameToken::ScExternalNameToken( sal_uInt16 nFileId, const String& rName ) :
-+ ScOpToken( ocExternalName, svExternalName ),
++ ScOpToken(ocExternalName, svExternalName),
+ mnFileId(nFileId),
+ maName(rName)
+{
+}
+
+ScExternalNameToken::ScExternalNameToken( const ScExternalNameToken& r ) :
-+ ScOpToken( r ),
++ ScOpToken(r),
+ mnFileId(r.mnFileId),
+ maName(r.maName)
+{
@@ -813,11 +1037,11 @@
+ return true;
+}
+
-+
++// ============================================================================
+
short* ScJumpToken::GetJump() const { return pJump; }
BOOL ScJumpToken::operator==( const ScToken& r ) const
- {
-@@ -1873,6 +1948,11 @@ ScToken* ScTokenArray::AddMatrix( ScMatrix* p )
+@@ -1873,6 +2047,11 @@ ScToken* ScTokenArray::AddMatrix( ScMatrix* p )
return Add( new ScMatrixToken( p ) );
}
@@ -933,6 +1157,790 @@
}
+diff --git sc/source/filter/excel/xeformula.cxx sc/source/filter/excel/xeformula.cxx
+index c85aad1..ca36c38 100644
+--- sc/source/filter/excel/xeformula.cxx
++++ sc/source/filter/excel/xeformula.cxx
+@@ -42,6 +42,12 @@
+ #include "xelink.hxx"
+ #include "xename.hxx"
+
++#include "document.hxx"
++#include "externalrefmgr.hxx"
++
++#include <memory>
++#include <stdio.h>
++
+ // External reference log =====================================================
+
+ XclExpRefLogEntry::XclExpRefLogEntry() :
+@@ -300,6 +306,7 @@ private:
+ void ProcessBoolean( const XclExpTokenData& rTokData );
+ void ProcessDdeLink( const XclExpTokenData& rTokData, sal_uInt8 nExpClass );
+ void ProcessExternal( const XclExpTokenData& rTokData, sal_uInt8 nExpClass );
++ void ProcessExternalName( const XclExpTokenData& rTokData, sal_uInt8 nExpClass );
+
+ void ProcessFunction( const XclExpTokenData& rTokData, sal_uInt8 nExpClass );
+ void PrepareFunction( XclExpFuncData& rFuncData );
+@@ -1110,11 +1117,18 @@ XclExpTokenData XclExpFmlaCompImpl::RangeTerm( XclExpTokenData aTokData, sal_uIn
+
+ XclExpTokenData XclExpFmlaCompImpl::Factor( XclExpTokenData aTokData, sal_uInt8 nExpClass )
+ {
++ fprintf(stdout, "XclExpFmlaCompImpl::Factor: --begin\n");
+ if( !mbOk || !aTokData.Is() ) return XclExpTokenData();
+
+ StackVar eTokType = aTokData.GetType();
+ OpCode eOpCode = aTokData.GetOpCode();
+
++ if (eOpCode == ocExternalName)
++ {
++ ProcessExternalName( aTokData, nExpClass );
++ return GetNextToken();
++ }
++
+ switch( eTokType )
+ {
+ case svUnknown: mbOk = false; break;
+@@ -1146,6 +1160,7 @@ XclExpTokenData XclExpFmlaCompImpl::Factor( XclExpTokenData aTokData, sal_uInt8
+ }
+ }
+
++ fprintf(stdout, "XclExpFmlaCompImpl::Factor: --end\n");
+ return GetNextToken();
+ }
+
+@@ -1249,6 +1264,72 @@ void XclExpFmlaCompImpl::ProcessExternal( const XclExpTokenData& rTokData, sal_u
+ ProcessFunction( rTokData, nExpClass );
+ }
+
++void XclExpFmlaCompImpl::ProcessExternalName( const XclExpTokenData& rTokData, sal_uInt8 nExpClass )
++{
++ fprintf(stdout, "XclExpFmlaCompImpl::ProcessExternalName: --begin\n");
++ StackVar eType = rTokData.GetType();
++
++ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
++ USHORT nFileId = rTokData.mpScToken->GetIndex();
++ switch (eType)
++ {
++ case svSingleRef:
++ {
++ fprintf(stdout, "XclExpFmlaCompImpl::ProcessExternalName: svSingleRef not supported yet\n");
++ }
++ break;
++ case svDoubleRef:
++ {
++ fprintf(stdout, "XclExpFmlaCompImpl::ProcessExternalName: svDoubleRef not supported yet\n");
++ }
++ break;
++ case svExternalName:
++ {
++ fprintf(stdout, "XclExpFmlaCompImpl::ProcessExternalName: svExternalName\n");
++ const String& aName = rTokData.mpScToken->GetString();
++ fprintf(stdout, "XclExpFmlaCompImpl::ProcessExternalName: file id = %d; name = '%s'\n",
++ nFileId, rtl::OUStringToOString(aName, RTL_TEXTENCODING_UTF8).getStr());
++
++ const String* pFile = pRefMgr->getExternalFileName(nFileId);
++ fprintf(stdout, "XclExpFmlaCompImpl::ProcessExternalName: file name = '%s'\n",
++ rtl::OUStringToOString(*pFile, RTL_TEXTENCODING_UTF8).getStr());
++
++ ScTokenArray* pArray = pRefMgr->getRangeNameTokens(nFileId, aName);
++ if (!pArray || !mpScBasePos)
++ {
++ AppendErrorToken(XclTools::GetXclErrorCode(errNoName), rTokData.mnSpaces);
++ break;
++ }
++
++ ::std::auto_ptr<ScTokenArray> pNew(pArray->Clone());
++ for (ScToken* p = pNew->First(); p; p = pNew->Next())
++ {
++ if (p->GetOpCode() == ocExternalName)
++ {
++ if (p->GetType() == svSingleRef)
++ {
++ SingleRefData aData(p->GetSingleRef());
++ aData.CalcAbsIfRel(*mpScBasePos);
++ mpLinkMgr->StoreCell(nFileId, aData);
++// mpLinkMgr->FindExtSheet(nFileId);
++ }
++ else if (p->GetType() == svDoubleRef)
++ {
++ ComplRefData aData(p->GetDoubleRef());
++ aData.CalcAbsIfRel(*mpScBasePos);
++ mpLinkMgr->StoreCellRange(nFileId, aData);
++// mpLinkMgr->FindExtSheet(nFileId);
++ }
++ }
++ }
++
++ }
++ break;
++ }
++
++ fprintf(stdout, "XclExpFmlaCompImpl::ProcessExternalName: --end\n");
++}
++
+ void XclExpFmlaCompImpl::ProcessFunction( const XclExpTokenData& rTokData, sal_uInt8 nExpClass )
+ {
+ OpCode eOpCode = rTokData.GetOpCode();
+@@ -1751,6 +1832,9 @@ XclExpRefLogEntry* XclExpFmlaCompImpl::GetNewRefLogEntry()
+
+ void XclExpFmlaCompImpl::ProcessCellRef( const XclExpTokenData& rTokData, sal_uInt8 nExpClass )
+ {
++ fprintf(stdout, "XclExpFmlaCompImpl::ProcessCellRef: --begin (type = %d; opcode = %d)\n",
++ rTokData.GetType(), rTokData.GetOpCode());
++
+ // get the Excel address components, adjust internal data in aRefData
+ bool bNatLangRef = (meBiff == EXC_BIFF8) && mpScBasePos && (rTokData.GetOpCode() == ocColRowName);
+ SingleRefData aRefData( rTokData.mpScToken->GetSingleRef() );
+@@ -1771,7 +1855,10 @@ void XclExpFmlaCompImpl::ProcessCellRef( const XclExpTokenData& rTokData, sal_uI
+ {
+ // store external cell contents in CRN records
+ if( maCfg.mbFromCell && mpLinkMgr && mpScBasePos )
++ {
++ fprintf(stdout, "XclExpFmlaCompImpl::ProcessCellRef: store external cell contents in CRN records\n");
+ mpLinkMgr->StoreCell( aRefData );
++ }
+
+ // create the tRef, tRefErr, tRefN, tRef3d, or tRefErr3d token
+ if( !maCfg.mb3DRefOnly && IsRef2D( aRefData ) )
+@@ -1805,6 +1892,7 @@ void XclExpFmlaCompImpl::ProcessCellRef( const XclExpTokenData& rTokData, sal_uI
+ AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
+ }
+ }
++ fprintf(stdout, "XclExpFmlaCompImpl::ProcessCellRef: --end\n");
+ }
+
+ void XclExpFmlaCompImpl::ProcessRangeRef( const XclExpTokenData& rTokData, sal_uInt8 nExpClass )
+diff --git sc/source/filter/excel/xelink.cxx sc/source/filter/excel/xelink.cxx
+index b1bacad..660f944 100644
+--- sc/source/filter/excel/xelink.cxx
++++ sc/source/filter/excel/xelink.cxx
+@@ -38,6 +38,15 @@
+ #include "document.hxx"
+ #include "cell.hxx"
+ #include "scextopt.hxx"
++#include "externalrefmgr.hxx"
++
++#include <vector>
++#include <memory>
++#include <stdio.h>
++
++using ::std::auto_ptr;
++using ::std::find_if;
++using ::std::vector;
+
+ // ============================================================================
+ // *** Helper classes ***
+@@ -220,6 +229,9 @@ public:
+ /** Stores all cells in the given range in the CRN list. */
+ void StoreCellRange( const XclExpRoot& rRoot, const ScRange& rRange );
+
++ void StoreCell( const XclExpRoot& rRoot, const ScAddress& rCell, const ScToken& rToken );
++ void StoreCellRange( const XclExpRoot& rRoot, const ScRange& rRange, const ScToken& rToken );
++
+ /** Writes the XCT and all CRN records. */
+ virtual void Save( XclExpStream& rStrm );
+
+@@ -319,6 +331,11 @@ public:
+ /** Stores all cells in the given range in the CRN list of the specified SUPBOOK sheet. */
+ void StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab );
+
++ void StoreCell( sal_uInt16 nSBTab, const ScAddress& rCell, const ScToken& rToken );
++ void StoreCellRange( sal_uInt16 nSBTab, const ScRange& rRange, const ScToken& rToken );
++
++ sal_uInt16 GetTabIndex( const String& rTabName );
++
+ /** Inserts a new sheet name into the SUPBOOK and returns the SUPBOOK internal sheet index. */
+ sal_uInt16 InsertTabName( const String& rTabName );
+ /** Finds or inserts an EXTERNNAME record for add-ins.
+@@ -394,6 +411,9 @@ public:
+ /** Stores all cells in the given range in a CRN record list. */
+ void StoreCellRange( const ScRange& rRange );
+
++ void StoreCell( sal_uInt16 nFileId, const ScAddress& rCell );
++ void StoreCellRange( sal_uInt16 nFileId, const ScRange& rRange );
++
+ /** Finds or inserts an EXTERNNAME record for an add-in function name.
+ @param rnSupbook Returns the index of the SUPBOOK record which contains the add-in function name.
+ @param rnExtName Returns the 1-based EXTERNNAME record index. */
+@@ -410,6 +430,15 @@ public:
+ /** Writes all SUPBOOK records with their sub records. */
+ virtual void Save( XclExpStream& rStrm );
+
++ struct XclExpSBIndex
++ {
++ sal_uInt16 mnSupbook; /// SUPBOOK index for an Excel sheet.
++ sal_uInt16 mnSBTab; /// Sheet name index in SUPBOOK for an Excel sheet.
++ inline void Set( sal_uInt16 nSupbook, sal_uInt16 nSBTab )
++ { mnSupbook = nSupbook; mnSBTab = nSBTab; }
++ };
++ typedef ::std::vector< XclExpSBIndex > XclExpSBIndexVec;
++
+ private:
+ typedef XclExpRecordList< XclExpSupbook > XclExpSupbookList;
+ typedef XclExpSupbookList::RecordRefType XclExpSupbookRef;
+@@ -435,15 +464,6 @@ private:
+ void AddExtSupbook( SCTAB nScTab );
+
+ private:
+- struct XclExpSBIndex
+- {
+- sal_uInt16 mnSupbook; /// SUPBOOK index for an Excel sheet.
+- sal_uInt16 mnSBTab; /// Sheet name in SUPBOOK for an Excel sheet.
+- inline void Set( sal_uInt16 nSupbook, sal_uInt16 nSBTab )
+- { mnSupbook = nSupbook; mnSBTab = nSBTab; }
+- };
+- typedef ::std::vector< XclExpSBIndex > XclExpSBIndexVec;
+-
+ XclExpSupbookList maSupbookList; /// List of all SUPBOOK records.
+ XclExpSBIndexVec maSBIndexVec; /// SUPBOOK and sheet name index for each Excel sheet.
+ sal_uInt16 mnOwnDocSB; /// Index to SUPBOOK for own document.
+@@ -467,6 +487,9 @@ public:
+ /** Derived classes store all cells in the given range in a CRN record list. */
+ virtual void StoreCellRange( const SingleRefData& rRef1, const SingleRefData& rRef2 ) = 0;
+
++ virtual void StoreCell( sal_uInt16 nFileId, const SingleRefData& rRef ) = 0;
++ virtual void StoreCellRange( sal_uInt16 nFileId, const SingleRefData& rRef1, const SingleRefData& rRef2 ) = 0;
++
+ /** Derived classes find or insert an EXTERNNAME record for an add-in function name. */
+ virtual bool InsertAddIn(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
+@@ -499,6 +522,9 @@ public:
+
+ virtual void StoreCellRange( const SingleRefData& rRef1, const SingleRefData& rRef2 );
+
++ virtual void StoreCell( sal_uInt16 nFileId, const SingleRefData& rRef );
++ virtual void StoreCellRange( sal_uInt16 nFileId, const SingleRefData& rRef1, const SingleRefData& rRef2 );
++
+ virtual bool InsertAddIn(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
+ const String& rName );
+@@ -552,6 +578,9 @@ public:
+
+ virtual void StoreCellRange( const SingleRefData& rRef1, const SingleRefData& rRef2 );
+
++ virtual void StoreCell( sal_uInt16 nFileId, const SingleRefData& rRef );
++ virtual void StoreCellRange( sal_uInt16 nFileId, const SingleRefData& rRef1, const SingleRefData& rRef2 );
++
+ virtual bool InsertAddIn(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
+ const String& rName );
+@@ -1013,6 +1042,8 @@ XclExpXct::XclExpXct( const String& rTabName, sal_uInt16 nSBTab ) :
+ maTabName( rTabName ),
+ mnSBTab( nSBTab )
+ {
++ fprintf(stdout, "XclExpXct::XclExpXct: sheet name = '%s'; supbook sheet index = %d\n",
++ rtl::OUStringToOString(rTabName, RTL_TEXTENCODING_UTF8).getStr(), nSBTab);
+ }
+
+ void XclExpXct::StoreCellRange( const XclExpRoot& rRoot, const ScRange& rRange )
+@@ -1066,6 +1097,83 @@ void XclExpXct::StoreCellRange( const XclExpRoot& rRoot, const ScRange& rRange )
+ maUsedCells.SetMultiMarkArea( rRange );
+ }
+
++void XclExpXct::StoreCell( const XclExpRoot& rRoot, const ScAddress& rCell, const ScToken& rToken )
++{
++ fprintf(stdout, "XclExpXct::StoreCell: --begin\n");
++ switch (rToken.GetType())
++ {
++ case svString:
++ {
++ XclExpCrnRef xCrn(
++ new XclExpCrnString(rCell.Col(), rCell.Row(), rToken.GetString()));
++ maCrnList.AppendRecord(xCrn);
++ }
++ break;
++ case svDouble:
++ {
++ XclExpCrnRef xCrn(
++ new XclExpCrnDouble(rCell.Col(), rCell.Row(), rToken.GetDouble()));
++ maCrnList.AppendRecord(xCrn);
++ }
++ break;
++ case svEmptyCell:
++ {
++ XclExpCrnRef xCrn(
++ new XclExpCrnDouble(rCell.Col(), rCell.Row(), 0.0));
++ maCrnList.AppendRecord(xCrn);
++ }
++ break;
++ }
++ fprintf(stdout, "XclExpXct::StoreCell: --end\n");
++}
++
++void XclExpXct::StoreCellRange( const XclExpRoot& rRoot, const ScRange& rRange, const ScToken& rToken )
++{
++ fprintf(stdout, "XclExpXct::StoreCellRange: --begin\n");
++ if (rToken.GetType() != svMatrix)
++ return;
++
++ if (rRange.aStart.Tab() != rRange.aEnd.Tab())
++ return;
++
++ const ScMatrix* pMtx = rToken.GetMatrix();
++ if (!pMtx)
++ return;
++
++ SCSIZE nCols, nRows;
++ pMtx->GetDimensions(nCols, nRows);
++ fprintf(stdout, "XclExpXct::StoreCellRange: cols = %d; rows = %d\n", nCols, nRows);
++ const ScAddress& s = rRange.aStart;
++ const ScAddress& e = rRange.aEnd;
++ if (nCols != e.Col() - s.Col() + 1 || nRows != e.Row() - s.Row() + 1)
++ {
++ // size mis-match!
++ fprintf(stdout, "XclExpXct::StoreCellRange: matrix and range sizes differ!\n");
++ return;
++ }
++
++ for (SCSIZE nCol = 0; nCol < nCols; ++nCol)
++ {
++ for (SCSIZE nRow = 0; nRow < nRows; ++nRow)
++ {
++ if (pMtx->IsString(nCol, nRow))
++ {
++ XclExpCrnRef xCrn(new XclExpCrnString(
++ s.Col() + nCol, s.Row() + nRow, pMtx->GetString(nCol, nRow)));
++ maCrnList.AppendRecord(xCrn);
++ }
++ else if (pMtx->IsValueOrEmpty(nCol, nRow))
++ {
++ XclExpCrnRef xCrn(new XclExpCrnDouble(
++ s.Col() + nCol, s.Row() + nRow, pMtx->GetDouble(nCol, nRow)));
++ maCrnList.AppendRecord(xCrn);
++ }
++ }
++ }
++
++ fprintf(stdout, "XclExpXct::StoreCellRange: --end\n");
++}
++
+ void XclExpXct::Save( XclExpStream& rStrm )
+ {
+ XclExpRecord::Save( rStrm );
+@@ -1206,13 +1314,60 @@ void XclExpSupbook::StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab )
+ xXct->StoreCellRange( GetRoot(), rRange );
+ }
+
++void XclExpSupbook::StoreCell( sal_uInt16 nSBTab, const ScAddress& rCell, const ScToken& rToken )
++{
++ XclExpXctRef xXct = maXctList.GetRecord(nSBTab);
++ if (!xXct.is())
++ return;
++
++ xXct->StoreCell(GetRoot(), rCell, rToken);
++}
++
++void XclExpSupbook::StoreCellRange( sal_uInt16 nSBTab, const ScRange& rRange, const ScToken& rToken )
++{
++ fprintf(stdout, "XclExpSupbook::StoreCellRange: --begin\n");
++ if (rRange.aStart.Tab() != rRange.aEnd.Tab())
++ {
++ // multi-table range is not allowed!
++ fprintf(stdout, "XclExpSupbook::StoreCellRange: multi-table range is not allowed\n");
++ return;
++ }
++
++ XclExpXctRef xXct = maXctList.GetRecord(nSBTab);
++ if (!xXct.is())
++ {
++ fprintf(stdout, "XclExpSupbook::StoreCellRange: no xct instance\n");
++ return;
++ }
++
++ xXct->StoreCellRange(GetRoot(), rRange, rToken);
++ fprintf(stdout, "XclExpSupbook::StoreCellRange: --end\n");
++}
++
++sal_uInt16 XclExpSupbook::GetTabIndex( const String& rTabName )
++{
++ XclExpString aXclName(rTabName);
++ size_t nSize = maXctList.GetSize();
++ for (size_t i = 0; i < nSize; ++i)
++ {
++ XclExpXctRef aRec = maXctList.GetRecord(i);
++ if (aXclName == aRec->GetTabName())
++ return ulimit_cast<sal_uInt16>(i);
++ }
++ return InsertTabName(rTabName);
++}
++
+ sal_uInt16 XclExpSupbook::InsertTabName( const String& rTabName )
+ {
++ fprintf(stdout, "XclExpSupbook::InsertTabName: --begin (sheet name = '%s')\n",
++ rtl::OUStringToOString(rTabName, RTL_TEXTENCODING_UTF8).getStr());
++
+ DBG_ASSERT( meType == EXC_SBTYPE_EXTERN, "XclExpSupbook::InsertTabName - don't insert sheet names here" );
+ sal_uInt16 nSBTab = ulimit_cast< sal_uInt16 >( maXctList.GetSize() );
+ XclExpXctRef xXct( new XclExpXct( rTabName, nSBTab ) );
+ AddRecSize( xXct->GetTabName().GetSize() );
+ maXctList.AppendRecord( xXct );
++ fprintf(stdout, "XclExpSupbook::InsertTabName: --end (sheet index = %d)\n", nSBTab);
+ return nSBTab;
+ }
+
+@@ -1244,6 +1399,13 @@ const XclExpString* XclExpSupbook::GetTabName( sal_uInt16 nSBTab ) const
+
+ void XclExpSupbook::WriteBody( XclExpStream& rStrm )
+ {
++ fprintf(stdout, "XclExpSupbook::WriteBody: --begin\n");
++
++ fprintf(stdout, "XclExpSupbook::WriteBody: url = '%s'\n",
++ rtl::OUStringToOString(maUrl, RTL_TEXTENCODING_UTF8).getStr());
++
++ fprintf(stdout, "XclExpSupbook::WriteBody: sheet count = %d\n", mnXclTabCount);
++
+ switch( meType )
+ {
+ case EXC_SBTYPE_SELF:
+@@ -1265,6 +1427,7 @@ void XclExpSupbook::WriteBody( XclExpStream& rStrm )
+ default:
+ DBG_ERRORFILE( "XclExpSupbook::WriteBody - unknown SUPBOOK type" );
+ }
++ fprintf(stdout, "XclExpSupbook::WriteBody: --end\n");
+ }
+
+ // All SUPBOOKS in a document =================================================
+@@ -1274,11 +1437,15 @@ XclExpSupbookBuffer::XclExpSupbookBuffer( const XclExpRoot& rRoot ) :
+ mnOwnDocSB( SAL_MAX_UINT16 ),
+ mnAddInSB( SAL_MAX_UINT16 )
+ {
++ fprintf(stdout, "XclExpSupbookBuffer::XclExpSupbookBuffer: --begin ctor\n");
++
+ XclExpTabInfo& rTabInfo = GetTabInfo();
+ sal_uInt16 nXclCnt = rTabInfo.GetXclTabCount();
+ sal_uInt16 nCodeCnt = static_cast< sal_uInt16 >( GetExtDocOptions().GetCodeNameCount() );
+ size_t nCount = nXclCnt + rTabInfo.GetXclExtTabCount();
+
++ fprintf(stdout, "XclExpSupbookBuffer::XclExpSupbookBuffer: external tab count = %d\n", nCount);
++
+ DBG_ASSERT( nCount > 0, "XclExpSupbookBuffer::XclExpSupbookBuffer - no sheets to export" );
+ if( nCount )
+ {
+@@ -1288,7 +1455,11 @@ XclExpSupbookBuffer::XclExpSupbookBuffer( const XclExpRoot& rRoot ) :
+ XclExpSupbookRef xSupbook( new XclExpSupbook( GetRoot(), ::std::max( nXclCnt, nCodeCnt ) ) );
+ mnOwnDocSB = Append( xSupbook );
+ for( sal_uInt16 nXclTab = 0; nXclTab < nXclCnt; ++nXclTab )
++ {
++ fprintf(stdout, "XclExpSupbookBuffer::XclExpSupbookBuffer: supbook index = %d; sheet index = %d (internal)\n",
++ mnOwnDocSB, nXclTab);
+ maSBIndexVec[ nXclTab ].Set( mnOwnDocSB, nXclTab );
++ }
+
+ // add SUPBOOKs with external references
+ for( SCTAB nScTab = 0, nScCnt = rTabInfo.GetScTabCount(); nScTab < nScCnt; ++nScTab )
+@@ -1352,6 +1523,147 @@ void XclExpSupbookBuffer::StoreCellRange( const ScRange& rRange )
+ }
+ }
+
++namespace {
++
++class FindSBIndexEntry
++{
++public:
++ explicit FindSBIndexEntry(sal_uInt16 nSupbookId, sal_uInt16 nTabId) :
++ mnSupbookId(nSupbookId), mnTabId(nTabId) {}
++
++ bool operator()(const XclExpSupbookBuffer::XclExpSBIndex& r) const
++ {
++ return mnSupbookId == r.mnSupbook && mnTabId == r.mnSBTab;
++ }
++
++private:
++ sal_uInt16 mnSupbookId;
++ sal_uInt16 mnTabId;
++};
++
++}
++
++void XclExpSupbookBuffer::StoreCell( sal_uInt16 nFileId, const ScAddress& rCell )
++{
++ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
++ const String* pUrl = pRefMgr->getExternalFileName(nFileId);
++ if (!pUrl)
++ return;
++
++ fprintf(stdout, "XclExpSupbookBuffer::StoreCell: --begin (file url = '%s')\n",
++ rtl::OUStringToOString(*pUrl, RTL_TEXTENCODING_UTF8).getStr());
++
++ XclExpSupbookRef xSupbook;
++ sal_uInt16 nSupbookId;
++ if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
++ {
++ fprintf(stdout, "XclExpSupbookBuffer::StoreCellRange: supbook for given url does not exist\n");
++ xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
++ nSupbookId = Append(xSupbook);
++ }
++
++ ScToken* pToken = pRefMgr->getSingleRefToken(nFileId, rCell, NULL);
++ if (!pToken)
++ return;
++
++ const String* pTabName = pRefMgr->getExternalTableName(nFileId, rCell.Tab());
++ if (!pTabName)
++ return;
++
++ fprintf(stdout, "XclExpSupbookBuffer::StoreCell: tab name = '%s'\n",
++ rtl::OUStringToOString(*pTabName, RTL_TEXTENCODING_UTF8).getStr());
++
++ sal_uInt16 nSheetId = xSupbook->GetTabIndex(*pTabName);
++ FindSBIndexEntry f(nSupbookId, nSheetId);
++ XclExpSBIndexVec::iterator itrEnd = maSBIndexVec.end();
++ XclExpSBIndexVec::const_iterator itr = find_if(maSBIndexVec.begin(), itrEnd, f);
++ if (itr == itrEnd)
++ {
++ maSBIndexVec.push_back(XclExpSBIndex());
++ XclExpSBIndex& r = maSBIndexVec.back();
++ r.mnSupbook = nSupbookId;
++ r.mnSBTab = nSheetId;
++ }
++
++ xSupbook->StoreCell(nSheetId, rCell, *pToken);
++}
++
++void XclExpSupbookBuffer::StoreCellRange( sal_uInt16 nFileId, const ScRange& rRange )
++{
++ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
++ const String* pUrl = pRefMgr->getExternalFileName(nFileId);
++ if (!pUrl)
++ return;
++
++ fprintf(stdout, "XclExpSupbookBuffer::StoreCellRange: --begin (file url = '%s')\n",
++ rtl::OUStringToOString(*pUrl, RTL_TEXTENCODING_UTF8).getStr());
++
++ XclExpSupbookRef xSupbook;
++ sal_uInt16 nSupbookId;
++ if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
++ {
++ fprintf(stdout, "XclExpSupbookBuffer::StoreCellRange: supbook for given url does not exist\n");
++ xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
++ nSupbookId = Append(xSupbook);
++ }
++
++ SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
++
++ // If this is a multi-table range, get token for each table.
++ vector<ScToken*> aMatrixList;
++ aMatrixList.reserve(nTab2 - nTab1 + 1);
++ ScTokenArray* pArray = pRefMgr->getDoubleRefTokens(nFileId, rRange, NULL);
++ if (!pArray)
++ return;
++
++ auto_ptr<ScTokenArray> pNew(pArray->Clone());
++ for (ScToken* p = pNew->First(); p; p = pNew->Next())
++ {
++ if (p->GetType() == svMatrix)
++ aMatrixList.push_back(p);
++ else if (p->GetOpCode() != ocSep)
++ {
++ fprintf(stdout, "XclExpSupbookBuffer::StoreCellRange: this is supposed to be ocSep!!!\n");
++ return;
++ }
++ }
++
++ if (aMatrixList.size() != nTab2 - nTab1 + 1)
++ {
++ fprintf(stdout, "XclExpSupbookBuffer::StoreCellRange: matrix size mismatch!\n");
++ return;
++ }
++
++ ScRange aRange(rRange);
++ aRange.aStart.SetTab(0);
++ aRange.aEnd.SetTab(0);
++ for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
++ {
++ const String* pTabName = pRefMgr->getExternalTableName(nFileId, nTab);
++ if (!pTabName)
++ continue;
++
++ fprintf(stdout, "XclExpSupbookBuffer::StoreCellRange: tab name = '%s'\n",
++ rtl::OUStringToOString(*pTabName, RTL_TEXTENCODING_UTF8).getStr());
++
++ sal_uInt16 nSheetId = xSupbook->GetTabIndex(*pTabName);
++ FindSBIndexEntry f(nSupbookId, nSheetId);
++ XclExpSBIndexVec::iterator itrEnd = maSBIndexVec.end();
++ XclExpSBIndexVec::const_iterator itr = find_if(maSBIndexVec.begin(), itrEnd, f);
++ if (itr == itrEnd)
++ {
++ maSBIndexVec.push_back(XclExpSBIndex());
++ XclExpSBIndex& r = maSBIndexVec.back();
++ r.mnSupbook = nSupbookId;
++ r.mnSBTab = nSheetId;
++ }
++
++ xSupbook->StoreCellRange(nSheetId, aRange, *aMatrixList[nTab-nTab1]);
++ }
++
++ fprintf(stdout, "XclExpSupbookBuffer::StoreCellRange: --end\n");
++}
++
+ bool XclExpSupbookBuffer::InsertAddIn(
+ sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const String& rName )
+ {
+@@ -1385,7 +1697,9 @@ bool XclExpSupbookBuffer::InsertDde(
+
+ void XclExpSupbookBuffer::Save( XclExpStream& rStrm )
+ {
++ fprintf(stdout, "XclExpSupbookBuffer::Save: --begin\n");
+ maSupbookList.Save( rStrm );
++ fprintf(stdout, "XclExpSupbookBuffer::Save: --end\n");
+ }
+
+ bool XclExpSupbookBuffer::GetSupbookUrl(
+@@ -1426,11 +1740,17 @@ sal_uInt16 XclExpSupbookBuffer::Append( XclExpSupbookRef xSupbook )
+
+ void XclExpSupbookBuffer::AddExtSupbook( SCTAB nScTab )
+ {
++ fprintf(stdout, "XclExpSupbookBuffer::AddExtSupbook: --begin (sctab = %d)\n", nScTab);
++
+ sal_uInt16 nXclTab = GetTabInfo().GetXclTab( nScTab );
++ fprintf(stdout, "XclExpSupbookBuffer::AddExtSupbook: xlstab = %d\n", nXclTab);
+ DBG_ASSERT( nXclTab < maSBIndexVec.size(), "XclExpSupbookBuffer::AddExtSupbook - out of range" );
+
+ // find ext doc name or append new one, save position in maSBIndexBuffer
+ const String& rUrl = GetDoc().GetLinkDoc( nScTab );
++ fprintf(stdout, "XclExpSupbookBuffer::AddExtSupbook: url = '%s'\n",
++ rtl::OUStringToOString(rUrl, RTL_TEXTENCODING_UTF8).getStr());
++
+ DBG_ASSERT( rUrl.Len(), "XclExpSupbookBuffer::AddExtSupbook - missing external linked sheet" );
+ sal_uInt16 nSupbook;
+ XclExpSupbookRef xSupbook;
+@@ -1439,10 +1759,15 @@ void XclExpSupbookBuffer::AddExtSupbook( SCTAB nScTab )
+ xSupbook.reset( new XclExpSupbook( GetRoot(), rUrl ) );
+ nSupbook = Append( xSupbook );
+ }
++ fprintf(stdout, "XclExpSupbookBuffer::AddExtSupbook: nSupbook = %d\n", nSupbook);
+
+ // append new sheet name, save SUPBOOK and sheet position in maSBIndexVec
+ maSBIndexVec[ nXclTab ].mnSupbook = nSupbook;
+ maSBIndexVec[ nXclTab ].mnSBTab = xSupbook->InsertTabName( GetDoc().GetLinkTab( nScTab ) );
++
++ fprintf(stdout, "XclExpSupbookBuffer::AddExtSupbook: supbook = %d; sheet index = %d; sheet name = '%s'\n",
++ nSupbook, maSBIndexVec[nXclTab].mnSBTab,
++ rtl::OUStringToOString(GetDoc().GetLinkTab(nScTab), RTL_TEXTENCODING_UTF8).getStr());
+ }
+
+ // Export link manager ========================================================
+@@ -1490,6 +1815,16 @@ void XclExpLinkManagerImpl5::StoreCellRange( const SingleRefData& /*rRef1*/, con
+ // not implemented
+ }
+
++void XclExpLinkManagerImpl5::StoreCell( sal_uInt16 /*nFileId*/, const SingleRefData& /*rRef*/ )
++{
++ // not implemented
++}
++
++void XclExpLinkManagerImpl5::StoreCellRange( sal_uInt16 /*nFileId*/, const SingleRefData& /*rRef1*/, const SingleRefData& /*rRef2*/ )
++{
++ // not implemented
++}
++
+ bool XclExpLinkManagerImpl5::InsertAddIn(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
+ {
+@@ -1640,10 +1975,15 @@ void XclExpLinkManagerImpl8::StoreCellRange( const SingleRefData& rRef1, const S
+ ScRange aRange(
+ static_cast< SCCOL >( rRef1.nCol ), static_cast< SCROW >( rRef1.nRow ), 0,
+ static_cast< SCCOL >( rRef2.nCol ), static_cast< SCROW >( rRef2.nRow ), 0 );
++ String aStr;
++ aRange.Format(aStr, SCR_ABS_3D, &GetDoc());
++ fprintf(stdout, "XclExpLinkManagerImpl8::StoreCellRange: range = '%s'\n",
++ rtl::OUStringToOString(aStr, RTL_TEXTENCODING_UTF8).getStr());
+ for( SCTAB nScTab = nFirstScTab; nScTab <= nLastScTab; ++nScTab )
+ {
+ if( rTabInfo.IsExternalTab( nScTab ) )
+ {
++ fprintf(stdout, "XclExpLinkManagerImpl8::StoreCellRange: %d is an external sheet\n", nScTab);
+ aRange.aStart.SetTab( nScTab );
+ aRange.aEnd.SetTab( nScTab );
+ maSBBuffer.StoreCellRange( aRange );
+@@ -1652,6 +1992,36 @@ void XclExpLinkManagerImpl8::StoreCellRange( const SingleRefData& rRef1, const S
+ }
+ }
+
++void XclExpLinkManagerImpl8::StoreCell( sal_uInt16 nFileId, const SingleRefData& rRef )
++{
++ ScAddress aAddr(rRef.nCol, rRef.nRow, rRef.nTab);
++ maSBBuffer.StoreCell(nFileId, aAddr);
++}
++
++void XclExpLinkManagerImpl8::StoreCellRange( sal_uInt16 nFileId, const SingleRefData& rRef1, const SingleRefData& rRef2 )
++{
++ fprintf(stdout, "XclExpLinkManagerImpl8::StoreCellRange: --begin (file id = %d)\n", nFileId);
++
++ // XclExpXti -- stores supbook ID and first and last sheet IDs for EXTERNSHEET.
++ //
++ // XclExpSupbookBuffer -- stores
++
++ // 1) Insert into supbook buffer first, and get the supbook ID.
++ SCTAB nFirstScTab = static_cast<SCTAB>(rRef1.nTab);
++ SCTAB nLastScTab = static_cast<SCTAB>(rRef2.nTab);
++ ScRange aRange(static_cast<SCCOL>(rRef1.nCol), static_cast<SCROW>(rRef1.nRow), static_cast<SCTAB>(rRef1.nTab),
++ static_cast<SCCOL>(rRef2.nCol), static_cast<SCROW>(rRef2.nRow), static_cast<SCTAB>(rRef2.nTab));
++ maSBBuffer.StoreCellRange(nFileId, aRange);
++// for (SCTAB nScTab = nFirstScTab; nScTab <= nLastScTab; ++nScTab)
++// {
++// aRange.aStart.SetTab(nScTab);
++// aRange.aEnd.SetTab(nScTab);
++// maSBBuffer.StoreCellRange(nFileId, aRange);
++// }
++
++ fprintf(stdout, "XclExpLinkManagerImpl8::StoreCellRange: --end\n");
++}
++
+ bool XclExpLinkManagerImpl8::InsertAddIn(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
+ {
+@@ -1693,13 +2063,20 @@ void XclExpLinkManagerImpl8::Save( XclExpStream& rStrm )
+ aIt->Save( rStrm );
+ rStrm.EndRecord();
+ }
++ else
++ {
++ fprintf(stdout, "XclExpLinkManagerImpl8::Save: xti (external table index) list is empty - nothing to save\n");
++ maSBBuffer.Save(rStrm);
++ }
+ }
+
+ sal_uInt16 XclExpLinkManagerImpl8::InsertXti( const XclExpXti& rXti )
+ {
+- for( XclExpXtiVec::const_iterator aIt = maXtiVec.begin(), aEnd = maXtiVec.end(); aIt != aEnd; ++aIt )
++ using ::std::distance;
++ for( XclExpXtiVec::const_iterator aIt = maXtiVec.begin(), aBeg = maXtiVec.begin(), aEnd = maXtiVec.end();
++ aIt != aEnd; ++aIt )
+ if( *aIt == rXti )
+- return ulimit_cast< sal_uInt16 >( aIt - maXtiVec.begin() );
++ return ulimit_cast< sal_uInt16 >( distance(aBeg, aIt) );
+ maXtiVec.push_back( rXti );
+ return ulimit_cast< sal_uInt16 >( maXtiVec.size() - 1 );
+ }
+@@ -1755,6 +2132,16 @@ void XclExpLinkManager::StoreCellRange( const ComplRefData& rRef )
+ mxImpl->StoreCellRange( rRef.Ref1, rRef.Ref2 );
+ }
+
++void XclExpLinkManager::StoreCell( sal_uInt16 nFileId, const SingleRefData& rRef )
++{
++ mxImpl->StoreCell( nFileId, rRef );
++}
++
++void XclExpLinkManager::StoreCellRange( sal_uInt16 nFileId, const ComplRefData& rRef )
++{
++ mxImpl->StoreCellRange( nFileId, rRef.Ref1, rRef.Ref2 );
++}
++
+ bool XclExpLinkManager::InsertAddIn(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
+ {
+@@ -1770,7 +2157,9 @@ bool XclExpLinkManager::InsertDde(
+
+ void XclExpLinkManager::Save( XclExpStream& rStrm )
+ {
++ fprintf(stdout, "XclExpLinkManager::Save: --begin\n");
+ mxImpl->Save( rStrm );
++ fprintf(stdout, "XclExpLinkManager::Save: --end\n");
+ }
+
+ // ============================================================================
diff --git sc/source/filter/excel/xilink.cxx sc/source/filter/excel/xilink.cxx
index e351863..b58f6ec 100644
--- sc/source/filter/excel/xilink.cxx
@@ -1020,6 +2028,21 @@
inline const TokenId LastId( void ) const;
inline const ScTokenArray* operator []( const TokenId nId );
+diff --git sc/source/filter/inc/xelink.hxx sc/source/filter/inc/xelink.hxx
+index 795219c..37f1457 100644
+--- sc/source/filter/inc/xelink.hxx
++++ sc/source/filter/inc/xelink.hxx
+@@ -178,6 +178,10 @@ public:
+ /** Stores all cells in the given range in a CRN record list. */
+ void StoreCellRange( const ComplRefData& rRef );
+
++ void StoreCell( sal_uInt16 nFileId, const SingleRefData& rRef );
++
++ void StoreCellRange( sal_uInt16 nFileId, const ComplRefData& rRef );
++
+ /** Finds or inserts an EXTERNNAME record for an add-in function name.
+ @param rnExtSheet (out-param) Returns the index of the EXTSHEET structure for the add-in function name.
+ @param rnExtName (out-param) Returns the 1-based EXTERNNAME record index.
diff --git sc/source/filter/inc/xilink.hxx sc/source/filter/inc/xilink.hxx
index 0d547fe..3c2d0d9 100644
--- sc/source/filter/inc/xilink.hxx
@@ -1036,10 +2059,10 @@
For OLE object links: Decodes to class name and document URL.
diff --git sc/source/ui/docshell/externalrefmgr.cxx sc/source/ui/docshell/externalrefmgr.cxx
new file mode 100644
-index 0000000..adb7452
+index 0000000..c7c0bae
--- /dev/null
+++ sc/source/ui/docshell/externalrefmgr.cxx
-@@ -0,0 +1,788 @@
+@@ -0,0 +1,789 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -1112,6 +2135,9 @@
+using ::std::find;
+using ::std::distance;
+
++#define SRCDOC_LIFE_SPAN 6000 // 1 minute (in 100th of sec)
++#define SRCDOC_SCAN_INTERVAL 1000*2 // every 2 seconds (in msec)
++
+ScExternalRefLink::ScExternalRefLink(ScDocument* pDoc, sal_uInt16 nFileId, const String& rFilter) :
+ ::sfx2::SvBaseLink(::sfx2::LINKUPDATE_ONCALL, FORMAT_FILE),
+ mnFileId(nFileId),
@@ -1303,8 +2329,7 @@
+ mpDoc(pDoc)
+{
+ maSrcDocTimer.SetTimeoutHdl( LINK(this, ScExternalRefManager, TimeOutHdl) );
-+// maSrcDocTimer.SetTimeout(60000*5); // every 5 minutes
-+ maSrcDocTimer.SetTimeout(1000*2); // every 2 seconds
++ maSrcDocTimer.SetTimeout(SRCDOC_SCAN_INTERVAL);
+}
+
+ScExternalRefManager::~ScExternalRefManager()
@@ -1312,9 +2337,10 @@
+ clear();
+}
+
-+ScToken* ScExternalRefManager::getSingleRefToken(sal_uInt16 nFileId, const ScAddress& rCell, const ScAddress& rCurPos)
++ScToken* ScExternalRefManager::getSingleRefToken(sal_uInt16 nFileId, const ScAddress& rCell, const ScAddress* pCurPos)
+{
-+ // TODO: add the current cell position to the list.
++ if (pCurPos)
++ insertReferencingCell(nFileId, *pCurPos);
+ return getSingleRefToken(nFileId, rCell);
+}
+
@@ -1358,9 +2384,10 @@
+ return pTok.get();
+}
+
-+ScTokenArray* ScExternalRefManager::getDoubleRefTokens(sal_uInt16 nFileId, const ScRange& rRange, const ScAddress& rCurPos)
++ScTokenArray* ScExternalRefManager::getDoubleRefTokens(sal_uInt16 nFileId, const ScRange& rRange, const ScAddress* pCurPos)
+{
-+ // TODO: add the current cell position to the list of affected cells.
++ if (pCurPos)
++ insertReferencingCell(nFileId, *pCurPos);
+ return getDoubleRefTokens(nFileId, rRange);
+}
+
@@ -1402,19 +2429,22 @@
+ return pArray.get();
+}
+
-+ScTokenArray* ScExternalRefManager::getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress& rCurPos)
++ScTokenArray* ScExternalRefManager::getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos)
+{
++ if (pCurPos)
+ {
+ String aCellStr;
-+ rCurPos.Format(aCellStr, SCA_ABS_3D);
++ pCurPos->Format(aCellStr, SCA_ABS_3D);
+ const String* pFile = getExternalFileName(nFileId);
-+ fprintf(stdout, "ScExternalRefManager::getRangeNameTokens: --begin (file = '%s'; name = '%s'; pos = '%s')\n",
++ fprintf(stdout, "ScExternalRefManager::getRangeNameTokens: --begin (file = '%s' [%d]; name = '%s'; pos = '%s')\n",
+ rtl::OUStringToOString(*pFile, RTL_TEXTENCODING_UTF8).getStr(),
++ nFileId,
+ rtl::OUStringToOString(rName, RTL_TEXTENCODING_UTF8).getStr(),
+ rtl::OUStringToOString(aCellStr, RTL_TEXTENCODING_UTF8).getStr());
+ }
+
-+ insertReferencingCell(nFileId, rCurPos);
++ if (pCurPos)
++ insertReferencingCell(nFileId, *pCurPos);
+
+ // First, check if this name has already been cached.
+ RangeNameMap& rMap = getDocumentCache(nFileId)->maRangeNames;
@@ -1457,46 +2487,17 @@
+ case svSingleRef:
+ {
+ fprintf(stdout, "ScDocument::FindExternalRangeName: single ref\n");
-+ SingleRefData aRef(pToken->GetSingleRef());
-+ if (aRef.IsTabRel())
-+ break;
-+
-+ // The sheet reference is absolute. Get the cell from the
-+ // source document, and convert it to a static value.
-+
-+ aRef.CalcAbsIfRel(rCurPos);
-+ ScToken* pTok = getSingleRefToken(nFileId, ScAddress(aRef.nCol, aRef.nRow, aRef.nTab));
-+ if (pTok)
-+ {
-+ pNew->AddToken(*pTok);
-+ bTokenAdded = true;
-+ }
++ ScExternalSingleRefToken aNewToken(nFileId, pToken->GetSingleRef());
++ pNew->AddToken(aNewToken);
++ bTokenAdded = true;
+ }
+ break;
+ case svDoubleRef:
+ {
+ fprintf(stdout, "ScDocument::FindExternalRangeName: double ref\n");
-+ ComplRefData aComRef(pToken->GetDoubleRef());
-+ if (aComRef.Ref1.IsTabRel() || aComRef.Ref2.IsTabRel())
-+ break;
-+
-+ aComRef.CalcAbsIfRel(rCurPos);
-+ SCsTAB nTab1 = aComRef.Ref1.nTab;
-+ SCsCOL nCol1 = aComRef.Ref1.nCol;
-+ SCsROW nRow1 = aComRef.Ref1.nRow;
-+ SCsTAB nTab2 = aComRef.Ref2.nTab;
-+ SCsCOL nCol2 = aComRef.Ref2.nCol;
-+ SCsROW nRow2 = aComRef.Ref2.nRow;
-+
-+ ScTokenArray* pArray = getDoubleRefTokens(nFileId, ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
-+ if (pArray)
-+ {
-+ for (ScToken* p = pArray->First(); p; p = pArray->Next())
-+ {
-+ pNew->AddToken(*p);
-+ bTokenAdded = true;
-+ }
-+ }
++ ScExternalDoubleRefToken aNewToken(nFileId, pToken->GetDoubleRef());
++ pNew->AddToken(aNewToken);
++ bTokenAdded = true;
+ }
+ break;
+ }
@@ -1517,13 +2518,8 @@
+ if (itr == maRefCells.end())
+ {
+ const String* pFile = getExternalFileName(nFileId);
-+ if (pFile)
-+ {
-+ fprintf(stdout, "ScExternalRefManager::refreshAllReferencingCells: no referencing cells for names from '%s'\n",
-+ rtl::OUStringToOString(*pFile, RTL_TEXTENCODING_UTF8).getStr());
-+ }
-+ else
-+ fprintf(stdout, "ScExternalRefManager::refreshAllReferencingCells: file name not found (file ID = %d)\n", nFileId);
++ fprintf(stdout, "ScExternalRefManager::refreshAllReferencingCells: no referencing cells for names from '%s'\n",
++ rtl::OUStringToOString(*pFile, RTL_TEXTENCODING_UTF8).getStr());
+ return;
+ }
+
@@ -1612,11 +2608,27 @@
+ maDocShells.insert(DocShellMap::value_type(nFileId, aSrcDoc));
+ if (!maLinkedDocs.count(nFileId))
+ {
++ // Source document not linked yet. Link it now.
+ insertExternalFileLink(nFileId, aFilter);
+ maLinkedDocs.insert(nFileId);
+ }
+ SfxObjectShell* p = aSrcDoc.maShell;
-+ return static_cast<ScDocShell*>(p)->GetDocument();
++ ScDocument* pSrcDoc = static_cast<ScDocShell*>(p)->GetDocument();
++
++ // Store all its table names. Excel exporter needs this info.
++ vector<String> aTableNames;
++ SCTAB nCount = pSrcDoc->GetTableCount();
++ aTableNames.reserve(nCount);
++ for (SCTAB i = 0; i < nCount; ++i)
++ {
++ String aTabName;
++ pSrcDoc->GetName(i, aTabName);
++ aTableNames.push_back(aTabName);
++ }
++ DocCache* pCache = getDocumentCache(nFileId);
++ pCache->maTableNames.swap(aTableNames);
++
++ return pSrcDoc;
+}
+
+SfxObjectShellRef ScExternalRefManager::loadSrcDocument(const String& rFile, String& rFilter)
@@ -1729,12 +2741,24 @@
+ return static_cast<sal_uInt16>(maFileNames.size() - 1);
+}
+
-+const String* ScExternalRefManager::getExternalFileName(sal_uInt16 nIndex) const
++const String* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId) const
+{
-+ if (nIndex >= maFileNames.size())
++ if (nFileId >= maFileNames.size())
+ return NULL;
+
-+ return &maFileNames[nIndex];
++ return &maFileNames[nFileId];
++}
++
++const String* ScExternalRefManager::getExternalTableName(sal_uInt16 nFileId, SCTAB nTabId)
++{
++ if (nFileId >= maFileNames.size())
++ return NULL;
++
++ DocCache* pCache = getDocumentCache(nFileId);
++ if (nTabId >= pCache->maTableNames.size())
++ return NULL;
++
++ return &pCache->maTableNames[nTabId];
+}
+
+template<typename MapContainer>
@@ -1763,9 +2787,8 @@
+ rtl::OUStringToOString(*pOldFile, RTL_TEXTENCODING_UTF8).getStr(),
+ rtl::OUStringToOString(rNewFile, RTL_TEXTENCODING_UTF8).getStr());
+
-+ removeSrcDocument(nFileId, false);
+ maFileNames[nFileId] = rNewFile;
-+ refreshAllReferencingCells(nFileId);
++ refreshNames(nFileId);
+}
+
+void ScExternalRefManager::removeSrcDocument(sal_uInt16 nFileId, bool bBreakLink)
@@ -1807,10 +2830,10 @@
+ {
+ // in 100th of a second.
+ sal_Int32 nSinceLastAccess = (Time() - itr->second.maLastAccess).GetTime();
-+ const String* pStr = getExternalFileName(itr->first);
-+ if (pStr)
-+ fprintf(stdout, "ScExternalRefManager::purgeStaleSrcDocument: file = '%s'; since last access = %ld\n",
-+ rtl::OUStringToOString(*pStr, RTL_TEXTENCODING_UTF8).getStr(), nSinceLastAccess);
++// const String* pStr = getExternalFileName(itr->first);
++// if (pStr)
++// fprintf(stdout, "ScExternalRefManager::purgeStaleSrcDocument: file = '%s'; since last access = %ld\n",
++// rtl::OUStringToOString(*pStr, RTL_TEXTENCODING_UTF8).getStr(), nSinceLastAccess);
+
+ if (nSinceLastAccess < nTimeOut)
+ aNewDocShells.insert(*itr);
@@ -1824,10 +2847,11 @@
+IMPL_LINK(ScExternalRefManager, TimeOutHdl, AutoTimer*, pTimer)
+{
+ if (pTimer == &maSrcDocTimer)
-+ purgeStaleSrcDocument(1000); // max life span is 10 seconds (TODO: configure this).
++ purgeStaleSrcDocument(SRCDOC_LIFE_SPAN);
+
+ return 0;
+}
++
diff --git sc/source/ui/docshell/makefile.mk sc/source/ui/docshell/makefile.mk
index db83fec..6286dfb 100644
--- sc/source/ui/docshell/makefile.mk
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]