ooo-build r13428 - in trunk: . patches/test
- From: kyoshida svn gnome org
- To: svn-commits-list gnome org
- Subject: ooo-build r13428 - in trunk: . patches/test
- Date: Tue, 29 Jul 2008 14:21:14 +0000 (UTC)
Author: kyoshida
Date: Tue Jul 29 14:21:14 2008
New Revision: 13428
URL: http://svn.gnome.org/viewvc/ooo-build?rev=13428&view=rev
Log:
2008-07-29 Kohei Yoshida <kyoshida novell com>
* patches/test/calc-external-defined-names.diff: worked on using the
new external ref manager code for the existing cell and cell range
references. Still a long road ahead but the end is approaching...
hopefully.
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 Tue Jul 29 14:21:14 2008
@@ -1,3 +1,44 @@
+diff --git sc/inc/address.hxx sc/inc/address.hxx
+index f92fc8e..f15a341 100644
+--- sc/inc/address.hxx
++++ sc/inc/address.hxx
+@@ -287,6 +287,15 @@ public:
+ };
+ static const Details detailsOOOa1;
+
++ struct ExternalInfo
++ {
++ String maTabName;
++ sal_uInt16 mnFileId;
++ bool mbExternal;
++
++ inline ExternalInfo() : mnFileId(0), mbExternal(false) {}
++ };
++
+ inline ScAddress() : nRow(0), nCol(0), nTab(0) {}
+ inline ScAddress( SCCOL nColP, SCROW nRowP, SCTAB nTabP )
+ : nRow(nRowP), nCol(nColP), nTab(nTabP)
+@@ -317,8 +326,8 @@ public:
+ inline void GetVars( SCCOL& nColP, SCROW& nRowP, SCTAB& nTabP ) const
+ { nColP = nCol; nRowP = nRow; nTabP = nTab; }
+
+- USHORT Parse( const String&, ScDocument* = NULL,
+- const Details& rDetails = detailsOOOa1);
++ USHORT Parse( const String&, ScDocument* = NULL,
++ const Details& rDetails = detailsOOOa1, ExternalInfo* pExtInfo = NULL);
+ void Format( String&, USHORT = 0, ScDocument* = NULL,
+ const Details& rDetails = detailsOOOa1) const;
+
+@@ -463,7 +472,8 @@ public:
+ inline bool In( const ScRange& ) const; // is Range& in Range?
+
+ USHORT Parse( const String&, ScDocument* = NULL,
+- const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
++ const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
++ ScAddress::ExternalInfo* pExtInfo = NULL );
+ USHORT ParseAny( const String&, ScDocument* = NULL,
+ const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
+ USHORT ParseCols( const String&, ScDocument* = NULL,
diff --git sc/inc/compiler.hrc sc/inc/compiler.hrc
index 92b7e82..22d77cb 100644
--- sc/inc/compiler.hrc
@@ -49,7 +90,7 @@
/*** error constants #... ***/
#define SC_OPCODE_START_ERRORS 30
diff --git sc/inc/compiler.hxx sc/inc/compiler.hxx
-index 2d816d1..332dd31 100644
+index 2d816d1..74f8f35 100644
--- sc/inc/compiler.hxx
+++ sc/inc/compiler.hxx
@@ -45,6 +45,7 @@
@@ -60,26 +101,41 @@
namespace com { namespace sun { namespace star {
namespace sheet {
-@@ -151,6 +152,10 @@ public:
+@@ -100,6 +101,7 @@ namespace com { namespace sun { namespace star {
+ class ScDocument;
+ class ScMatrix;
+ class ScRangeData;
++class ScExternalRefManager;
+
+ // constants and data types internal to compiler
+
+@@ -151,6 +153,15 @@ public:
bool bHasForceArray;
} sbyte;
ComplRefData aRef;
+ struct {
++ sal_uInt16 nFileId;
++ sal_Unicode cTabName[MAXSTRLEN+1];
++ ComplRefData aRef;
++ } extref;
++ struct {
+ sal_uInt16 nFileId;
+ sal_Unicode cName[MAXSTRLEN+1];
+ } extname;
ScMatrix* pMat;
USHORT nIndex; // index into name collection
sal_Unicode cStr[ MAXSTRLEN+1 ]; // string (up to 255 characters + 0)
-@@ -180,6 +185,7 @@ public:
+@@ -180,6 +191,9 @@ public:
void SetDouble( double fVal );
void SetInt( int nVal );
void SetName( USHORT n );
++ void SetExternalSingleRef( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef );
++ void SetExternalDoubleRef( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef );
+ void SetExternalName( sal_uInt16 nFileId, const String& rName );
void SetMatrix( ScMatrix* p );
void SetExternal(const sal_Unicode* pStr);
// These methods are ok to use, reference count not cleared.
-@@ -228,6 +234,16 @@ public:
+@@ -228,6 +242,28 @@ public:
xub_StrLen nSrcPos,
const CharClass* pCharClass) const = 0;
@@ -93,10 +149,22 @@
+
+ virtual String makeExternalNameStr( const String& rFile, const String& rName ) const = 0;
+
++ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
++ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
++ ScExternalRefManager* pRefMgr ) const
++ {
++ }
++
++ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
++ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
++ ScExternalRefManager* pRefMgr ) const
++ {
++ }
++
enum SpecialSymbolType
{
/**
-@@ -447,6 +463,7 @@ private:
+@@ -447,6 +483,7 @@ private:
BOOL IsDoubleReference( const String& );
BOOL IsMacro( const String& );
BOOL IsNamedRange( const String& );
@@ -135,10 +203,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..c034a5b
+index 0000000..1245062
--- /dev/null
+++ sc/inc/externalrefmgr.hxx
-@@ -0,0 +1,224 @@
+@@ -0,0 +1,288 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -186,11 +254,14 @@
+
+class ScDocument;
+class ScToken;
++class ScMatrix;
+class ScTokenArray;
+class String;
+class SfxObjectShellRef;
+class Window;
+
++class ScExternalRefCache;
++
+class ScExternalRefLink : public ::sfx2::SvBaseLink
+{
+public:
@@ -217,6 +288,45 @@
+
+// ============================================================================
+
++/**
++ * Cache table for external reference data.
++ */
++class ScExternalRefCache
++{
++public:
++ typedef ::boost::shared_ptr<ScToken> TokenRef;
++ typedef ::boost::shared_ptr<ScMatrix> MatrixRef;
++
++ ScExternalRefCache();
++ ~ScExternalRefCache();
++
++ ScToken* getCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol);
++ ScTokenArray* getCellRangeData(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange);
++
++ void setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, TokenRef pToken);
++ void setCellRangeData(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange,
++ const ::std::vector<MatrixRef>& rData);
++
++private:
++ typedef ::std::hash_map<SCCOL, TokenRef> RowDataType;
++ typedef ::std::hash_map<SCROW, RowDataType> TableDataType;
++ typedef ::boost::shared_ptr<TableDataType> TableDataTypeRef;
++ typedef ::std::vector<TableDataTypeRef> TableListType;
++
++ typedef ::std::hash_map<String, size_t, ScStringHashCode> TableNameIndexMap;
++
++ struct DocItem
++ {
++ TableListType maTables;
++ TableNameIndexMap maTableNameIndex;
++ };
++ typedef ::std::hash_map<sal_uInt16, DocItem> DocDataType;
++
++ DocDataType maDocs;
++};
++
++// ============================================================================
++
+class ScExternalRefManager
+{
+private:
@@ -274,8 +384,15 @@
+ explicit ScExternalRefManager(ScDocument* pDoc);
+ ~ScExternalRefManager();
+
++ ScToken* getSingleRefToken(sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell, const ScAddress* pCurPos, SCTAB* pTab);
++#if 1
+ ScToken* getSingleRefToken(sal_uInt16 nFileId, const ScAddress& rCell, const ScAddress* pCurPos);
++#endif
++
++ ScTokenArray* getDoubleRefTokens(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos);
++#if 1
+ ScTokenArray* getDoubleRefTokens(sal_uInt16 nFileId, const ScRange& rRange, const ScAddress* pCurPos);
++#endif
+
+ /**
+ * Get an array of tokens corresponding with a specified name in a
@@ -300,6 +417,16 @@
+ sal_uInt16 getExternalFileId(const String& rFile);
+ const String* getExternalFileName(sal_uInt16 nFileId) const;
+ const String* getExternalTableName(sal_uInt16 nFileId, SCTAB nTabId);
++
++ /**
++ * Get the table index of an external table from its name.
++ *
++ * @param nFileId external file ID
++ * @param rTabName table name
++ *
++ * @return table index, or -1 if the name is not found.
++ */
++ SCTAB getExternalTableId(sal_uInt16 nFileId, const String& rTabName);
+
+ void refreshNames(sal_uInt16 nFileId);
+ void switchSrcFile(sal_uInt16 nFileId, const String& rNewFile);
@@ -310,7 +437,10 @@
+ ScExternalRefManager();
+ ScExternalRefManager(const ScExternalRefManager&);
+
++#if 1
+ ScToken* getSingleRefToken(sal_uInt16 nFileId, const ScAddress& rCell);
++#endif
++
+ ScTokenArray* getDoubleRefTokens(sal_uInt16 nFileId, const ScRange& rRange);
+
+ void refreshAllReferencingCells(sal_uInt16 nFileId);
@@ -333,6 +463,8 @@
+ void purgeStaleSrcDocument(sal_Int32 nTimeOut);
+
+private:
++ ScExternalRefCache maRefCache;
++
+ ScDocument* mpDoc;
+
+ /**
@@ -376,7 +508,7 @@
ocIf = SC_OPCODE_IF,
ocChose = SC_OPCODE_CHOSE,
diff --git sc/inc/token.hxx sc/inc/token.hxx
-index ded3a94..a28da1c 100644
+index ded3a94..92a9137 100644
--- sc/inc/token.hxx
+++ sc/inc/token.hxx
@@ -64,7 +64,7 @@ enum StackVarEnum
@@ -388,7 +520,7 @@
svError, // error token
svMissing = 0x70, // 0 or ""
svSep, // separator, ocSep, ocOpen, ocClose
-@@ -448,6 +448,61 @@ public:
+@@ -448,6 +448,65 @@ public:
};
@@ -396,15 +528,17 @@
+{
+private:
+ sal_uInt16 mnFileId;
++ String maTabName;
+ SingleRefData maSingleRef;
+
+ ScExternalSingleRefToken(); // disabled
+public:
-+ ScExternalSingleRefToken( sal_uInt16 nFileId, const SingleRefData& r );
++ ScExternalSingleRefToken( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& r );
+ ScExternalSingleRefToken( const ScExternalSingleRefToken& r );
+ virtual ~ScExternalSingleRefToken();
+
+ virtual USHORT GetIndex() const;
++ virtual const String& GetString() const;
+ virtual const SingleRefData& GetSingleRef() const;
+ virtual SingleRefData& GetSingleRef();
+ virtual BOOL operator==( const ScToken& rToken ) const;
@@ -415,15 +549,17 @@
+{
+private:
+ sal_uInt16 mnFileId;
-+ ComplRefData maDoubleRef;
++ String maTabName; // name of the first sheet
++ ComplRefData maDoubleRef;
+
+ ScExternalDoubleRefToken(); // disabled
+public:
-+ ScExternalDoubleRefToken( sal_uInt16 nFileId, const ComplRefData& r );
++ ScExternalDoubleRefToken( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& r );
+ ScExternalDoubleRefToken( const ScExternalDoubleRefToken& r );
+ virtual ~ScExternalDoubleRefToken();
+
-+ virtual USHORT GetIndex() const;
++ virtual USHORT GetIndex() const;
++ virtual const String& GetString() const;
+ virtual const ComplRefData& GetDoubleRef() const;
+ virtual ComplRefData& GetDoubleRef();
+ virtual BOOL operator==( const ScToken& rToken ) const;
@@ -451,17 +587,54 @@
{
private:
diff --git sc/inc/tokenarray.hxx sc/inc/tokenarray.hxx
-index 1d903ce..f7c4d6b 100644
+index 1d903ce..1e94c2f 100644
--- sc/inc/tokenarray.hxx
+++ sc/inc/tokenarray.hxx
-@@ -193,6 +193,7 @@ public:
+@@ -193,6 +193,9 @@ public:
ScToken* AddDoubleReference( const ComplRefData& rRef );
ScToken* AddName( USHORT n );
ScToken* AddMatrix( ScMatrix* p );
+ ScToken* AddExternalName( sal_uInt16 nFileId, const String& rName );
++ ScToken* AddExternalSingleReference( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef );
++ ScToken* AddExternalDoubleReference( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef );
ScToken* AddExternal( const sal_Unicode* pStr );
/** Xcl import may play dirty tricks with OpCode!=ocExternal.
Others don't use! */
+diff --git sc/source/core/data/cell.cxx sc/source/core/data/cell.cxx
+index a68efc0..a1e3c12 100644
+--- sc/source/core/data/cell.cxx
++++ sc/source/core/data/cell.cxx
+@@ -87,6 +87,30 @@ static const sal_Char __FAR_DATA msgDbgInfinity[] =
+ "NICHTS anruehren und ER bescheid sagen!";
+ #endif
+
++
++namespace {
++
++#include <string>
++
++class StackPrinter
++{
++public:
++ explicit StackPrinter(const char* msg) :
++ msMsg(msg)
++ {
++ fprintf(stdout, "%s: --begin\n", msMsg.c_str());
++ }
++
++ ~StackPrinter()
++ {
++ fprintf(stdout, "%s: --end\n", msMsg.c_str());
++ }
++
++private:
++ ::std::string msMsg;
++};
++
++}
+ // -----------------------------------------------------------------------
+
+ ScBaseCell::ScBaseCell( CellType eNewType ) :
diff --git sc/source/core/data/documen2.cxx sc/source/core/data/documen2.cxx
index 85ad0e5..f04061f 100644
--- sc/source/core/data/documen2.cxx
@@ -532,8 +705,239 @@
BOOL ScDocument::InsertLinkedEmptyTab( SCTAB& rnTab, const String& rFileName,
const String& rFilterName, const String& rFilterOpt, const String& rTabName )
{
+diff --git sc/source/core/tool/address.cxx sc/source/core/tool/address.cxx
+index 2cb5dce..39cdd8e 100644
+--- sc/source/core/tool/address.cxx
++++ sc/source/core/tool/address.cxx
+@@ -35,6 +35,7 @@
+ #include "global.hxx"
+ #include "compiler.hxx"
+ #include "document.hxx"
++#include "externalrefmgr.hxx"
+
+ #include "globstr.hrc"
+ #include <sal/alloca.h>
+@@ -45,6 +46,31 @@
+ #include <tools/urlobj.hxx>
+ using namespace ::com::sun::star;
+
++
++namespace {
++
++#include <string>
++
++class StackPrinter
++{
++public:
++ explicit StackPrinter(const char* msg) :
++ msMsg(msg)
++ {
++ fprintf(stdout, "%s: --begin\n", msMsg.c_str());
++ }
++
++ ~StackPrinter()
++ {
++ fprintf(stdout, "%s: --end\n", msMsg.c_str());
++ }
++
++private:
++ ::std::string msMsg;
++};
++
++}
++
+ ////////////////////////////////////////////////////////////////////////////
+ const ScAddress::Details ScAddress::detailsOOOa1( CONV_OOO, 0, 0 );
+
+@@ -713,15 +739,16 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+ }
+
+ static USHORT
+-lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+- ScDocument* pDoc, ScAddress& rAddr )
++lcl_ScAddress_Parse_OOo( const sal_Unicode* p, ScDocument* pDoc, ScAddress& rAddr,
++ ScAddress::ExternalInfo* pExtInfo = NULL )
+ {
++ StackPrinter aStack("::lcl_ScAddress_Parse_OOo");
+ USHORT nRes = 0;
+ String aDocName; // der pure Dokumentenname
+ String aDocTab; // zusammengesetzt fuer Table
+ String aTab;
+ BOOL bExtDoc = FALSE;
+- BOOL bNeedExtTab = FALSE;
++ const ScAddress aCurPos(rAddr);
+
+ // Lets see if this is a reference to something in an external file.
+ // A Documentname is always quoted and has a trailing #
+@@ -795,35 +822,11 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+ }
+ if( *p++ != '.' )
+ nBits = 0;
+- if ( pDoc )
++
++ if (pDoc)
+ {
+- if ( bExtDoc )
+- {
+- bExternal = TRUE;
+- aDocTab += aTab; // "'Doc'#Tab"
+- if ( !pDoc->GetTable( aDocTab, nTab ) )
+- {
+- if ( pDoc->ValidTabName( aTab ) )
+- {
+- aDocName = ScGlobal::GetAbsDocName( aDocName,
+- pDoc->GetDocumentShell() );
+- aDocTab = ScGlobal::GetDocTabName( aDocName, aTab );
+- if ( !pDoc->GetTable( aDocTab, nTab ) )
+- {
+- // erst einfuegen, wenn Rest der Ref ok
+- bNeedExtTab = TRUE;
+- nBits = 0;
+- }
+- }
+- else
+- nBits = 0;
+- }
+- }
+- else
+- {
+- if ( !pDoc->GetTable( aTab, nTab ) )
+- nBits = 0;
+- }
++ if ( !pDoc->GetTable( aTab, nTab ) )
++ nBits = 0;
+ }
+ else
+ nBits = 0;
+@@ -884,16 +887,33 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+ if( !nBits )
+ p = q;
+ }
+- if ( bNeedExtTab )
++
++ if (bExtDoc)
+ {
+- if ( (nRes & SCA_VALID_ROW) && (nRes & SCA_VALID_COL)
+- && pDoc->LinkExternalTab( nTab, aDocTab, aDocName, aTab ) )
++ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
++ pRefMgr->convertToAbsName(aDocName);
++ fprintf(stdout, "lcl_ScAddress_Parse_OOo: doc name = '%s'; tab = '%s' col = %d row = %ld\n",
++ rtl::OUStringToOString(aDocName, RTL_TEXTENCODING_UTF8).getStr(),
++ rtl::OUStringToOString(aTab, RTL_TEXTENCODING_UTF8).getStr(), nCol, nRow);
++
++ // TODO: Make sure the document exists!
++
++ sal_uInt16 nFileId = pRefMgr->getExternalFileId(aDocName);
++ if (pExtInfo && !pExtInfo->mbExternal)
++ {
++ pExtInfo->mbExternal = true;
++ pExtInfo->maTabName = aTab;
++ pExtInfo->mnFileId = nFileId;
++ }
++
++ if (pRefMgr->getSingleRefToken(nFileId, aTab, ScAddress(nCol, nRow, 0), NULL, &nTab))
+ {
+ nRes |= SCA_VALID_TAB;
+ }
+ else
+- nRes = 0; // #NAME? statt #REF!, Dateiname bleibt erhalten
++ nRes = 0;
+ }
++
+ if ( !(nRes & SCA_VALID_ROW) && (nRes & SCA_VALID_COL)
+ && !( (nRes & SCA_TAB_3D) && (nRes & SCA_VALID_TAB)) )
+ { // keine Row, keine Tab, aber Col => DM (...), B (...) o.ae.
+@@ -912,9 +932,8 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+ }
+
+ static USHORT
+-lcl_ScAddress_Parse ( BOOL& bExternal, const sal_Unicode* p,
+- ScDocument* pDoc, ScAddress& rAddr,
+- const ScAddress::Details& rDetails )
++lcl_ScAddress_Parse ( const sal_Unicode* p, ScDocument* pDoc, ScAddress& rAddr,
++ const ScAddress::Details& rDetails, ScAddress::ExternalInfo* pExtInfo = NULL )
+ {
+ if( !*p )
+ return 0;
+@@ -924,7 +943,7 @@ lcl_ScAddress_Parse ( BOOL& bExternal, const sal_Unicode* p,
+ default :
+ case ScAddress::CONV_OOO:
+ {
+- return lcl_ScAddress_Parse_OOo( bExternal, p, pDoc, rAddr );
++ return lcl_ScAddress_Parse_OOo( p, pDoc, rAddr, pExtInfo );
+ }
+
+ case ScAddress::CONV_XL_A1:
+@@ -949,9 +968,8 @@ bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
+ SCTAB nDefTab, ScRefAddress& rRefAddress,
+ const ScAddress::Details& rDetails )
+ {
+- BOOL bExternal = FALSE;
+ ScAddress aAddr( 0, 0, nDefTab );
+- USHORT nRes = lcl_ScAddress_Parse( bExternal, rRefString.GetBuffer(), pDoc, aAddr, rDetails );
++ USHORT nRes = lcl_ScAddress_Parse( rRefString.GetBuffer(), pDoc, aAddr, rDetails, NULL );
+ if( nRes & SCA_VALID )
+ {
+ rRefAddress.Set( aAddr,
+@@ -988,10 +1006,9 @@ bool ConvertDoubleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab
+
+
+ USHORT ScAddress::Parse( const String& r, ScDocument* pDoc,
+- const Details& rDetails)
++ const Details& rDetails, ExternalInfo* pExtInfo )
+ {
+- BOOL bExternal = FALSE;
+- return lcl_ScAddress_Parse( bExternal, r.GetBuffer(), pDoc, *this, rDetails );
++ return lcl_ScAddress_Parse( r.GetBuffer(), pDoc, *this, rDetails, pExtInfo );
+ }
+
+
+@@ -1060,7 +1077,7 @@ void ScRange::ExtendTo( const ScRange& rRange )
+ }
+
+ static USHORT
+-lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
++lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc, ScAddress::ExternalInfo* pExtInfo = NULL )
+ {
+ USHORT nRes1 = 0, nRes2 = 0;
+ xub_StrLen nTmp = 0;
+@@ -1073,13 +1090,12 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
+ String aTmp( r );
+ sal_Unicode* p = aTmp.GetBufferAccess();
+ p[ nPos ] = 0;
+- BOOL bExternal = FALSE;
+- if( (nRes1 = lcl_ScAddress_Parse_OOo( bExternal, p, pDoc, aRange.aStart ) ) != 0 )
++ if( (nRes1 = lcl_ScAddress_Parse_OOo( p, pDoc, aRange.aStart, pExtInfo ) ) != 0 )
+ {
+ aRange.aEnd = aRange.aStart; // die Tab _muss_ gleich sein, so ist`s weniger Code
+- if ( (nRes2 = lcl_ScAddress_Parse_OOo( bExternal, p + nPos+ 1, pDoc, aRange.aEnd ) ) != 0 )
++ if ( (nRes2 = lcl_ScAddress_Parse_OOo( p + nPos+ 1, pDoc, aRange.aEnd, NULL ) ) != 0 )
+ {
+- if ( bExternal && aRange.aStart.Tab() != aRange.aEnd.Tab() )
++ if ( pExtInfo && pExtInfo->mbExternal && aRange.aStart.Tab() != aRange.aEnd.Tab() )
+ nRes2 &= ~SCA_VALID_TAB; // #REF!
+ else
+ {
+@@ -1132,7 +1148,7 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
+ }
+
+ USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
+- const ScAddress::Details& rDetails )
++ const ScAddress::Details& rDetails, ScAddress::ExternalInfo* pExtInfo )
+ {
+ if ( r.Len() <= 0 )
+ return 0;
+@@ -1141,7 +1157,7 @@ USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
+ {
+ default :
+ case ScAddress::CONV_OOO:
+- return lcl_ScRange_Parse_OOo( *this, r, pDoc );
++ return lcl_ScRange_Parse_OOo( *this, r, pDoc, pExtInfo );
+
+ case ScAddress::CONV_XL_A1:
+ return lcl_ScRange_Parse_XL_A1( *this, r.GetBuffer(), pDoc, FALSE );
diff --git sc/source/core/tool/compiler.cxx sc/source/core/tool/compiler.cxx
-index f88d5d3..c763f91 100644
+index f88d5d3..563adf9 100644
--- sc/source/core/tool/compiler.cxx
+++ sc/source/core/tool/compiler.cxx
@@ -74,9 +74,38 @@
@@ -759,7 +1163,7 @@
return pCharClass->parseAnyToken( rFormula,
nSrcPos, nStartFlags, aAddAllowed, nContFlags, aAddAllowed );
}
-@@ -1368,6 +1565,16 @@ struct ConventionOOO_A1 : public Convention_A1
+@@ -1368,6 +1565,81 @@ struct ConventionOOO_A1 : public Convention_A1
return sal_Unicode(0);
}
@@ -773,10 +1177,75 @@
+ {
+ return lcl_makeExternalNameStr(rFile, rName, sal_Unicode('#'));
+ }
++
++ bool makeExternalSingleRefStr( ::rtl::OUStringBuffer& rBuffer, sal_uInt16 nFileId,
++ const String& rTabName, const SingleRefData& rRef,
++ ScExternalRefManager* pRefMgr, bool bDisplayTabName ) const
++ {
++ if (bDisplayTabName)
++ {
++ String aFile;
++ const String* p = pRefMgr->getExternalFileName(nFileId);
++ if (p)
++ aFile = *p;
++ aFile.SearchAndReplaceAllAscii("'", String::CreateFromAscii("''"));
++
++ rBuffer.append(sal_Unicode('\''));
++ rBuffer.append(aFile);
++ rBuffer.append(sal_Unicode('\''));
++ rBuffer.append(sal_Unicode('#'));
++
++ // external reference is always 3D and the sheet is absolute.
++ rBuffer.append(sal_Unicode('$'));
++ bool bQuote = (rTabName.Search(sal_Unicode(' '), 0) != STRING_NOTFOUND);
++ if (bQuote)
++ rBuffer.append(sal_Unicode('\''));
++ rBuffer.append(rTabName);
++ if (bQuote)
++ rBuffer.append(sal_Unicode('\''));
++
++ rBuffer.append(sal_Unicode('.'));
++ }
++
++ if (!rRef.IsColRel())
++ rBuffer.append(sal_Unicode('$'));
++ rBuffer.append(MakeColStr(rRef.nCol));
++ if (!rRef.IsRowRel())
++ rBuffer.append(sal_Unicode('$'));
++ rBuffer.append(MakeRowStr(rRef.nRow));
++
++ return true;
++ }
++
++ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
++ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
++ ScExternalRefManager* pRefMgr ) const
++ {
++ SingleRefData aRef(rRef);
++ aRef.CalcAbsIfRel(rCompiler.GetPos());
++
++ makeExternalSingleRefStr(rBuffer, nFileId, rTabName, aRef, pRefMgr, true);
++ }
++
++ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
++ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
++ ScExternalRefManager* pRefMgr ) const
++ {
++ ComplRefData aRef(rRef);
++ aRef.CalcAbsIfRel(rCompiler.GetPos());
++
++ if (!makeExternalSingleRefStr(rBuffer, nFileId, rTabName, aRef.Ref1, pRefMgr, true))
++ return;
++
++ rBuffer.append(sal_Unicode(':'));
++
++ // TODO: Get the real table name of the last table.
++ makeExternalSingleRefStr(rBuffer, nFileId, rTabName, aRef.Ref2, pRefMgr, (aRef.Ref1.nTab != aRef.Ref2.nTab));
++ }
};
-@@ -1489,6 +1696,16 @@ struct ConventionXL
+@@ -1489,6 +1761,16 @@ struct ConventionXL
}
return sal_Unicode(0);
}
@@ -793,7 +1262,7 @@
};
struct ConventionXL_A1 : public Convention_A1, public ConventionXL
-@@ -1587,6 +1804,16 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
+@@ -1587,6 +1869,16 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
{
return ConventionXL::getSpecialSymbol(eSymType);
}
@@ -810,7 +1279,7 @@
};
static const ConventionXL_A1 ConvXL_A1;
-@@ -1714,6 +1941,16 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
+@@ -1714,6 +2006,16 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
{
return ConventionXL::getSpecialSymbol(eSymType);
}
@@ -827,7 +1296,7 @@
};
static const ConventionXL_R1C1 ConvXL_R1C1;
-@@ -1888,6 +2125,7 @@ sal_Unicode* lcl_UnicodeStrNCpy( sal_Unicode* pDst, const sal_Unicode* pSrc, xub
+@@ -1888,6 +2190,7 @@ sal_Unicode* lcl_UnicodeStrNCpy( sal_Unicode* pDst, const sal_Unicode* pSrc, xub
xub_StrLen ScCompiler::NextSymbol(bool bInArray)
{
@@ -835,7 +1304,7 @@
cSymbol[MAXSTRLEN-1] = 0; // Stopper
sal_Unicode* pSym = cSymbol;
const sal_Unicode* const pStart = aFormula.GetBuffer();
-@@ -1912,6 +2150,11 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
+@@ -1912,6 +2215,11 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
bool bAutoIntersection = false;
int nRefInSheetName = 0;
mnPredetectedReference = 0;
@@ -847,7 +1316,7 @@
// try to parse simple tokens before calling i18n parser
while ((c != 0) && (eState != ssStop) )
{
-@@ -2169,7 +2412,7 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
+@@ -2169,7 +2477,7 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
static const int kQuote = kInc * 2;
static const int kPast = kInc * 3;
bool bAddToSymbol = true;
@@ -856,7 +1325,7 @@
{
// eat it, no sheet name
bAddToSymbol = false;
-@@ -2184,7 +2427,7 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
+@@ -2184,7 +2492,7 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
}
else if (nRefInSheetName < kPast)
{
@@ -865,7 +1334,7 @@
nRefInSheetName += kDollar;
else if ('\'' == c)
{
-@@ -2235,6 +2478,7 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
+@@ -2235,6 +2543,7 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
cLast = c;
c = *pSrc;
}
@@ -873,7 +1342,7 @@
if ( bi18n )
{
nSrcPos = sal::static_int_cast<xub_StrLen>( nSrcPos + nSpaces );
-@@ -2287,6 +2531,9 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
+@@ -2287,6 +2596,9 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
aCorrectedSymbol = cSymbol;
if (bAutoIntersection && nSpaces > 1)
--nSpaces; // replace '!!' with only one space
@@ -883,7 +1352,91 @@
return nSpaces;
}
-@@ -2669,6 +2916,30 @@ BOOL ScCompiler::IsNamedRange( const String& rUpperName )
+@@ -2506,7 +2818,8 @@ BOOL ScCompiler::IsDoubleReference( const String& rName )
+ {
+ ScRange aRange( aPos, aPos );
+ const ScAddress::Details aDetails( pConv->meConv, aPos );
+- USHORT nFlags = aRange.Parse( rName, pDoc, aDetails );
++ ScAddress::ExternalInfo aExtInfo;
++ USHORT nFlags = aRange.Parse( rName, pDoc, aDetails, &aExtInfo );
+ if( nFlags & SCA_VALID )
+ {
+ ScRawToken aToken;
+@@ -2525,23 +2838,41 @@ BOOL ScCompiler::IsDoubleReference( const String& rName )
+ aRef.Ref2.SetTabDeleted( TRUE ); // #REF!
+ aRef.Ref2.SetFlag3D( ( nFlags & SCA_TAB2_3D ) != 0 );
+ aRef.CalcRelFromAbs( aPos );
+- aToken.SetDoubleReference( aRef );
++ if (aExtInfo.mbExternal)
++ {
++ aToken.SetExternalDoubleRef(aExtInfo.mnFileId, aExtInfo.maTabName, aRef);
++ }
++ else
++ {
++ aToken.SetDoubleReference(aRef);
++ }
+ pRawToken = aToken.Clone();
+ }
+
++ bool bRes = (nFlags & SCA_VALID) != 0;
++ fprintf(stdout, "ScCompiler::IsDoubleReference: is double ref? (%s)\n", bRes?"yes":"no");
+ return ( nFlags & SCA_VALID ) != 0;
+ }
+
+
+ BOOL ScCompiler::IsSingleReference( const String& rName )
+ {
++ StackPrinter aStack("ScCompiler::IsSingleReference");
++ fprintf(stdout, "ScCompiler::IsSingleReference: symbol ='%s'\n", rtl::OUStringToOString(rName, RTL_TEXTENCODING_UTF8).getStr());
++
+ ScAddress aAddr( aPos );
+ const ScAddress::Details aDetails( pConv->meConv, aPos );
+- USHORT nFlags = aAddr.Parse( rName, pDoc, aDetails );
++ ScAddress::ExternalInfo aExtInfo;
++ USHORT nFlags = aAddr.Parse( rName, pDoc, aDetails, &aExtInfo );
+ // Something must be valid in order to recognize Sheet1.blah or blah.a1
+ // as a (wrong) reference.
+ if( nFlags & ( SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB ) )
+ {
++ if (aExtInfo.mbExternal)
++ fprintf(stdout, "ScCompiler::IsSingleReference: this is an external single ref\n");
++ else
++ fprintf(stdout, "ScCompiler::IsSingleReference: this is an internal single ref\n");
++
+ ScRawToken aToken;
+ SingleRefData aRef;
+ aRef.InitAddress( aAddr );
+@@ -2561,16 +2892,28 @@ BOOL ScCompiler::IsSingleReference( const String& rName )
+ nFlags |= SCA_VALID;
+ }
+ aRef.CalcRelFromAbs( aPos );
+- aToken.SetSingleReference( aRef );
++ fprintf(stdout, "ScCompiler::IsSingleReference: abs col = %d; row = %d; tab = %d\n", aRef.nCol, aRef.nRow, aRef.nTab);
++ fprintf(stdout, "ScCompiler::IsSingleReference: rel col = %d; row = %d; tab = %d\n",
++ aRef.nRelCol, aRef.nRelRow, aRef.nRelTab);
++ fprintf(stdout, "ScCompiler::IsSingleReference: col rel (%d); row rel (%d); tab rel (%d)\n",
++ aRef.IsColRel(), aRef.IsRowRel(), aRef.IsTabRel());
++
++ if (aExtInfo.mbExternal)
++ aToken.SetExternalSingleRef(aExtInfo.mnFileId, aExtInfo.maTabName, aRef);
++ else
++ aToken.SetSingleReference(aRef);
+ pRawToken = aToken.Clone();
+ }
+
++ fprintf(stdout, "ScCompiler::IsSingleReference: is single ref? (%s)\n", (nFlags&SCA_VALID)?"yes":"no");
+ return ( nFlags & SCA_VALID ) != 0;
+ }
+
+
+ BOOL ScCompiler::IsReference( const String& rName )
+ {
++ StackPrinter aStack("ScCompiler::IsReference");
++
+ // Has to be called before IsValue
+ sal_Unicode ch1 = rName.GetChar(0);
+ sal_Unicode cDecSep = ( mxSymbols->isEnglish() ? '.' :
+@@ -2669,6 +3012,30 @@ BOOL ScCompiler::IsNamedRange( const String& rUpperName )
return FALSE;
}
@@ -914,7 +1467,7 @@
BOOL ScCompiler::IsDBRange( const String& rName )
{
USHORT n;
-@@ -3267,6 +3538,7 @@ BOOL ScCompiler::NextNewToken( bool bInArray )
+@@ -3267,6 +3634,7 @@ BOOL ScCompiler::NextNewToken( bool bInArray )
&& !(bAllowBooleans && IsBoolean( aUpper ))
&& !IsValue( aUpper )
&& !IsNamedRange( aUpper )
@@ -922,7 +1475,7 @@
&& !IsDBRange( aUpper )
&& !IsColRowName( aUpper )
&& !(bMayBeFuncName && IsMacro( aUpper ))
-@@ -3593,6 +3865,69 @@ BOOL ScCompiler::GetToken()
+@@ -3593,6 +3961,69 @@ BOOL ScCompiler::GetToken()
}
if( pToken->GetOpCode() == ocSubTotal )
glSubTotal = TRUE;
@@ -959,7 +1512,7 @@
+
+ aData.CalcAbsIfRel(aPos);
+ ScAddress aAddr(aData.nCol, aData.nRow, aData.nTab);
-+ ScToken* pNew = pRefMgr->getSingleRefToken(pToken->GetIndex(), aAddr, &aPos);
++ ScToken* pNew = pRefMgr->getSingleRefToken(pToken->GetIndex(), pToken->GetString(), aAddr, &aPos, NULL);
+ if (pNew)
+ {
+ pToken = pNew->Clone();
@@ -978,7 +1531,7 @@
+ 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);
++ ScTokenArray* pNew = pRefMgr->getDoubleRefTokens(pToken->GetIndex(), pToken->GetString(), aRange, &aPos);
+ if (pNew)
+ {
+ PushTokenArray(pNew->Clone(), true);
@@ -992,46 +1545,323 @@
else if( pToken->GetOpCode() == ocName )
{
ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( pToken->GetIndex() );
-@@ -5543,6 +5878,15 @@ ScToken* ScCompiler::CreateStringFromToken( rtl::OUStringBuffer& rBuffer, ScToke
+@@ -5543,6 +5974,7 @@ ScToken* ScCompiler::CreateStringFromToken( rtl::OUStringBuffer& rBuffer, ScToke
BOOL bSpaces = FALSE;
ScToken* t = pTokenP;
OpCode eOp = t->GetOpCode();
-+ if (eOp == ocExternalName)
-+ {
-+ const String *pStr = pDoc->GetExternalRefManager()->getExternalFileName(t->GetIndex());
-+ if (pStr)
-+ {
-+ rBuffer.append(pConv->makeExternalNameStr(*pStr, t->GetString()));
-+ }
-+ }
+
if( eOp >= ocAnd && eOp <= ocOr )
{
// AND, OR infix?
+@@ -5590,111 +6022,141 @@ ScToken* ScCompiler::CreateStringFromToken( rtl::OUStringBuffer& rBuffer, ScToke
+ DBG_ERRORFILE("unknown OpCode");
+ rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
+ }
+- if( bNext ) switch( t->GetType() )
++ if (bNext)
+ {
+- case svDouble:
+- AppendDouble( rBuffer, t->GetDouble() );
+- break;
+-
+- case svString:
+- if( eOp == ocBad )
+- rBuffer.append(t->GetString());
+- else
+- AppendString( rBuffer, t->GetString() );
+- break;
+- case svSingleRef:
++ if (eOp == ocExternalName)
+ {
+- SingleRefData& rRef = t->GetSingleRef();
+- ComplRefData aRef;
+- aRef.Ref1 = aRef.Ref2 = rRef;
+- if ( eOp == ocColRowName )
++ fprintf(stdout, "ScCompiler::CreateStringFromToken: external name token\n");
++ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
++ switch (t->GetType())
+ {
+- rRef.CalcAbsIfRel( aPos );
+- if ( pDoc->HasStringData( rRef.nCol, rRef.nRow, rRef.nTab ) )
+- {
+- String aStr;
+- pDoc->GetString( rRef.nCol, rRef.nRow, rRef.nTab, aStr );
+- EnQuote( aStr );
+- rBuffer.append(aStr);
+- }
+- else
++ case svExternalName:
+ {
+- rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
+- pConv->MakeRefStr (rBuffer, *this, aRef, TRUE );
++ const String *pStr = pRefMgr->getExternalFileName(t->GetIndex());
++ String aFileName = pStr ? *pStr : ScGlobal::GetRscString(STR_NO_NAME_REF);
++ rBuffer.append(pConv->makeExternalNameStr(
++ aFileName, t->GetString()));
+ }
++ break;
++ case svSingleRef:
++ pConv->makeExternalRefStr(
++ rBuffer, *this, t->GetIndex(), t->GetString(), t->GetSingleRef(), pRefMgr);
++ break;
++ case svDoubleRef:
++ pConv->makeExternalRefStr(
++ rBuffer, *this, t->GetIndex(), t->GetString(), t->GetDoubleRef(), pRefMgr);
++ break;
+ }
+- else
+- pConv->MakeRefStr( rBuffer, *this, aRef, TRUE );
+ }
+- break;
+- case svDoubleRef:
+- pConv->MakeRefStr( rBuffer, *this, t->GetDoubleRef(), FALSE );
+- break;
+- case svMatrix:
+- CreateStringFromScMatrix( rBuffer, t->GetMatrix() );
+- break;
+-
+- case svIndex:
++ else
+ {
+- rtl::OUStringBuffer aBuffer;
+- switch ( eOp )
++ switch( t->GetType() )
+ {
+- case ocName:
++ case svDouble:
++ AppendDouble( rBuffer, t->GetDouble() );
++ break;
++
++ case svString:
++ if( eOp == ocBad )
++ rBuffer.append(t->GetString());
++ else
++ AppendString( rBuffer, t->GetString() );
++ break;
++ case svSingleRef:
+ {
+- ScRangeData* pData = pDoc->GetRangeName()->FindIndex(t->GetIndex());
+- if (pData)
++ SingleRefData& rRef = t->GetSingleRef();
++ ComplRefData aRef;
++ aRef.Ref1 = aRef.Ref2 = rRef;
++ if ( eOp == ocColRowName )
+ {
+- if (pData->HasType(RT_SHARED))
+- pData->UpdateSymbol( aBuffer, aPos, GetGrammar());
++ rRef.CalcAbsIfRel( aPos );
++ if ( pDoc->HasStringData( rRef.nCol, rRef.nRow, rRef.nTab ) )
++ {
++ String aStr;
++ pDoc->GetString( rRef.nCol, rRef.nRow, rRef.nTab, aStr );
++ EnQuote( aStr );
++ rBuffer.append(aStr);
++ }
+ else
+- aBuffer.append(pData->GetName());
++ {
++ rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
++ pConv->MakeRefStr (rBuffer, *this, aRef, TRUE );
++ }
+ }
++ else
++ pConv->MakeRefStr( rBuffer, *this, aRef, TRUE );
+ }
+- break;
+- case ocDBArea:
++ break;
++ case svDoubleRef:
++ pConv->MakeRefStr( rBuffer, *this, t->GetDoubleRef(), FALSE );
++ break;
++ case svMatrix:
++ CreateStringFromScMatrix( rBuffer, t->GetMatrix() );
++ break;
++
++ case svIndex:
+ {
+- ScDBData* pDBData = pDoc->GetDBCollection()->FindIndex(t->GetIndex());
+- if (pDBData)
+- aBuffer.append(pDBData->GetName());
++ rtl::OUStringBuffer aBuffer;
++ switch ( eOp )
++ {
++ case ocName:
++ {
++ ScRangeData* pData = pDoc->GetRangeName()->FindIndex(t->GetIndex());
++ if (pData)
++ {
++ if (pData->HasType(RT_SHARED))
++ pData->UpdateSymbol( aBuffer, aPos, GetGrammar());
++ else
++ aBuffer.append(pData->GetName());
++ }
++ }
++ break;
++ case ocDBArea:
++ {
++ ScDBData* pDBData = pDoc->GetDBCollection()->FindIndex(t->GetIndex());
++ if (pDBData)
++ aBuffer.append(pDBData->GetName());
++ }
++ break;
++ default:
++ ; // nothing
++ }
++ if ( aBuffer.getLength() )
++ rBuffer.append(aBuffer);
++ else
++ rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
++ break;
+ }
+- break;
+- default:
+- ; // nothing
+- }
+- if ( aBuffer.getLength() )
+- rBuffer.append(aBuffer);
+- else
+- rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
+- break;
+- }
+- case svExternal:
+- {
+- // mapped or translated name of AddIns
+- String aAddIn( t->GetExternal() );
+- bool bMapped = mxSymbols->isPODF(); // ODF 1.1 directly uses programmatical name
+- if (!bMapped && mxSymbols->hasExternals())
+- {
+- ScExternalHashMap::const_iterator iLook = mxSymbols->getReverseExternalHashMap()->find( aAddIn);
+- if (iLook != mxSymbols->getReverseExternalHashMap()->end())
++ case svExternal:
+ {
+- aAddIn = (*iLook).second;
+- bMapped = true;
++ // mapped or translated name of AddIns
++ String aAddIn( t->GetExternal() );
++ bool bMapped = mxSymbols->isPODF(); // ODF 1.1 directly uses programmatical name
++ if (!bMapped && mxSymbols->hasExternals())
++ {
++ ScExternalHashMap::const_iterator iLook = mxSymbols->getReverseExternalHashMap()->find( aAddIn);
++ if (iLook != mxSymbols->getReverseExternalHashMap()->end())
++ {
++ aAddIn = (*iLook).second;
++ bMapped = true;
++ }
++ }
++ if (!bMapped && !mxSymbols->isEnglish())
++ ScGlobal::GetAddInCollection()->LocalizeString( aAddIn );
++ rBuffer.append(aAddIn);
+ }
+- }
+- if (!bMapped && !mxSymbols->isEnglish())
+- ScGlobal::GetAddInCollection()->LocalizeString( aAddIn );
+- rBuffer.append(aAddIn);
++ break;
++ case svByte:
++ case svJump:
++ case svFAP:
++ case svMissing:
++ case svSep:
++ break; // Opcodes
++ default:
++ DBG_ERROR("ScCompiler:: GetStringFromToken errUnknownVariable");
++ } // of switch
+ }
+- break;
+- case svByte:
+- case svJump:
+- case svFAP:
+- case svMissing:
+- case svSep:
+- break; // Opcodes
+- default:
+- DBG_ERROR("ScCompiler:: GetStringFromToken errUnknownVariable");
+- } // of switch
++ }
+ if( bSpaces )
+ rBuffer.append(sal_Unicode(' '));
+ if ( bAllowArrAdvance )
diff --git sc/source/core/tool/token.cxx sc/source/core/tool/token.cxx
-index a20cbd5..5486519 100644
+index a20cbd5..25090a8 100644
--- sc/source/core/tool/token.cxx
+++ sc/source/core/tool/token.cxx
-@@ -54,6 +54,8 @@
+@@ -54,6 +54,33 @@
#include "parclass.hxx"
#include "jumpmatrix.hxx"
+using ::std::vector;
+
- // ImpTokenIterator wird je Interpreter angelegt, mehrfache auch durch
- // SubCode via ScTokenIterator Push/Pop moeglich
- IMPL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator, 32, 16 )
-@@ -209,6 +211,19 @@ void ScRawToken::SetName( USHORT n )
- nRefCnt = 0;
- }
-
-+void ScRawToken::SetExternalName( sal_uInt16 nFileId, const String& rName )
-+{
-+ eOp = ocExternalName;
-+ eType = svExternalName;
-+ nRefCnt = 0;
+
-+ extname.nFileId = nFileId;
++namespace {
++
++#include <string>
++
++class StackPrinter
++{
++public:
++ explicit StackPrinter(const char* msg) :
++ msMsg(msg)
++ {
++ fprintf(stdout, "%s: --begin\n", msMsg.c_str());
++ }
++
++ ~StackPrinter()
++ {
++ fprintf(stdout, "%s: --end\n", msMsg.c_str());
++ }
++
++private:
++ ::std::string msMsg;
++};
++
++}
++
+ // ImpTokenIterator wird je Interpreter angelegt, mehrfache auch durch
+ // SubCode via ScTokenIterator Push/Pop moeglich
+ IMPL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator, 32, 16 )
+@@ -209,6 +236,51 @@ void ScRawToken::SetName( USHORT n )
+ nRefCnt = 0;
+ }
+
++void ScRawToken::SetExternalSingleRef( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef )
++{
++ eOp = ocExternalName;
++ eType = svSingleRef;
++ nRefCnt = 0;
++
++ extref.nFileId = nFileId;
++ extref.aRef.Ref1 =
++ extref.aRef.Ref2 = rRef;
++
++ xub_StrLen n = rTabName.Len();
++ fprintf(stdout, "ScRawToken::SetExternalSingleRef: tab name = '%s'; len = %d\n",
++ rtl::OUStringToOString(rTabName, RTL_TEXTENCODING_UTF8).getStr(), n);
++
++ memcpy(extref.cTabName, rTabName.GetBuffer(), n*sizeof(sal_Unicode));
++ extref.cTabName[n] = 0;
++}
++
++void ScRawToken::SetExternalDoubleRef( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef )
++{
++ eOp = ocExternalName;
++ eType = svDoubleRef;
++ nRefCnt = 0;
++
++ extref.nFileId = nFileId;
++ extref.aRef = rRef;
++
++ xub_StrLen n = rTabName.Len();
++ memcpy(extref.cTabName, rTabName.GetBuffer(), n*sizeof(sal_Unicode));
++ extref.cTabName[n] = 0;
++}
++
++void ScRawToken::SetExternalName( sal_uInt16 nFileId, const String& rName )
++{
++ eOp = ocExternalName;
++ eType = svExternalName;
++ nRefCnt = 0;
++
++ extname.nFileId = nFileId;
+
+ xub_StrLen n = rName.Len();
+ memcpy(extname.cName, rName.GetBuffer(), n*sizeof(sal_Unicode));
@@ -1041,19 +1871,81 @@
ComplRefData& ScRawToken::GetReference()
{
DBG_ASSERT( lcl_IsReference( eOp, GetType() ), "GetReference: no Ref" );
-@@ -269,6 +284,7 @@ ScRawToken* ScRawToken::Clone() const
- case svSingleRef:
- case svDoubleRef: n += sizeof(aRef); break;
- case svMatrix: n += sizeof(ScMatrix*); break;
-+ case svExternalName: n += sizeof(extname); break;
- case svIndex: n += sizeof(USHORT); break;
- case svJump: n += nJump[ 0 ] * 2 + 2; break;
- case svExternal: n = sal::static_int_cast<USHORT>( n + GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ) ); break;
-@@ -325,8 +341,14 @@ ScToken* ScRawToken::CreateToken() const
- return new ScMatrixToken( pMat );
+@@ -260,22 +332,34 @@ ScRawToken* ScRawToken::Clone() const
+ static USHORT nOffset = lcl_ScRawTokenOffset(); // offset of sbyte
+ USHORT n = nOffset;
+
+- switch( eType )
++ if (eOp == ocExternalName)
+ {
+- case svSep: break;
+- case svByte: n += sizeof(ScRawToken::sbyte); break;
+- case svDouble: n += sizeof(double); break;
+- case svString: n = sal::static_int_cast<USHORT>( n + GetStrLenBytes( cStr ) + GetStrLenBytes( 1 ) ); break;
+- case svSingleRef:
+- case svDoubleRef: n += sizeof(aRef); break;
+- case svMatrix: n += sizeof(ScMatrix*); break;
+- case svIndex: n += sizeof(USHORT); break;
+- case svJump: n += nJump[ 0 ] * 2 + 2; break;
+- case svExternal: n = sal::static_int_cast<USHORT>( n + GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ) ); break;
+- default:
+- {
+- DBG_ERROR1( "unknown ScRawToken::Clone() type %d", int(eType));
+- }
++ switch (eType)
++ {
++ case svSingleRef:
++ case svDoubleRef: n += sizeof(extref); break;
++ case svExternalName: n += sizeof(extname); break;
++ }
++ }
++ else
++ {
++ switch( eType )
++ {
++ case svSep: break;
++ case svByte: n += sizeof(ScRawToken::sbyte); break;
++ case svDouble: n += sizeof(double); break;
++ case svString: n = sal::static_int_cast<USHORT>( n + GetStrLenBytes( cStr ) + GetStrLenBytes( 1 ) ); break;
++ case svSingleRef:
++ case svDoubleRef: n += sizeof(aRef); break;
++ case svMatrix: n += sizeof(ScMatrix*); break;
++ case svIndex: n += sizeof(USHORT); break;
++ case svJump: n += nJump[ 0 ] * 2 + 2; break;
++ case svExternal: n = sal::static_int_cast<USHORT>( n + GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ) ); break;
++ default:
++ {
++ DBG_ERROR1( "unknown ScRawToken::Clone() type %d", int(eType));
++ }
++ }
+ }
+ p = (ScRawToken*) new BYTE[ n ];
+ memcpy( p, this, n * sizeof(BYTE) );
+@@ -311,12 +395,22 @@ ScToken* ScRawToken::CreateToken() const
+ case svSingleRef :
+ if (eOp == ocPush)
+ return new ScSingleRefToken( aRef.Ref1 );
++ else if (eOp == ocExternalName)
++ {
++ String aTabName(extref.cTabName);
++ return new ScExternalSingleRefToken(extref.nFileId, aTabName, extref.aRef.Ref1);
++ }
+ else
+ return new ScSingleRefOpToken( eOp, aRef.Ref1 );
//break;
+ case svDoubleRef :
+ if (eOp == ocPush)
+ return new ScDoubleRefToken( aRef );
++ else if (eOp == ocExternalName)
++ {
++ String aTabName(extref.cTabName);
++ return new ScExternalDoubleRefToken(extref.nFileId, aTabName, extref.aRef);
++ }
+ else
+ return new ScDoubleRefOpToken( eOp, aRef );
+ //break;
+@@ -327,6 +421,11 @@ ScToken* ScRawToken::CreateToken() const
case svIndex :
-+ fprintf(stdout, "ScRawToken::CreateToken: creating index token ... (op = %d)\n", eOp);
return new ScIndexToken( eOp, nIndex );
//break;
+ case svExternalName:
@@ -1064,7 +1956,7 @@
case svJump :
return new ScJumpToken( eOp, (short*) nJump );
//break;
-@@ -478,6 +500,7 @@ BOOL ScToken::IsMatrixFunction() const
+@@ -478,6 +577,7 @@ BOOL ScToken::IsMatrixFunction() const
ScToken* ScToken::Clone() const
{
@@ -1072,7 +1964,7 @@
switch ( GetType() )
{
case svByte :
-@@ -487,20 +510,24 @@ ScToken* ScToken::Clone() const
+@@ -487,20 +587,24 @@ ScToken* ScToken::Clone() const
return new ScDoubleToken( *static_cast<const ScDoubleToken*>(this) );
//break;
case svString :
@@ -1100,7 +1992,7 @@
else
return new ScDoubleRefOpToken( *static_cast<const ScDoubleRefOpToken*>(this) );
//break;
-@@ -522,6 +549,9 @@ ScToken* ScToken::Clone() const
+@@ -522,6 +626,9 @@ ScToken* ScToken::Clone() const
case svExternal :
return new ScExternalToken( *static_cast<const ScExternalToken*>(this) );
//break;
@@ -1110,15 +2002,48 @@
case svFAP :
return new ScFAPToken( *static_cast<const ScFAPToken*>(this) );
//break;
-@@ -1035,6 +1065,150 @@ BOOL ScIndexToken::operator==( const ScToken& r ) const
+@@ -660,6 +767,7 @@ ScTokenRef ScToken::ExtendRangeReference( ScToken & rTok1, ScToken & rTok2,
+ return NULL;
+
+ ScTokenRef xRes;
++ bool bExternal = rTok1.GetOpCode() == ocExternalName;
+ if (sv1 == svSingleRef && sv2 == svSingleRef)
+ {
+ // Range references like Sheet1.A1:A2 are generalized and built by
+@@ -671,7 +779,10 @@ ScTokenRef ScToken::ExtendRangeReference( ScToken & rTok1, ScToken & rTok2,
+ aRef.Ref1 = aRef.Ref2 = p1->GetSingleRef();
+ aRef.Ref2.SetFlag3D( false);
+ aRef.Extend( p2->GetSingleRef(), rPos);
+- xRes = new ScDoubleRefToken( aRef);
++ if (bExternal)
++ xRes = new ScExternalDoubleRefToken(rTok1.GetIndex(), rTok1.GetString(), aRef);
++ else
++ xRes = new ScDoubleRefToken( aRef);
+ }
+ else
+ {
+@@ -694,7 +805,10 @@ ScTokenRef ScToken::ExtendRangeReference( ScToken & rTok1, ScToken & rTok2,
+ {
+ if (!pRefList->size())
+ return NULL;
+- xRes = new ScDoubleRefToken( (*pRefList)[0] );
++ if (bExternal)
++ xRes = new ScExternalDoubleRefToken(rTok1.GetIndex(), rTok1.GetString(), (*pRefList)[0]);
++ else
++ xRes = new ScDoubleRefToken( (*pRefList)[0] );
+ }
+ if (!xRes)
+ return NULL; // shouldn't happen..
+@@ -1035,6 +1149,170 @@ BOOL ScIndexToken::operator==( const ScToken& r ) const
return ScToken::operator==( r ) && nIndex == r.GetIndex();
}
+// ============================================================================
+
-+ScExternalSingleRefToken::ScExternalSingleRefToken( sal_uInt16 nFileId, const SingleRefData& r ) :
++ScExternalSingleRefToken::ScExternalSingleRefToken( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& r ) :
+ ScOpToken(ocExternalName, svSingleRef),
+ mnFileId(nFileId),
++ maTabName(rTabName),
+ maSingleRef(r)
+{
+}
@@ -1126,6 +2051,7 @@
+ScExternalSingleRefToken::ScExternalSingleRefToken( const ScExternalSingleRefToken& r ) :
+ ScOpToken(r),
+ mnFileId(r.mnFileId),
++ maTabName(r.maTabName),
+ maSingleRef(r.maSingleRef)
+{
+}
@@ -1139,6 +2065,11 @@
+ return mnFileId;
+}
+
++const String& ScExternalSingleRefToken::GetString() const
++{
++ return maTabName;
++}
++
+const SingleRefData& ScExternalSingleRefToken::GetSingleRef() const
+{
+ return maSingleRef;
@@ -1157,14 +2088,18 @@
+ if (mnFileId != r.GetIndex())
+ return false;
+
++ if (maTabName != r.GetString())
++ return false;
++
+ return maSingleRef == r.GetSingleRef();
+}
+
+// ============================================================================
+
-+ScExternalDoubleRefToken::ScExternalDoubleRefToken( sal_uInt16 nFileId, const ComplRefData& r ) :
++ScExternalDoubleRefToken::ScExternalDoubleRefToken( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& r ) :
+ ScOpToken(ocExternalName, svDoubleRef),
+ mnFileId(nFileId),
++ maTabName(rTabName),
+ maDoubleRef(r)
+{
+}
@@ -1172,6 +2107,7 @@
+ScExternalDoubleRefToken::ScExternalDoubleRefToken( const ScExternalDoubleRefToken& r ) :
+ ScOpToken(r),
+ mnFileId(r.mnFileId),
++ maTabName(r.maTabName),
+ maDoubleRef(r.maDoubleRef)
+{
+}
@@ -1185,6 +2121,11 @@
+ return mnFileId;
+}
+
++const String& ScExternalDoubleRefToken::GetString() const
++{
++ return maTabName;
++}
++
+const ComplRefData& ScExternalDoubleRefToken::GetDoubleRef() const
+{
+ return maDoubleRef;
@@ -1203,6 +2144,9 @@
+ if (mnFileId != r.GetIndex())
+ return false;
+
++ if (maTabName != r.GetString())
++ return false;
++
+ return maDoubleRef == r.GetDoubleRef();
+}
+
@@ -1261,7 +2205,7 @@
short* ScJumpToken::GetJump() const { return pJump; }
BOOL ScJumpToken::operator==( const ScToken& r ) const
-@@ -1893,6 +2067,11 @@ ScToken* ScTokenArray::AddMatrix( ScMatrix* p )
+@@ -1893,6 +2171,21 @@ ScToken* ScTokenArray::AddMatrix( ScMatrix* p )
return Add( new ScMatrixToken( p ) );
}
@@ -1270,51 +2214,341 @@
+ return Add( new ScExternalNameToken(nFileId, rName) );
+}
+
++ScToken* ScTokenArray::AddExternalSingleReference( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef )
++{
++ return Add( new ScExternalSingleRefToken(nFileId, rTabName, rRef) );
++}
++
++ScToken* ScTokenArray::AddExternalDoubleReference( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef )
++{
++ return Add( new ScExternalDoubleRefToken(nFileId, rTabName, rRef) );
++}
++
ScToken* ScTokenArray::AddColRowName( const SingleRefData& rRef )
{
return Add( new ScSingleRefOpToken( ocColRowName, rRef ) );
diff --git sc/source/filter/excel/excform8.cxx sc/source/filter/excel/excform8.cxx
-index ebf8543..da9ded9 100644
+index ebf8543..e4968c2 100644
--- sc/source/filter/excel/excform8.cxx
+++ sc/source/filter/excel/excform8.cxx
-@@ -41,6 +41,7 @@
+@@ -41,6 +41,32 @@
#include "xilink.hxx"
#include "xiname.hxx"
+#include "externalrefmgr.hxx"
++
++
++namespace {
++
++#include <string>
++
++class StackPrinter
++{
++public:
++ explicit StackPrinter(const char* msg) :
++ msMsg(msg)
++ {
++ fprintf(stdout, "%s: --begin\n", msMsg.c_str());
++ }
++
++ ~StackPrinter()
++ {
++ fprintf(stdout, "%s: --end\n", msMsg.c_str());
++ }
++
++private:
++ ::std::string msMsg;
++};
++
++}
ExcelToSc8::ExcelToSc8( const XclImpRoot& rRoot ) :
ExcelToSc( rRoot ),
-@@ -608,8 +609,22 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
+@@ -53,15 +79,23 @@ ExcelToSc8::~ExcelToSc8()
+ {
+ }
+
+-
+-BOOL ExcelToSc8::Read3DTabReference( XclImpStream& rStrm, SCTAB& rFirstTab, SCTAB& rLastTab )
++bool ExcelToSc8::GetExternalFileIdFromXti( UINT16 nIxti, sal_uInt16& rFileId ) const
+ {
+- rFirstTab = rLastTab = 0;
++ const String* pFileUrl = rLinkMan.GetSupbookUrl(nIxti);
++ if (!pFileUrl || pFileUrl->Len() == 0)
++ return false;
+
+- UINT16 nIxti;
+- rStrm >> nIxti;
++ String aFileUrl = ScGlobal::GetAbsDocName(*pFileUrl, GetDocShell());
++ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
++ rFileId = pRefMgr->getExternalFileId(aFileUrl);
+
+- return rLinkMan.GetScTabRange( rFirstTab, rLastTab, nIxti );
++ return true;
++}
++
++bool ExcelToSc8::Read3DTabReference( SCTAB& rFirstTab, SCTAB& rLastTab, UINT16 nIxti )
++{
++ rFirstTab = rLastTab = 0;
++ return rLinkMan.GetScTabRange(rFirstTab, rLastTab, nIxti);
+ }
+
+
+@@ -608,8 +642,14 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
{
case xlExtName:
{
- aStack << aPool.Store( ocNoName, pExtName->GetName() );
- GetTracer().TraceFormulaExtName();
-+ const String* pFileUrl = rLinkMan.GetSupbookUrl(nXtiIndex);
-+ if (!pFileUrl)
-+ {
++ sal_uInt16 nFileId;
++ if (!GetExternalFileIdFromXti(nXtiIndex, nFileId))
++ {
+ aStack << aPool.Store(ocNoName, pExtName->GetName());
+ break;
+ }
+
-+ String aFileUrl = ScGlobal::GetAbsDocName(*pFileUrl, GetDocShell());
-+ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
-+ sal_uInt16 nFileId = pRefMgr->getExternalFileId(aFileUrl);
-+ fprintf(stdout, "ExcelToSc8::Convert: external name (file: %s; name: %s; file id: %d)\n",
-+ rtl::OUStringToOString(aFileUrl, RTL_TEXTENCODING_UTF8).getStr(),
-+ rtl::OUStringToOString(pExtName->GetName(), RTL_TEXTENCODING_UTF8).getStr(),
-+ nFileId);
-+
+ aStack << aPool.StoreExtName(nFileId, pExtName->GetName());
}
break;
+@@ -657,47 +697,81 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
+ case 0x7C:
+ case 0x3C: // Deleted 3-D Cell Reference [ 277]
+ {
+- UINT16 nRw, nGrbitCol;
++ fprintf(stdout, "ExcelToSc8::Convert: cell reference\n");
++ UINT16 nIxti, nRw, nGrbitCol;
+ SCTAB nTabFirst, nTabLast;
+
+- BOOL bOK = Read3DTabReference( aIn, nTabFirst, nTabLast );
+- aIn >> nRw >> nGrbitCol;
++ aIn >> nIxti >> nRw >> nGrbitCol;
+
+- if( bOK )
+- {
+- aSRD.nTab = nTabFirst;
+- aSRD.SetFlag3D( TRUE );
+- aSRD.SetTabRel( FALSE );
++ if (!Read3DTabReference(nTabFirst, nTabLast, nIxti))
++ {
++ aPool << ocBad;
++ aPool >> aStack;
++ break;
++ }
+
+- ExcRelToScRel8( nRw, nGrbitCol, aSRD, bRangeName );
++ bool bExternal = !rLinkMan.IsSelfRef(nIxti);
++ fprintf(stdout, "ExcelToSc8::Convert: first tab = %d; last tab = %d; external (%d)\n", nTabFirst, nTabLast, bExternal);
+
+- switch ( nOp )
+- {
+- case 0x5C:
+- case 0x7C:
+- case 0x3C: // Deleted 3-D Cell Reference [ 277]
+- // no information which part is deleted, set both
+- aSRD.SetColDeleted( TRUE );
+- aSRD.SetRowDeleted( TRUE );
+- }
+- if ( !ValidTab(nTabFirst) )
+- aSRD.SetTabDeleted( TRUE );
++ aSRD.nTab = nTabFirst;
++ aSRD.SetFlag3D( TRUE );
++ aSRD.SetTabRel( FALSE );
+
+- if( nTabLast != nTabFirst )
+- {
+- aCRD.Ref1 = aCRD.Ref2 = aSRD;
+- aCRD.Ref2.nTab = nTabLast;
++ ExcRelToScRel8( nRw, nGrbitCol, aSRD, bRangeName );
++
++ switch ( nOp )
++ {
++ case 0x5C:
++ case 0x7C:
++ case 0x3C: // Deleted 3-D Cell Reference [ 277]
++ // no information which part is deleted, set both
++ aSRD.SetColDeleted( TRUE );
++ aSRD.SetRowDeleted( TRUE );
++ }
++
++ if (bExternal)
++ {
++ // nTabFirst and nTabLast are the indices of the refernced
++ // sheets in the SUPBOOK record, hence do not represent
++ // the actual indices of the original sheets since the
++ // SUPBOOK record only stores referenced sheets and skips
++ // the ones that are not referenced.
++
++ const String& rTabName = rLinkMan.GetSupbookTabName(nIxti, nTabFirst);
++ fprintf(stdout, "ExcelToSc8::Convert: tab name of first sheet = '%s'\n",
++ rtl::OUStringToOString(rTabName, RTL_TEXTENCODING_UTF8).getStr());
++
++ sal_uInt16 nFileId;
++ if (!GetExternalFileIdFromXti(nIxti, nFileId))
++ {
++ aPool << ocBad;
++ aPool >> aStack;
++ break;
++ }
++ if (nTabLast != nTabFirst)
++ {
++ aCRD.Ref1 = aCRD.Ref2 = aSRD;
++ aCRD.Ref2.nTab = nTabLast;
++ aStack << aPool.StoreExtRef(nFileId, rTabName, aCRD);
++ }
++ else
++ aStack << aPool.StoreExtRef(nFileId, rTabName, aSRD);
++ }
++ else
++ {
++ if ( !ValidTab(nTabFirst))
++ aSRD.SetTabDeleted( TRUE );
++
++ if( nTabLast != nTabFirst )
++ {
++ aCRD.Ref1 = aCRD.Ref2 = aSRD;
++ aCRD.Ref2.nTab = nTabLast;
+ aCRD.Ref2.SetTabDeleted( !ValidTab(nTabLast) );
+- aStack << aPool.Store( aCRD );
+- }
+- else
+- aStack << aPool.Store( aSRD );
+- }
+- else
+- {
+- aPool << ocBad;
+- aPool >> aStack;
+- }
++ aStack << aPool.Store( aCRD );
++ }
++ else
++ aStack << aPool.Store( aSRD );
++ }
+ }
+ break;
+ case 0x5B:
+@@ -707,55 +781,75 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
+ case 0x7D:
+ case 0x3D: // Deleted 3-D Area Reference [ 277]
+ {
+- UINT16 nRw1, nGrbitCol1, nRw2, nGrbitCol2;
++ fprintf(stdout, "ExcelToSc8::Convert: area reference\n");
++ UINT16 nIxti, nRw1, nGrbitCol1, nRw2, nGrbitCol2;
+ SCTAB nTabFirst, nTabLast;
++ aIn >> nIxti >> nRw1 >> nRw2 >> nGrbitCol1 >> nGrbitCol2;
+
+- BOOL bOK = Read3DTabReference( aIn, nTabFirst, nTabLast );
+- aIn >> nRw1 >> nRw2 >> nGrbitCol1 >> nGrbitCol2;
+-
+- if( bOK )
++ if (!Read3DTabReference(nTabFirst, nTabLast, nIxti))
+ {
+- SingleRefData &rR1 = aCRD.Ref1;
+- SingleRefData &rR2 = aCRD.Ref2;
++ aPool << ocBad;
++ aPool >> aStack;
++ break;
++ }
+
+- rR1.nTab = nTabFirst;
+- rR2.nTab = nTabLast;
+- rR1.SetFlag3D( TRUE );
+- rR1.SetTabRel( FALSE );
+- rR2.SetFlag3D( nTabFirst != nTabLast );
+- rR2.SetTabRel( FALSE );
++ bool bExternal = !rLinkMan.IsSelfRef(nIxti);
++ fprintf(stdout, "ExcelToSc8::Convert: first tab = %d; last tab = %d; external (%d)\n", nTabFirst, nTabLast, bExternal);
++
++ SingleRefData &rR1 = aCRD.Ref1;
++ SingleRefData &rR2 = aCRD.Ref2;
+
+- ExcRelToScRel8( nRw1, nGrbitCol1, aCRD.Ref1, bRangeName );
+- ExcRelToScRel8( nRw2, nGrbitCol2, aCRD.Ref2, bRangeName );
++ rR1.nTab = nTabFirst;
++ rR2.nTab = nTabLast;
++ rR1.SetFlag3D( TRUE );
++ rR1.SetTabRel( FALSE );
++ rR2.SetFlag3D( nTabFirst != nTabLast );
++ rR2.SetTabRel( FALSE );
+
+- if( IsComplColRange( nGrbitCol1, nGrbitCol2 ) )
+- SetComplCol( aCRD );
+- else if( IsComplRowRange( nRw1, nRw2 ) )
+- SetComplRow( aCRD );
++ ExcRelToScRel8( nRw1, nGrbitCol1, aCRD.Ref1, bRangeName );
++ ExcRelToScRel8( nRw2, nGrbitCol2, aCRD.Ref2, bRangeName );
+
+- switch ( nOp )
+- {
+- case 0x5D:
+- case 0x7D:
+- case 0x3D: // Deleted 3-D Area Reference [ 277]
+- // no information which part is deleted, set all
+- rR1.SetColDeleted( TRUE );
+- rR1.SetRowDeleted( TRUE );
+- rR2.SetColDeleted( TRUE );
+- rR2.SetRowDeleted( TRUE );
+- }
+- if ( !ValidTab(nTabFirst) )
+- rR1.SetTabDeleted( TRUE );
+- if ( !ValidTab(nTabLast) )
+- rR2.SetTabDeleted( TRUE );
++ if( IsComplColRange( nGrbitCol1, nGrbitCol2 ) )
++ SetComplCol( aCRD );
++ else if( IsComplRowRange( nRw1, nRw2 ) )
++ SetComplRow( aCRD );
+
+- aStack << aPool.Store( aCRD );
+- }
+- else
+- {
+- aPool << ocBad;
+- aPool >> aStack;
+- }
++ switch ( nOp )
++ {
++ case 0x5D:
++ case 0x7D:
++ case 0x3D: // Deleted 3-D Area Reference [ 277]
++ // no information which part is deleted, set all
++ rR1.SetColDeleted( TRUE );
++ rR1.SetRowDeleted( TRUE );
++ rR2.SetColDeleted( TRUE );
++ rR2.SetRowDeleted( TRUE );
++ }
++
++ if (bExternal)
++ {
++ const String& rTabName = rLinkMan.GetSupbookTabName(nIxti, nTabFirst);
++ fprintf(stdout, "ExcelToSc8::Convert: tab name of first sheet = '%s'\n",
++ rtl::OUStringToOString(rTabName, RTL_TEXTENCODING_UTF8).getStr());
++
++ sal_uInt16 nFileId;
++ if (!GetExternalFileIdFromXti(nIxti, nFileId))
++ {
++ aPool << ocBad;
++ aPool >> aStack;
++ break;
++ }
++ aStack << aPool.StoreExtRef(nFileId, rTabName, aCRD);
++ }
++ else
++ {
++ if ( !ValidTab(nTabFirst) )
++ rR1.SetTabDeleted( TRUE );
++ if ( !ValidTab(nTabLast) )
++ rR2.SetTabDeleted( TRUE );
++
++ aStack << aPool.Store( aCRD );
++ }
+ }
+ break;
+ default: bError = TRUE;
diff --git sc/source/filter/excel/tokstack.cxx sc/source/filter/excel/tokstack.cxx
-index 20ada63..821a4ad 100644
+index 20ada63..9c4ddba 100644
--- sc/source/filter/excel/tokstack.cxx
+++ sc/source/filter/excel/tokstack.cxx
-@@ -395,6 +395,16 @@ void TokenPool::GetElement( const UINT16 nId )
+@@ -395,6 +395,34 @@ void TokenPool::GetElement( const UINT16 nId )
pScToken->AddMatrix( p );
}
break;
@@ -1327,11 +2561,29 @@
+ pScToken->AddExternalName(r.mnFileId, r.maName);
+ }
+ }
++ case T_ExtRefC:
++ {
++ UINT16 n = pElement[nId];
++ if (n < maExtCellRefs.size())
++ {
++ const ExtCellRef& r = maExtCellRefs[n];
++ pScToken->AddExternalSingleReference(r.mnFileId, r.maTabName, r.maRef);
++ }
++ }
++ case T_ExtRefA:
++ {
++ UINT16 n = pElement[nId];
++ if (n < maExtAreaRefs.size())
++ {
++ const ExtAreaRef& r = maExtAreaRefs[n];
++ pScToken->AddExternalDoubleReference(r.mnFileId, r.maTabName, r.maRef);
++ }
++ }
+ break;
default:
DBG_ERROR("-TokenPool::GetElement(): Zustand undefiniert!?");
}
-@@ -477,6 +487,16 @@ void TokenPool::GetElementRek( const UINT16 nId )
+@@ -477,6 +505,34 @@ void TokenPool::GetElementRek( const UINT16 nId )
pScToken->AddMatrix( p );
}
break;
@@ -1344,11 +2596,29 @@
+ pScToken->AddExternalName(r.mnFileId, r.maName);
+ }
+ }
++ case T_ExtRefC:
++ {
++ UINT16 n = pElement[*pAkt];
++ if (n < maExtCellRefs.size())
++ {
++ const ExtCellRef& r = maExtCellRefs[n];
++ pScToken->AddExternalSingleReference(r.mnFileId, r.maTabName, r.maRef);
++ }
++ }
++ case T_ExtRefA:
++ {
++ UINT16 n = pElement[*pAkt];
++ if (n < maExtAreaRefs.size())
++ {
++ const ExtAreaRef& r = maExtAreaRefs[n];
++ pScToken->AddExternalDoubleReference(r.mnFileId, r.maTabName, r.maRef);
++ }
++ }
+ break;
default:
DBG_ERROR("-TokenPool::GetElementRek(): Zustand undefiniert!?");
}
-@@ -724,9 +744,28 @@ const TokenId TokenPool::StoreMatrix( SCSIZE nC, SCSIZE nR )
+@@ -724,9 +780,68 @@ const TokenId TokenPool::StoreMatrix( SCSIZE nC, SCSIZE nR )
return ( const TokenId ) nElementAkt;
}
@@ -1370,15 +2640,55 @@
+ return static_cast<const TokenId>(nElementAkt);
+}
+
++const TokenId TokenPool::StoreExtRef( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef )
++{
++ if ( nElementAkt >= nElement )
++ GrowElement();
++
++ pElement[nElementAkt] = static_cast<UINT16>(maExtCellRefs.size());
++ pType[nElementAkt] = T_ExtRefC;
++
++ maExtCellRefs.push_back(ExtCellRef());
++ ExtCellRef& r = maExtCellRefs.back();
++ r.mnFileId = nFileId;
++ r.maTabName = rTabName;
++ r.maRef = rRef;
++
++ ++nElementAkt;
++
++ return static_cast<const TokenId>(nElementAkt);
++}
++
++const TokenId TokenPool::StoreExtRef( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef )
++{
++ if ( nElementAkt >= nElement )
++ GrowElement();
++
++ pElement[nElementAkt] = static_cast<UINT16>(maExtAreaRefs.size());
++ pType[nElementAkt] = T_ExtRefA;
++
++ maExtAreaRefs.push_back(ExtAreaRef());
++ ExtAreaRef& r = maExtAreaRefs.back();
++ r.mnFileId = nFileId;
++ r.maTabName = rTabName;
++ r.maRef = rRef;
++
++ ++nElementAkt;
++
++ return static_cast<const TokenId>(nElementAkt);
++}
++
void TokenPool::Reset( void )
{
nP_IdAkt = nP_IdLast = nElementAkt = nP_StrAkt = nP_DblAkt = nP_ErrAkt = nP_RefTrAkt = nP_ExtAkt = nP_NlfAkt = nP_MatrixAkt = 0;
+ maExtNames.clear();
++ maExtCellRefs.clear();
++ maExtAreaRefs.clear();
}
diff --git sc/source/filter/excel/xeformula.cxx sc/source/filter/excel/xeformula.cxx
-index 3db8da7..97692bc 100644
+index 3db8da7..65a5775 100644
--- sc/source/filter/excel/xeformula.cxx
+++ sc/source/filter/excel/xeformula.cxx
@@ -42,6 +42,12 @@
@@ -1394,7 +2704,40 @@
// External reference log =====================================================
XclExpRefLogEntry::XclExpRefLogEntry() :
-@@ -299,6 +305,7 @@ private:
+@@ -225,6 +231,32 @@ void XclExpFuncData::IncExpParamClassIdx()
+ ++mnClassIdx;
+ }
+
++// reference handling ---------------------------------------------------------
++
++namespace {
++
++inline bool lclIsRefRel2D( const SingleRefData& rRefData )
++{
++ return rRefData.IsColRel() || rRefData.IsRowRel();
++}
++
++inline bool lclIsRefDel2D( const SingleRefData& rRefData )
++{
++ return rRefData.IsColDeleted() || rRefData.IsRowDeleted();
++}
++
++inline bool lclIsRefRel2D( const ComplRefData& rRefData )
++{
++ return lclIsRefRel2D( rRefData.Ref1 ) || lclIsRefRel2D( rRefData.Ref2 );
++}
++
++inline bool lclIsRefDel2D( const ComplRefData& rRefData )
++{
++ return lclIsRefDel2D( rRefData.Ref1 ) || lclIsRefDel2D( rRefData.Ref2 );
++}
++
++} // namespace
++
+ // ----------------------------------------------------------------------------
+
+ /** Implementation class of the export formula compiler. */
+@@ -299,6 +331,7 @@ private:
void ProcessBoolean( const XclExpTokenData& rTokData );
void ProcessDdeLink( const XclExpTokenData& rTokData, sal_uInt8 nExpClass );
void ProcessExternal( const XclExpTokenData& rTokData, sal_uInt8 nExpClass );
@@ -1402,7 +2745,7 @@
void ProcessFunction( const XclExpTokenData& rTokData, sal_uInt8 nExpClass );
void PrepareFunction( XclExpFuncData& rFuncData );
-@@ -1114,6 +1121,12 @@ XclExpTokenData XclExpFmlaCompImpl::Factor( XclExpTokenData aTokData, sal_uInt8
+@@ -1114,6 +1147,12 @@ XclExpTokenData XclExpFmlaCompImpl::Factor( XclExpTokenData aTokData, sal_uInt8
StackVar eTokType = aTokData.GetType();
OpCode eOpCode = aTokData.GetOpCode();
@@ -1415,7 +2758,7 @@
switch( eTokType )
{
case svUnknown: mbOk = false; break;
-@@ -1248,6 +1261,66 @@ void XclExpFmlaCompImpl::ProcessExternal( const XclExpTokenData& rTokData, sal_u
+@@ -1248,6 +1287,107 @@ void XclExpFmlaCompImpl::ProcessExternal( const XclExpTokenData& rTokData, sal_u
ProcessFunction( rTokData, nExpClass );
}
@@ -1430,11 +2773,50 @@
+ case svSingleRef:
+ {
+ fprintf(stdout, "XclExpFmlaCompImpl::ProcessExternalName: svSingleRef not supported yet\n");
++ if (!mpScBasePos)
++ {
++ AppendErrorToken(EXC_ERR_REF, rTokData.mnSpaces);
++ break;
++ }
++ SingleRefData aRef(rTokData.mpScToken->GetSingleRef());
++ aRef.CalcAbsIfRel(*mpScBasePos);
++ ScToken* p = pRefMgr->getSingleRefToken(nFileId, ScAddress(aRef.nCol, aRef.nRow, aRef.nTab), NULL);
++ if (!p)
++ {
++ AppendErrorToken(EXC_ERR_REF, rTokData.mnSpaces);
++ break;
++ }
++
++ mpLinkMgr->StoreCell(nFileId, rTokData.mpScToken->GetString(), aRef);
++
++ XclAddress aXclPos(ScAddress::UNINITIALIZED);
++ ConvertRefData(aRef, aXclPos, false, false, false);
++
++ const String* pFile = pRefMgr->getExternalFileName(nFileId);
++ sal_uInt16 nExtSheet, nFirstSBTab, nLastSBTab;
++ mpLinkMgr->FindExtSheet(nFileId, nExtSheet, nFirstSBTab, nLastSBTab,
++ aRef.nTab, aRef.nTab, GetNewRefLogEntry());
++ sal_uInt8 nBaseId = lclIsRefDel2D(aRef) ? EXC_TOKID_REFERR3D : EXC_TOKID_REF3D;
++ AppendOpTokenId(GetTokenId(nBaseId, EXC_TOKCLASS_REF), nExpClass, rTokData.mnSpaces);
++ Append(nExtSheet);
++ if (meBiff <= EXC_BIFF5)
++ {
++ Append(0, 8);
++ Append(static_cast<sal_uInt16>(nFirstSBTab));
++ Append(static_cast<sal_uInt16>(nFirstSBTab));
++ }
++ AppendAddress(aXclPos);
+ }
+ break;
+ case svDoubleRef:
+ {
+ fprintf(stdout, "XclExpFmlaCompImpl::ProcessExternalName: svDoubleRef not supported yet\n");
++ if (!mpScBasePos)
++ {
++ AppendErrorToken(XclTools::GetXclErrorCode(errNoRef), rTokData.mnSpaces);
++ break;
++ }
++ AppendBoolToken(true, rTokData.mnSpaces);
+ }
+ break;
+ case svExternalName:
@@ -1449,6 +2831,8 @@
+ break;
+ }
+
++ // Go through all these tokens to store the external cell/range
++ // references for CRN records.
+ for (ScToken* p = pArray->First(); p; p = pArray->Next())
+ {
+ if (p->GetOpCode() == ocExternalName)
@@ -1457,13 +2841,13 @@
+ {
+ SingleRefData aData(p->GetSingleRef());
+ aData.CalcAbsIfRel(*mpScBasePos);
-+ mpLinkMgr->StoreCell(nFileId, aData);
++ mpLinkMgr->StoreCell(nFileId, p->GetString(), aData);
+ }
+ else if (p->GetType() == svDoubleRef)
+ {
+ ComplRefData aData(p->GetDoubleRef());
+ aData.CalcAbsIfRel(*mpScBasePos);
-+ mpLinkMgr->StoreCellRange(nFileId, aData);
++ mpLinkMgr->StoreCellRange(nFileId, p->GetString(), aData);
+ }
+ }
+ }
@@ -1482,8 +2866,41 @@
void XclExpFmlaCompImpl::ProcessFunction( const XclExpTokenData& rTokData, sal_uInt8 nExpClass )
{
OpCode eOpCode = rTokData.GetOpCode();
+@@ -1623,32 +1763,6 @@ void XclExpFmlaCompImpl::AppendTrailingParam( XclExpFuncData& rFuncData )
+ }
+ }
+
+-// reference handling ---------------------------------------------------------
+-
+-namespace {
+-
+-inline bool lclIsRefRel2D( const SingleRefData& rRefData )
+-{
+- return rRefData.IsColRel() || rRefData.IsRowRel();
+-}
+-
+-inline bool lclIsRefDel2D( const SingleRefData& rRefData )
+-{
+- return rRefData.IsColDeleted() || rRefData.IsRowDeleted();
+-}
+-
+-inline bool lclIsRefRel2D( const ComplRefData& rRefData )
+-{
+- return lclIsRefRel2D( rRefData.Ref1 ) || lclIsRefRel2D( rRefData.Ref2 );
+-}
+-
+-inline bool lclIsRefDel2D( const ComplRefData& rRefData )
+-{
+- return lclIsRefDel2D( rRefData.Ref1 ) || lclIsRefDel2D( rRefData.Ref2 );
+-}
+-
+-} // namespace
+-
+ // ----------------------------------------------------------------------------
+
+ SCTAB XclExpFmlaCompImpl::GetScTab( const SingleRefData& rRefData ) const
diff --git sc/source/filter/excel/xelink.cxx sc/source/filter/excel/xelink.cxx
-index b1bacad..2b54a89 100644
+index b1bacad..ebd2999 100644
--- sc/source/filter/excel/xelink.cxx
+++ sc/source/filter/excel/xelink.cxx
@@ -38,6 +38,15 @@
@@ -1569,13 +2986,13 @@
/** 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 );
++ void StoreCell( sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell );
++ void StoreCellRange( sal_uInt16 nFileId, const String& rTabName, 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. */
-@@ -407,9 +447,22 @@ public:
+@@ -407,9 +447,25 @@ public:
sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
const String& rApplic, const String& rTopic, const String& rItem );
@@ -1583,6 +3000,9 @@
+ sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const String& rUrl,
+ const String& rName, const ScTokenArray* pArray );
+
++ XclExpXti GetXti( sal_uInt16 nFileId, sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
++ XclExpRefLogEntry* pRefLogEntry = NULL );
++
/** Writes all SUPBOOK records with their sub records. */
virtual void Save( XclExpStream& rStrm );
@@ -1598,7 +3018,7 @@
private:
typedef XclExpRecordList< XclExpSupbook > XclExpSupbookList;
typedef XclExpSupbookList::RecordRefType XclExpSupbookRef;
-@@ -435,15 +488,6 @@ private:
+@@ -435,15 +491,6 @@ private:
void AddExtSupbook( SCTAB nScTab );
private:
@@ -1614,17 +3034,25 @@
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 +511,9 @@ public:
+@@ -464,9 +511,17 @@ public:
+ /** Derived classes search for a special EXTERNSHEET index for the own document. */
+ virtual sal_uInt16 FindExtSheet( sal_Unicode cCode ) = 0;
+
++ virtual void FindExtSheet( sal_uInt16 nFileId, sal_uInt16& rnExtSheet,
++ sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
++ sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
++ XclExpRefLogEntry* pRefLogEntry ) = 0;
++
/** 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;
++ virtual void StoreCell( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef ) = 0;
++ virtual void StoreCellRange( sal_uInt16 nFileId, const String& rTabName, 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,
-@@ -476,6 +523,10 @@ public:
+@@ -476,6 +531,10 @@ public:
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
const String& rApplic, const String& rTopic, const String& rItem ) = 0;
@@ -1635,12 +3063,19 @@
/** Derived classes write the entire link table to the passed stream. */
virtual void Save( XclExpStream& rStrm ) = 0;
-@@ -499,13 +550,21 @@ public:
-
+@@ -497,15 +556,28 @@ public:
+ XclExpRefLogEntry* pRefLogEntry );
+ virtual sal_uInt16 FindExtSheet( sal_Unicode cCode );
+
++ virtual void FindExtSheet( sal_uInt16 nFileId, sal_uInt16& rnExtSheet,
++ sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
++ sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
++ XclExpRefLogEntry* pRefLogEntry );
++
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 void StoreCell( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef );
++ virtual void StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef1, const SingleRefData& rRef2 );
+
virtual bool InsertAddIn(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
@@ -1657,12 +3092,19 @@
virtual void Save( XclExpStream& rStrm );
private:
-@@ -552,13 +611,21 @@ public:
-
+@@ -550,15 +622,28 @@ public:
+ XclExpRefLogEntry* pRefLogEntry );
+ virtual sal_uInt16 FindExtSheet( sal_Unicode cCode );
+
++ virtual void FindExtSheet( sal_uInt16 nFileId, sal_uInt16& rnExtSheet,
++ sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
++ sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
++ XclExpRefLogEntry* pRefLogEntry );
++
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 void StoreCell( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef );
++ virtual void StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef1, const SingleRefData& rRef2 );
+
virtual bool InsertAddIn(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
@@ -1679,7 +3121,7 @@
virtual void Save( XclExpStream& rStrm );
private:
-@@ -885,6 +952,94 @@ void XclExpExtNameDde::WriteAddData( XclExpStream& rStrm )
+@@ -885,6 +970,94 @@ void XclExpExtNameDde::WriteAddData( XclExpStream& rStrm )
mxMatrix->Save( rStrm );
}
@@ -1774,7 +3216,7 @@
// List of external names =====================================================
XclExpExtNameBuffer::XclExpExtNameBuffer( const XclExpRoot& rRoot ) :
-@@ -920,6 +1075,12 @@ sal_uInt16 XclExpExtNameBuffer::InsertDde(
+@@ -920,6 +1093,12 @@ sal_uInt16 XclExpExtNameBuffer::InsertDde(
return nIndex;
}
@@ -1787,7 +3229,7 @@
void XclExpExtNameBuffer::Save( XclExpStream& rStrm )
{
maNameList.Save( rStrm );
-@@ -1066,6 +1227,78 @@ void XclExpXct::StoreCellRange( const XclExpRoot& rRoot, const ScRange& rRange )
+@@ -1066,6 +1245,78 @@ void XclExpXct::StoreCellRange( const XclExpRoot& rRoot, const ScRange& rRange )
maUsedCells.SetMultiMarkArea( rRange );
}
@@ -1866,7 +3308,7 @@
void XclExpXct::Save( XclExpStream& rStrm )
{
XclExpRecord::Save( rStrm );
-@@ -1206,6 +1439,41 @@ void XclExpSupbook::StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab )
+@@ -1206,6 +1457,41 @@ void XclExpSupbook::StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab )
xXct->StoreCellRange( GetRoot(), rRange );
}
@@ -1908,7 +3350,7 @@
sal_uInt16 XclExpSupbook::InsertTabName( const String& rTabName )
{
DBG_ASSERT( meType == EXC_SBTYPE_EXTERN, "XclExpSupbook::InsertTabName - don't insert sheet names here" );
-@@ -1226,6 +1494,11 @@ sal_uInt16 XclExpSupbook::InsertDde( const String& rItem )
+@@ -1226,6 +1512,11 @@ sal_uInt16 XclExpSupbook::InsertDde( const String& rItem )
return GetExtNameBuffer().InsertDde( maUrl, maDdeTopic, rItem );
}
@@ -1920,7 +3362,7 @@
void XclExpSupbook::Save( XclExpStream& rStrm )
{
// SUPBOOK record
-@@ -1352,6 +1625,131 @@ void XclExpSupbookBuffer::StoreCellRange( const ScRange& rRange )
+@@ -1352,6 +1643,135 @@ void XclExpSupbookBuffer::StoreCellRange( const ScRange& rRange )
}
}
@@ -1944,7 +3386,7 @@
+
+}
+
-+void XclExpSupbookBuffer::StoreCell( sal_uInt16 nFileId, const ScAddress& rCell )
++void XclExpSupbookBuffer::StoreCell( sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell )
+{
+ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
+ const String* pUrl = pRefMgr->getExternalFileName(nFileId);
@@ -1959,16 +3401,17 @@
+ nSupbookId = Append(xSupbook);
+ }
+
-+ ScToken* pToken = pRefMgr->getSingleRefToken(nFileId, rCell, NULL);
++ ScToken* pToken = pRefMgr->getSingleRefToken(nFileId, rTabName, rCell, NULL, NULL);
+ if (!pToken)
+ return;
+
-+ const String* pTabName = pRefMgr->getExternalTableName(nFileId, rCell.Tab());
-+ if (!pTabName)
-+ return;
++// const String* pTabName = pRefMgr->getExternalTableName(nFileId, rCell.Tab());
++// if (!pTabName)
++// return;
+
-+ sal_uInt16 nSheetId = xSupbook->GetTabIndex(*pTabName);
++ sal_uInt16 nSheetId = xSupbook->GetTabIndex(rTabName);
+ FindSBIndexEntry f(nSupbookId, nSheetId);
++ fprintf(stdout, "XclExpSupbookBuffer::StoreCell: supbook id = %d; sheet id = %d\n", nSupbookId, nSheetId);
+ XclExpSBIndexVec::iterator itrEnd = maSBIndexVec.end();
+ XclExpSBIndexVec::const_iterator itr = find_if(maSBIndexVec.begin(), itrEnd, f);
+ if (itr == itrEnd)
@@ -1982,7 +3425,7 @@
+ xSupbook->StoreCell(nSheetId, rCell, *pToken);
+}
+
-+void XclExpSupbookBuffer::StoreCellRange( sal_uInt16 nFileId, const ScRange& rRange )
++void XclExpSupbookBuffer::StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange )
+{
+ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
+ const String* pUrl = pRefMgr->getExternalFileName(nFileId);
@@ -1998,11 +3441,12 @@
+ }
+
+ SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
++ SCTAB nTabCount = rRange.aEnd.Tab() - rRange.aStart.Tab() + 1;
+
+ // 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);
++ aMatrixList.reserve(nTabCount);
++ ScTokenArray* pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, rRange, NULL);
+ if (!pArray)
+ return;
+
@@ -2018,22 +3462,24 @@
+ }
+ }
+
-+ if (aMatrixList.size() != nTab2 - nTab1 + 1)
++ if (aMatrixList.size() != nTabCount)
+ {
+ // matrix size mis-match !
+ return;
+ }
+
++ sal_uInt16 nFirstSheetId = xSupbook->GetTabIndex(rTabName);
++
+ ScRange aRange(rRange);
+ aRange.aStart.SetTab(0);
+ aRange.aEnd.SetTab(0);
-+ for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
++ for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
+ {
+ const String* pTabName = pRefMgr->getExternalTableName(nFileId, nTab);
+ if (!pTabName)
+ continue;
+
-+ sal_uInt16 nSheetId = xSupbook->GetTabIndex(*pTabName);
++ sal_uInt16 nSheetId = nFirstSheetId + static_cast<sal_uInt16>(nTab);
+ FindSBIndexEntry f(nSupbookId, nSheetId);
+ XclExpSBIndexVec::iterator itrEnd = maSBIndexVec.end();
+ XclExpSBIndexVec::const_iterator itr = find_if(maSBIndexVec.begin(), itrEnd, f);
@@ -2052,7 +3498,7 @@
bool XclExpSupbookBuffer::InsertAddIn(
sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const String& rName )
{
-@@ -1383,6 +1781,20 @@ bool XclExpSupbookBuffer::InsertDde(
+@@ -1383,6 +1803,72 @@ bool XclExpSupbookBuffer::InsertDde(
return rnExtName > 0;
}
@@ -2070,19 +3516,83 @@
+ return rnExtName > 0;
+}
+
++XclExpXti XclExpSupbookBuffer::GetXti( sal_uInt16 nFileId, sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
++ XclExpRefLogEntry* pRefLogEntry )
++{
++ XclExpXti aXti(0, EXC_NOTAB, EXC_NOTAB);
++ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
++ const String* pUrl = pRefMgr->getExternalFileName(nFileId);
++ if (!pUrl)
++ return aXti;
++
++ XclExpSupbookRef xSupbook;
++ sal_uInt16 nSupbookId;
++ if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
++ {
++ xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
++ nSupbookId = Append(xSupbook);
++ }
++ aXti.mnSupbook = nSupbookId;
++
++ for (sal_uInt16 nTab = nFirstXclTab; nTab <= nLastXclTab; ++nTab)
++ {
++ const String* pTabName = pRefMgr->getExternalTableName(nFileId, nTab);
++ if (!pTabName)
++ continue;
++
++ 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;
++ }
++ if (nTab == nFirstXclTab)
++ aXti.mnFirstSBTab = nSheetId;
++ if (nTab == nLastXclTab)
++ aXti.mnLastSBTab = nSheetId;
++ }
++
++ if (pRefLogEntry)
++ {
++ pRefLogEntry->mnFirstXclTab = nFirstXclTab;
++ pRefLogEntry->mnLastXclTab = nLastXclTab;
++ if (xSupbook.is())
++ xSupbook->FillRefLogEntry(*pRefLogEntry, aXti.mnFirstSBTab, aXti.mnLastSBTab);
++ }
++
++ return aXti;
++}
++
void XclExpSupbookBuffer::Save( XclExpStream& rStrm )
{
maSupbookList.Save( rStrm );
-@@ -1490,6 +1902,16 @@ void XclExpLinkManagerImpl5::StoreCellRange( const SingleRefData& /*rRef1*/, con
+@@ -1485,11 +1971,28 @@ sal_uInt16 XclExpLinkManagerImpl5::FindExtSheet( sal_Unicode cCode )
+ return nExtSheet;
+ }
+
++void XclExpLinkManagerImpl5::FindExtSheet(
++ sal_uInt16 /*nFileId*/, sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnFirstSBTab*/, sal_uInt16& /*rnLastSBTab*/,
++ sal_uInt16 /*nFirstXclTab*/, sal_uInt16 /*nLastXclTab*/, XclExpRefLogEntry* /*pRefLogEntry*/ )
++{
++ // not implemented
++}
++
+ void XclExpLinkManagerImpl5::StoreCellRange( const SingleRefData& /*rRef1*/, const SingleRefData& /*rRef2*/ )
+ {
// not implemented
}
-+void XclExpLinkManagerImpl5::StoreCell( sal_uInt16 /*nFileId*/, const SingleRefData& /*rRef*/ )
++void XclExpLinkManagerImpl5::StoreCell( sal_uInt16 /*nFileId*/, const String& /*rTabName*/, const SingleRefData& /*rRef*/ )
+{
+ // not implemented
+}
+
-+void XclExpLinkManagerImpl5::StoreCellRange( sal_uInt16 /*nFileId*/, const SingleRefData& /*rRef1*/, const SingleRefData& /*rRef2*/ )
++void XclExpLinkManagerImpl5::StoreCellRange( sal_uInt16 /*nFileId*/, const String& /*rTabName*/, const SingleRefData& /*rRef1*/, const SingleRefData& /*rRef2*/ )
+{
+ // not implemented
+}
@@ -2090,7 +3600,7 @@
bool XclExpLinkManagerImpl5::InsertAddIn(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
{
-@@ -1510,6 +1932,14 @@ bool XclExpLinkManagerImpl5::InsertDde(
+@@ -1510,6 +2013,14 @@ bool XclExpLinkManagerImpl5::InsertDde(
return false;
}
@@ -2105,27 +3615,44 @@
void XclExpLinkManagerImpl5::Save( XclExpStream& rStrm )
{
if( sal_uInt16 nExtSheetCount = GetExtSheetCount() )
-@@ -1652,6 +2082,19 @@ void XclExpLinkManagerImpl8::StoreCellRange( const SingleRefData& rRef1, const S
+@@ -1630,6 +2141,16 @@ sal_uInt16 XclExpLinkManagerImpl8::FindExtSheet( sal_Unicode cCode )
+ return InsertXti( maSBBuffer.GetXti( EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
+ }
+
++void XclExpLinkManagerImpl8::FindExtSheet(
++ sal_uInt16 nFileId, sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
++ sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab, XclExpRefLogEntry* pRefLogEntry )
++{
++ XclExpXti aXti = maSBBuffer.GetXti(nFileId, nFirstXclTab, nLastXclTab, pRefLogEntry);
++ rnExtSheet = InsertXti(aXti);
++ rnFirstSBTab = aXti.mnFirstSBTab;
++ rnLastSBTab = aXti.mnLastSBTab;
++}
++
+ void XclExpLinkManagerImpl8::StoreCellRange( const SingleRefData& rRef1, const SingleRefData& rRef2 )
+ {
+ if( !rRef1.IsDeleted() && !rRef2.IsDeleted() && (rRef1.nTab >= 0) && (rRef2.nTab >= 0) )
+@@ -1652,6 +2173,19 @@ void XclExpLinkManagerImpl8::StoreCellRange( const SingleRefData& rRef1, const S
}
}
-+void XclExpLinkManagerImpl8::StoreCell( sal_uInt16 nFileId, const SingleRefData& rRef )
++void XclExpLinkManagerImpl8::StoreCell( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef )
+{
+ ScAddress aAddr(rRef.nCol, rRef.nRow, rRef.nTab);
-+ maSBBuffer.StoreCell(nFileId, aAddr);
++ maSBBuffer.StoreCell(nFileId, rTabName, aAddr);
+}
+
-+void XclExpLinkManagerImpl8::StoreCellRange( sal_uInt16 nFileId, const SingleRefData& rRef1, const SingleRefData& rRef2 )
++void XclExpLinkManagerImpl8::StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef1, const SingleRefData& rRef2 )
+{
+ 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);
++ maSBBuffer.StoreCellRange(nFileId, rTabName, aRange);
+}
+
bool XclExpLinkManagerImpl8::InsertAddIn(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
{
-@@ -1677,6 +2120,18 @@ bool XclExpLinkManagerImpl8::InsertDde(
+@@ -1677,6 +2211,18 @@ bool XclExpLinkManagerImpl8::InsertDde(
return false;
}
@@ -2144,24 +3671,39 @@
void XclExpLinkManagerImpl8::Save( XclExpStream& rStrm )
{
if( !maXtiVec.empty() )
-@@ -1755,6 +2210,16 @@ void XclExpLinkManager::StoreCellRange( const ComplRefData& rRef )
+@@ -1745,6 +2291,14 @@ sal_uInt16 XclExpLinkManager::FindExtSheet( sal_Unicode cCode )
+ return mxImpl->FindExtSheet( cCode );
+ }
+
++void XclExpLinkManager::FindExtSheet( sal_uInt16 nFileId, sal_uInt16& rnExtSheet,
++ sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
++ sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
++ XclExpRefLogEntry* pRefLogEntry )
++{
++ mxImpl->FindExtSheet( nFileId, rnExtSheet, rnFirstSBTab, rnLastSBTab, nFirstXclTab, nLastXclTab, pRefLogEntry );
++}
++
+ void XclExpLinkManager::StoreCell( const SingleRefData& rRef )
+ {
+ mxImpl->StoreCellRange( rRef, rRef );
+@@ -1755,6 +2309,16 @@ void XclExpLinkManager::StoreCellRange( const ComplRefData& rRef )
mxImpl->StoreCellRange( rRef.Ref1, rRef.Ref2 );
}
-+void XclExpLinkManager::StoreCell( sal_uInt16 nFileId, const SingleRefData& rRef )
++void XclExpLinkManager::StoreCell( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef )
+{
-+ mxImpl->StoreCell( nFileId, rRef );
++ mxImpl->StoreCell( nFileId, rTabName, rRef );
+}
+
-+void XclExpLinkManager::StoreCellRange( sal_uInt16 nFileId, const ComplRefData& rRef )
++void XclExpLinkManager::StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef )
+{
-+ mxImpl->StoreCellRange( nFileId, rRef.Ref1, rRef.Ref2 );
++ mxImpl->StoreCellRange( nFileId, rTabName, rRef.Ref1, rRef.Ref2 );
+}
+
bool XclExpLinkManager::InsertAddIn(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
{
-@@ -1768,6 +2233,13 @@ bool XclExpLinkManager::InsertDde(
+@@ -1768,6 +2332,13 @@ bool XclExpLinkManager::InsertDde(
return mxImpl->InsertDde( rnExtSheet, rnExtName, rApplic, rTopic, rItem );
}
@@ -2176,10 +3718,97 @@
{
mxImpl->Save( rStrm );
diff --git sc/source/filter/excel/xilink.cxx sc/source/filter/excel/xilink.cxx
-index 01932a5..b20849e 100644
+index 01932a5..38b846b 100644
--- sc/source/filter/excel/xilink.cxx
+++ sc/source/filter/excel/xilink.cxx
-@@ -191,6 +191,11 @@ public:
+@@ -39,6 +39,31 @@
+ #include "xihelper.hxx"
+ #include "xiname.hxx"
+
++
++namespace {
++
++#include <string>
++
++class StackPrinter
++{
++public:
++ explicit StackPrinter(const char* msg) :
++ msMsg(msg)
++ {
++ fprintf(stdout, "%s: --begin\n", msMsg.c_str());
++ }
++
++ ~StackPrinter()
++ {
++ fprintf(stdout, "%s: --end\n", msMsg.c_str());
++ }
++
++private:
++ ::std::string msMsg;
++};
++
++}
++
+ // ============================================================================
+ // *** Helper classes ***
+ // ============================================================================
+@@ -52,8 +77,10 @@ public:
+ /** Reads a cached value and stores it with its cell address. */
+ explicit XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos );
+
++#if 0
+ /** Copies the cached value to sheet nTab in the document. */
+ void SetCell( const XclImpRoot& rRoot, SCTAB nScTab ) const;
++#endif
+
+ private:
+ XclAddress maXclPos; /// Excel position of the cached cell.
+@@ -76,11 +103,13 @@ public:
+ /** Reads a CRN record (external referenced cell) at the specified address. */
+ void ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos );
+
++#if 0
+ /** Creates a new linked table in the passed document and fills it with the cached cells.
+ @descr Stores the index of the new sheet, will be accessible with GetScTab(). */
+ void CreateAndFillTable(
+ const XclImpRoot& rRoot, const String& rAbsUrl,
+ const String& rFilterName, const String& rFilterOpt );
++#endif
+
+ private:
+ typedef ScfDelList< XclImpCrn > XclImpCrnList;
+@@ -112,11 +141,13 @@ public:
+
+ /** Returns the URL of the external document. */
+ inline const String& GetXclUrl() const { return maXclUrl; }
+-
++#if 0
+ /** Returns Calc sheet index from Excel sheet index. */
+ SCTAB GetScTabNum( sal_uInt16 nXclTab ) const;
+ /** Returns Calc sheet index from sheet name. */
+ SCTAB GetScTabNum( const String& rTabName ) const;
++#endif
++ sal_uInt16 GetXclTabNum( const String& rTabName ) const;
+
+ /** Returns the external name specified by an index from the Excel document (one-based). */
+ const XclImpExtName* GetExternName( sal_uInt16 nXclIndex ) const;
+@@ -128,10 +159,14 @@ public:
+ /** Returns the specified macro name (1-based) or an empty string on error. */
+ const String& GetMacroName( sal_uInt16 nXclNameIdx ) const;
+
++ const String& GetTabName( sal_uInt16 nXtiTab ) const;
++
++#if 0
+ /** Creates all sheets of this external document.
+ @param nFirstTab The external Excel index of the first sheet to be created.
+ @param nLastTab The external Excel index of the last sheet to be created. */
+ void CreateTables( sal_uInt16 nSBTabFirst, sal_uInt16 nSBTabLast );
++#endif
+
+ private:
+ typedef ScfDelList< XclImpSupbookTab > XclImpSupbookTabList;
+@@ -191,6 +226,13 @@ public:
sal_uInt16 nXtiIndex ) const;
/** Returns the specified external name or 0 on error. */
const XclImpExtName* GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const;
@@ -2188,10 +3817,155 @@
+ the index. */
+ const String* GetSupbookUrl( sal_uInt16 nXtiIndex ) const;
+
++ const String& GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const;
++
/** Tries to decode the URL of the specified XTI entry to OLE or DDE link components.
@descr For DDE links: Decodes to application name and topic.
For OLE object links: Decodes to class name and document URL.
-@@ -584,6 +589,14 @@ const XclImpExtName* XclImpLinkManagerImpl::GetExternName( sal_uInt16 nXtiIndex,
+@@ -198,19 +240,23 @@ public:
+ bool GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const;
+ /** Returns the specified macro name or an empty string on error. */
+ const String& GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const;
+-
++#if 0
+ /** Returns the Calc sheet index of a table in an external document.
+ @return Calc sheet index or EXC_TAB_INVALID on error. */
+ SCTAB GetScTab( const String& rUrl, const String& rTabName ) const;
++#endif
++ sal_uInt16 GetXclTab( const String& rUrl, const String& rTabName ) const;
+
+ private:
+ /** Returns the specified SUPBOOK (external document). */
+ const XclImpSupbook* GetSupbook( sal_uInt32 nXtiIndex ) const;
+ /** Returns the SUPBOOK (external workbook) specified by its URL. */
+ const XclImpSupbook* GetSupbook( const String& rUrl ) const;
+-
++#if 0
+ /** Creates all external sheets in the Calc document. */
+ void CreateTables();
++#endif
++ void LoadCachedValues();
+
+ /** Finds the largest range of sheet indexes in a SUPBOOK after a start sheet index.
+ @param rnSBTabFirst (out-param) The first sheet index of the range in SUPBOOK is returned here.
+@@ -341,6 +387,7 @@ XclImpCrn::XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos ) :
+ {
+ }
+
++#if 0
+ void XclImpCrn::SetCell( const XclImpRoot& rRoot, SCTAB nScTab ) const
+ {
+ ScAddress aScPos( ScAddress::UNINITIALIZED );
+@@ -365,6 +412,7 @@ void XclImpCrn::SetCell( const XclImpRoot& rRoot, SCTAB nScTab ) const
+ }
+ }
+ }
++#endif
+
+ // Sheet in an external document ==============================================
+
+@@ -383,6 +431,7 @@ void XclImpSupbookTab::ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos )
+ maCrnList.Append( new XclImpCrn( rStrm, rXclPos ) );
+ }
+
++#if 0
+ void XclImpSupbookTab::CreateAndFillTable( const XclImpRoot& rRoot,
+ const String& rAbsUrl, const String& rFilterName, const String& rFilterOpt )
+ {
+@@ -391,6 +440,7 @@ void XclImpSupbookTab::CreateAndFillTable( const XclImpRoot& rRoot,
+ for( const XclImpCrn* pCrn = maCrnList.First(); pCrn; pCrn = maCrnList.Next() )
+ pCrn->SetCell( rRoot, mnScTab );
+ }
++#endif
+
+ // External document (SUPBOOK) ================================================
+
+@@ -457,13 +507,14 @@ void XclImpSupbook::ReadExternname( XclImpStream& rStrm )
+ {
+ maExtNameList.Append( new XclImpExtName( rStrm, meType == EXC_SBTYPE_ADDIN ) );
+ }
+-
++#if 0
+ SCTAB XclImpSupbook::GetScTabNum( sal_uInt16 nXclTab ) const
+ {
+ if( meType == EXC_SBTYPE_SELF )
+ return static_cast< SCTAB >( nXclTab );
+- const XclImpSupbookTab* pSBTab = maSupbTabList.GetObject( nXclTab );
+- return pSBTab ? pSBTab->GetScTab() : SCTAB_INVALID;
++ return SCTAB_INVALID;
++// const XclImpSupbookTab* pSBTab = maSupbTabList.GetObject( nXclTab );
++// return pSBTab ? pSBTab->GetScTab() : SCTAB_INVALID;
+ }
+
+ SCTAB XclImpSupbook::GetScTabNum( const String& rTabName ) const
+@@ -473,6 +524,15 @@ SCTAB XclImpSupbook::GetScTabNum( const String& rTabName ) const
+ return pSBTab->GetScTab();
+ return SCTAB_INVALID;
+ }
++#endif
++sal_uInt16 XclImpSupbook::GetXclTabNum( const String& rTabName ) const
++{
++ sal_uInt16 nTabNum = 0;
++ for (const XclImpSupbookTab* pSBTab = maSupbTabList.First(); pSBTab; pSBTab = maSupbTabList.Next(), ++nTabNum)
++ if (pSBTab->GetTabName() == rTabName)
++ return nTabNum;
++ return EXC_NOTAB;
++}
+
+ const XclImpExtName* XclImpSupbook::GetExternName( sal_uInt16 nXclIndex ) const
+ {
+@@ -492,6 +552,22 @@ const String& XclImpSupbook::GetMacroName( sal_uInt16 nXclNameIdx ) const
+ return (pName && pName->IsVBName()) ? pName->GetScName() : EMPTY_STRING;
+ }
+
++const String& XclImpSupbook::GetTabName( sal_uInt16 nXtiTab ) const
++{
++ if (maSupbTabList.Empty())
++ return EMPTY_STRING;
++
++ sal_uInt16 i = 0;
++ for (XclImpSupbookTab* p = maSupbTabList.First(); p; p = maSupbTabList.Next(), ++i)
++ {
++ if (i == nXtiTab)
++ return p->GetTabName();
++ }
++
++ return EMPTY_STRING;
++}
++
++#if 0
+ void XclImpSupbook::CreateTables( sal_uInt16 nSBTabFirst, sal_uInt16 nSBTabLast )
+ {
+ if( (meType == EXC_SBTYPE_EXTERN) && (GetExtDocOptions().GetDocSettings().mnLinkCnt == 0) && GetDocShell() )
+@@ -508,6 +584,7 @@ void XclImpSupbook::CreateTables( sal_uInt16 nSBTabFirst, sal_uInt16 nSBTabLast
+ pSBTab->CreateAndFillTable( GetRoot(), aAbsUrl, maFilterName, maFilterOpt );
+ }
+ }
++#endif
+
+ // Import link manager ========================================================
+
+@@ -531,7 +608,7 @@ void XclImpLinkManagerImpl::ReadExternsheet( XclImpStream& rStrm )
+ --nXtiCount;
+ }
+
+- CreateTables();
++ LoadCachedValues();
+ }
+
+ void XclImpLinkManagerImpl::ReadSupbook( XclImpStream& rStrm )
+@@ -570,8 +647,8 @@ bool XclImpLinkManagerImpl::GetScTabRange(
+ {
+ if( const XclImpSupbook* pSupbook = maSupbookList.GetObject( pXti->mnSupbook ) )
+ {
+- rnFirstScTab = pSupbook->GetScTabNum( pXti->mnSBTabFirst );
+- rnLastScTab = pSupbook->GetScTabNum( pXti->mnSBTabLast );
++ rnFirstScTab = pXti->mnSBTabFirst;
++ rnLastScTab = pXti->mnSBTabLast;
+ return true;
+ }
+ }
+@@ -584,6 +661,20 @@ const XclImpExtName* XclImpLinkManagerImpl::GetExternName( sal_uInt16 nXtiIndex,
return pSupbook ? pSupbook->GetExternName( nExtName ) : 0;
}
@@ -2203,10 +3977,60 @@
+ return &p->GetXclUrl();
+}
+
- bool XclImpLinkManagerImpl::GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const
- {
- const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
-@@ -707,6 +720,11 @@ const XclImpExtName* XclImpLinkManager::GetExternName( sal_uInt16 nXtiIndex, sal
++const String& XclImpLinkManagerImpl::GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const
++{
++ const XclImpSupbook* p = GetSupbook(nXti);
++ return p ? p->GetTabName(nXtiTab) : EMPTY_STRING;
++}
++
+ bool XclImpLinkManagerImpl::GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const
+ {
+ const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
+@@ -595,12 +686,18 @@ const String& XclImpLinkManagerImpl::GetMacroName( sal_uInt16 nExtSheet, sal_uIn
+ const XclImpSupbook* pSupbook = GetSupbook( nExtSheet );
+ return pSupbook ? pSupbook->GetMacroName( nExtName ) : EMPTY_STRING;
+ }
+-
++#if 0
+ SCTAB XclImpLinkManagerImpl::GetScTab( const String& rUrl, const String& rTabName ) const
+ {
+ const XclImpSupbook* pSupbook = GetSupbook( rUrl );
+ return pSupbook ? pSupbook->GetScTabNum( rTabName ) : SCTAB_INVALID;
+ }
++#endif
++sal_uInt16 XclImpLinkManagerImpl::GetXclTab( const String& rUrl, const String& rTabName ) const
++{
++ const XclImpSupbook* pSupbook = GetSupbook( rUrl );
++ return pSupbook ? pSupbook->GetXclTabNum( rTabName ) : EXC_NOTAB;
++}
+
+ const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( sal_uInt32 nXtiIndex ) const
+ {
+@@ -616,6 +713,7 @@ const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( const String& rUrl ) con
+ return 0;
+ }
+
++#if 0
+ void XclImpLinkManagerImpl::CreateTables()
+ {
+ DBG_ASSERT( !mbCreated, "XclImpLinkManager::CreateTables - multiple call" );
+@@ -637,6 +735,15 @@ void XclImpLinkManagerImpl::CreateTables()
+ }
+ mbCreated = true;
+ }
++#endif
++
++void XclImpLinkManagerImpl::LoadCachedValues()
++{
++ // Read all CRN records which can be accessed via XclImpSupbook, and store
++ // the cached values to the external reference manager.
++
++ // TODO: Implement this.
++}
+
+ bool XclImpLinkManagerImpl::FindNextTabRange(
+ sal_uInt16& rnSBTabFirst, sal_uInt16& rnSBTabLast,
+@@ -707,6 +814,16 @@ const XclImpExtName* XclImpLinkManager::GetExternName( sal_uInt16 nXtiIndex, sal
return mxImpl->GetExternName( nXtiIndex, nExtName );
}
@@ -2215,11 +4039,76 @@
+ return mxImpl->GetSupbookUrl(nXtiIndex);
+}
+
++const String& XclImpLinkManager::GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const
++{
++ return mxImpl->GetSupbookTabName(nXti, nXtiTab);
++}
++
bool XclImpLinkManager::GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const
{
return mxImpl->GetLinkData( rApplic, rTopic, nXtiIndex );
+@@ -716,11 +833,16 @@ const String& XclImpLinkManager::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16
+ {
+ return mxImpl->GetMacroName( nExtSheet, nExtName );
+ }
+-
++#if 0
+ SCTAB XclImpLinkManager::GetScTab( const String& rUrl, const String& rTabName ) const
+ {
+ return mxImpl->GetScTab( rUrl, rTabName );
+ }
++#endif
++sal_uInt16 XclImpLinkManager::GetXclTab( const String& rUrl, const String& rTabName ) const
++{
++ return mxImpl->GetXclTab( rUrl, rTabName );
++}
+
+ // ============================================================================
+
+diff --git sc/source/filter/inc/XclImpChangeTrack.hxx sc/source/filter/inc/XclImpChangeTrack.hxx
+index 2335c6c..399a650 100644
+--- sc/source/filter/inc/XclImpChangeTrack.hxx
++++ sc/source/filter/inc/XclImpChangeTrack.hxx
+@@ -182,7 +182,7 @@ class XclImpChTrFmlConverter : public ExcelToSc8
+ private:
+ XclImpChangeTrack& rChangeTrack;
+
+- virtual BOOL Read3DTabReference( XclImpStream& rStrm, SCTAB& rFirstTab, SCTAB& rLastTab );
++ virtual bool Read3DTabReference( SCTAB& rFirstTab, SCTAB& rLastTab, UINT16 nIxti );
+
+ public:
+ inline XclImpChTrFmlConverter(
+diff --git sc/source/filter/inc/excform.hxx sc/source/filter/inc/excform.hxx
+index 915dd98..6913b25 100644
+--- sc/source/filter/inc/excform.hxx
++++ sc/source/filter/inc/excform.hxx
+@@ -113,8 +113,9 @@ private:
+ void ExcRelToScRel8( UINT16 nRow, UINT16 nCol, SingleRefData&,
+ const BOOL bName );
+
+- // this function must read 2 bytes from stream and adjust <nBytesLeft>
+- virtual BOOL Read3DTabReference( XclImpStream& rStrm, SCTAB& rFirstTab, SCTAB& rLastTab );
++ bool GetExternalFileIdFromXti( UINT16 nIxti, sal_uInt16& rFileId ) const;
++
++ virtual bool Read3DTabReference( SCTAB& rFirstTab, SCTAB& rLastTab, UINT16 nIxti );
+
+ public:
+ ExcelToSc8( const XclImpRoot& rRoot );
+diff --git sc/source/filter/inc/fdumper.hxx sc/source/filter/inc/fdumper.hxx
+index aea8de6..8f57403 100644
+--- sc/source/filter/inc/fdumper.hxx
++++ sc/source/filter/inc/fdumper.hxx
+@@ -31,7 +31,7 @@
+ #ifndef SC_FDUMPER_HXX
+ #define SC_FDUMPER_HXX
+
+-#define SCF_INCL_DUMPER (OSL_DEBUG_LEVEL > 0)
++#define SCF_INCL_DUMPER (OSL_DEBUG_LEVEL > 0) && 0
+
+ #include <map>
+ #include <math.h>
diff --git sc/source/filter/inc/tokstack.hxx sc/source/filter/inc/tokstack.hxx
-index 89e955a..02429d3 100644
+index 89e955a..5bb6772 100644
--- sc/source/filter/inc/tokstack.hxx
+++ sc/source/filter/inc/tokstack.hxx
@@ -35,6 +35,8 @@
@@ -2231,15 +4120,17 @@
typedef OpCode DefTokenId;
// in PRODUCT version: ambiguity between OpCode (being USHORT) and UINT16
-@@ -78,6 +80,7 @@ enum E_TYPE
+@@ -78,6 +80,9 @@ enum E_TYPE
T_Ext, // irgendwas Unbekanntes mit Funktionsnamen
T_Nlf, // token for natural language formula
T_Matrix, // token for inline arrays
+ T_ExtName, // token for external names
++ T_ExtRefC,
++ T_ExtRefA,
T_Error // fuer Abfrage im Fehlerfall
};
-@@ -134,6 +137,14 @@ class TokenPool
+@@ -134,6 +139,32 @@ class TokenPool
UINT16 nP_Matrix;
UINT16 nP_MatrixAkt;
@@ -2251,33 +4142,91 @@
+ };
+ ::std::vector<ExtName> maExtNames;
+
++ /** for storage of external cell references */
++ struct ExtCellRef
++ {
++ sal_uInt16 mnFileId;
++ String maTabName;
++ SingleRefData maRef;
++ };
++ ::std::vector<ExtCellRef> maExtCellRefs;
++
++ /** for storage of external area references */
++ struct ExtAreaRef
++ {
++ sal_uInt16 mnFileId;
++ String maTabName;
++ ComplRefData maRef;
++ };
++ ::std::vector<ExtAreaRef> maExtAreaRefs;
++
UINT16* pElement; // Array mit Indizes fuer Elemente
E_TYPE* pType; // ...mit Typ-Info
UINT16* pSize; // ...mit Laengenangabe (Anz. UINT16)
-@@ -180,6 +191,7 @@ class TokenPool
+@@ -180,12 +211,14 @@ class TokenPool
// 4 externals (e.g. AddIns, Makros...)
const TokenId StoreNlf( const SingleRefData& rTr );
const TokenId StoreMatrix( SCSIZE nC, SCSIZE nR );
+ const TokenId StoreExtName( sal_uInt16 nFileId, const String& rName );
++ const TokenId StoreExtRef( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef );
++ const TokenId StoreExtRef( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef );
inline const TokenId LastId( void ) const;
inline const ScTokenArray* operator []( const TokenId nId );
+ void Reset( void );
+ inline E_TYPE GetType( const TokenId& nId ) const;
+- inline const SingleRefData* GetSRD( const TokenId& nId ) const;
+ BOOL IsSingleOp( const TokenId& nId, const DefTokenId eId ) const;
+ const String* GetExternal( const TokenId& nId ) const;
+ const String* GetString( const TokenId& nId ) const;
+@@ -374,21 +407,5 @@ inline E_TYPE TokenPool::GetType( const TokenId& rId ) const
+ }
+
+
+-inline const SingleRefData* TokenPool::GetSRD( const TokenId& rId ) const
+-{
+- SingleRefData* pRet;
+-
+- UINT16 nId = (UINT16) rId - 1;
+-
+- if( nId < nElementAkt && pType[ nId ] == T_RefC )
+- pRet = ppP_RefTr[ pElement[ nId ] ];
+- else
+- pRet = NULL;
+-
+- return pRet;
+-}
+-
+-
+-
+ #endif
+
diff --git sc/source/filter/inc/xelink.hxx sc/source/filter/inc/xelink.hxx
-index 795219c..2d528d9 100644
+index 795219c..53e864f 100644
--- sc/source/filter/inc/xelink.hxx
+++ sc/source/filter/inc/xelink.hxx
-@@ -178,6 +178,10 @@ public:
+@@ -173,11 +173,20 @@ public:
+ /** Searches for a special EXTERNSHEET index for the own document. */
+ sal_uInt16 FindExtSheet( sal_Unicode cCode );
+
++ void FindExtSheet( sal_uInt16 nFileId, sal_uInt16& rnExtSheet,
++ sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
++ sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
++ XclExpRefLogEntry* pRefLogEntry = NULL );
++
+ /** Stores the cell with the given address in a CRN record list. */
+ void StoreCell( const SingleRefData& rRef );
/** 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 StoreCell( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef );
+
-+ void StoreCellRange( sal_uInt16 nFileId, const ComplRefData& rRef );
++ void StoreCellRange( sal_uInt16 nFileId, const String& rTabName, 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.
-@@ -193,6 +197,10 @@ public:
+@@ -193,6 +202,10 @@ public:
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
const String& rApplic, const String& rTopic, const String& rItem );
@@ -2289,25 +4238,65 @@
virtual void Save( XclExpStream& rStrm );
diff --git sc/source/filter/inc/xilink.hxx sc/source/filter/inc/xilink.hxx
-index 0d547fe..3c2d0d9 100644
+index 0d547fe..c9d7567 100644
--- sc/source/filter/inc/xilink.hxx
+++ sc/source/filter/inc/xilink.hxx
-@@ -179,6 +179,9 @@ public:
+@@ -179,6 +179,11 @@ public:
sal_uInt16 nXtiIndex ) const;
/** Returns the specified external name or 0 on error. */
const XclImpExtName* GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const;
+
+ const String* GetSupbookUrl( sal_uInt16 nXtiIndex ) const;
+
++ const String& GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const;
++
/** Tries to decode the URL of the specified XTI entry to OLE or DDE link components.
@descr For DDE links: Decodes to application name and topic.
For OLE object links: Decodes to class name and document URL.
+@@ -186,10 +191,12 @@ public:
+ bool GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const;
+ /** Returns the specified macro name or an empty string on error. */
+ const String& GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const;
+-
++#if 0
+ /** Returns the Calc sheet index of a table in an external document.
+ @return Calc sheet index or EXC_TAB_INVALID on error. */
+ SCTAB GetScTab( const String& rUrl, const String& rTabName ) const;
++#endif
++ sal_uInt16 GetXclTab( const String& rUrl, const String& rTabName ) const;
+
+ private:
+ typedef ::std::auto_ptr< XclImpLinkManagerImpl > XclImpLinkMgrImplPtr;
+diff --git sc/source/filter/xcl97/XclImpChangeTrack.cxx sc/source/filter/xcl97/XclImpChangeTrack.cxx
+index 022b472..75cc8c6 100644
+--- sc/source/filter/xcl97/XclImpChangeTrack.cxx
++++ sc/source/filter/xcl97/XclImpChangeTrack.cxx
+@@ -176,7 +176,7 @@ sal_Bool XclImpChangeTrack::Read3DTabRefInfo( SCTAB& rFirstTab, SCTAB& rLastTab
+ // - sheet name, always separated from URL
+ String aTabName( pStrm->ReadUniString() );
+ pStrm->Ignore( 1 );
+- rFirstTab = rLastTab = static_cast<SCTAB>(GetLinkManager().GetScTab( aUrl, aTabName ));
++ rFirstTab = rLastTab = static_cast<SCTAB>(GetLinkManager().GetXclTab( aUrl, aTabName ));
+ }
+ return sal_True;
+ }
+@@ -490,9 +490,8 @@ XclImpChTrFmlConverter::~XclImpChTrFmlConverter()
+ }
+
+ // virtual, called from ExcToSc8::Convert()
+-BOOL XclImpChTrFmlConverter::Read3DTabReference( XclImpStream& rStrm, SCTAB& rFirstTab, SCTAB& rLastTab )
++bool XclImpChTrFmlConverter::Read3DTabReference( SCTAB& rFirstTab, SCTAB& rLastTab, UINT16 /*nIxti*/ )
+ {
+- rStrm.Ignore( 2 );
+ return rChangeTrack.Read3DTabRefInfo( rFirstTab, rLastTab );
+ }
+
diff --git sc/source/ui/docshell/externalrefmgr.cxx sc/source/ui/docshell/externalrefmgr.cxx
new file mode 100644
-index 0000000..1e6da7c
+index 0000000..b1d4117
--- /dev/null
+++ sc/source/ui/docshell/externalrefmgr.cxx
-@@ -0,0 +1,795 @@
+@@ -0,0 +1,1115 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -2380,9 +4369,219 @@
+using ::std::find;
+using ::std::distance;
+
-+#define SRCDOC_LIFE_SPAN 6000 // 1 minute (in 100th of sec)
++
++namespace {
++
++#include <string>
++
++class StackPrinter
++{
++public:
++ explicit StackPrinter(const char* msg) :
++ msMsg(msg)
++ {
++ fprintf(stdout, "%s: --begin\n", msMsg.c_str());
++ }
++
++ ~StackPrinter()
++ {
++ fprintf(stdout, "%s: --end\n", msMsg.c_str());
++ }
++
++private:
++ ::std::string msMsg;
++};
++
++}
++
++#define SRCDOC_LIFE_SPAN 6000 // 1 minute (in 100th of a sec)
+#define SRCDOC_SCAN_INTERVAL 1000*2 // every 2 seconds (in msec)
+
++// ============================================================================
++
++ScExternalRefCache::ScExternalRefCache()
++{
++}
++ScExternalRefCache::~ScExternalRefCache()
++{
++}
++
++ScToken* ScExternalRefCache::getCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol)
++{
++ StackPrinter __stack_print__("ScExternalRefCache::getCellData");
++
++ DocDataType::iterator itrDoc = maDocs.find(nFileId);
++ if (itrDoc == maDocs.end())
++ // specified document is not cached.
++ return NULL;
++
++ DocItem& rDoc = itrDoc->second;
++ TableNameIndexMap::iterator itrTabId = rDoc.maTableNameIndex.find(rTabName);
++ if (itrTabId == rDoc.maTableNameIndex.end())
++ // the specified table is not in cache.
++ return NULL;
++
++ TableDataTypeRef pTableData = rDoc.maTables[itrTabId->second];
++ TableDataType::iterator itrTable = pTableData->find(nRow);
++ if (itrTable == pTableData->end())
++ // this table doesn't have the specified row.
++ return NULL;
++
++ RowDataType& rRowData = itrTable->second;
++ RowDataType::iterator itrRow = rRowData.find(nCol);
++ if (itrRow == rRowData.end())
++ // this row doesn't have the specified column.
++ return NULL;
++
++ return itrRow->second.get();
++}
++
++ScTokenArray* ScExternalRefCache::getCellRangeData(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange)
++{
++ StackPrinter __stack_print__("ScExternalRefCache::getCellRangeData");
++
++ DocDataType::iterator itrDoc = maDocs.find(nFileId);
++ if (itrDoc == maDocs.end())
++ // specified document is not cached.
++ return NULL;
++
++ DocItem& rDoc = itrDoc->second;
++ TableNameIndexMap::iterator itrTabId = rDoc.maTableNameIndex.find(rTabName);
++ if (itrTabId == rDoc.maTableNameIndex.end())
++ // the specified table is not in cache.
++ return NULL;
++
++ const ScAddress& s = rRange.aStart;
++ const ScAddress& e = rRange.aEnd;
++
++ SCTAB nTab1 = s.Tab(), nTab2 = e.Tab();
++ SCCOL nCol1 = s.Col(), nCol2 = e.Col();
++ SCROW nRow1 = s.Row(), nRow2 = e.Row();
++
++ // Make sure I have all the tables cached.
++ size_t nTabFirstId = itrTabId->second;
++ size_t nTabLastId = nTabFirstId + nTab2 - nTab1;
++ if (nTabLastId >= rDoc.maTables.size())
++ // not all tables are cached.
++ return NULL;
++
++ auto_ptr<ScTokenArray> pArray(new ScTokenArray);
++ bool bFirstTab = true;
++ for (size_t nTab = nTabFirstId; nTab <= nTabLastId; ++nTab)
++ {
++ TableDataTypeRef pTab = rDoc.maTables[nTab];
++
++ ScMatrixRef xMat = new ScMatrix(
++ static_cast<SCSIZE>(nCol2-nCol1+1), static_cast<SCSIZE>(nRow2-nRow1+1));
++
++
++ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
++ {
++ TableDataType::iterator itrTable = pTab->find(nRow);
++ if (itrTable == pTab->end())
++ // this table doesn't have the specified row.
++ return NULL;
++
++ RowDataType& rRowData = itrTable->second;
++
++ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
++ {
++ RowDataType::iterator itrRow = rRowData.find(nCol);
++ if (itrRow == rRowData.end())
++ // this row doesn't have the specified column.
++ return NULL;
++
++ ScToken* pToken = itrRow->second.get();
++ SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
++ switch (pToken->GetType())
++ {
++ case svDouble:
++ xMat->PutDouble(pToken->GetDouble(), nC, nR);
++ break;
++ case svString:
++ xMat->PutString(pToken->GetString(), nC, nR);
++ break;
++ default:
++ xMat->PutEmpty(nC, nR);
++ }
++ }
++ }
++ if (!bFirstTab)
++ pArray->AddOpCode(ocSep);
++
++ ScMatrix* pMat2 = xMat;
++ ScMatrixToken aToken(pMat2);
++ pArray->AddToken(aToken);
++
++ bFirstTab = false;
++ }
++ return pArray.release();
++}
++
++void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, TokenRef pToken)
++{
++ StackPrinter __stack_print__("ScExternalRefCache::setCellData");
++
++ using ::std::pair;
++ DocDataType::iterator itrDoc = maDocs.find(nFileId);
++ if (itrDoc == maDocs.end())
++ {
++ // specified document is not cached.
++ pair<DocDataType::iterator, bool> res = maDocs.insert(
++ DocDataType::value_type(nFileId, DocItem()));
++
++ if (!res.second)
++ // insertion failed.
++ return;
++
++ itrDoc = res.first;
++ }
++
++ DocItem& rDoc = itrDoc->second;
++
++ // See if the table by this name already exists.
++ TableNameIndexMap::iterator itrTabName = rDoc.maTableNameIndex.find(rTabName);
++ if (itrTabName == rDoc.maTableNameIndex.end())
++ {
++ // Insert a new table by this name.
++ rDoc.maTables.push_back(TableDataTypeRef(new TableDataType));
++ pair<TableNameIndexMap::iterator, bool> res = rDoc.maTableNameIndex.insert(
++ TableNameIndexMap::value_type(rTabName, rDoc.maTables.size()-1));
++
++ if (!res.second)
++ return;
++
++ itrTabName = res.first;
++ }
++
++ TableDataTypeRef pTableData = rDoc.maTables[itrTabName->second];
++ TableDataType::iterator itrRow = pTableData->find(nRow);
++ if (itrRow == pTableData->end())
++ {
++ // This row does not exist yet.
++ pair<TableDataType::iterator, bool> res = pTableData->insert(
++ TableDataType::value_type(nRow, RowDataType()));
++
++ if (!res.second)
++ return;
++
++ itrRow = res.first;
++ }
++
++ // Insert this token into the specified column location. I don't need to
++ // check for existing data. Just overwrite it.
++ RowDataType& rRow = itrRow->second;
++ rRow.insert(RowDataType::value_type(nCol, pToken));
++ fprintf(stdout, "ScExternalRefCache::setCellData: token inserted\n");
++}
++
++void ScExternalRefCache::setCellRangeData(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange,
++ const vector<MatrixRef>& rData)
++{
++}
++
++// ============================================================================
++
+ScExternalRefLink::ScExternalRefLink(ScDocument* pDoc, sal_uInt16 nFileId, const String& rFilter) :
+ ::sfx2::SvBaseLink(::sfx2::LINKUPDATE_ONCALL, FORMAT_FILE),
+ mnFileId(nFileId),
@@ -2446,6 +4645,8 @@
+
+static ScToken* lcl_convertToToken(ScBaseCell* pCell)
+{
++ StackPrinter __stack_print__("::lcl_convertToToken");
++
+ if (!pCell)
+ return NULL;
+
@@ -2455,6 +4656,7 @@
+ {
+ String aStr;
+ static_cast<ScStringCell*>(pCell)->GetString(aStr);
++ fprintf(stdout, "lcl_convertToToken: string type (%s)\n", rtl::OUStringToOString(aStr, RTL_TEXTENCODING_UTF8).getStr());
+ ScStringToken aToken(aStr);
+ return aToken.Clone();
+ }
@@ -2463,11 +4665,13 @@
+ {
+ double fVal = static_cast<ScValueCell*>(pCell)->GetValue();
+ ScDoubleToken aToken(fVal);
++ fprintf(stdout, "lcl_convertToToken: value type (%g)\n", fVal);
+ return aToken.Clone();
+ }
+ break;
+ case CELLTYPE_FORMULA:
+ {
++ fprintf(stdout, "lcl_convertToToken: formula type\n");
+ ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
+ if (pFCell->IsValue())
+ {
@@ -2582,6 +4786,64 @@
+ clear();
+}
+
++ScToken* ScExternalRefManager::getSingleRefToken(sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell,
++ const ScAddress* pCurPos, SCTAB* pTab)
++{
++ StackPrinter __stack_print__("ScExternalRefManager::getSingleRefToken");
++ fprintf(stdout, "ScExternalRefManager::getSingleRefToken: file id = %d; tab name = '%s'\n", nFileId,
++ rtl::OUStringToOString(rTabName, RTL_TEXTENCODING_UTF8).getStr());
++
++ if (pCurPos)
++ insertReferencingCell(nFileId, *pCurPos);
++
++ if (pTab)
++ *pTab = -1;
++
++ // Check if the given table name and the cell position is cached.
++ ScToken* pToken = maRefCache.getCellData(nFileId, rTabName, rCell.Row(), rCell.Col());
++ if (pToken)
++ {
++ fprintf(stdout, "ScExternalRefManager::getSingleRefToken: cell reference cached.\n");
++ return pToken;
++ }
++
++ fprintf(stdout, "ScExternalRefManager::getSingleRefToken: cell reference not cached.\n");
++
++ // reference not cached. read from the source document.
++ ScDocument* pSrcDoc = getSrcDocument(nFileId);
++ if (!pSrcDoc)
++ {
++ fprintf(stdout, "ScExternalRefManager::getSingleRefToken: source document NULL\n");
++ return NULL;
++ }
++
++ ScBaseCell* pCell = NULL;
++ SCTAB nTab;
++ if (!pSrcDoc->GetTable(rTabName, nTab))
++ {
++ // specified table name doesn't exist in the source document.
++ fprintf(stdout, "ScExternalRefManager::getSingleRefToken: tab name doesn't exist in the source document.\n");
++ return NULL;
++ }
++
++ if (pTab)
++ *pTab = nTab;
++
++ pSrcDoc->GetCell(rCell.Col(), rCell.Row(), nTab, pCell);
++ TokenRef pTok(lcl_convertToToken(pCell));
++
++ if (!pTok.get())
++ {
++ // Cell in the source document is probably empty.
++ pTok.reset(new ScEmptyCellToken(false, false));
++ }
++
++ // Now, insert the token into cache table.
++ maRefCache.setCellData(nFileId, rTabName, rCell.Row(), rCell.Col(), pTok);
++ return pTok.get();
++}
++
++#if 1
+ScToken* ScExternalRefManager::getSingleRefToken(sal_uInt16 nFileId, const ScAddress& rCell, const ScAddress* pCurPos)
+{
+ if (pCurPos)
@@ -2628,14 +4890,35 @@
+ fprintf(stdout, "ScExternalRefManager::getSingleRefToken: --end\n");
+ return pTok.get();
+}
++#endif
+
-+ScTokenArray* ScExternalRefManager::getDoubleRefTokens(sal_uInt16 nFileId, const ScRange& rRange, const ScAddress* pCurPos)
++ScTokenArray* ScExternalRefManager::getDoubleRefTokens(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos)
+{
+ if (pCurPos)
+ insertReferencingCell(nFileId, *pCurPos);
-+ return getDoubleRefTokens(nFileId, rRange);
++
++ // Check if the given table name and the cell position is cached.
++ auto_ptr<ScTokenArray> pArray;
++ pArray.reset(maRefCache.getCellRangeData(nFileId, rTabName, rRange));
++ if (pArray.get())
++ {
++ fprintf(stdout, "ScExternalRefManager::getDoubleRefTokens: range reference cached.\n");
++ return pArray.release();
++ }
++
++
++ SCTAB nTab = getExternalTableId(nFileId, rTabName);
++ if (nTab < 0)
++ return NULL;
++
++ ScRange aRange(rRange);
++ SCTAB nTabSpan = aRange.aEnd.Tab() - aRange.aStart.Tab();
++ aRange.aStart.SetTab(nTab);
++ aRange.aEnd.SetTab(nTab + nTabSpan);
++ return getDoubleRefTokens(nFileId, aRange);
+}
+
++#if 1
+ScTokenArray* ScExternalRefManager::getDoubleRefTokens(sal_uInt16 nFileId, const ScRange& rRange)
+{
+ {
@@ -2673,6 +4956,7 @@
+ fprintf(stdout, "ScExternalRefManager::getDoubleRefToken: --end\n");
+ return pArray.get();
+}
++#endif
+
+ScTokenArray* ScExternalRefManager::getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos)
+{
@@ -2732,7 +5016,7 @@
+ case svSingleRef:
+ {
+ fprintf(stdout, "ScDocument::FindExternalRangeName: single ref\n");
-+ ScExternalSingleRefToken aNewToken(nFileId, pToken->GetSingleRef());
++ ScExternalSingleRefToken aNewToken(nFileId, String(), pToken->GetSingleRef());
+ pNew->AddToken(aNewToken);
+ bTokenAdded = true;
+ }
@@ -2740,7 +5024,7 @@
+ case svDoubleRef:
+ {
+ fprintf(stdout, "ScDocument::FindExternalRangeName: double ref\n");
-+ ScExternalDoubleRefToken aNewToken(nFileId, pToken->GetDoubleRef());
++ ScExternalDoubleRefToken aNewToken(nFileId, String(), pToken->GetDoubleRef());
+ pNew->AddToken(aNewToken);
+ bTokenAdded = true;
+ }
@@ -2948,8 +5232,8 @@
+ pCode->Reset();
+ for (ScToken* p = pCode->First(); p; p = pCode->Next())
+ {
-+ // TODO: once we have implemented a new token for the external
-+ // references, we will also query for that token type.
++ // External names, external cell and range references all have a
++ // ocExternalName token.
+ if (p->GetOpCode() == ocExternalName)
+ {
+ bCompile = true;
@@ -2972,7 +5256,7 @@
+
+void ScExternalRefManager::convertToAbsName(String& rFile) const
+{
-+ ScDocShell* pDocShell = ScDocShell::GetViewData()->GetDocShell();
++ SfxObjectShell* pDocShell = mpDoc->GetDocumentShell();
+ rFile = ScGlobal::GetAbsDocName(rFile, pDocShell);
+}
+
@@ -3012,6 +5296,31 @@
+ return &pCache->maTableNames[nTabId];
+}
+
++SCTAB ScExternalRefManager::getExternalTableId(sal_uInt16 nFileId, const String& rTabName)
++{
++ vector<String>& rNames = getDocumentCache(nFileId)->maTableNames;
++ vector<String>::iterator itrBeg = rNames.begin(), itrEnd = rNames.end();
++ vector<String>::iterator itr = find(itrBeg, itrEnd, rTabName);
++ if (itr != itrEnd)
++ // found in cache
++ return static_cast<SCTAB>(distance(itrBeg, itr));
++
++ // Loading the source document resets the table name vector.
++ ScDocument* pSrcDoc = getSrcDocument(nFileId);
++ if (!pSrcDoc)
++ // source document could not be loaded.
++ return -1;
++
++ itrBeg = rNames.begin();
++ itrEnd = rNames.end();
++ itr = find(itrBeg, itrEnd, rTabName);
++ if (itr != itrEnd)
++ // found in the source document
++ return static_cast<SCTAB>(distance(itrBeg, itr));
++
++ return -1;
++}
++
+template<typename MapContainer>
+static void lcl_removeByFileId(sal_uInt16 nFileId, MapContainer& rMap)
+{
@@ -3139,3 +5448,47 @@
$(SLO)$/tablink.obj \
$(SLO)$/arealink.obj \
$(SLO)$/dbdocfun.obj \
+diff --git sc/source/ui/view/viewfun3.cxx sc/source/ui/view/viewfun3.cxx
+index e42ed5d..e660e1c 100644
+--- sc/source/ui/view/viewfun3.cxx
++++ sc/source/ui/view/viewfun3.cxx
+@@ -212,6 +212,31 @@
+
+ using namespace com::sun::star;
+
++
++namespace {
++
++#include <string>
++
++class StackPrinter
++{
++public:
++ explicit StackPrinter(const char* msg) :
++ msMsg(msg)
++ {
++ fprintf(stdout, "%s: --begin\n", msMsg.c_str());
++ }
++
++ ~StackPrinter()
++ {
++ fprintf(stdout, "%s: --end\n", msMsg.c_str());
++ }
++
++private:
++ ::std::string msMsg;
++};
++
++}
++
+ // STATIC DATA ---------------------------------------------------------------
+
+
+@@ -748,6 +773,7 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
+ InsCellCmd eMoveMode, USHORT nUndoExtraFlags,
+ BOOL bAllowDialogs )
+ {
++ StackPrinter aStack("ScViewFunc::PasteFromClip");
+ if (!pClipDoc)
+ {
+ DBG_ERROR("PasteFromClip: pClipDoc=0 not allowed");
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]