ooo-build r13628 - in trunk: . patches/dev300 patches/test
- From: kyoshida svn gnome org
- To: svn-commits-list gnome org
- Subject: ooo-build r13628 - in trunk: . patches/dev300 patches/test
- Date: Tue, 19 Aug 2008 15:10:45 +0000 (UTC)
Author: kyoshida
Date: Tue Aug 19 15:10:44 2008
New Revision: 13628
URL: http://svn.gnome.org/viewvc/ooo-build?rev=13628&view=rev
Log:
2008-08-19 Kohei Yoshida <kyoshida novell com>
* patches/dev300/calc-external-defined-names.diff: updated the patch
with the change introduced by the patch below.
* patches/test/calc-external-ref-odf-cache.diff: removed as this has
been combined with the patch above.
Removed:
trunk/patches/test/calc-external-ref-odf-cache.diff
Modified:
trunk/ChangeLog
trunk/patches/dev300/calc-external-defined-names.diff
Modified: trunk/patches/dev300/calc-external-defined-names.diff
==============================================================================
--- trunk/patches/dev300/calc-external-defined-names.diff (original)
+++ trunk/patches/dev300/calc-external-defined-names.diff Tue Aug 19 15:10:44 2008
@@ -169,10 +169,10 @@
BOOL IsColRowName( const String& );
BOOL IsBoolean( const String& );
diff --git sc/inc/document.hxx sc/inc/document.hxx
-index 80fc25c..a5c0240 100644
+index 1de31e7..8c50532 100644
--- sc/inc/document.hxx
+++ sc/inc/document.hxx
-@@ -93,6 +93,7 @@ class ScDocOptions;
+@@ -93,6 +93,7 @@ class ScDocProtection;
class ScDocumentPool;
class ScDrawLayer;
class ScExtDocOptions;
@@ -207,10 +207,10 @@
diff --git sc/inc/externalrefmgr.hxx sc/inc/externalrefmgr.hxx
new file mode 100644
-index 0000000..8a11b5d
+index 0000000..7398ed1
--- /dev/null
+++ sc/inc/externalrefmgr.hxx
-@@ -0,0 +1,342 @@
+@@ -0,0 +1,373 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -322,7 +322,9 @@
+ ~Table();
+
+ void setCell(SCROW nRow, SCCOL nCol, TokenRef pToken);
-+ ScToken* getCell(SCROW nRow, SCCOL nCol) const;
++ TokenRef getCell(SCROW nRow, SCCOL nCol) const;
++ void getAllRows(::std::vector<SCROW>& rRows) const;
++ void getAllCols(SCROW nRow, ::std::vector<SCCOL>& rCols) const;
+
+ private:
+ RowsDataType maRows;
@@ -388,7 +390,7 @@
+ *
+ * @return pointer to the cache table instance
+ */
-+ Table* getCacheTable(sal_uInt16 nFileId, const String& rTabName);
++ Table* getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew = true);
+
+ void clearCache(sal_uInt16 nFileId);
+
@@ -430,7 +432,8 @@
+ }
+ };
+
-+ struct SrcDoc
++ /** Shell instance for a source document. */
++ struct SrcShell
+ {
+ SfxObjectShellRef maShell;
+ Time maLastAccess;
@@ -439,13 +442,23 @@
+ typedef ::boost::shared_ptr<ScToken> TokenRef;
+ typedef ::boost::shared_ptr<ScTokenArray> TokenArrayRef;
+
-+ typedef ::std::hash_map<sal_uInt16, SrcDoc> DocShellMap;
-+ typedef ::std::hash_set<sal_uInt16, ScStringHashCode> LinkedDocSet;
++ typedef ::std::hash_map<sal_uInt16, SrcShell> DocShellMap;
++ typedef ::std::hash_set<sal_uInt16> LinkedDocSet;
+
+ typedef ::std::hash_set<ScAddress, AddressHash, ::std::equal_to<ScAddress> > RefCellSet;
+ typedef ::std::hash_map<sal_uInt16, RefCellSet> RefCellMap;
+
+public:
++ /** Source document meta-data container. */
++ struct SrcFileData
++ {
++ String maFileName;
++ String maRelativeName;
++ String maFilterName;
++ String maFilterOptions;
++ };
++
++public:
+ explicit ScExternalRefManager(ScDocument* pDoc);
+ ~ScExternalRefManager();
+
@@ -482,6 +495,8 @@
+ */
+ ScTokenArray* getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos = NULL);
+
++ bool isOwnDocument(const String& rFile) const;
++
+ /**
+ * Takes a flat file name, and convert it to an absolute URL path. An
+ * absolute URL path begines with 'file:///.
@@ -491,9 +506,26 @@
+ void convertToAbsName(String& rFile) const;
+ sal_uInt16 getExternalFileId(const String& rFile);
+ const String* getExternalFileName(sal_uInt16 nFileId) const;
++ const SrcFileData* getExternalFileData(sal_uInt16 nFileId) const;
++
+ const ::std::vector<String>* getAllCachedTableNames(sal_uInt16 nFileId) const;
++ sal_uInt16 getCachedFileCount() const;
+ void refreshNames(sal_uInt16 nFileId);
+ void switchSrcFile(sal_uInt16 nFileId, const String& rNewFile);
++
++ void setRelativeFileName(sal_uInt16 nFileId, const String& rRelUrl);
++
++ /**
++ * Set the filter name and options if any for a given source document.
++ * These values get reset whne the source document ever gets reloaded.
++ *
++ * @param nFileId
++ * @param rFilterName
++ * @param rOptions
++ * @return
++ */
++ void setFilterData(sal_uInt16 nFileId, const String& rFilterName, const String& rOptions);
++
+ void removeSrcDocument(sal_uInt16 nFileId, bool bBreakLink);
+ void clear();
+
@@ -508,7 +540,7 @@
+ void insertReferencingCell(sal_uInt16 nFileId, const ScAddress& rCell);
+
+ ScDocument* getSrcDocument(sal_uInt16 nFileId);
-+ SfxObjectShellRef loadSrcDocument(const String& rFile, String& rFilter);
++ SfxObjectShellRef loadSrcDocument(sal_uInt16 nFileId, const String& rFile, String& rFilter);
+
+ void maybeLinkExternalFile(sal_uInt16 nFileId);
+
@@ -523,15 +555,14 @@
+ void purgeStaleSrcDocument(sal_Int32 nTimeOut);
+
+private:
-+ /** cache only of referenced ranges and names from source documents. */
++ /** cache of referenced ranges and names from source documents. */
+ ScExternalRefCache maRefCache;
+
+ ScDocument* mpDoc;
+
+ /**
-+ * Source document cache. This stores the original source document
-+ * instances. The source documents get purged after certain period of
-+ * time.
++ * Source document cache. This stores the original source document shell
++ * instances. They get purged after a certain period of time.
+ */
+ DocShellMap maDocShells;
+
@@ -545,7 +576,7 @@
+ RefCellMap maRefCells;
+
+ /** original source file index. */
-+ ::std::vector<String> maFileNames;
++ ::std::vector<SrcFileData> maSrcFiles;
+
+ AutoTimer maSrcDocTimer;
+ DECL_LINK(TimeOutHdl, AutoTimer*);
@@ -693,10 +724,10 @@
ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( t->GetIndex() );
if( pRangeData )
diff --git sc/source/core/data/documen2.cxx sc/source/core/data/documen2.cxx
-index 050e413..d9dccd9 100644
+index b75279e..d739a17 100644
--- sc/source/core/data/documen2.cxx
+++ sc/source/core/data/documen2.cxx
-@@ -93,6 +93,7 @@
+@@ -94,6 +94,7 @@
#include "recursionhelper.hxx"
#include "lookupcache.hxx"
#include "tabprotection.hxx"
@@ -704,7 +735,7 @@
#include <com/sun/star/document/XVbaEventsHelper.hpp>
// pImpl because including lookupcache.hxx in document.hxx isn't wanted, and
-@@ -152,6 +153,7 @@ ScDocument::ScDocument( ScDocumentMode eMode,
+@@ -153,6 +154,7 @@ ScDocument::ScDocument( ScDocumentMode eMode,
pScriptTypeData( NULL ),
pCacheFieldEditEngine( NULL ),
pDocProtection( NULL ),
@@ -712,7 +743,7 @@
pViewOptions( NULL ),
pDocOptions( NULL ),
pExtDocOptions( NULL ),
-@@ -382,6 +384,11 @@ ScDocument::~ScDocument()
+@@ -383,6 +385,11 @@ ScDocument::~ScDocument()
pLinkManager->Remove( 0, pLinkManager->GetLinks().Count() );
}
@@ -809,7 +840,7 @@
{
if (pLinkManager)
diff --git sc/source/core/tool/address.cxx sc/source/core/tool/address.cxx
-index 2cb5dce..80dfb34 100644
+index 2cb5dce..c1906dd 100644
--- sc/source/core/tool/address.cxx
+++ sc/source/core/tool/address.cxx
@@ -35,6 +35,7 @@
@@ -1031,7 +1062,7 @@
{
const sal_Unicode* pTmp = NULL;
String aExternDocName, aStartTabName, aEndTabName;
-@@ -442,6 +439,15 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -442,6 +439,18 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
#endif
p = lcl_ScRange_Parse_XL_Header( r, p, pDoc,
aExternDocName, aStartTabName, aEndTabName, nFlags );
@@ -1039,15 +1070,18 @@
+ if (aExternDocName.Len() > 0)
+ {
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
-+ pExtInfo->mbExternal = true;
-+ pExtInfo->maTabName = aStartTabName;
-+ pExtInfo->mnFileId = pRefMgr->getExternalFileId(aExternDocName);
++ if (!pRefMgr->isOwnDocument(aExternDocName))
++ {
++ pExtInfo->mbExternal = true;
++ pExtInfo->maTabName = aStartTabName;
++ pExtInfo->mnFileId = pRefMgr->getExternalFileId(aExternDocName);
++ }
+ }
+
if( NULL == p )
return 0;
-@@ -480,8 +486,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -480,8 +489,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
r.aStart.SetCol( 0 );
r.aEnd.SetCol( MAXCOL );
@@ -1057,7 +1091,7 @@
}
else if( NULL == (p = lcl_r1c1_get_col( p, rDetails, &r.aStart, &nFlags )))
goto failed;
-@@ -501,8 +506,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -501,8 +509,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
return nFlags;
}
@@ -1067,7 +1101,7 @@
}
p = pTmp;
-@@ -517,8 +521,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -517,8 +524,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
}
nFlags |= (nFlags2 << 4);
@@ -1077,7 +1111,7 @@
}
else if( *p == 'C' || *p == 'c' ) // full col C#
{
-@@ -550,8 +553,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -550,8 +556,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
r.aStart.SetRow( 0 );
r.aEnd.SetRow( MAXROW );
@@ -1087,7 +1121,7 @@
}
failed :
-@@ -604,7 +606,8 @@ static USHORT
+@@ -604,7 +609,8 @@ static USHORT
lcl_ScRange_Parse_XL_A1( ScRange& r,
const sal_Unicode* p,
ScDocument* pDoc,
@@ -1097,7 +1131,7 @@
{
const sal_Unicode* tmp1, *tmp2;
String aExternDocName, aStartTabName, aEndTabName; // for external link table
-@@ -619,6 +622,15 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -619,6 +625,18 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
#endif
p = lcl_ScRange_Parse_XL_Header( r, p, pDoc,
aExternDocName, aStartTabName, aEndTabName, nFlags );
@@ -1105,15 +1139,18 @@
+ if (aExternDocName.Len() > 0)
+ {
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
-+ pExtInfo->mbExternal = true;
-+ pExtInfo->maTabName = aStartTabName;
-+ pExtInfo->mnFileId = pRefMgr->getExternalFileId(aExternDocName);
++ if (!pRefMgr->isOwnDocument(aExternDocName))
++ {
++ pExtInfo->mbExternal = true;
++ pExtInfo->maTabName = aStartTabName;
++ pExtInfo->mnFileId = pRefMgr->getExternalFileId(aExternDocName);
++ }
+ }
+
if( NULL == p )
return 0;
-@@ -640,8 +652,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -640,8 +658,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
SCA_VALID_COL | SCA_VALID_COL2 |
SCA_COL_ABSOLUTE | SCA_COL2_ABSOLUTE;
nFlags |= (nFlags2 << 4);
@@ -1123,7 +1160,7 @@
}
tmp2 = lcl_a1_get_row( tmp1, &r.aStart, &nFlags );
-@@ -661,8 +672,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -661,8 +678,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
SCA_VALID_ROW | SCA_VALID_ROW2 |
SCA_ROW_ABSOLUTE | SCA_ROW2_ABSOLUTE;
nFlags |= (nFlags2 << 4);
@@ -1133,7 +1170,7 @@
}
// prepare as if it's a singleton, in case we want to fall back */
-@@ -672,8 +682,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -672,8 +688,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
if ( bOnlyAcceptSingle )
{
if ( *tmp2 == 0 )
@@ -1143,7 +1180,7 @@
else
{
// any trailing invalid character must invalidate the address.
-@@ -692,12 +701,11 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -692,12 +707,11 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
p = tmp2;
tmp1 = lcl_a1_get_col( p+1, &r.aEnd, &nFlags2 );
if( !tmp1 ) // strange, but valid singleton
@@ -1159,7 +1196,7 @@
if ( *tmp2 != 0 )
{
-@@ -708,20 +716,19 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -708,20 +722,19 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
}
nFlags |= (nFlags2 << 4);
@@ -1184,7 +1221,7 @@
// Lets see if this is a reference to something in an external file.
// A Documentname is always quoted and has a trailing #
-@@ -795,35 +802,11 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+@@ -795,35 +808,11 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
}
if( *p++ != '.' )
nBits = 0;
@@ -1224,7 +1261,7 @@
}
else
nBits = 0;
-@@ -884,16 +867,30 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+@@ -884,16 +873,32 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
if( !nBits )
p = q;
}
@@ -1238,28 +1275,32 @@
+ pRefMgr->convertToAbsName(aDocName);
+
+ // TODO: Do we need to check if the document exists before going further?
-+
-+ 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))
++ if (!pRefMgr->isOwnDocument(aDocName))
{
- nRes |= SCA_VALID_TAB;
+- nRes |= SCA_VALID_TAB;
++ 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;
}
- else
+- 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 +909,8 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+@@ -912,9 +917,8 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
}
static USHORT
@@ -1271,7 +1312,7 @@
{
if( !*p )
return 0;
-@@ -924,20 +920,20 @@ lcl_ScAddress_Parse ( BOOL& bExternal, const sal_Unicode* p,
+@@ -924,20 +928,20 @@ lcl_ScAddress_Parse ( BOOL& bExternal, const sal_Unicode* p,
default :
case ScAddress::CONV_OOO:
{
@@ -1295,7 +1336,7 @@
rAddr = r.aStart;
return nFlags;
}
-@@ -949,9 +945,8 @@ bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
+@@ -949,9 +953,8 @@ bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
SCTAB nDefTab, ScRefAddress& rRefAddress,
const ScAddress::Details& rDetails )
{
@@ -1306,7 +1347,7 @@
if( nRes & SCA_VALID )
{
rRefAddress.Set( aAddr,
-@@ -988,10 +983,9 @@ bool ConvertDoubleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab
+@@ -988,10 +991,9 @@ bool ConvertDoubleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab
USHORT ScAddress::Parse( const String& r, ScDocument* pDoc,
@@ -1319,7 +1360,7 @@
}
-@@ -1060,7 +1054,7 @@ void ScRange::ExtendTo( const ScRange& rRange )
+@@ -1060,7 +1062,7 @@ void ScRange::ExtendTo( const ScRange& rRange )
}
static USHORT
@@ -1328,7 +1369,7 @@
{
USHORT nRes1 = 0, nRes2 = 0;
xub_StrLen nTmp = 0;
-@@ -1073,13 +1067,12 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
+@@ -1073,13 +1075,12 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
String aTmp( r );
sal_Unicode* p = aTmp.GetBufferAccess();
p[ nPos ] = 0;
@@ -1345,7 +1386,7 @@
nRes2 &= ~SCA_VALID_TAB; // #REF!
else
{
-@@ -1132,7 +1125,7 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
+@@ -1132,7 +1133,7 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
}
USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
@@ -1354,7 +1395,7 @@
{
if ( r.Len() <= 0 )
return 0;
-@@ -1141,13 +1134,13 @@ USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
+@@ -1141,13 +1142,13 @@ USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
{
default :
case ScAddress::CONV_OOO:
@@ -2928,10 +2969,10 @@
{
DBG_ASSERT_BIFF( GetBiff() == EXC_BIFF5 );
diff --git sc/source/filter/excel/excform8.cxx sc/source/filter/excel/excform8.cxx
-index ebf8543..46a5163 100644
+index ebf8543..e0467a0 100644
--- sc/source/filter/excel/excform8.cxx
+++ sc/source/filter/excel/excform8.cxx
-@@ -41,6 +41,11 @@
+@@ -41,6 +41,18 @@
#include "xilink.hxx"
#include "xiname.hxx"
@@ -2940,10 +2981,17 @@
+#include <vector>
+
+using ::std::vector;
++
++ExcelToSc8::ExternalTabInfo::ExternalTabInfo() :
++ mnFileId(0), mbExternal(false)
++{
++}
++
++// ============================================================================
ExcelToSc8::ExcelToSc8( const XclImpRoot& rRoot ) :
ExcelToSc( rRoot ),
-@@ -53,15 +58,33 @@ ExcelToSc8::~ExcelToSc8()
+@@ -53,15 +65,33 @@ ExcelToSc8::~ExcelToSc8()
{
}
@@ -2981,7 +3029,7 @@
}
-@@ -608,8 +631,15 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
+@@ -608,8 +638,15 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
{
case xlExtName:
{
@@ -2999,7 +3047,7 @@
}
break;
-@@ -657,47 +687,67 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
+@@ -657,47 +694,67 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
case 0x7C:
case 0x3C: // Deleted 3-D Cell Reference [ 277]
{
@@ -3101,7 +3149,7 @@
}
break;
case 0x5B:
-@@ -707,55 +757,61 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
+@@ -707,55 +764,61 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
case 0x7D:
case 0x3D: // Deleted 3-D Area Reference [ 277]
{
@@ -3206,7 +3254,7 @@
}
break;
default: bError = TRUE;
-@@ -1143,7 +1199,130 @@ ConvErr ExcelToSc8::Convert( _ScRangeListTabs& rRangeList, XclImpStream& aIn, sa
+@@ -1143,7 +1206,130 @@ ConvErr ExcelToSc8::Convert( _ScRangeListTabs& rRangeList, XclImpStream& aIn, sa
return eRet;
}
@@ -5134,7 +5182,7 @@
public:
inline XclImpChTrFmlConverter(
diff --git sc/source/filter/inc/excform.hxx sc/source/filter/inc/excform.hxx
-index 915dd98..279cbbd 100644
+index 915dd98..3059d6d 100644
--- sc/source/filter/inc/excform.hxx
+++ sc/source/filter/inc/excform.hxx
@@ -35,6 +35,7 @@
@@ -5156,7 +5204,13 @@
virtual BOOL GetAbsRefs( ScRangeList& rRangeList, XclImpStream& rStrm, sal_Size nLen );
void GetDummy( const ScTokenArray*& );
-@@ -107,14 +112,24 @@ class XclImpLinkManager;
+@@ -102,19 +107,32 @@ inline BOOL ExcelToSc::IsComplRowRange( const UINT16 nRow1, const UINT16 nRow2 )
+ return ( ( nRow1 & 0x3FFF ) == 0x0000 ) && ( ( nRow2 & 0x3FFF ) == 0x3FFF );
+ }
+
++// ============================================================================
+
+ class XclImpLinkManager;
class ExcelToSc8 : public ExcelToSc
{
@@ -5167,6 +5221,8 @@
+ String maTabName;
+ sal_uInt16 mnFileId;
+ bool mbExternal;
++
++ ExternalTabInfo();
+ };
+
private:
@@ -5183,7 +5239,7 @@
public:
ExcelToSc8( const XclImpRoot& rRoot );
-@@ -124,6 +139,9 @@ public:
+@@ -124,6 +142,9 @@ public:
virtual ConvErr Convert( _ScRangeListTabs&, XclImpStream& rStrm, sal_Size nFormulaLen, SCsTAB nTab, const FORMULA_TYPE eFT = FT_CellFormula );
@@ -5458,68 +5514,2003 @@
+ return rChangeTrack.Read3DTabRefInfo( rFirstTab, rLastTab, rExtInfo );
}
-diff --git sc/source/ui/docshell/docsh4.cxx sc/source/ui/docshell/docsh4.cxx
-index bc5975d..6701d1c 100644
---- sc/source/ui/docshell/docsh4.cxx
-+++ sc/source/ui/docshell/docsh4.cxx
-@@ -123,6 +123,7 @@ using namespace ::com::sun::star;
- #include <com/sun/star/document/UpdateDocMode.hpp>
- #include "scresid.hxx" //add by CHINA001
- #include "scabstdlg.hxx" //CHINA001
+diff --git sc/source/filter/xml/XMLDDELinksContext.cxx sc/source/filter/xml/XMLDDELinksContext.cxx
+index 81ec1d2..4ab6982 100644
+--- sc/source/filter/xml/XMLDDELinksContext.cxx
++++ sc/source/filter/xml/XMLDDELinksContext.cxx
+@@ -46,6 +46,7 @@
+
+ using namespace com::sun::star;
+ using namespace xmloff::token;
++using ::rtl::OUString;
+
+ //------------------------------------------------------------------
+
+diff --git sc/source/filter/xml/XMLTableShapeImportHelper.cxx sc/source/filter/xml/XMLTableShapeImportHelper.cxx
+index bb6fe74..219b5cc 100644
+--- sc/source/filter/xml/XMLTableShapeImportHelper.cxx
++++ sc/source/filter/xml/XMLTableShapeImportHelper.cxx
+@@ -49,6 +49,7 @@
+
+ using namespace ::com::sun::star;
+ using namespace xmloff::token;
++using ::rtl::OUString;
+
+ XMLTableShapeImportHelper::XMLTableShapeImportHelper(
+ ScXMLImport& rImp, SvXMLImportPropertyMapper *pImpMapper ) :
+diff --git sc/source/filter/xml/XMLTrackedChangesContext.cxx sc/source/filter/xml/XMLTrackedChangesContext.cxx
+index a779ddf..3b2ea17 100644
+--- sc/source/filter/xml/XMLTrackedChangesContext.cxx
++++ sc/source/filter/xml/XMLTrackedChangesContext.cxx
+@@ -48,6 +48,7 @@
+
+ using namespace com::sun::star;
+ using namespace xmloff::token;
++using ::rtl::OUString;
+
+ //-----------------------------------------------------------------------------
+
+diff --git sc/source/filter/xml/makefile.mk sc/source/filter/xml/makefile.mk
+index 68ee10b..d44da6b 100644
+--- sc/source/filter/xml/makefile.mk
++++ sc/source/filter/xml/makefile.mk
+@@ -57,6 +57,7 @@ CXXFILES = \
+ xmlexprt.cxx \
+ xmlbodyi.cxx \
+ xmltabi.cxx \
++ xmlexternaltabi.cxx \
+ xmlrowi.cxx \
+ xmlcelli.cxx \
+ xmlconti.cxx \
+@@ -106,6 +107,7 @@ SLOFILES = \
+ $(SLO)$/xmlexprt.obj \
+ $(SLO)$/xmlbodyi.obj \
+ $(SLO)$/xmltabi.obj \
++ $(SLO)$/xmlexternaltabi.obj \
+ $(SLO)$/xmlrowi.obj \
+ $(SLO)$/xmlcelli.obj \
+ $(SLO)$/xmlconti.obj \
+diff --git sc/source/filter/xml/xmlbodyi.cxx sc/source/filter/xml/xmlbodyi.cxx
+index 5f3545a..76780d3 100644
+--- sc/source/filter/xml/xmlbodyi.cxx
++++ sc/source/filter/xml/xmlbodyi.cxx
+@@ -67,6 +67,7 @@
+
+ using namespace com::sun::star;
+ using namespace xmloff::token;
++using ::rtl::OUString;
+
+ //------------------------------------------------------------------
+
+diff --git sc/source/filter/xml/xmlcelli.cxx sc/source/filter/xml/xmlcelli.cxx
+index 92eb208..a990e54 100644
+--- sc/source/filter/xml/xmlcelli.cxx
++++ sc/source/filter/xml/xmlcelli.cxx
+@@ -146,185 +146,131 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
+ rtl::OUString aLocalName;
+ rtl::OUString* pStyleName = NULL;
+ rtl::OUString* pCurrencySymbol = NULL;
+- for( sal_Int16 i=0; i < nAttrCount; ++i )
++ const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
++ for (sal_Int16 i = 0; i < nAttrCount; ++i)
+ {
+- sal_uInt16 nPrefix = rXMLImport.GetNamespaceMap().GetKeyByAttrName(
+- xAttrList->getNameByIndex( i ), &aLocalName );
+- const rtl::OUString& sValue(xAttrList->getValueByIndex( i ));
++ sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
++ xAttrList->getNameByIndex(i), &aLocalName);
+
+- if (nPrefix == XML_NAMESPACE_TABLE)
+- {
+- sal_uInt32 nLength(aLocalName.getLength());
+-
+- switch (nLength)
++ const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
++ sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
++ switch (nToken)
++ {
++ case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
++ pStyleName = new rtl::OUString(sValue);
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME:
++ DBG_ASSERT(!pContentValidationName, "here should be only one Validation Name");
++ pContentValidationName = new rtl::OUString(sValue);
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS:
++ bIsMerged = sal_True;
++ nMergedRows = sValue.toInt32();
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS:
++ bIsMerged = sal_True;
++ nMergedCols = sValue.toInt32();
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS:
++ bIsMatrix = sal_True;
++ nMatrixCols = sValue.toInt32();
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS:
++ bIsMatrix = sal_True;
++ nMatrixRows = sValue.toInt32();
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
++ nCellsRepeated = std::max( sValue.toInt32(), (sal_Int32) 1 );
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
++ nCellType = GetScImport().GetCellType(sValue);
++ bIsEmpty = sal_False;
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
+ {
+- case 7 :
+- {
+- if (IsXMLToken(aLocalName, XML_FORMULA))
+- {
+- if (sValue.getLength())
+- {
+- DBG_ASSERT(!pOUFormula, "here should be only one formula");
+- DELETEZ( pOUFormula);
+- rtl::OUString sFormula;
+- sal_uInt16 nFormulaPrefix = GetImport().GetNamespaceMap().
+- _GetKeyByAttrName( sValue, &sFormula, sal_False );
+-
+- if (ScXMLImport::IsAcceptedFormulaNamespace(
+- nFormulaPrefix, sValue, eGrammar,
+- eStorageGrammar))
+- {
+- // Namespaces we accept.
+- pOUFormula = new rtl::OUString( sFormula);
+- }
+- else
+- {
+- // No namespace => entire string.
+- // Also unknown namespace included in formula,
+- // so hopefully will result in string or
+- // compile error.
+- pOUFormula = new rtl::OUString( sValue);
+- }
+- }
+- }
+- }
+- break;
+- case 10 :
+- {
+- if (IsXMLToken(aLocalName, XML_STYLE_NAME))
+- pStyleName = new rtl::OUString(sValue);
+- }
+- break;
+- case 19 :
++ if (sValue.getLength())
+ {
+- if (IsXMLToken(aLocalName, XML_NUMBER_ROWS_SPANNED))
+- {
+- bIsMerged = sal_True;
+- nMergedRows = sValue.toInt32();
+- }
++ rXMLImport.GetMM100UnitConverter().convertDouble(fValue, sValue);
++ bIsEmpty = sal_False;
+ }
+- break;
+- case 22 :
+- {
+- if (IsXMLToken(aLocalName, XML_NUMBER_COLUMNS_SPANNED))
+- {
+- bIsMerged = sal_True;
+- nMergedCols = sValue.toInt32();
+- }
+- }
+- break;
+- case 23 :
+- {
+- if (IsXMLToken(aLocalName, XML_NUMBER_COLUMNS_REPEATED))
+- nCellsRepeated = std::max( sValue.toInt32(), (sal_Int32) 1 );
+- else if (IsXMLToken(aLocalName, XML_CONTENT_VALIDATION_NAME))
+- {
+- DBG_ASSERT(!pContentValidationName, "here should be only one Validation Name");
+- pContentValidationName = new rtl::OUString(sValue);
+- }
+- }
+- break;
+- case 26 :
+- {
+- if (IsXMLToken(aLocalName, XML_NUMBER_MATRIX_ROWS_SPANNED))
+- {
+- bIsMatrix = sal_True;
+- nMatrixRows = sValue.toInt32();
+- }
+- }
+- break;
+- case 29 :
+- {
+- if (IsXMLToken(aLocalName, XML_NUMBER_MATRIX_COLUMNS_SPANNED))
+- {
+- bIsMatrix = sal_True;
+- nMatrixCols = sValue.toInt32();
+- }
+- }
+- break;
+ }
+- }
+- else if (nPrefix == XML_NAMESPACE_OFFICE)
+- {
+- sal_uInt32 nLength(aLocalName.getLength());
+-
+- switch (nLength)
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
+ {
+- case 5 :
++ if (sValue.getLength() && rXMLImport.SetNullDateOnUnitConverter())
+ {
+- if (IsXMLToken(aLocalName, XML_VALUE))
+- {
+- if (sValue.getLength())
+- {
+- rXMLImport.GetMM100UnitConverter().convertDouble(fValue, sValue);
+- bIsEmpty = sal_False;
+- }
+- }
++ rXMLImport.GetMM100UnitConverter().convertDateTime(fValue, sValue);
++ bIsEmpty = sal_False;
+ }
+- break;
+- case 8 :
++ }
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
++ {
++ if (sValue.getLength())
+ {
+- if (IsXMLToken(aLocalName, XML_CURRENCY))
+- pCurrencySymbol = new rtl::OUString(sValue);
++ rXMLImport.GetMM100UnitConverter().convertTime(fValue, sValue);
++ bIsEmpty = sal_False;
+ }
+- break;
+- case 10 :
++ }
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
++ {
++ if (sValue.getLength())
+ {
+- if (IsXMLToken(aLocalName, XML_VALUE_TYPE))
+- {
+- nCellType = GetCellType(sValue);
+- bIsEmpty = sal_False;
+- }
+- else if (IsXMLToken(aLocalName, XML_DATE_VALUE))
+- {
+- if (sValue.getLength() && rXMLImport.SetNullDateOnUnitConverter())
+- {
+- rXMLImport.GetMM100UnitConverter().convertDateTime(fValue, sValue);
+- bIsEmpty = sal_False;
+- }
+- }
+- else if (IsXMLToken(aLocalName, XML_TIME_VALUE))
+- {
+- if (sValue.getLength())
+- {
+- rXMLImport.GetMM100UnitConverter().convertTime(fValue, sValue);
+- bIsEmpty = sal_False;
+- }
+- }
++ DBG_ASSERT(!pOUTextValue, "here should be only one string value");
++ pOUTextValue = new rtl::OUString(sValue);
++ bIsEmpty = sal_False;
+ }
+- break;
+- case 12 :
++ }
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
++ {
++ if (sValue.getLength())
+ {
+- if (IsXMLToken(aLocalName, XML_STRING_VALUE))
+- {
+- if (sValue.getLength())
+- {
+- DBG_ASSERT(!pOUTextValue, "here should be only one string value");
+- pOUTextValue = new rtl::OUString(sValue);
+- bIsEmpty = sal_False;
+- }
+- }
++ if ( IsXMLToken(sValue, XML_TRUE) )
++ fValue = 1.0;
++ else if ( IsXMLToken(sValue, XML_FALSE) )
++ fValue = 0.0;
++ else
++ rXMLImport.GetMM100UnitConverter().convertDouble(fValue, sValue);
++ bIsEmpty = sal_False;
+ }
+- break;
+- case 13 :
++ }
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA:
++ {
++ if (sValue.getLength())
+ {
+- if (IsXMLToken(aLocalName, XML_BOOLEAN_VALUE))
+- {
+- if (sValue.getLength())
+- {
+- if ( IsXMLToken(sValue, XML_TRUE) )
+- fValue = 1.0;
+- else if ( IsXMLToken(sValue, XML_FALSE) )
+- fValue = 0.0;
+- else
+- rXMLImport.GetMM100UnitConverter().convertDouble(fValue, sValue);
+- bIsEmpty = sal_False;
+- }
+- }
++ DBG_ASSERT(!pOUFormula, "here should be only one formula");
++ DELETEZ( pOUFormula);
++ rtl::OUString sFormula;
++ sal_uInt16 nFormulaPrefix = GetImport().GetNamespaceMap().
++ _GetKeyByAttrName( sValue, &sFormula, sal_False );
++
++ if (ScXMLImport::IsAcceptedFormulaNamespace(
++ nFormulaPrefix, sValue, eGrammar,
++ eStorageGrammar))
++ {
++ // Namespaces we accept.
++ pOUFormula = new rtl::OUString( sFormula);
++ }
++ else
++ {
++ // No namespace => entire string.
++ // Also unknown namespace included in formula,
++ // so hopefully will result in string or
++ // compile error.
++ pOUFormula = new rtl::OUString( sValue);
++ }
+ }
+- break;
+ }
+- }
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY:
++ pCurrencySymbol = new rtl::OUString(sValue);
++ break;
++ default:
++ ;
++ }
+ }
+ if (pOUFormula)
+ {
+@@ -335,32 +281,6 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
+ rXMLImport.GetStylesImportHelper()->SetAttributes(pStyleName, pCurrencySymbol, nCellType);
+ }
+
+-sal_Int16 ScXMLTableRowCellContext::GetCellType(const rtl::OUString& sOUValue) const
+-{
+- if (IsXMLToken(sOUValue, XML_FLOAT))
+- return util::NumberFormat::NUMBER;
+- else
+- if (IsXMLToken(sOUValue, XML_STRING))
+- return util::NumberFormat::TEXT;
+- else
+- if (IsXMLToken(sOUValue, XML_TIME))
+- return util::NumberFormat::TIME;
+- else
+- if (IsXMLToken(sOUValue, XML_DATE))
+- return util::NumberFormat::DATETIME;
+- else
+- if (IsXMLToken(sOUValue, XML_PERCENTAGE))
+- return util::NumberFormat::PERCENT;
+- else
+- if (IsXMLToken(sOUValue, XML_CURRENCY))
+- return util::NumberFormat::CURRENCY;
+- else
+- if (IsXMLToken(sOUValue, XML_BOOLEAN))
+- return util::NumberFormat::LOGICAL;
+- else
+- return util::NumberFormat::UNDEFINED;
+-}
+-
+ ScXMLTableRowCellContext::~ScXMLTableRowCellContext()
+ {
+ if (pOUTextValue)
+diff --git sc/source/filter/xml/xmlcelli.hxx sc/source/filter/xml/xmlcelli.hxx
+index b1de3ee..589077d 100644
+--- sc/source/filter/xml/xmlcelli.hxx
++++ sc/source/filter/xml/xmlcelli.hxx
+@@ -95,8 +95,6 @@ class ScXMLTableRowCellContext : public SvXMLImportContext
+ const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); }
+ ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); }
+
+- sal_Int16 GetCellType(const rtl::OUString& sOUValue) const;
+-
+ sal_Bool IsMerged (const com::sun::star::uno::Reference <com::sun::star::table::XCellRange>& xCellRange,
+ const sal_Int32 nCol, const sal_Int32 nRow,
+ com::sun::star::table::CellRangeAddress& aCellAddress) const;
+diff --git sc/source/filter/xml/xmldpimp.cxx sc/source/filter/xml/xmldpimp.cxx
+index e29223a..604e04e 100644
+--- sc/source/filter/xml/xmldpimp.cxx
++++ sc/source/filter/xml/xmldpimp.cxx
+@@ -65,6 +65,7 @@
+
+ using namespace com::sun::star;
+ using namespace xmloff::token;
++using ::rtl::OUString;
+
+ //------------------------------------------------------------------
+
+diff --git sc/source/filter/xml/xmlexprt.cxx sc/source/filter/xml/xmlexprt.cxx
+index 52f5145..38a37d6 100644
+--- sc/source/filter/xml/xmlexprt.cxx
++++ sc/source/filter/xml/xmlexprt.cxx
+@@ -68,6 +68,7 @@
+ #include "convuno.hxx"
+ #include "postit.hxx"
+ #include "tabprotection.hxx"
+#include "externalrefmgr.hxx"
- #include "sharedocdlg.hxx"
+ #include <xmloff/xmltoken.hxx>
+ #include <xmloff/xmlnmspe.hxx>
+@@ -129,6 +130,8 @@
-@@ -540,6 +541,7 @@ void ScDocShell::Execute( SfxRequest& rReq )
- if (nDlgRet == RET_YES || nSet==LM_ALWAYS)
- {
- ReloadTabLinks();
-+ aDocument.UpdateExternalRefLinks();
- aDocument.UpdateDdeLinks();
- aDocument.UpdateAreaLinks();
+ #include <sfx2/objsh.hxx>
-diff --git sc/source/ui/docshell/externalrefmgr.cxx sc/source/ui/docshell/externalrefmgr.cxx
-new file mode 100644
-index 0000000..8b5858d
---- /dev/null
-+++ sc/source/ui/docshell/externalrefmgr.cxx
-@@ -0,0 +1,1161 @@
-+/*************************************************************************
-+ *
-+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-+ *
-+ * Copyright 2008 by Sun Microsystems, Inc.
-+ *
-+ * OpenOffice.org - a multi-platform office productivity suite
-+ *
-+ * $RCSfile: document.hxx,v $
-+ * $Revision: 1.112 $
-+ *
-+ * This file is part of OpenOffice.org.
-+ *
-+ * OpenOffice.org is free software: you can redistribute it and/or modify
-+ * it under the terms of the GNU Lesser General Public License version 3
-+ * only, as published by the Free Software Foundation.
-+ *
-+ * OpenOffice.org is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU Lesser General Public License version 3 for more details
-+ * (a copy is included in the LICENSE file that accompanied this code).
-+ *
-+ * You should have received a copy of the GNU Lesser General Public License
-+ * version 3 along with OpenOffice.org. If not, see
-+ * <http://www.openoffice.org/license.html>
-+ * for a copy of the LGPLv3 License.
-+ *
-+ ************************************************************************/
++#include <vector>
+
-+// MARKER(update_precomp.py): autogen include statement, do not remove
-+#include "precompiled_sc.hxx"
+ //! not found in unonames.hxx
+ #define SC_STANDARDFORMAT "StandardFormat"
+ #define SC_LAYERID "LayerID"
+@@ -152,6 +155,7 @@
+ using namespace rtl;
+ using namespace com::sun::star;
+ using namespace xmloff::token;
++using ::std::vector;
+
+ //----------------------------------------------------------------------------
+
+@@ -479,6 +483,12 @@ ScXMLExport::ScXMLExport(
+
+ if( (getExportFlags() & (EXPORT_STYLES|EXPORT_AUTOSTYLES|EXPORT_MASTERSTYLES|EXPORT_CONTENT) ) != 0 )
+ {
++ // This name is reserved for the external ref cache tables. This
++ // should not conflict with user-defined styles since this name is
++ // used for a table style which is not available in the UI.
++ sExternalRefTabStyleName = rtl::OUString::createFromAscii("ta_extref");
++ GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_TABLE, sExternalRefTabStyleName);
++
+ sAttrName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_NAME));
+ sAttrStyleName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_STYLE_NAME));
+ sAttrColumnsRepeated = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_NUMBER_COLUMNS_REPEATED));
+@@ -1422,180 +1432,181 @@ void ScXMLExport::_ExportContent()
+ DBG_ERROR("no shared data setted");
+ }
+ ScXMLExportDatabaseRanges aExportDatabaseRanges(*this);
+- if (!GetModel().is())
++ if (!GetModel().is())
+ return;
+
+- uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
++ uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
+ if ( !xSpreadDoc.is() )
+ return;
+
+- uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
+- if ( xIndex.is() )
+- {
+- //_GetNamespaceMap().ClearQNamesCache();
+- pChangeTrackingExportHelper->CollectAndWriteChanges();
+- WriteCalculationSettings(xSpreadDoc);
+- sal_Int32 nTableCount(xIndex->getCount());
+- ScMyAreaLinksContainer aAreaLinks;
+- GetAreaLinks( xSpreadDoc, aAreaLinks );
+- ScMyEmptyDatabaseRangesContainer aEmptyRanges(aExportDatabaseRanges.GetEmptyDatabaseRanges());
+- ScMyDetectiveOpContainer aDetectiveOpContainer;
+- GetDetectiveOpList( aDetectiveOpContainer );
+-
+- pCellStyles->Sort();
+- pMergedRangesContainer->Sort();
+- pSharedData->GetDetectiveObjContainer()->Sort();
+-
+- pCellsItr->Clear();
+- pCellsItr->SetShapes( pSharedData->GetShapesContainer() );
+- pCellsItr->SetNoteShapes( pSharedData->GetNoteShapes() );
+- pCellsItr->SetMergedRanges( pMergedRangesContainer );
+- pCellsItr->SetAreaLinks( &aAreaLinks );
+- pCellsItr->SetEmptyDatabaseRanges( &aEmptyRanges );
+- pCellsItr->SetDetectiveObj( pSharedData->GetDetectiveObjContainer() );
+- pCellsItr->SetDetectiveOp( &aDetectiveOpContainer );
+-
+- if (nTableCount > 0)
+- pValidationsContainer->WriteValidations(*this);
+- WriteTheLabelRanges( xSpreadDoc );
+- for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable)
+- {
+- uno::Reference<sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
+- if (xTable.is())
+- {
+- xCurrentTable.set(xTable);
+- xCurrentTableCellRange.set(xTable, uno::UNO_QUERY);
+- uno::Reference<container::XNamed> xName (xTable, uno::UNO_QUERY );
+- if ( xName.is() )
+- {
+- nCurrentTable = sal::static_int_cast<sal_uInt16>( nTable );
+- rtl::OUString sOUTableName(xName->getName());
+- AddAttribute(sAttrName, sOUTableName);
+- AddAttribute(sAttrStyleName, aTableStyles[nTable]);
+- uno::Reference<util::XProtectable> xProtectable (xTable, uno::UNO_QUERY);
+- if (xProtectable.is() && xProtectable->isProtected())
+- {
+- AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE);
+- rtl::OUStringBuffer aBuffer;
+- if (pDoc)
++ uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
++ if ( xIndex.is() )
++ {
++ //_GetNamespaceMap().ClearQNamesCache();
++ pChangeTrackingExportHelper->CollectAndWriteChanges();
++ WriteCalculationSettings(xSpreadDoc);
++ sal_Int32 nTableCount(xIndex->getCount());
++ ScMyAreaLinksContainer aAreaLinks;
++ GetAreaLinks( xSpreadDoc, aAreaLinks );
++ ScMyEmptyDatabaseRangesContainer aEmptyRanges(aExportDatabaseRanges.GetEmptyDatabaseRanges());
++ ScMyDetectiveOpContainer aDetectiveOpContainer;
++ GetDetectiveOpList( aDetectiveOpContainer );
++
++ pCellStyles->Sort();
++ pMergedRangesContainer->Sort();
++ pSharedData->GetDetectiveObjContainer()->Sort();
++
++ pCellsItr->Clear();
++ pCellsItr->SetShapes( pSharedData->GetShapesContainer() );
++ pCellsItr->SetNoteShapes( pSharedData->GetNoteShapes() );
++ pCellsItr->SetMergedRanges( pMergedRangesContainer );
++ pCellsItr->SetAreaLinks( &aAreaLinks );
++ pCellsItr->SetEmptyDatabaseRanges( &aEmptyRanges );
++ pCellsItr->SetDetectiveObj( pSharedData->GetDetectiveObjContainer() );
++ pCellsItr->SetDetectiveOp( &aDetectiveOpContainer );
++
++ if (nTableCount > 0)
++ pValidationsContainer->WriteValidations(*this);
++ WriteTheLabelRanges( xSpreadDoc );
++ for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable)
++ {
++ uno::Reference<sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
++ if (xTable.is())
++ {
++ xCurrentTable.set(xTable);
++ xCurrentTableCellRange.set(xTable, uno::UNO_QUERY);
++ uno::Reference<container::XNamed> xName (xTable, uno::UNO_QUERY );
++ if ( xName.is() )
++ {
++ nCurrentTable = sal::static_int_cast<sal_uInt16>( nTable );
++ rtl::OUString sOUTableName(xName->getName());
++ AddAttribute(sAttrName, sOUTableName);
++ AddAttribute(sAttrStyleName, aTableStyles[nTable]);
++ uno::Reference<util::XProtectable> xProtectable (xTable, uno::UNO_QUERY);
++ if (xProtectable.is() && xProtectable->isProtected())
++ {
++ AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE);
++ rtl::OUStringBuffer aBuffer;
++ if (pDoc)
++ {
++ ScTableProtection* pProtect = pDoc->GetTabProtection(static_cast<SCTAB>(nTable));
++ if (pProtect)
++ SvXMLUnitConverter::encodeBase64(aBuffer, pProtect->getPasswordHash(PASSHASH_OOO));
++ }
++ if (aBuffer.getLength())
++ AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
++ }
++ rtl::OUString sPrintRanges;
++ table::CellRangeAddress aColumnHeaderRange;
++ sal_Bool bHasColumnHeader;
++ GetColumnRowHeader(bHasColumnHeader, aColumnHeaderRange, bHasRowHeader, aRowHeaderRange, sPrintRanges);
++ if( sPrintRanges.getLength() )
++ AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT_RANGES, sPrintRanges );
++ else if (!pDoc->IsPrintEntireSheet(static_cast<SCTAB>(nTable)))
++ AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT, XML_FALSE);
++ SvXMLElementExport aElemT(*this, sElemTab, sal_True, sal_True);
++ CheckAttrList();
++ WriteTableSource();
++ WriteScenario();
++ uno::Reference<drawing::XDrawPage> xDrawPage;
++ if (pSharedData->HasForm(nTable, xDrawPage) && xDrawPage.is())
++ {
++ ::xmloff::OOfficeFormsExport aForms(*this);
++ GetFormExport()->exportForms( xDrawPage );
++ sal_Bool bRet(GetFormExport()->seekPage( xDrawPage ));
++ DBG_ASSERT( bRet, "OFormLayerXMLExport::seekPage failed!" );
++ (void)bRet; // avoid warning in product version
++ }
++ if (pSharedData->HasDrawPage())
++ {
++ GetShapeExport()->seekShapes(uno::Reference<drawing::XShapes>(pSharedData->GetDrawPage(nTable), uno::UNO_QUERY));
++ WriteTableShapes();
++ }
++ table::CellRangeAddress aRange(GetEndAddress(xTable, nTable));
++ pSharedData->SetLastColumn(nTable, aRange.EndColumn);
++ pSharedData->SetLastRow(nTable, aRange.EndRow);
++ pCellsItr->SetCurrentTable(static_cast<SCTAB>(nTable), xCurrentTable);
++ pGroupColumns->NewTable();
++ pGroupRows->NewTable();
++ FillColumnRowGroups();
++ if (bHasColumnHeader)
++ pSharedData->SetLastColumn(nTable, aColumnHeaderRange.EndColumn);
++ bRowHeaderOpen = sal_False;
++ if (bHasRowHeader)
++ pSharedData->SetLastRow(nTable, aRowHeaderRange.EndRow);
++ pDefaults->FillDefaultStyles(nTable, pSharedData->GetLastRow(nTable),
++ pSharedData->GetLastColumn(nTable), pCellStyles, pDoc);
++ pRowFormatRanges->SetRowDefaults(pDefaults->GetRowDefaults());
++ pRowFormatRanges->SetColDefaults(pDefaults->GetColDefaults());
++ pCellStyles->SetRowDefaults(pDefaults->GetRowDefaults());
++ pCellStyles->SetColDefaults(pDefaults->GetColDefaults());
++ ExportColumns(nTable, aColumnHeaderRange, bHasColumnHeader);
++ sal_Bool bIsFirst(sal_True);
++ sal_Int32 nEqualCells(0);
++ ScMyCell aCell;
++ ScMyCell aPrevCell;
++ while(pCellsItr->GetNext(aCell, pCellStyles))
++ {
++ if (bIsFirst)
++ {
++ ExportFormatRanges(0, 0, aCell.aCellAddress.Column - 1, aCell.aCellAddress.Row, nTable);
++ aPrevCell = aCell;
++ bIsFirst = sal_False;
++ }
++ else
++ {
++ if ((aPrevCell.aCellAddress.Row == aCell.aCellAddress.Row) &&
++ (aPrevCell.aCellAddress.Column + nEqualCells + 1 == aCell.aCellAddress.Column))
++ {
++ if(IsCellEqual(aPrevCell, aCell))
++ ++nEqualCells;
++ else
+ {
+- ScTableProtection* pProtect = pDoc->GetTabProtection(static_cast<SCTAB>(nTable));
+- if (pProtect)
+- SvXMLUnitConverter::encodeBase64(aBuffer, pProtect->getPasswordHash(PASSHASH_OOO));
++ SetRepeatAttribute(nEqualCells);
++ WriteCell(aPrevCell);
++ nEqualCells = 0;
++ aPrevCell = aCell;
+ }
+- if (aBuffer.getLength())
+- AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
+- }
+- rtl::OUString sPrintRanges;
+- table::CellRangeAddress aColumnHeaderRange;
+- sal_Bool bHasColumnHeader;
+- GetColumnRowHeader(bHasColumnHeader, aColumnHeaderRange, bHasRowHeader, aRowHeaderRange, sPrintRanges);
+- if( sPrintRanges.getLength() )
+- AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT_RANGES, sPrintRanges );
+- else if (!pDoc->IsPrintEntireSheet(static_cast<SCTAB>(nTable)))
+- AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT, XML_FALSE);
+- SvXMLElementExport aElemT(*this, sElemTab, sal_True, sal_True);
+- CheckAttrList();
+- WriteTableSource();
+- WriteScenario();
+- uno::Reference<drawing::XDrawPage> xDrawPage;
+- if (pSharedData->HasForm(nTable, xDrawPage) && xDrawPage.is())
+- {
+- ::xmloff::OOfficeFormsExport aForms(*this);
+- GetFormExport()->exportForms( xDrawPage );
+- sal_Bool bRet(GetFormExport()->seekPage( xDrawPage ));
+- DBG_ASSERT( bRet, "OFormLayerXMLExport::seekPage failed!" );
+- (void)bRet; // avoid warning in product version
+- }
+- if (pSharedData->HasDrawPage())
+- {
+- GetShapeExport()->seekShapes(uno::Reference<drawing::XShapes>(pSharedData->GetDrawPage(nTable), uno::UNO_QUERY));
+- WriteTableShapes();
+- }
+- table::CellRangeAddress aRange(GetEndAddress(xTable, nTable));
+- pSharedData->SetLastColumn(nTable, aRange.EndColumn);
+- pSharedData->SetLastRow(nTable, aRange.EndRow);
+- pCellsItr->SetCurrentTable(static_cast<SCTAB>(nTable), xCurrentTable);
+- pGroupColumns->NewTable();
+- pGroupRows->NewTable();
+- FillColumnRowGroups();
+- if (bHasColumnHeader)
+- pSharedData->SetLastColumn(nTable, aColumnHeaderRange.EndColumn);
+- bRowHeaderOpen = sal_False;
+- if (bHasRowHeader)
+- pSharedData->SetLastRow(nTable, aRowHeaderRange.EndRow);
+- pDefaults->FillDefaultStyles(nTable, pSharedData->GetLastRow(nTable),
+- pSharedData->GetLastColumn(nTable), pCellStyles, pDoc);
+- pRowFormatRanges->SetRowDefaults(pDefaults->GetRowDefaults());
+- pRowFormatRanges->SetColDefaults(pDefaults->GetColDefaults());
+- pCellStyles->SetRowDefaults(pDefaults->GetRowDefaults());
+- pCellStyles->SetColDefaults(pDefaults->GetColDefaults());
+- ExportColumns(nTable, aColumnHeaderRange, bHasColumnHeader);
+- sal_Bool bIsFirst(sal_True);
+- sal_Int32 nEqualCells(0);
+- ScMyCell aCell;
+- ScMyCell aPrevCell;
+- while(pCellsItr->GetNext(aCell, pCellStyles))
+- {
+- if (bIsFirst)
+- {
+- ExportFormatRanges(0, 0, aCell.aCellAddress.Column - 1, aCell.aCellAddress.Row, nTable);
+- aPrevCell = aCell;
+- bIsFirst = sal_False;
+- }
+- else
+- {
+- if ((aPrevCell.aCellAddress.Row == aCell.aCellAddress.Row) &&
+- (aPrevCell.aCellAddress.Column + nEqualCells + 1 == aCell.aCellAddress.Column))
+- {
+- if(IsCellEqual(aPrevCell, aCell))
+- ++nEqualCells;
+- else
+- {
+- SetRepeatAttribute(nEqualCells);
+- WriteCell(aPrevCell);
+- nEqualCells = 0;
+- aPrevCell = aCell;
+- }
+- }
+- else
+- {
+- SetRepeatAttribute(nEqualCells);
+- WriteCell(aPrevCell);
+- ExportFormatRanges(aPrevCell.aCellAddress.Column + nEqualCells + 1, aPrevCell.aCellAddress.Row,
+- aCell.aCellAddress.Column - 1, aCell.aCellAddress.Row, nTable);
+- nEqualCells = 0;
+- aPrevCell = aCell;
+- }
+- }
+- }
+- if (!bIsFirst)
+- {
+- SetRepeatAttribute(nEqualCells);
+- WriteCell(aPrevCell);
+- ExportFormatRanges(aPrevCell.aCellAddress.Column + nEqualCells + 1, aPrevCell.aCellAddress.Row,
+- pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
+- }
+- else
+- ExportFormatRanges(0, 0, pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
+- CloseRow(pSharedData->GetLastRow(nTable));
+- nEqualCells = 0;
+- }
+- }
+- RemoveTempAnnotaionShape(nTable);
++ }
++ else
++ {
++ SetRepeatAttribute(nEqualCells);
++ WriteCell(aPrevCell);
++ ExportFormatRanges(aPrevCell.aCellAddress.Column + nEqualCells + 1, aPrevCell.aCellAddress.Row,
++ aCell.aCellAddress.Column - 1, aCell.aCellAddress.Row, nTable);
++ nEqualCells = 0;
++ aPrevCell = aCell;
++ }
++ }
++ }
++ if (!bIsFirst)
++ {
++ SetRepeatAttribute(nEqualCells);
++ WriteCell(aPrevCell);
++ ExportFormatRanges(aPrevCell.aCellAddress.Column + nEqualCells + 1, aPrevCell.aCellAddress.Row,
++ pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
++ }
++ else
++ ExportFormatRanges(0, 0, pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
++ CloseRow(pSharedData->GetLastRow(nTable));
++ nEqualCells = 0;
++ }
++ }
++ RemoveTempAnnotaionShape(nTable);
+
+- IncrementProgressBar(sal_False);
+- }
+- }
+- WriteNamedExpressions(xSpreadDoc);
+- aExportDatabaseRanges.WriteDatabaseRanges(xSpreadDoc);
+- ScXMLExportDataPilot aExportDataPilot(*this);
+- aExportDataPilot.WriteDataPilots(xSpreadDoc);
+- WriteConsolidation();
+- ScXMLExportDDELinks aExportDDELinks(*this);
+- aExportDDELinks.WriteDDELinks(xSpreadDoc);
+- IncrementProgressBar(sal_True, 0);
+- GetProgressBarHelper()->SetValue(GetProgressBarHelper()->GetReference());
++ IncrementProgressBar(sal_False);
++ }
++ }
++ WriteExternalRefCaches();
++ WriteNamedExpressions(xSpreadDoc);
++ aExportDatabaseRanges.WriteDatabaseRanges(xSpreadDoc);
++ ScXMLExportDataPilot aExportDataPilot(*this);
++ aExportDataPilot.WriteDataPilots(xSpreadDoc);
++ WriteConsolidation();
++ ScXMLExportDDELinks aExportDDELinks(*this);
++ aExportDDELinks.WriteDDELinks(xSpreadDoc);
++ IncrementProgressBar(sal_True, 0);
++ GetProgressBarHelper()->SetValue(GetProgressBarHelper()->GetReference());
+ }
+
+ void ScXMLExport::_ExportStyles( sal_Bool bUsed )
+@@ -2000,6 +2011,15 @@ void ScXMLExport::_ExportAutoStyles()
+
+ GetShapeExport()->exportAutoStyles();
+ GetFormExport()->exportAutoStyles( );
+
++ {
++ // Special table style for the external ref cache tables.
++ AddAttribute(XML_NAMESPACE_STYLE, XML_NAME, sExternalRefTabStyleName);
++ AddAttribute(XML_NAMESPACE_STYLE, XML_FAMILY, XML_TABLE);
++ SvXMLElementExport aElemStyle(*this, XML_NAMESPACE_STYLE, XML_STYLE, sal_True, sal_True);
++ AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY, XML_FALSE);
++ SvXMLElementExport aElemStyleTabProps(*this, XML_NAMESPACE_STYLE, XML_TABLE_PROPERTIES, sal_True, sal_True);
++ }
+ }
+ if (getExportFlags() & EXPORT_MASTERSTYLES)
+ {
+@@ -3316,6 +3336,182 @@ void ScXMLExport::WriteNamedExpressions(const com::sun::star::uno::Reference <co
+ }
+ }
+
++void ScXMLExport::WriteExternalRefCaches()
++{
++ if (!pDoc)
++ return;
+
++ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
++ sal_uInt16 nCount = pRefMgr->getCachedFileCount();
++ for (sal_uInt16 nFileId = 0; nFileId < nCount; ++nFileId)
++ {
++ const String* pUrl = pRefMgr->getExternalFileName(nFileId);
++ if (!pUrl)
++ continue;
+
-+// INCLUDE ---------------------------------------------------------------
++ const vector<String>* pTabNames = pRefMgr->getAllCachedTableNames(nFileId);
++ if (!pTabNames)
++ continue;
++
++ for (vector<String>::const_iterator itr = pTabNames->begin(), itrEnd = pTabNames->end();
++ itr != itrEnd; ++itr)
++ {
++ ScExternalRefCache::Table* pTable = pRefMgr->getCacheTable(nFileId, *itr);
++ if (!pTable)
++ continue;
++
++ OUStringBuffer aBuf;
++ aBuf.append(sal_Unicode('\''));
++ aBuf.append(*pUrl);
++ aBuf.append(sal_Unicode('\''));
++ aBuf.append(sal_Unicode('#'));
++ aBuf.append(*itr);
++ AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, aBuf.makeStringAndClear());
++ AddAttribute(XML_NAMESPACE_TABLE, XML_PRINT, GetXMLToken(XML_FALSE));
++ AddAttribute(XML_NAMESPACE_TABLE, XML_STYLE_NAME, sExternalRefTabStyleName);
++ SvXMLElementExport aElemTable(*this, XML_NAMESPACE_TABLE, XML_TABLE, sal_True, sal_True);
++ {
++ const ScExternalRefManager::SrcFileData* pExtFileData = pRefMgr->getExternalFileData(nFileId);
++ if (pExtFileData)
++ {
++ String aRelUrl;
++ if (pExtFileData->maRelativeName.Len())
++ aRelUrl = pExtFileData->maRelativeName;
++ else
++ aRelUrl = GetRelativeReference(pExtFileData->maRelativeName);
++ AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, aRelUrl);
++ AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, *itr);
++ if (pExtFileData->maFilterName.Len())
++ AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_NAME, pExtFileData->maFilterName);
++ if (pExtFileData->maFilterOptions.Len())
++ AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_OPTIONS, pExtFileData->maFilterOptions);
++ AddAttribute(XML_NAMESPACE_TABLE, XML_MODE, XML_COPY_RESULTS_ONLY);
++ }
++ SvXMLElementExport aElemTableSource(*this, XML_NAMESPACE_TABLE, XML_TABLE_SOURCE, sal_True, sal_True);
++ }
++
++ // Write cache content for this table.
++ vector<SCROW> aRows;
++ pTable->getAllRows(aRows);
++ SCROW nLastRow = 0;
++ bool bFirstRow = true;
++ for (vector<SCROW>::const_iterator itrRow = aRows.begin(), itrRowEnd = aRows.end();
++ itrRow != itrRowEnd; ++itrRow)
++ {
++ SCROW nRow = *itrRow;
++ if (bFirstRow)
++ {
++ if (nRow > 0)
++ {
++ if (nRow > 1)
++ {
++ OUStringBuffer aVal;
++ aVal.append(nRow);
++ AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, aVal.makeStringAndClear());
++ }
++ SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True);
++ OUStringBuffer aVal;
++ aVal.append(static_cast<sal_Int32>(MAXCOLCOUNT));
++ AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
++ SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
++ }
++ }
++ else
++ {
++ SCROW nRowGap = nRow - nLastRow;
++ if (nRowGap > 1)
++ {
++ if (nRowGap > 2)
++ {
++ OUStringBuffer aVal;
++ aVal.append(static_cast<sal_Int32>(nRowGap-1));
++ AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, aVal.makeStringAndClear());
++ }
++ SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True);
++ OUStringBuffer aVal;
++ aVal.append(static_cast<sal_Int32>(MAXCOLCOUNT));
++ AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
++ SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
++ }
++ }
++ SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True);
++
++ vector<SCCOL> aCols;
++ pTable->getAllCols(nRow, aCols);
++ SCCOL nLastCol = 0;
++ bool bFirstCol = true;
++ for (vector<SCCOL>::const_iterator itrCol = aCols.begin(), itrColEnd = aCols.end();
++ itrCol != itrColEnd; ++itrCol)
++ {
++ SCCOL nCol = *itrCol;
++ if (bFirstCol)
++ {
++ if (nCol > 0)
++ {
++ if (nCol > 1)
++ {
++ OUStringBuffer aVal;
++ aVal.append(static_cast<sal_Int32>(nCol));
++ AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
++ }
++ SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
++ }
++ }
++ else
++ {
++ SCCOL nColGap = nCol - nLastCol;
++ if (nColGap > 1)
++ {
++ if (nColGap > 2)
++ {
++ OUStringBuffer aVal;
++ aVal.append(static_cast<sal_Int32>(nColGap-1));
++ AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
++ }
++ SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
++ }
++ }
++
++ // Write out this cell.
++ ScToken* pToken = pTable->getCell(nRow, nCol).get();
++ OUString aStrVal;
++ if (pToken)
++ {
++ switch(pToken->GetType())
++ {
++ case svDouble:
++ {
++ AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT);
++ OUStringBuffer aVal;
++ aVal.append(pToken->GetDouble());
++ aStrVal = aVal.makeStringAndClear();
++ AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE, aStrVal);
++ }
++ break;
++ case svString:
++ {
++ AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING);
++ aStrVal = pToken->GetString();
++ }
++ break;
++ default:
++ ;
++ }
++ }
++ SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
++ SvXMLElementExport aElemText(*this, XML_NAMESPACE_TEXT, XML_P, sal_True, sal_True);
++ Characters(aStrVal);
++
++ nLastCol = nCol;
++ bFirstCol = false;
++ }
++ nLastRow = nRow;
++ bFirstRow = false;
++ }
++ }
++ }
++}
++
+ // core implementation
+ void ScXMLExport::WriteConsolidation()
+ {
+diff --git sc/source/filter/xml/xmlexprt.hxx sc/source/filter/xml/xmlexprt.hxx
+index 779f94e..6a366f5 100644
+--- sc/source/filter/xml/xmlexprt.hxx
++++ sc/source/filter/xml/xmlexprt.hxx
+@@ -98,6 +98,7 @@ class ScXMLExport : public SvXMLExport
+ ScChangeTrackingExportHelper* pChangeTrackingExportHelper;
+ const rtl::OUString sLayerID;
+ const rtl::OUString sCaptionShape;
++ rtl::OUString sExternalRefTabStyleName;
+ rtl::OUString sAttrName;
+ rtl::OUString sAttrStyleName;
+ rtl::OUString sAttrColumnsRepeated;
+@@ -194,6 +195,7 @@ class ScXMLExport : public SvXMLExport
+ void WriteTheLabelRanges(const com::sun::star::uno::Reference< com::sun::star::sheet::XSpreadsheetDocument >& xSpreadDoc);
+ void WriteLabelRanges( const com::sun::star::uno::Reference< com::sun::star::container::XIndexAccess >& xRangesIAccess, sal_Bool bColumn );
+ void WriteNamedExpressions(const com::sun::star::uno::Reference <com::sun::star::sheet::XSpreadsheetDocument>& xSpreadDoc);
++ void WriteExternalRefCaches();
+ void WriteConsolidation(); // core implementation
+
+ void CollectUserDefinedNamespaces(const SfxItemPool* pPool, sal_uInt16 nAttrib);
+diff --git sc/source/filter/xml/xmlexternaltabi.cxx sc/source/filter/xml/xmlexternaltabi.cxx
+new file mode 100644
+index 0000000..e1d0ebd
+--- /dev/null
++++ sc/source/filter/xml/xmlexternaltabi.cxx
+@@ -0,0 +1,343 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: xmlcoli.hxx,v $
++ * $Revision: 1.9 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org. If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++// MARKER(update_precomp.py): autogen include statement, do not remove
++#include "precompiled_sc.hxx"
++
++
++
++// INCLUDE ---------------------------------------------------------------
++
++#include "xmlexternaltabi.hxx"
++#include "xmlimprt.hxx"
++#include "xmltabi.hxx"
++
++#include "token.hxx"
++#include "document.hxx"
++
++#include <xmloff/nmspmap.hxx>
++#include <xmloff/xmlnmspe.hxx>
++#include <xmloff/xmltoken.hxx>
++#include <xmloff/xmluconv.hxx>
++#include <com/sun/star/util/NumberFormat.hpp>
++
++using namespace ::com::sun::star;
++
++using ::rtl::OUString;
++using ::com::sun::star::uno::Reference;
++using ::com::sun::star::xml::sax::XAttributeList;
++
++// ============================================================================
++
++ScXMLExternalRefTabSourceContext::ScXMLExternalRefTabSourceContext(
++ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
++ const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
++ SvXMLImportContext( rImport, nPrefix, rLName ),
++ mrScImport(rImport),
++ mrExternalRefInfo(rRefInfo)
++{
++ using namespace ::xmloff::token;
++
++ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
++ for (sal_Int16 i = 0; i < nAttrCount; ++i)
++ {
++ const rtl::OUString& sAttrName = xAttrList->getNameByIndex(i);
++ rtl::OUString aLocalName;
++ sal_uInt16 nAttrPrefix = mrScImport.GetNamespaceMap().GetKeyByAttrName(sAttrName, &aLocalName);
++ const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
++ if (nAttrPrefix == XML_NAMESPACE_XLINK)
++ {
++ if (IsXMLToken(aLocalName, XML_HREF))
++ maRelativeUrl = sValue;
++ }
++ else if (nAttrPrefix == XML_NAMESPACE_TABLE)
++ {
++ if (IsXMLToken(aLocalName, XML_TABLE_NAME))
++ maTableName = sValue;
++ else if (IsXMLToken(aLocalName, XML_FILTER_NAME))
++ maFilterName = sValue;
++ else if (IsXMLToken(aLocalName, XML_FILTER_OPTIONS))
++ maFilterOptions = sValue;
++ }
++ }
++}
++
++ScXMLExternalRefTabSourceContext::~ScXMLExternalRefTabSourceContext()
++{
++}
++
++SvXMLImportContext* ScXMLExternalRefTabSourceContext::CreateChildContext(
++ USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& /*xAttrList*/ )
++{
++ return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
++}
++
++void ScXMLExternalRefTabSourceContext::EndElement()
++{
++ ScDocument* pDoc = mrScImport.GetDocument();
++ if (!pDoc)
++ return;
++
++ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
++ if (!maRelativeUrl.equals(mrExternalRefInfo.maFileUrl))
++ pRefMgr->setRelativeFileName(mrExternalRefInfo.mnFileId, maRelativeUrl);
++ pRefMgr->setFilterData(mrExternalRefInfo.mnFileId, maFilterName, maFilterOptions);
++}
++
++// ============================================================================
++
++ScXMLExternalRefRowContext::ScXMLExternalRefRowContext(
++ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
++ const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
++ SvXMLImportContext( rImport, nPrefix, rLName ),
++ mrScImport(rImport),
++ mrExternalRefInfo(rRefInfo),
++ mnRepeatRowCount(1)
++{
++ mrExternalRefInfo.mnCol = 0;
++
++ sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
++ const SvXMLTokenMap& rAttrTokenMap = mrScImport.GetTableRowAttrTokenMap();
++ for( sal_Int16 i=0; i < nAttrCount; ++i )
++ {
++ const rtl::OUString& sAttrName = xAttrList->getNameByIndex(i);
++ rtl::OUString aLocalName;
++ sal_uInt16 nAttrPrefix = mrScImport.GetNamespaceMap().GetKeyByAttrName(sAttrName, &aLocalName);
++ const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
++
++ switch (rAttrTokenMap.Get(nAttrPrefix, aLocalName))
++ {
++ case XML_TOK_TABLE_ROW_ATTR_REPEATED:
++ {
++ mnRepeatRowCount = std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
++ }
++ break;
++ }
++ }
++}
++
++ScXMLExternalRefRowContext::~ScXMLExternalRefRowContext()
++{
++}
++
++SvXMLImportContext* ScXMLExternalRefRowContext::CreateChildContext(
++ USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
++{
++ const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowElemTokenMap();
++ sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
++ if (nToken == XML_TOK_TABLE_ROW_CELL)
++ return new ScXMLExternalRefCellContext(mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
++
++ return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
++}
++
++void ScXMLExternalRefRowContext::EndElement()
++{
++ ScExternalRefCache::Table* pTab = mrExternalRefInfo.mpCacheTable;
++
++ for (sal_Int32 i = 1; i < mnRepeatRowCount; ++i)
++ {
++ for (sal_Int32 j = 0; j < mrExternalRefInfo.mnCol; ++j)
++ {
++ ScExternalRefCache::TokenRef pToken = pTab->getCell(
++ static_cast<SCROW>(mrExternalRefInfo.mnRow), static_cast<SCCOL>(j));
++
++ if (pToken.get())
++ {
++ pTab->setCell(static_cast<SCROW>(
++ mrExternalRefInfo.mnRow+i), static_cast<SCCOL>(j), pToken);
++ }
++ }
++ }
++ mrExternalRefInfo.mnRow += mnRepeatRowCount;
++}
++
++// ============================================================================
++
++ScXMLExternalRefCellContext::ScXMLExternalRefCellContext(
++ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
++ const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
++ SvXMLImportContext( rImport, nPrefix, rLName ),
++ mrScImport(rImport),
++ mrExternalRefInfo(rRefInfo),
++ mfCellValue(0.0),
++ mnRepeatCount(1),
++ mnCellType(::com::sun::star::util::NumberFormat::UNDEFINED),
++ mbIsNumeric(false),
++ mbIsEmpty(true)
++{
++ using namespace ::xmloff::token;
++
++ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
++ const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
++ for (sal_Int16 i = 0; i < nAttrCount; ++i)
++ {
++ OUString aLocalName;
++ sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
++ xAttrList->getNameByIndex(i), &aLocalName);
++
++ const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
++ sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
++
++ switch (nToken)
++ {
++ case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
++ {
++ mnRepeatCount = ::std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
++ }
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
++ {
++ mnCellType = mrScImport.GetCellType(sValue);
++ }
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
++ {
++ if (sValue.getLength())
++ {
++ mrScImport.GetMM100UnitConverter().convertDouble(mfCellValue, sValue);
++ mbIsNumeric = true;
++ mbIsEmpty = false;
++ }
++ }
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
++ {
++ if (sValue.getLength() && mrScImport.SetNullDateOnUnitConverter())
++ {
++ mrScImport.GetMM100UnitConverter().convertDateTime(mfCellValue, sValue);
++ mbIsNumeric = true;
++ mbIsEmpty = false;
++ }
++ }
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
++ {
++ if (sValue.getLength())
++ {
++ mrScImport.GetMM100UnitConverter().convertTime(mfCellValue, sValue);
++ mbIsNumeric = true;
++ mbIsEmpty = false;
++ }
++ }
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
++ {
++ if (sValue.getLength())
++ {
++ maCellString = sValue;
++ mbIsNumeric = false;
++ mbIsEmpty = false;
++ }
++ }
++ break;
++ case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
++ {
++ if (sValue.getLength())
++ {
++ mfCellValue = IsXMLToken(sValue, XML_TRUE) ? 1.0 : 0.0;
++ mbIsNumeric = true;
++ mbIsEmpty = false;
++ }
++ }
++ break;
++ default:
++ ;
++ }
++ }
++}
++
++ScXMLExternalRefCellContext::~ScXMLExternalRefCellContext()
++{
++}
++
++SvXMLImportContext* ScXMLExternalRefCellContext::CreateChildContext(
++ USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
++{
++ const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowCellElemTokenMap();
++ sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
++ if (nToken == XML_TOK_TABLE_ROW_CELL_P)
++ return new ScXMLExternalRefCellTextContext(mrScImport, nPrefix, rLocalName, xAttrList, maCellString);
++
++ return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
++}
++
++void ScXMLExternalRefCellContext::EndElement()
++{
++ if (maCellString.getLength())
++ mbIsEmpty = false;
++
++ for (sal_Int32 i = 0; i < mnRepeatCount; ++i, ++mrExternalRefInfo.mnCol)
++ {
++ if (mbIsEmpty)
++ continue;
++
++ ScExternalRefCache::TokenRef aToken;
++ if (mbIsNumeric)
++ aToken.reset(new ScDoubleToken(mfCellValue));
++ else
++ aToken.reset(new ScStringToken(maCellString));
++
++ mrExternalRefInfo.mpCacheTable->setCell(
++ static_cast<SCROW>(mrExternalRefInfo.mnRow),
++ static_cast<SCCOL>(mrExternalRefInfo.mnCol),
++ aToken);
++ }
++}
++
++// ============================================================================
++
++ScXMLExternalRefCellTextContext::ScXMLExternalRefCellTextContext(
++ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
++ const Reference<XAttributeList>& /*xAttrList*/, OUString& rCellString ) :
++ SvXMLImportContext( rImport, nPrefix, rLName ),
++ mrScImport(rImport),
++ mrCellString(rCellString)
++{
++}
++
++ScXMLExternalRefCellTextContext::~ScXMLExternalRefCellTextContext()
++{
++}
++
++SvXMLImportContext* ScXMLExternalRefCellTextContext::CreateChildContext(
++ USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& /*xAttrList*/ )
++{
++ return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
++}
++
++void ScXMLExternalRefCellTextContext::Characters(const OUString& rChar)
++{
++ mrCellString = rChar;
++}
++
++void ScXMLExternalRefCellTextContext::EndElement()
++{
++}
+diff --git sc/source/filter/xml/xmlexternaltabi.hxx sc/source/filter/xml/xmlexternaltabi.hxx
+new file mode 100644
+index 0000000..6f26789
+--- /dev/null
++++ sc/source/filter/xml/xmlexternaltabi.hxx
+@@ -0,0 +1,149 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: xmlcoli.hxx,v $
++ * $Revision: 1.9 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org. If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#ifndef SC_XMLEXTERNALTABI_HXX
++#define SC_XMLEXTERNALTABI_HXX
++
++#include <xmloff/xmlictxt.hxx>
++
++class ScXMLImport;
++struct ScXMLExternalTabData;
++
++class ScXMLExternalRefTabSourceContext : public SvXMLImportContext
++{
++public:
++ ScXMLExternalRefTabSourceContext( ScXMLImport& rImport, USHORT nPrefix,
++ const ::rtl::OUString& rLName,
++ const ::com::sun::star::uno::Reference<
++ ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
++ ScXMLExternalTabData& rRefInfo );
++
++ virtual ~ScXMLExternalRefTabSourceContext();
++
++ virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
++ const ::rtl::OUString& rLocalName,
++ const ::com::sun::star::uno::Reference<
++ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
++
++ virtual void EndElement();
++private:
++ ScXMLImport& mrScImport;
++ ScXMLExternalTabData& mrExternalRefInfo;
++
++ ::rtl::OUString maRelativeUrl;
++ ::rtl::OUString maTableName;
++ ::rtl::OUString maFilterName;
++ ::rtl::OUString maFilterOptions;
++};
++
++// ============================================================================
++
++class ScXMLExternalRefRowContext : public SvXMLImportContext
++{
++public:
++ ScXMLExternalRefRowContext( ScXMLImport& rImport, USHORT nPrefix,
++ const ::rtl::OUString& rLName,
++ const ::com::sun::star::uno::Reference<
++ ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
++ ScXMLExternalTabData& rRefInfo );
++
++ virtual ~ScXMLExternalRefRowContext();
++
++ virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
++ const ::rtl::OUString& rLocalName,
++ const ::com::sun::star::uno::Reference<
++ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
++
++ virtual void EndElement();
++private:
++ ScXMLImport& mrScImport;
++ ScXMLExternalTabData& mrExternalRefInfo;
++ sal_Int32 mnRepeatRowCount;
++};
++
++// ============================================================================
++
++class ScXMLExternalRefCellContext : public SvXMLImportContext
++{
++public:
++ ScXMLExternalRefCellContext( ScXMLImport& rImport, USHORT nPrefix,
++ const ::rtl::OUString& rLName,
++ const ::com::sun::star::uno::Reference<
++ ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
++ ScXMLExternalTabData& rRefInfo );
++
++ virtual ~ScXMLExternalRefCellContext();
++
++ virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
++ const ::rtl::OUString& rLocalName,
++ const ::com::sun::star::uno::Reference<
++ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
++
++ virtual void EndElement();
++
++private:
++ ScXMLImport& mrScImport;
++ ScXMLExternalTabData& mrExternalRefInfo;
++ ::rtl::OUString maCellString;
++ double mfCellValue;
++ sal_Int32 mnRepeatCount;
++ sal_Int16 mnCellType;
++ bool mbIsNumeric;
++ bool mbIsEmpty;
++};
++
++// ============================================================================
++
++class ScXMLExternalRefCellTextContext : public SvXMLImportContext
++{
++public:
++ ScXMLExternalRefCellTextContext( ScXMLImport& rImport, USHORT nPrefix,
++ const ::rtl::OUString& rLName,
++ const ::com::sun::star::uno::Reference<
++ ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
++ ::rtl::OUString& rCellString );
++
++ virtual ~ScXMLExternalRefCellTextContext();
++
++ virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
++ const ::rtl::OUString& rLocalName,
++ const ::com::sun::star::uno::Reference<
++ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
++
++ virtual void Characters(const ::rtl::OUString& rChar);
++
++ virtual void EndElement();
++
++private:
++ ScXMLImport& mrScImport;
++ ::rtl::OUString& mrCellString;
++};
++
++#endif
+diff --git sc/source/filter/xml/xmlimprt.cxx sc/source/filter/xml/xmlimprt.cxx
+index 47b26b9..3541e45 100644
+--- sc/source/filter/xml/xmlimprt.cxx
++++ sc/source/filter/xml/xmlimprt.cxx
+@@ -104,6 +104,7 @@
+
+ using namespace com::sun::star;
+ using namespace ::xmloff::token;
++using ::rtl::OUString;
+
+ OUString SAL_CALL ScXMLImport_getImplementationName() throw()
+ {
+@@ -417,22 +418,22 @@ static __FAR_DATA SvXMLTokenMapEntry aTableRowCellTokenMap[] =
+
+ static __FAR_DATA SvXMLTokenMapEntry aTableRowCellAttrTokenMap[] =
+ {
+- { XML_NAMESPACE_TABLE, XML_STYLE_NAME, XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME },
+- { XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME },
+- { XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS },
+- { XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS },
+- { XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_COLUMNS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS },
+- { XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_ROWS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS },
+- { XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED },
+- { XML_NAMESPACE_TABLE, XML_VALUE_TYPE, XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE },
+- { XML_NAMESPACE_TABLE, XML_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_VALUE },
+- { XML_NAMESPACE_TABLE, XML_DATE_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE },
+- { XML_NAMESPACE_TABLE, XML_TIME_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE },
+- { XML_NAMESPACE_TABLE, XML_STRING_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE },
+- { XML_NAMESPACE_TABLE, XML_BOOLEAN_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE },
+- { XML_NAMESPACE_TABLE, XML_FORMULA, XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA },
+- { XML_NAMESPACE_TABLE, XML_CURRENCY, XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY },
+- XML_TOKEN_MAP_END
++ { XML_NAMESPACE_TABLE, XML_STYLE_NAME, XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME },
++ { XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME },
++ { XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS },
++ { XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS },
++ { XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_COLUMNS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS },
++ { XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_ROWS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS },
++ { XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED },
++ { XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE },
++ { XML_NAMESPACE_OFFICE, XML_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_VALUE },
++ { XML_NAMESPACE_OFFICE, XML_DATE_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE },
++ { XML_NAMESPACE_OFFICE, XML_TIME_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE },
++ { XML_NAMESPACE_OFFICE, XML_STRING_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE },
++ { XML_NAMESPACE_OFFICE, XML_BOOLEAN_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE },
++ { XML_NAMESPACE_OFFICE, XML_FORMULA, XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA },
++ { XML_NAMESPACE_OFFICE, XML_CURRENCY, XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY },
++ XML_TOKEN_MAP_END
+ };
+
+ static __FAR_DATA SvXMLTokenMapEntry aTableAnnotationAttrTokenMap[] =
+@@ -1561,6 +1562,25 @@ ScXMLImport::ScXMLImport(
+ GetXMLToken( XML_NP_PRESENTATION ),
+ GetXMLToken( XML_N_PRESENTATION ),
+ XML_NAMESPACE_PRESENTATION );
++
++ // initialize cell type map.
++ const struct { XMLTokenEnum _token; sal_Int16 _type; } aCellTypePairs[] =
++ {
++ { XML_FLOAT, util::NumberFormat::NUMBER },
++ { XML_STRING, util::NumberFormat::TEXT },
++ { XML_TIME, util::NumberFormat::TIME },
++ { XML_DATE, util::NumberFormat::DATETIME },
++ { XML_PERCENTAGE, util::NumberFormat::PERCENT },
++ { XML_CURRENCY, util::NumberFormat::CURRENCY },
++ { XML_BOOLEAN, util::NumberFormat::LOGICAL }
++ };
++ size_t n = sizeof(aCellTypePairs)/sizeof(aCellTypePairs[0]);
++ for (size_t i = 0; i < n; ++i)
++ {
++ aCellTypeMap.insert(
++ CellTypeMap::value_type(
++ GetXMLToken(aCellTypePairs[i]._token), aCellTypePairs[i]._type));
++ }
+ }
+
+ ScXMLImport::~ScXMLImport() throw()
+@@ -1777,6 +1797,15 @@ void ScXMLImport::SetStatistics(
+ }
+ }
+
++sal_Int16 ScXMLImport::GetCellType(const OUString& rStrValue) const
++{
++ CellTypeMap::const_iterator itr = aCellTypeMap.find(rStrValue);
++ if (itr != aCellTypeMap.end())
++ return itr->second;
++
++ return util::NumberFormat::UNDEFINED;
++}
++
+ XMLShapeImportHelper* ScXMLImport::CreateShapeImport()
+ {
+ /*UniReference < XMLPropertySetMapper > xShapeStylesPropertySetMapper = new XMLPropertySetMapper((XMLPropertyMapEntry*)aXMLScShapeStylesProperties, xScPropHdlFactory);
+diff --git sc/source/filter/xml/xmlimprt.hxx sc/source/filter/xml/xmlimprt.hxx
+index e4fd8a0..cace08e 100644
+--- sc/source/filter/xml/xmlimprt.hxx
++++ sc/source/filter/xml/xmlimprt.hxx
+@@ -40,7 +40,6 @@
+ #include <com/sun/star/frame/XModel.hpp>
+ #include <tools/time.hxx>
+ #include <com/sun/star/util/DateTime.hpp>
+-#include <vector>
+ #include "xmlsubti.hxx"
+ #include "global.hxx"
+ #include "grammar.hxx"
+@@ -55,12 +54,13 @@
+ #include <com/sun/star/util/XNumberFormatTypes.hpp>
+ #include <com/sun/star/sheet/XSheetCellRangeContainer.hpp>
+
++#include <vector>
++#include <hash_map>
++
+ class ScRangeList;
+ class ScMyStyleNumberFormats;
+ class XMLNumberFormatAttributesExportHelper;
+
+-using namespace rtl;
+-
+ enum ScXMLDocTokens
+ {
+ XML_TOK_DOC_FONTDECLS,
+@@ -643,6 +643,9 @@ class ScMyStylesImportHelper;
+
+ class ScXMLImport: public SvXMLImport
+ {
++ typedef ::std::hash_map< ::rtl::OUString, sal_Int16, ::rtl::OUStringHash > CellTypeMap;
++ CellTypeMap aCellTypeMap;
++
+ ScDocument* pDoc;
+ ScXMLChangeTrackingImportHelper* pChangeTrackingImportHelper;
+ ScMyViewContextList aViewContextList;
+@@ -810,6 +813,8 @@ public:
+
+ sal_Bool IsLatinDefaultStyle() const { return bLatinDefaultStyle; }
+
++ sal_Int16 GetCellType(const ::rtl::OUString& rStrValue) const;
++
+ // SvI18NMap& GetI18NMap() { return *pI18NMap; }
+
+ // inline const SvXMLImportItemMapper& GetParaItemMapper() const;
+diff --git sc/source/filter/xml/xmlsceni.cxx sc/source/filter/xml/xmlsceni.cxx
+index cfe859d..f4d6c89 100644
+--- sc/source/filter/xml/xmlsceni.cxx
++++ sc/source/filter/xml/xmlsceni.cxx
+@@ -50,6 +50,7 @@
+
+ using namespace com::sun::star;
+ using namespace xmloff::token;
++using ::rtl::OUString;
+
+ //------------------------------------------------------------------
+
+diff --git sc/source/filter/xml/xmlstyle.cxx sc/source/filter/xml/xmlstyle.cxx
+index 7aec632..863e82c 100644
+--- sc/source/filter/xml/xmlstyle.cxx
++++ sc/source/filter/xml/xmlstyle.cxx
+@@ -65,6 +65,7 @@
+
+ using namespace com::sun::star;
+ using namespace ::xmloff::token;
++using ::rtl::OUString;
+
+ #define MAP(name,prefix,token,type,context) { name, sizeof(name)-1, prefix, token, type, context, SvtSaveOptions::ODFVER_010 }
+ #define MAP_END() { NULL, 0, 0, XML_TOKEN_INVALID, 0, 0, SvtSaveOptions::ODFVER_010 }
+diff --git sc/source/filter/xml/xmlstyle.hxx sc/source/filter/xml/xmlstyle.hxx
+index 4d51084..ee9a2ea 100644
+--- sc/source/filter/xml/xmlstyle.hxx
++++ sc/source/filter/xml/xmlstyle.hxx
+@@ -40,8 +40,6 @@
+ #include <xmloff/xmlexppr.hxx>
+ #include <xmloff/contextid.hxx>
+
+-using namespace rtl;
+-
+ extern const XMLPropertyMapEntry aXMLScCellStylesProperties[];
+ extern const XMLPropertyMapEntry aXMLScColumnStylesProperties[];
+ extern const XMLPropertyMapEntry aXMLScRowStylesProperties[];
+diff --git sc/source/filter/xml/xmltabi.cxx sc/source/filter/xml/xmltabi.cxx
+index 4a0f83e..af80b31 100644
+--- sc/source/filter/xml/xmltabi.cxx
++++ sc/source/filter/xml/xmltabi.cxx
+@@ -40,6 +40,7 @@
+ #include "xmlrowi.hxx"
+ #include "xmlcoli.hxx"
+ #include "xmlsceni.hxx"
++#include "xmlexternaltabi.hxx"
+ #include "document.hxx"
+ #include "docuno.hxx"
+ #include "olinetab.hxx"
+@@ -48,6 +49,7 @@
+ #include "XMLTableSourceContext.hxx"
+ #include "XMLStylesImportHelper.hxx"
+ #include "rangeutl.hxx"
++#include "externalrefmgr.hxx"
+
+ #include <xmloff/xmltkmap.hxx>
+ #include <xmloff/nmspmap.hxx>
+@@ -63,6 +65,78 @@
+ using namespace com::sun::star;
+ using namespace xmloff::token;
+
++/**
++ * Determine whether this table is an external reference cache from its
++ * name. There is currently no way of determining whether a table is a
++ * regular table or an external reference cache other than examining the
++ * name itself. We should probably introduce a new boolean value for
++ * table:table element and use it instead of doing this, to make it more
++ * reliable and future-proof.
++ *
++ * @param rName
++ *
++ * @return
++ */
++static bool lcl_isExternalRefCache(const rtl::OUString& rName, rtl::OUString& rUrl, rtl::OUString& rExtTabName)
++{
++ // 'file:///path/to/file.ods'#MySheet
++ // 'file:///path/to/file.ods'#MySheet with space
++
++ static const sal_Unicode aPrefix[] = {
++ '\'', 'f', 'i', 'l', 'e', ':', '/', '/'
++ };
++
++ rtl::OUStringBuffer aUrlBuf, aTabNameBuf;
++ aUrlBuf.appendAscii("file://");
++ sal_Int32 n = rName.getLength();
++ const sal_Unicode* p = rName.getStr();
++
++ bool bInUrl = true;
++ sal_Unicode cPrev = 0;
++ for (sal_Int32 i = 0; i < n; ++i)
++ {
++ const sal_Unicode c = p[i];
++ if (i <= 7)
++ {
++ if (c != aPrefix[i])
++ return false;
++ }
++ else if (c == '\'')
++ {
++ if (!bInUrl)
++ return false;
++ bInUrl = false;
++ rUrl = aUrlBuf.makeStringAndClear();
++ }
++ else if (c == '#')
++ {
++ if (cPrev != '\'')
++ return false;
++ }
++ else if (bInUrl)
++ aUrlBuf.append(c);
++ else
++ aTabNameBuf.append(c);
++
++ cPrev = c;
++ }
++
++ if (bInUrl)
++ return false;
++
++ if (aTabNameBuf.getLength() == 0)
++ return false;
++
++ rExtTabName = aTabNameBuf.makeStringAndClear();
++
++ return true;
++}
++
++ScXMLExternalTabData::ScXMLExternalTabData() :
++ mpCacheTable(NULL), mnRow(0), mnCol(0), mnFileId(0)
++{
++}
++
+ //------------------------------------------------------------------
+
+ ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
+@@ -73,6 +147,7 @@ ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
+ const sal_Bool bTempIsSubTable,
+ const sal_Int32 nSpannedCols) :
+ SvXMLImportContext( rImport, nPrfx, rLName ),
++ pExternalRefInfo(NULL),
+ bStartFormPage(sal_False),
+ bPrintEntireSheet(sal_True)
+ {
+@@ -117,7 +192,26 @@ ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
+ break;
+ }
+ }
+- GetScImport().GetTables().NewSheet(sName, sStyleName, bProtection, sPassword);
++
++ rtl::OUString aExtUrl, aExtTabName;
++ if (lcl_isExternalRefCache(sName, aExtUrl, aExtTabName))
++ {
++ // This is an external ref cache table.
++ pExternalRefInfo.reset(new ScXMLExternalTabData);
++ pExternalRefInfo->maFileUrl = aExtUrl;
++ ScDocument* pDoc = GetScImport().GetDocument();
++ if (pDoc)
++ {
++ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
++ pExternalRefInfo->mnFileId = pRefMgr->getExternalFileId(aExtUrl);
++ pExternalRefInfo->mpCacheTable = pRefMgr->getCacheTable(pExternalRefInfo->mnFileId, aExtTabName);
++ }
++ }
++ else
++ {
++ // This is a regular table.
++ GetScImport().GetTables().NewSheet(sName, sStyleName, bProtection, sPassword);
++ }
+ }
+ else
+ {
+@@ -134,10 +228,30 @@ SvXMLImportContext *ScXMLTableContext::CreateChildContext( USHORT nPrefix,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
+ {
++ const SvXMLTokenMap& rTokenMap(GetScImport().GetTableElemTokenMap());
++ sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLName);
++ if (pExternalRefInfo.get())
++ {
++ // We only care about the table-row and table-source elements for
++ // external cache data.
++ switch (nToken)
++ {
++ case XML_TOK_TABLE_ROW:
++ return new ScXMLExternalRefRowContext(
++ GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
++ case XML_TOK_TABLE_SOURCE:
++ return new ScXMLExternalRefTabSourceContext(
++ GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
++ default:
++ ;
++ }
++
++ return new SvXMLImportContext(GetImport(), nPrefix, rLName);
++ }
++
+ SvXMLImportContext *pContext(0);
+
+- const SvXMLTokenMap& rTokenMap(GetScImport().GetTableElemTokenMap());
+- switch( rTokenMap.Get( nPrefix, rLName ) )
++ switch (nToken)
+ {
+ case XML_TOK_TABLE_COL_GROUP:
+ pContext = new ScXMLTableColsContext( GetScImport(), nPrefix,
+@@ -195,6 +309,8 @@ SvXMLImportContext *ScXMLTableContext::CreateChildContext( USHORT nPrefix,
+ pContext = GetScImport().GetFormImport()->createOfficeFormsContext( GetScImport(), nPrefix, rLName );
+ }
+ break;
++ default:
++ ;
+ }
+
+ if( !pContext )
+diff --git sc/source/filter/xml/xmltabi.hxx sc/source/filter/xml/xmltabi.hxx
+index 687cff8..e2960c2 100644
+--- sc/source/filter/xml/xmltabi.hxx
++++ sc/source/filter/xml/xmltabi.hxx
+@@ -30,13 +30,28 @@
+ #ifndef SC_XMLTABI_HXX
+ #define SC_XMLTABI_HXX
+
++#include "externalrefmgr.hxx"
++
+ #include <xmloff/xmlictxt.hxx>
++#include <memory>
+
+ class ScXMLImport;
+
++struct ScXMLExternalTabData
++{
++ String maFileUrl;
++ ScExternalRefCache::Table* mpCacheTable;
++ sal_Int32 mnRow;
++ sal_Int32 mnCol;
++ sal_uInt16 mnFileId;
++
++ ScXMLExternalTabData();
++};
++
+ class ScXMLTableContext : public SvXMLImportContext
+ {
+ rtl::OUString sPrintRanges;
++ ::std::auto_ptr<ScXMLExternalTabData> pExternalRefInfo;
+ sal_Bool bStartFormPage;
+ sal_Bool bPrintEntireSheet;
+
+diff --git sc/source/filter/xml/xmlwrap.cxx sc/source/filter/xml/xmlwrap.cxx
+index 851d338..035793b 100644
+--- sc/source/filter/xml/xmlwrap.cxx
++++ sc/source/filter/xml/xmlwrap.cxx
+@@ -85,6 +85,7 @@
+ #define MAP_LEN(x) x, sizeof(x) - 1
+
+ using namespace com::sun::star;
++using ::rtl::OUString;
+
+ // -----------------------------------------------------------------------
+
+diff --git sc/source/ui/docshell/docsh4.cxx sc/source/ui/docshell/docsh4.cxx
+index bc5975d..6701d1c 100644
+--- sc/source/ui/docshell/docsh4.cxx
++++ sc/source/ui/docshell/docsh4.cxx
+@@ -123,6 +123,7 @@ using namespace ::com::sun::star;
+ #include <com/sun/star/document/UpdateDocMode.hpp>
+ #include "scresid.hxx" //add by CHINA001
+ #include "scabstdlg.hxx" //CHINA001
++#include "externalrefmgr.hxx"
+
+ #include "sharedocdlg.hxx"
+
+@@ -540,6 +541,7 @@ void ScDocShell::Execute( SfxRequest& rReq )
+ if (nDlgRet == RET_YES || nSet==LM_ALWAYS)
+ {
+ ReloadTabLinks();
++ aDocument.UpdateExternalRefLinks();
+ aDocument.UpdateDdeLinks();
+ aDocument.UpdateAreaLinks();
+
+diff --git sc/source/ui/docshell/externalrefmgr.cxx sc/source/ui/docshell/externalrefmgr.cxx
+new file mode 100644
+index 0000000..8f34a8f
+--- /dev/null
++++ sc/source/ui/docshell/externalrefmgr.cxx
+@@ -0,0 +1,1267 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: document.hxx,v $
++ * $Revision: 1.112 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org. If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++// MARKER(update_precomp.py): autogen include statement, do not remove
++#include "precompiled_sc.hxx"
++
++
++
++// INCLUDE ---------------------------------------------------------------
+
+#include "externalrefmgr.hxx"
+#include "document.hxx"
@@ -5549,6 +7540,7 @@
+#include "unotools/ucbhelper.hxx"
+
+#include <memory>
++#include <algorithm>
+
+using ::std::auto_ptr;
+using ::com::sun::star::uno::Any;
@@ -5591,13 +7583,13 @@
+ rRow.insert(RowDataType::value_type(nCol, pToken));
+}
+
-+ScToken* ScExternalRefCache::Table::getCell(SCROW nRow, SCCOL nCol) const
++ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCROW nRow, SCCOL nCol) const
+{
+ RowsDataType::const_iterator itrTable = maRows.find(nRow);
+ if (itrTable == maRows.end())
+ {
+ // this table doesn't have the specified row.
-+ return NULL;
++ return TokenRef();
+ }
+
+ const RowDataType& rRowData = itrTable->second;
@@ -5605,10 +7597,42 @@
+ if (itrRow == rRowData.end())
+ {
+ // this row doesn't have the specified column.
-+ return NULL;
++ return TokenRef();
+ }
+
-+ return itrRow->second.get();
++ return itrRow->second;
++}
++
++void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows) const
++{
++ vector<SCROW> aRows;
++ aRows.reserve(maRows.size());
++ RowsDataType::const_iterator itr = maRows.begin(), itrEnd = maRows.end();
++ for (; itr != itrEnd; ++itr)
++ aRows.push_back(itr->first);
++
++ // hash map is not ordered, so we need to explicitly sort it.
++ ::std::sort(aRows.begin(), aRows.end());
++ rRows.swap(aRows);
++}
++
++void ScExternalRefCache::Table::getAllCols(SCROW nRow, vector<SCCOL>& rCols) const
++{
++ RowsDataType::const_iterator itrRow = maRows.find(nRow);
++ if (itrRow == maRows.end())
++ // this table doesn't have the specified row.
++ return;
++
++ const RowDataType& rRowData = itrRow->second;
++ vector<SCCOL> aCols;
++ aCols.reserve(rRowData.size());
++ RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end();
++ for (; itrCol != itrColEnd; ++itrCol)
++ aCols.push_back(itrCol->first);
++
++ // hash map is not ordered, so we need to explicitly sort it.
++ ::std::sort(aCols.begin(), aCols.end());
++ rCols.swap(aCols);
+}
+
+// ----------------------------------------------------------------------------
@@ -5643,7 +7667,7 @@
+ // the table data is not instantiated yet.
+ return NULL;
+ }
-+ return pTableData->getCell(nRow, nCol);
++ return pTableData->getCell(nRow, nCol).get();
+}
+
+ScTokenArray* ScExternalRefCache::getCellRangeData(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange)
@@ -5694,7 +7718,7 @@
+ {
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ {
-+ ScToken* pToken = pTab->getCell(nRow, nCol);
++ ScToken* pToken = pTab->getCell(nRow, nCol).get();
+ if (!pToken)
+ return NULL;
+
@@ -5895,7 +7919,7 @@
+ return &pDoc->maTableNames;
+}
+
-+ScExternalRefCache::Table* ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, const String& rTabName)
++ScExternalRefCache::Table* ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew)
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
@@ -5905,9 +7929,11 @@
+
+ size_t nIndex;
+ if (lcl_getTableDataIndex(rDoc.maTableNameIndex, rTabName, nIndex))
-+ {
++ // specified table found.
+ return rDoc.maTables[nIndex].get();
-+ }
++
++ if (!bCreateNew)
++ return NULL;
+
+ // Specified table doesn't exist yet. Create one.
+ TableTypeRef pTab(new Table);
@@ -6321,6 +8347,8 @@
+ bTokenAdded = true;
+ }
+ break;
++ default:
++ ; // nothing to do
+ }
+
+ if (!bTokenAdded)
@@ -6335,10 +8363,7 @@
+{
+ RefCellMap::iterator itr = maRefCells.find(nFileId);
+ if (itr == maRefCells.end())
-+ {
-+ const String* pFile = getExternalFileName(nFileId);
+ return;
-+ }
+
+ RefCellSet aNewSet;
+ RefCellSet& rSet = itr->second;
@@ -6397,8 +8422,8 @@
+ return NULL;
+
+ String aFilter;
-+ SrcDoc aSrcDoc;
-+ aSrcDoc.maShell = loadSrcDocument(*pFile, aFilter);
++ SrcShell aSrcDoc;
++ aSrcDoc.maShell = loadSrcDocument(nFileId, *pFile, aFilter);
+ if (!aSrcDoc.maShell.Is())
+ {
+ // source document could not be loaded.
@@ -6432,17 +8457,24 @@
+ return pSrcDoc;
+}
+
-+SfxObjectShellRef ScExternalRefManager::loadSrcDocument(const String& rFile, String& rFilter)
++SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, const String& rFile, String& rFilter)
+{
+ // First, make sure the file actually exists at the specified URL.
+ if (!utl::UCBContentHelper::Exists(rFile) || utl::UCBContentHelper::IsFolder(rFile))
+ // Either the specified file doesn't exist, or it's a folder.
+ return NULL;
+
++ if (isOwnDocument(rFile))
++ // Don't load itself. That would be asking for trouble.
++ return NULL;
++
+ String aOptions;
+ ScDocumentLoader::GetFilterName(rFile, rFilter, aOptions, true, false);
+ const SfxFilter* pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName(rFilter);
+
++ // Update the filter data now that we are loading it again.
++ setFilterData(nFileId, rFilter, aOptions);
++
+ SfxItemSet* pSet = new SfxAllItemSet(SFX_APP()->GetPool());
+ if (aOptions.Len())
+ pSet->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions));
@@ -6536,34 +8568,78 @@
+ return true;
+}
+
++bool ScExternalRefManager::isOwnDocument(const String& rFile) const
++{
++ SfxObjectShell* pShell = mpDoc->GetDocumentShell();
++ if (!pShell)
++ // This should not happen!
++ return true;
++
++ SfxMedium* pMed = pShell->GetMedium();
++ if (!pMed)
++ return false;
++
++ return pMed->GetName().Equals(rFile);
++}
++
+void ScExternalRefManager::convertToAbsName(String& rFile) const
+{
+ SfxObjectShell* pDocShell = mpDoc->GetDocumentShell();
+ rFile = ScGlobal::GetAbsDocName(rFile, pDocShell);
+}
+
++namespace {
++
++class FindSrcFileByName : public ::std::unary_function<ScExternalRefManager::SrcFileData, bool>
++{
++public:
++ FindSrcFileByName(const String& rMatchName) :
++ mrMatchName(rMatchName)
++ {
++ }
++
++ bool operator()(const ScExternalRefManager::SrcFileData& rSrcData) const
++ {
++ return rSrcData.maFileName.Equals(mrMatchName);
++ }
++
++private:
++ const String& mrMatchName;
++};
++
++}
+sal_uInt16 ScExternalRefManager::getExternalFileId(const String& rFile)
+{
+ using namespace std;
+
-+ vector<String>::const_iterator itrBeg = maFileNames.begin(), itrEnd = maFileNames.end();
-+ vector<String>::const_iterator itr = find(itrBeg, itrEnd, rFile);
++ vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
++ vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
+ if (itr != itrEnd)
+ {
+ size_t nId = distance(itrBeg, itr);
+ return static_cast<sal_uInt16>(nId);
+ }
+
-+ maFileNames.push_back(rFile);
-+ return static_cast<sal_uInt16>(maFileNames.size() - 1);
++ SrcFileData aData;
++ aData.maFileName = rFile;
++ maSrcFiles.push_back(aData);
++ return static_cast<sal_uInt16>(maSrcFiles.size() - 1);
+}
+
+const String* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId) const
+{
-+ if (nFileId >= maFileNames.size())
++ if (nFileId >= maSrcFiles.size())
+ return NULL;
+
-+ return &maFileNames[nFileId];
++ return &maSrcFiles[nFileId].maFileName;
++}
++
++const ScExternalRefManager::SrcFileData* ScExternalRefManager::getExternalFileData(sal_uInt16 nFileId) const
++{
++ if (nFileId >= maSrcFiles.size())
++ return NULL;
++
++ return &maSrcFiles[nFileId];
+}
+
+const vector<String>* ScExternalRefManager::getAllCachedTableNames(sal_uInt16 nFileId) const
@@ -6571,6 +8647,11 @@
+ return maRefCache.getAllTableNames(nFileId);
+}
+
++sal_uInt16 ScExternalRefManager::getCachedFileCount() const
++{
++ return static_cast<sal_uInt16>(maSrcFiles.size());
++}
++
+template<typename MapContainer>
+static void lcl_removeByFileId(sal_uInt16 nFileId, MapContainer& rMap)
+{
@@ -6589,10 +8670,26 @@
+
+void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const String& rNewFile)
+{
-+ maFileNames[nFileId] = rNewFile;
++ maSrcFiles[nFileId].maFileName = rNewFile;
++ maSrcFiles[nFileId].maRelativeName.Erase();
+ refreshNames(nFileId);
+}
+
++void ScExternalRefManager::setRelativeFileName(sal_uInt16 nFileId, const String& rRelUrl)
++{
++ if (nFileId >= maSrcFiles.size())
++ return;
++ maSrcFiles[nFileId].maRelativeName = rRelUrl;
++}
++
++void ScExternalRefManager::setFilterData(sal_uInt16 nFileId, const String& rFilterName, const String& rOptions)
++{
++ if (nFileId >= maSrcFiles.size())
++ return;
++ maSrcFiles[nFileId].maFilterName = rFilterName;
++ maSrcFiles[nFileId].maFilterOptions = rOptions;
++}
++
+void ScExternalRefManager::removeSrcDocument(sal_uInt16 nFileId, bool bBreakLink)
+{
+ maRefCache.clearCache(nFileId);
@@ -6617,7 +8714,7 @@
+
+bool ScExternalRefManager::hasExternalData() const
+{
-+ return !maFileNames.empty();
++ return !maSrcFiles.empty();
+}
+
+void ScExternalRefManager::purgeStaleSrcDocument(sal_Int32 nTimeOut)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]