[ooo-build-commit] Branch 'ooo/OOO310' - 2 commits - sc/inc sc/source
Jan Holesovsky
kendy at kemper.freedesktop.org
Mon Jul 27 17:15:34 PDT 2009
sc/inc/address.hxx | 6
sc/inc/compiler.hxx | 2
sc/inc/externalrefmgr.hxx | 73 ++++-
sc/inc/refdata.hxx | 21 +
sc/inc/table.hxx | 35 ++
sc/source/core/data/documen4.cxx | 11
sc/source/core/data/document.cxx | 2
sc/source/core/data/table3.cxx | 5
sc/source/core/inc/interpre.hxx | 26 +
sc/source/core/tool/address.cxx | 53 ++-
sc/source/core/tool/compiler.cxx | 125 +++++---
sc/source/core/tool/interpr1.cxx | 449 +++++++++++++++++++++++++++----
sc/source/core/tool/interpr4.cxx | 9
sc/source/core/tool/reftokenhelper.cxx | 55 +++
sc/source/filter/excel/xichart.cxx | 77 ++---
sc/source/filter/excel/xistyle.cxx | 114 ++++++-
sc/source/filter/excel/xltools.cxx | 42 +-
sc/source/filter/inc/xichart.hxx | 5
sc/source/filter/inc/xistyle.hxx | 22 -
sc/source/filter/inc/xlstyle.hxx | 6
sc/source/filter/inc/xltools.hxx | 10
sc/source/filter/xml/xmlexprt.cxx | 2
sc/source/filter/xml/xmlexternaltabi.cxx | 28 +
sc/source/ui/docshell/externalrefmgr.cxx | 187 +++++++++---
sc/source/ui/view/makefile.mk | 4
25 files changed, 1080 insertions(+), 289 deletions(-)
New commits:
commit 568da4a76cdb388bf0816bf7fbff227e7a205dfc
Author: Kurt Zenker <kz at openoffice.org>
Date: Mon Jul 27 16:12:56 2009 +0000
CWS-TOOLING: integrate CWS hr64
2009-07-21 13:24:57 +0200 hr r274189 : #i99576#: re-enable optimization for tabcont.cxx
2009-07-21 13:17:18 +0200 hr r274188 : #i99592: disable -xspace optimization for Solaris x86 and SunStudio 12, due to some mis-optimzation in sc and elsewhere. SunStudio 12 update 1 is OK, but needs a few unrelated changes which will be implemented in DEV300 code line
diff --git a/sc/source/ui/view/makefile.mk b/sc/source/ui/view/makefile.mk
index 9af8051..466ab5d 100644
--- a/sc/source/ui/view/makefile.mk
+++ b/sc/source/ui/view/makefile.mk
@@ -135,12 +135,10 @@ SLOFILES = \
$(SLO)$/viewfun4.obj \
$(SLO)$/viewfun2.obj
.ELIF "$(OS)$(COM)$(CPUNAME)"=="SOLARISC52INTEL"
-# tabcont can be removed if -xspace is no longer used (i99576, i99592)
NOOPTFILES=\
$(SLO)$/drawview.obj \
$(SLO)$/dbfunc2.obj \
- $(SLO)$/tabvwsh2.obj \
- $(SLO)$/tabcont.obj
+ $(SLO)$/tabvwsh2.obj
.ELSE
NOOPTFILES=\
commit a9e20342d5314fe9b0824bec0051232ad1fd55c8
Author: Kurt Zenker <kz at openoffice.org>
Date: Mon Jul 27 11:11:59 2009 +0000
CWS-TOOLING: integrate CWS dr68ooo311
2009-07-17 15:39:31 +0200 er r274096 : #i101544# more thorough reference checking in chart data ranges; also prevent some possible crash if invalid ranges were to be passed to document/cell access.
2009-07-16 13:51:42 +0200 er r274048 : #i101544# let ScRefTokenHelper::compileRangeRepresentation() fail on all possible non-reference occasions
2009-07-12 01:56:51 +0200 er r273910 : #i103317# adjust absolute external references if stored relative
2009-07-07 17:03:27 +0200 dr r273809 : #i103281# do not duplicate existing cell styles in BIFF import
2009-07-03 08:21:41 +0200 dr r273676 : #i10000# wntmsci12 warnings
2009-07-02 18:26:14 +0200 dr r273669 : #i10000# wntmsci12 warning ... again
2009-07-02 16:48:23 +0200 dr r273665 : #i10000# wntmsci12 warning
2009-07-02 15:13:36 +0200 dr r273655 : #i10000# missing d'tor
2009-06-29 13:44:32 +0200 er r273472 : for non-pro's sake
2009-06-29 11:30:20 +0200 dr r273458 : #i101662# port fix to ooo311
2009-06-26 18:32:46 +0200 er r273436 : #i101544# make range operator work again
2009-06-26 14:18:31 +0200 er r273412 : #i102388# make SUMIF and COUNTIF work on external references again (actually arrays)
2009-06-24 17:58:19 +0200 er r273358 : #i101645# INDIRECT marks external sheets as permanently referenced
2009-06-23 16:42:51 +0200 er r273296 : #i101645# create and resolve external reference on the fly if used in INDIRECT
diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx
index 2e81edd..e9f18f3 100644
--- a/sc/inc/address.hxx
+++ b/sc/inc/address.hxx
@@ -756,12 +756,14 @@ template< typename T > void PutInOrder( T& nStart, T& nEnd )
bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
SCTAB nDefTab, ScRefAddress& rRefAddress,
- const ScAddress::Details& rDetails = ScAddress::detailsOOOa1);
+ const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
+ ScAddress::ExternalInfo* pExtInfo = NULL );
bool ConvertDoubleRef(ScDocument* pDoc, const String& rRefString,
SCTAB nDefTab, ScRefAddress& rStartRefAddress,
ScRefAddress& rEndRefAddress,
- const ScAddress::Details& rDetails = ScAddress::detailsOOOa1);
+ const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
+ ScAddress::ExternalInfo* pExtInfo = NULL );
/// append alpha representation of column to buffer
SC_DLLPUBLIC void ScColToAlpha( rtl::OUStringBuffer& rBuffer, SCCOL nCol);
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index 2140998..7133450 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -311,9 +311,11 @@ private:
const CharClass* pCharClass; // which character classification is used for parseAnyToken
USHORT mnPredetectedReference; // reference when reading ODF, 0 (none), 1 (single) or 2 (double)
SCsTAB nMaxTab; // last sheet in document
+ sal_Int32 mnRangeOpPosInSymbol; // if and where a range operator is in symbol
const Convention *pConv;
bool mbCloseBrackets; // whether to close open brackets automatically, default TRUE
bool mbExtendedErrorDetection;
+ bool mbRewind; // whether symbol is to be rewound to some step during lexical analysis
BOOL NextNewToken(bool bInArray = false);
diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx
index 1ca3bac..f5b6e3f 100644
--- a/sc/inc/externalrefmgr.hxx
+++ b/sc/inc/externalrefmgr.hxx
@@ -132,15 +132,27 @@ public:
class Table
{
public:
+
+ enum ReferencedFlag
+ {
+ UNREFERENCED,
+ REFERENCED_MARKED, // marked as referenced during store to file
+ REFERENCED_PERMANENT // permanently marked, e.g. from within interpreter
+ };
+
Table();
~Table();
SC_DLLPUBLIC void setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex = 0);
TokenRef getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex = NULL) const;
bool hasRow( SCROW nRow ) const;
- /// A temporary state used only during store to file.
- bool isReferenced() const;
+ /** Set/clear referenced status flag only if current status is not
+ REFERENCED_PERMANENT. */
void setReferenced( bool bReferenced );
+ /// Unconditionally set the reference status flag.
+ void setReferencedFlag( ReferencedFlag eFlag );
+ ReferencedFlag getReferencedFlag() const;
+ bool isReferenced() const;
/// Obtain a sorted vector of rows.
void getAllRows(::std::vector<SCROW>& rRows) const;
/// Obtain a sorted vector of columns.
@@ -148,8 +160,8 @@ public:
void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const;
private:
- RowsDataType maRows;
- bool mbReferenced;
+ RowsDataType maRows;
+ ReferencedFlag meReferenced;
};
typedef ::boost::shared_ptr<Table> TableTypeRef;
@@ -219,9 +231,16 @@ public:
* Set a table as referenced, used only during store-to-file.
* @returns <TRUE/> if ALL tables of ALL documents are marked.
*/
- bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName );
+ bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets, bool bPermanent );
void setAllCacheTableReferencedStati( bool bReferenced );
bool areAllCacheTablesReferenced() const;
+
+ /**
+ * Set a table as permanently referenced, to be called if not in
+ * mark-during-store-to-file cycle.
+ */
+ void setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets );
+
private:
struct ReferencedStatus
{
@@ -403,10 +422,13 @@ public:
/** Source document meta-data container. */
struct SrcFileData
{
- String maFileName;
+ String maFileName; /// original file name as loaded from the file.
+ String maRealFileName; /// file name created from the relative name.
String maRelativeName;
String maFilterName;
String maFilterOptions;
+
+ void maybeCreateRealFileName(const String& rOwnDocName);
};
public:
@@ -497,10 +519,16 @@ public:
* Set a table as referenced, used only during store-to-file.
* @returns <TRUE/> if ALL tables of ALL external documents are marked.
*/
- bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName );
+ bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets );
void setAllCacheTableReferencedStati( bool bReferenced );
/**
+ * Set a table as permanently referenced, to be called if not in
+ * mark-during-store-to-file cycle.
+ */
+ void setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets );
+
+ /**
* @returns <TRUE/> if setAllCacheTableReferencedStati(false) was called,
* <FALSE/> if setAllCacheTableReferencedStati(true) was called.
*/
@@ -551,7 +579,7 @@ public:
*/
void convertToAbsName(String& rFile) const;
sal_uInt16 getExternalFileId(const String& rFile);
- const String* getExternalFileName(sal_uInt16 nFileId) const;
+ const String* getExternalFileName(sal_uInt16 nFileId);
bool hasExternalFile(sal_uInt16 nFileId) const;
bool hasExternalFile(const String& rFile) const;
const SrcFileData* getExternalFileData(sal_uInt16 nFileId) const;
@@ -560,8 +588,15 @@ public:
const String* getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const;
void refreshNames(sal_uInt16 nFileId);
void breakLink(sal_uInt16 nFileId);
- void switchSrcFile(sal_uInt16 nFileId, const String& rNewFile);
+ void switchSrcFile(sal_uInt16 nFileId, const String& rNewFile, const String& rNewFilter);
+ /**
+ * Set a relative file path for the specified file ID. Note that the
+ * caller must ensure that the passed URL is a valid relative URL.
+ *
+ * @param nFileId file ID for an external document
+ * @param rRelUrl relative URL
+ */
void setRelativeFileName(sal_uInt16 nFileId, const String& rRelUrl);
/**
@@ -581,9 +616,12 @@ public:
/**
* Re-generates relative names for all stored source files. This is
* necessary when exporting to an ods document, to ensure that all source
- * files have their respective relative names for xlink:href export.
+ * files have their respective relative names for xlink:href export.
+ *
+ * @param rBaseFileUrl Absolute URL of the content.xml fragment of the
+ * document being exported.
*/
- void resetSrcFileData();
+ void resetSrcFileData(const String& rBaseFileUrl);
/**
* Update a single referencing cell position.
@@ -650,6 +688,19 @@ private:
void maybeLinkExternalFile(sal_uInt16 nFileId);
+ /**
+ * Try to create a "real" file name from the relative path. The original
+ * file name may not point to the real document when the referencing and
+ * referenced documents have been moved.
+ *
+ * For the real file name to be created, the relative name should not be
+ * empty before calling this method, or the real file name will not be
+ * created.
+ *
+ * @param nFileId file ID for an external document
+ */
+ void maybeCreateRealFileName(sal_uInt16 nFileId);
+
bool compileTokensByCell(const ScAddress& rCell);
/**
diff --git a/sc/inc/refdata.hxx b/sc/inc/refdata.hxx
index 933999a..ac289a4 100644
--- a/sc/inc/refdata.hxx
+++ b/sc/inc/refdata.hxx
@@ -109,6 +109,8 @@ struct SC_DLLPUBLIC ScSingleRefData // Single reference (one address) int
inline BOOL IsRelName() const { return Flags.bRelName; }
inline BOOL Valid() const;
+ /// In external references nTab is -1
+ inline bool ValidExternal() const;
void SmartRelAbs( const ScAddress& rPos );
void CalcRelFromAbs( const ScAddress& rPos );
@@ -147,6 +149,13 @@ inline BOOL ScSingleRefData::Valid() const
nTab >= 0 && nTab <= MAXTAB;
}
+inline bool ScSingleRefData::ValidExternal() const
+{
+ return nCol >= 0 && nCol <= MAXCOL &&
+ nRow >= 0 && nRow <= MAXROW &&
+ nTab == -1;
+}
+
struct ScComplexRefData // Complex reference (a range) into the sheet
{
@@ -181,6 +190,10 @@ struct ScComplexRefData // Complex reference (a range) into the sheet
{ return Ref1.IsDeleted() || Ref2.IsDeleted(); }
inline BOOL Valid() const
{ return Ref1.Valid() && Ref2.Valid(); }
+ /** In external references nTab is -1 for the start tab and -1 for the end
+ tab if one sheet, or >=0 if more than one sheets. */
+ inline bool ValidExternal() const;
+
/// Absolute references have to be up-to-date when calling this!
void PutInOrder();
inline BOOL operator==( const ScComplexRefData& r ) const
@@ -192,4 +205,12 @@ struct ScComplexRefData // Complex reference (a range) into the sheet
ScComplexRefData& Extend( const ScComplexRefData & rRef, const ScAddress & rPos );
};
+inline bool ScComplexRefData::ValidExternal() const
+{
+ return Ref1.ValidExternal() &&
+ Ref2.nCol >= 0 && Ref2.nCol <= MAXCOL &&
+ Ref2.nRow >= 0 && Ref2.nRow <= MAXROW &&
+ Ref2.nTab >= Ref1.nTab;
+}
+
#endif
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index ba4b022..0ccdf90 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -254,16 +254,28 @@ public:
void GetString( SCCOL nCol, SCROW nRow, String& rString );
void GetInputString( SCCOL nCol, SCROW nRow, String& rString );
double GetValue( const ScAddress& rPos ) const
- { return aCol[rPos.Col()].GetValue( rPos.Row() ); }
+ {
+ return ValidColRow(rPos.Col(),rPos.Row()) ?
+ aCol[rPos.Col()].GetValue( rPos.Row() ) :
+ 0.0;
+ }
double GetValue( SCCOL nCol, SCROW nRow );
void GetFormula( SCCOL nCol, SCROW nRow, String& rFormula,
BOOL bAsciiExport = FALSE );
CellType GetCellType( const ScAddress& rPos ) const
- { return aCol[rPos.Col()].GetCellType( rPos.Row() ); }
+ {
+ return ValidColRow(rPos.Col(),rPos.Row()) ?
+ aCol[rPos.Col()].GetCellType( rPos.Row() ) :
+ CELLTYPE_NONE;
+ }
CellType GetCellType( SCCOL nCol, SCROW nRow ) const;
ScBaseCell* GetCell( const ScAddress& rPos ) const
- { return aCol[rPos.Col()].GetCell( rPos.Row() ); }
+ {
+ return ValidColRow(rPos.Col(),rPos.Row()) ?
+ aCol[rPos.Col()].GetCell( rPos.Row() ) :
+ NULL;
+ }
ScBaseCell* GetCell( SCCOL nCol, SCROW nRow ) const;
void GetLastDataPos(SCCOL& rCol, SCROW& rRow) const;
@@ -362,7 +374,11 @@ public:
SCCOL nEndCol, SCROW nEndRow ) const;
USHORT GetErrCode( const ScAddress& rPos ) const
- { return aCol[rPos.Col()].GetErrCode( rPos.Row() ); }
+ {
+ return ValidColRow(rPos.Col(),rPos.Row()) ?
+ aCol[rPos.Col()].GetErrCode( rPos.Row() ) :
+ 0;
+ }
//UNUSED2008-05 USHORT GetErrCode( SCCOL nCol, SCROW nRow ) const;
void ResetChanged( const ScRange& rRange );
@@ -438,7 +454,11 @@ public:
const ScPatternAttr* GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const;
ULONG GetNumberFormat( const ScAddress& rPos ) const
- { return aCol[rPos.Col()].GetNumberFormat( rPos.Row() ); }
+ {
+ return ValidColRow(rPos.Col(),rPos.Row()) ?
+ aCol[rPos.Col()].GetNumberFormat( rPos.Row() ) :
+ 0;
+ }
ULONG GetNumberFormat( SCCOL nCol, SCROW nRow ) const;
void MergeSelectionPattern( ScMergePatternState& rState,
const ScMarkData& rMark, BOOL bDeep ) const;
@@ -457,7 +477,10 @@ public:
void ApplyPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr );
void ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScPatternAttr& rAttr );
void SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr, BOOL bPutToPool = FALSE )
- { aCol[rPos.Col()].SetPattern( rPos.Row(), rAttr, bPutToPool ); }
+ {
+ if (ValidColRow(rPos.Col(),rPos.Row()))
+ aCol[rPos.Col()].SetPattern( rPos.Row(), rAttr, bPutToPool );
+ }
void SetPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr, BOOL bPutToPool = FALSE );
void ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
const ScPatternAttr& rPattern, short nNewType );
diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx
index 7b6b5be..29bec96 100644
--- a/sc/source/core/data/documen4.cxx
+++ b/sc/source/core/data/documen4.cxx
@@ -311,9 +311,16 @@ bool ScDocument::MarkUsedExternalReferences( ScTokenArray & rArr )
switch (t->GetType())
{
case svExternalSingleRef:
- case svExternalDoubleRef:
bAllMarked = pRefMgr->setCacheTableReferenced(
- t->GetIndex(), t->GetString());
+ t->GetIndex(), t->GetString(), 1);
+ break;
+ case svExternalDoubleRef:
+ {
+ const ScComplexRefData& rRef = t->GetDoubleRef();
+ size_t nSheets = rRef.Ref2.nTab - rRef.Ref1.nTab + 1;
+ bAllMarked = pRefMgr->setCacheTableReferenced(
+ t->GetIndex(), t->GetString(), nSheets);
+ }
break;
case svExternalName:
/* TODO: external names aren't supported yet, but would
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 783e3d4..a4c35ba 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2343,7 +2343,7 @@ void ScDocument::GetCell( SCCOL nCol, SCROW nRow, SCTAB nTab,
ScBaseCell* ScDocument::GetCell( const ScAddress& rPos ) const
{
SCTAB nTab = rPos.Tab();
- if ( pTab[nTab] )
+ if (ValidTab(nTab) && pTab[nTab])
return pTab[nTab]->GetCell( rPos );
DBG_ERROR("GetCell ohne Tabelle");
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index dfab329..51cd9a9 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1074,13 +1074,12 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
bOk = pTransliteration->isEqual( aCellStr, *rEntry.pStr );
else
{
- ::com::sun::star::uno::Sequence< sal_Int32 > xOff;
String aCell( pTransliteration->transliterate(
aCellStr, ScGlobal::eLnge, 0, aCellStr.Len(),
- &xOff ) );
+ NULL ) );
String aQuer( pTransliteration->transliterate(
*rEntry.pStr, ScGlobal::eLnge, 0, rEntry.pStr->Len(),
- &xOff ) );
+ NULL ) );
bOk = (aCell.Search( aQuer ) != STRING_NOTFOUND);
}
if ( rEntry.eOp == SC_NOT_EQUAL )
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index d55a18f..ca21e19 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -70,6 +70,21 @@ struct ScCompare
}
};
+struct ScCompareOptions
+{
+ ScQueryEntry aQueryEntry;
+ bool bRegEx;
+ bool bMatchWholeCell;
+ bool bIgnoreCase;
+
+ ScCompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg );
+private:
+ // Not implemented, prevent usage.
+ ScCompareOptions();
+ ScCompareOptions( const ScCompareOptions & );
+ ScCompareOptions& operator=( const ScCompareOptions & );
+};
+
class ScToken;
#define MAXSTACK (4096 / sizeof(formula::FormulaToken*))
@@ -356,9 +371,16 @@ void ScChoseJump();
// Returns true if last jump was executed and result matrix pushed.
bool JumpMatrix( short nStackLevel );
-double CompareFunc( const ScCompare& rComp );
+/** @param pOptions
+ NULL means case sensitivity document option is to be used!
+ */
+double CompareFunc( const ScCompare& rComp, ScCompareOptions* pOptions = NULL );
double Compare();
-ScMatrixRef CompareMat();
+/** @param pOptions
+ NULL means case sensitivity document option is to be used!
+ */
+ScMatrixRef CompareMat( ScCompareOptions* pOptions = NULL );
+ScMatrixRef QueryMat( ScMatrix* pMat, ScCompareOptions& rOptions );
void ScEqual();
void ScNotEqual();
void ScLess();
diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx
index 9ab62e4..297f648 100644
--- a/sc/source/core/tool/address.cxx
+++ b/sc/source/core/tool/address.cxx
@@ -1126,39 +1126,48 @@ lcl_ScAddress_Parse ( const sal_Unicode* p, ScDocument* pDoc, ScAddress& rAddr,
bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
SCTAB nDefTab, ScRefAddress& rRefAddress,
- const ScAddress::Details& rDetails )
+ const ScAddress::Details& rDetails,
+ ScAddress::ExternalInfo* pExtInfo /* = NULL */ )
{
- ScAddress aAddr( 0, 0, nDefTab );
- USHORT nRes = lcl_ScAddress_Parse( rRefString.GetBuffer(), pDoc, aAddr, rDetails, NULL );
- if( nRes & SCA_VALID )
+ bool bRet = false;
+ if (pExtInfo || (ScGlobal::FindUnquoted( rRefString, SC_COMPILER_FILE_TAB_SEP) == STRING_NOTFOUND))
{
- rRefAddress.Set( aAddr,
- ((nRes & SCA_COL_ABSOLUTE) == 0),
- ((nRes & SCA_ROW_ABSOLUTE) == 0),
- ((nRes & SCA_TAB_ABSOLUTE) == 0));
- return TRUE;
+ ScAddress aAddr( 0, 0, nDefTab );
+ USHORT nRes = aAddr.Parse( rRefString, pDoc, rDetails, pExtInfo);
+ if ( nRes & SCA_VALID )
+ {
+ rRefAddress.Set( aAddr,
+ ((nRes & SCA_COL_ABSOLUTE) == 0),
+ ((nRes & SCA_ROW_ABSOLUTE) == 0),
+ ((nRes & SCA_TAB_ABSOLUTE) == 0));
+ bRet = true;
+ }
}
- else
- return FALSE;
+ return bRet;
}
bool ConvertDoubleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab,
ScRefAddress& rStartRefAddress, ScRefAddress& rEndRefAddress,
- const ScAddress::Details& rDetails )
+ const ScAddress::Details& rDetails,
+ ScAddress::ExternalInfo* pExtInfo /* = NULL */ )
{
- BOOL bRet = FALSE;
- // FIXME : This will break for Lotus
- xub_StrLen nPos = rRefString.Search(':');
- if (nPos != STRING_NOTFOUND)
+ bool bRet = false;
+ if (pExtInfo || (ScGlobal::FindUnquoted( rRefString, SC_COMPILER_FILE_TAB_SEP) == STRING_NOTFOUND))
{
- String aTmp( rRefString );
- sal_Unicode* p = aTmp.GetBufferAccess();
- p[ nPos ] = 0;
- if( ConvertSingleRef( pDoc, p, nDefTab, rStartRefAddress, rDetails ) )
+ ScRange aRange( ScAddress( 0, 0, nDefTab));
+ USHORT nRes = aRange.Parse( rRefString, pDoc, rDetails, pExtInfo);
+ if ( nRes & SCA_VALID )
{
- nDefTab = rStartRefAddress.Tab();
- bRet = ConvertSingleRef( pDoc, p + nPos + 1, nDefTab, rEndRefAddress, rDetails );
+ rStartRefAddress.Set( aRange.aStart,
+ ((nRes & SCA_COL_ABSOLUTE) == 0),
+ ((nRes & SCA_ROW_ABSOLUTE) == 0),
+ ((nRes & SCA_TAB_ABSOLUTE) == 0));
+ rEndRefAddress.Set( aRange.aEnd,
+ ((nRes & SCA_COL2_ABSOLUTE) == 0),
+ ((nRes & SCA_ROW2_ABSOLUTE) == 0),
+ ((nRes & SCA_TAB2_ABSOLUTE) == 0));
+ bRet = true;
}
}
return bRet;
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 8af7c1d..8a1c4a1 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -1811,9 +1811,11 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos,ScTokenArra
aPos( rPos ),
pCharClass( ScGlobal::pCharClass ),
mnPredetectedReference(0),
+ mnRangeOpPosInSymbol(-1),
pConv( pConvOOO_A1 ),
mbCloseBrackets( true ),
- mbExtendedErrorDetection( false )
+ mbExtendedErrorDetection( false ),
+ mbRewind( false )
{
nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0;
}
@@ -1824,9 +1826,11 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos)
aPos( rPos ),
pCharClass( ScGlobal::pCharClass ),
mnPredetectedReference(0),
+ mnRangeOpPosInSymbol(-1),
pConv( pConvOOO_A1 ),
mbCloseBrackets( true ),
- mbExtendedErrorDetection( false )
+ mbExtendedErrorDetection( false ),
+ mbRewind( false )
{
nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0;
}
@@ -1962,7 +1966,7 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
sal_Unicode c = *pSrc;
sal_Unicode cLast = 0;
bool bQuote = false;
- bool bRangeOp = false;
+ mnRangeOpPosInSymbol = -1;
ScanState eState = ssGetChar;
xub_StrLen nSpaces = 0;
sal_Unicode cSep = mxSymbols->getSymbol( ocSep).GetChar(0);
@@ -2110,11 +2114,11 @@ Label_MaskStateMachine:
else
*pSym++ = c;
}
- else if (c == ':' && !bRangeOp)
+ else if (c == ':' && mnRangeOpPosInSymbol < 0)
{
// One range operator may form Sheet1.A:A, which we need to
// pass as one entity to IsReference().
- bRangeOp = true;
+ mnRangeOpPosInSymbol = pSym - &cSymbol[0];
if( pSym == &cSymbol[ MAXSTRLEN-1 ] )
{
SetError(errStringOverflow);
@@ -2409,7 +2413,7 @@ Label_MaskStateMachine:
{
nSrcPos = sal::static_int_cast<xub_StrLen>( nSrcPos + nSpaces );
String aSymbol;
- bRangeOp = false;
+ mnRangeOpPosInSymbol = -1;
USHORT nErr = 0;
do
{
@@ -2438,9 +2442,9 @@ Label_MaskStateMachine:
bi18n = (c == cSheetSep || c == SC_COMPILER_FILE_TAB_SEP);
}
// One range operator restarts parsing for second reference.
- if (c == ':' && !bRangeOp)
+ if (c == ':' && mnRangeOpPosInSymbol < 0)
{
- bRangeOp = true;
+ mnRangeOpPosInSymbol = aSymbol.Len();
bi18n = true;
}
if ( bi18n )
@@ -2460,6 +2464,14 @@ Label_MaskStateMachine:
nSrcPos = sal::static_int_cast<xub_StrLen>( pSrc - pStart );
*pSym = 0;
}
+ if (mnRangeOpPosInSymbol >= 0 && mnRangeOpPosInSymbol == (pSym-1) - &cSymbol[0])
+ {
+ // This is a trailing range operator, which is nonsense. Will be caught
+ // in next round.
+ mnRangeOpPosInSymbol = -1;
+ *--pSym = 0;
+ --nSrcPos;
+ }
if ( bAutoCorrect )
aCorrectedSymbol = cSymbol;
if (bAutoIntersection && nSpaces > 1)
@@ -2835,8 +2847,21 @@ BOOL ScCompiler::IsReference( const String& rName )
// Though the range operator is handled explicitly, when encountering
// something like Sheet1.A:A we will have to treat it as one entity if it
// doesn't pass as single cell reference.
- if (ScGlobal::FindUnquoted( rName, ':') != STRING_NOTFOUND)
- return IsDoubleReference( rName);
+ if (mnRangeOpPosInSymbol > 0) // ":foo" would be nonsense
+ {
+ if (IsDoubleReference( rName))
+ return true;
+ // Now try with a symbol up to the range operator, rewind source
+ // position.
+ sal_Int32 nLen = mnRangeOpPosInSymbol;
+ while (cSymbol[++nLen])
+ ;
+ cSymbol[mnRangeOpPosInSymbol] = 0;
+ nSrcPos = static_cast< xub_StrLen >( nSrcPos - (nLen - mnRangeOpPosInSymbol) );
+ mnRangeOpPosInSymbol = -1;
+ mbRewind = true;
+ return true; // end all checks
+ }
return false;
}
@@ -3515,48 +3540,52 @@ BOOL ScCompiler::NextNewToken( bool bInArray )
else
bMayBeFuncName = TRUE; // operators and other opcodes
- String aOrg( cSymbol ); // preserve file names in IsReference()
- String aUpper( ScGlobal::pCharClass->upper( aOrg ) );
+ do
+ {
+ mbRewind = false;
+ String aOrg( cSymbol ); // preserve file names in IsReference()
+ String aUpper( ScGlobal::pCharClass->upper( aOrg ) );
#if 0
- fprintf( stderr, "Token '%s'\n",
- rtl::OUStringToOString( aUpper, RTL_TEXTENCODING_UTF8 ).getStr() );
+ fprintf( stderr, "Token '%s'\n",
+ rtl::OUStringToOString( aUpper, RTL_TEXTENCODING_UTF8 ).getStr() );
#endif
- // Column 'DM' ("Deutsche Mark", German currency) couldn't be
- // referred to => IsReference() before IsValue().
- // #42016# Italian ARCTAN.2 resulted in #REF! => IsOpcode() before
- // IsReference().
- // IsBoolean before isValue to catch inline bools without the kludge
- // for inline arrays.
- if ( !(bMayBeFuncName && IsOpCode( aUpper, bInArray ))
- && !IsReference( aOrg )
- && !(bAllowBooleans && IsBoolean( aUpper ))
- && !IsValue( aUpper )
- && !IsNamedRange( aUpper )
- && !IsExternalNamedRange(aOrg)
- && !IsDBRange( aUpper )
- && !IsColRowName( aUpper )
- && !(bMayBeFuncName && IsMacro( aUpper ))
- && !(bMayBeFuncName && IsOpCode2( aUpper )) )
- {
- if ( mbExtendedErrorDetection )
+ // Column 'DM' ("Deutsche Mark", German currency) couldn't be
+ // referred to => IsReference() before IsValue().
+ // #42016# Italian ARCTAN.2 resulted in #REF! => IsOpcode() before
+ // IsReference().
+ // IsBoolean before isValue to catch inline bools without the kludge
+ // for inline arrays.
+ if ( !(bMayBeFuncName && IsOpCode( aUpper, bInArray ))
+ && !IsReference( aOrg )
+ && !(bAllowBooleans && IsBoolean( aUpper ))
+ && !IsValue( aUpper )
+ && !IsNamedRange( aUpper )
+ && !IsExternalNamedRange(aOrg)
+ && !IsDBRange( aUpper )
+ && !IsColRowName( aUpper )
+ && !(bMayBeFuncName && IsMacro( aUpper ))
+ && !(bMayBeFuncName && IsOpCode2( aUpper )) )
{
- // set an error and end compilation
- SetError( errNoName );
- return FALSE;
- }
- else
- {
- // Provide single token information and continue. Do not set an
- // error, that would prematurely end compilation. Simple
- // unknown names are handled by the interpreter.
- ScGlobal::pCharClass->toLower( aUpper );
- aToken.SetString( aUpper.GetBuffer() );
- aToken.NewOpCode( ocBad );
- pRawToken = aToken.Clone();
- if ( bAutoCorrect )
- AutoCorrectParsedSymbol();
+ if ( mbExtendedErrorDetection )
+ {
+ // set an error and end compilation
+ SetError( errNoName );
+ return FALSE;
+ }
+ else
+ {
+ // Provide single token information and continue. Do not set an
+ // error, that would prematurely end compilation. Simple
+ // unknown names are handled by the interpreter.
+ ScGlobal::pCharClass->toLower( aUpper );
+ aToken.SetString( aUpper.GetBuffer() );
+ aToken.NewOpCode( ocBad );
+ pRawToken = aToken.Clone();
+ if ( bAutoCorrect )
+ AutoCorrectParsedSymbol();
+ }
}
- }
+ } while (mbRewind);
}
return TRUE;
}
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 6a1f5c1..fb56ebb 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -1,7 +1,7 @@
/*************************************************************************
*
* 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
@@ -71,6 +71,7 @@
#include "lookupcache.hxx"
#include "rangenam.hxx"
#include "compiler.hxx"
+#include "externalrefmgr.hxx"
#define SC_DOUBLE_MAXVALUE 1.7e307
@@ -324,7 +325,7 @@ void lcl_AdjustJumpMatrix( ScJumpMatrix* pJumpM, ScMatrixRef& pResMat, SCSIZE nP
SCSIZE nAdjustCols, nAdjustRows;
pJumpM->GetDimensions( nJumpCols, nJumpRows );
pJumpM->GetResMatDimensions( nResCols, nResRows );
- if (( nJumpCols == 1 && nParmCols > nResCols ) ||
+ if (( nJumpCols == 1 && nParmCols > nResCols ) ||
( nJumpRows == 1 && nParmRows > nResRows ))
{
if ( nJumpCols == 1 && nJumpRows == 1 )
@@ -626,7 +627,20 @@ bool ScInterpreter::JumpMatrix( short nStackLevel )
}
-double ScInterpreter::CompareFunc( const ScCompare& rComp )
+ScCompareOptions::ScCompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg ) :
+ aQueryEntry(rEntry),
+ bRegEx(bReg),
+ bMatchWholeCell(pDoc->GetDocOptions().IsMatchWholeCell()),
+ bIgnoreCase(true)
+{
+ bRegEx = (bRegEx && (aQueryEntry.eOp == SC_EQUAL || aQueryEntry.eOp == SC_NOT_EQUAL));
+ // Interpreter functions usually are case insensitive, except the simple
+ // comparison operators, for which these options aren't used. Override in
+ // struct if needed.
+}
+
+
+double ScInterpreter::CompareFunc( const ScCompare& rComp, ScCompareOptions* pOptions )
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::CompareFunc" );
// Keep DoubleError if encountered
@@ -698,7 +712,53 @@ double ScInterpreter::CompareFunc( const ScCompare& rComp )
fRes = 1; // number is less than string
else
{
- if (pDok->GetDocOptions().IsIgnoreCase())
+ // Both strings.
+ if (pOptions)
+ {
+ // All similar to Sctable::ValidQuery(), *rComp.pVal[1] actually
+ // is/must be identical to *rEntry.pStr, which is essential for
+ // regex to work through GetSearchTextPtr().
+ ScQueryEntry& rEntry = pOptions->aQueryEntry;
+ DBG_ASSERT( *rComp.pVal[1] == *rEntry.pStr, "ScInterpreter::CompareFunc: broken options");
+ if (pOptions->bRegEx)
+ {
+ xub_StrLen nStart = 0;
+ xub_StrLen nStop = rComp.pVal[0]->Len();
+ bool bMatch = rEntry.GetSearchTextPtr(
+ !pOptions->bIgnoreCase)->SearchFrwrd( *rComp.pVal[0],
+ &nStart, &nStop);
+ if (bMatch && pOptions->bMatchWholeCell && (nStart != 0 || nStop != rComp.pVal[0]->Len()))
+ bMatch = false; // RegEx must match entire string.
+ fRes = (bMatch ? 0 : 1);
+ }
+ else if (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)
+ {
+ ::utl::TransliterationWrapper* pTransliteration =
+ (pOptions->bIgnoreCase ? ScGlobal::pTransliteration :
+ ScGlobal::pCaseTransliteration);
+ bool bMatch;
+ if (pOptions->bMatchWholeCell)
+ bMatch = pTransliteration->isEqual( *rComp.pVal[0], *rComp.pVal[1]);
+ else
+ {
+ String aCell( pTransliteration->transliterate(
+ *rComp.pVal[0], ScGlobal::eLnge, 0,
+ rComp.pVal[0]->Len(), NULL));
+ String aQuer( pTransliteration->transliterate(
+ *rComp.pVal[1], ScGlobal::eLnge, 0,
+ rComp.pVal[1]->Len(), NULL));
+ bMatch = (aCell.Search( aQuer ) != STRING_NOTFOUND);
+ }
+ fRes = (bMatch ? 0 : 1);
+ }
+ else if (pOptions->bIgnoreCase)
+ fRes = (double) ScGlobal::pCollator->compareString(
+ *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
+ else
+ fRes = (double) ScGlobal::pCaseCollator->compareString(
+ *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
+ }
+ else if (pDok->GetDocOptions().IsIgnoreCase())
fRes = (double) ScGlobal::pCollator->compareString(
*rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
else
@@ -763,7 +823,7 @@ double ScInterpreter::Compare()
}
-ScMatrixRef ScInterpreter::CompareMat()
+ScMatrixRef ScInterpreter::CompareMat( ScCompareOptions* pOptions )
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::CompareMat" );
String aVal1, aVal2;
@@ -855,7 +915,7 @@ ScMatrixRef ScInterpreter::CompareMat()
aComp.bEmpty[i] = FALSE;
}
}
- pResMat->PutDouble( CompareFunc( aComp ), j,k );
+ pResMat->PutDouble( CompareFunc( aComp, pOptions ), j,k );
}
else
pResMat->PutString( ScGlobal::GetRscString(STR_NO_VALUE), j,k );
@@ -885,7 +945,7 @@ ScMatrixRef ScInterpreter::CompareMat()
*aComp.pVal[i] = pMat[i]->GetString(j);
aComp.bEmpty[i] = pMat[i]->IsEmpty(j);
}
- pResMat->PutDouble( CompareFunc( aComp ), j );
+ pResMat->PutDouble( CompareFunc( aComp, pOptions ), j );
}
}
}
@@ -894,6 +954,52 @@ ScMatrixRef ScInterpreter::CompareMat()
}
+ScMatrixRef ScInterpreter::QueryMat( ScMatrix* pMat, ScCompareOptions& rOptions )
+{
+ short nSaveCurFmtType = nCurFmtType;
+ short nSaveFuncFmtType = nFuncFmtType;
+ PushMatrix( pMat);
+ if (rOptions.aQueryEntry.bQueryByString)
+ PushString( *rOptions.aQueryEntry.pStr);
+ else
+ PushDouble( rOptions.aQueryEntry.nVal);
+ ScMatrixRef pResultMatrix = CompareMat( &rOptions);
+ nCurFmtType = nSaveCurFmtType;
+ nFuncFmtType = nSaveFuncFmtType;
+ if (nGlobalError || !pResultMatrix)
+ {
+ SetError( errIllegalParameter);
+ return pResultMatrix;
+ }
+
+ switch (rOptions.aQueryEntry.eOp)
+ {
+ case SC_EQUAL:
+ pResultMatrix->CompareEqual();
+ break;
+ case SC_LESS:
+ pResultMatrix->CompareLess();
+ break;
+ case SC_GREATER:
+ pResultMatrix->CompareGreater();
+ break;
+ case SC_LESS_EQUAL:
+ pResultMatrix->CompareLessEqual();
+ break;
+ case SC_GREATER_EQUAL:
+ pResultMatrix->CompareGreaterEqual();
+ break;
+ case SC_NOT_EQUAL:
+ pResultMatrix->CompareNotEqual();
+ break;
+ default:
+ SetError( errIllegalArgument);
+ DBG_ERROR1( "ScInterpreter::QueryMat: unhandled comparison operator: %d", (int)rOptions.aQueryEntry.eOp);
+ }
+ return pResultMatrix;
+}
+
+
void ScInterpreter::ScEqual()
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::ScEqual" );
@@ -1818,7 +1924,7 @@ void ScInterpreter::ScCell()
else if( aInfoType.EqualsAscii( "COORD" ) )
{ // address, lotus 1-2-3 formatted: $TABLE:$COL$ROW
// Yes, passing tab as col is intentional!
- ScAddress( static_cast<SCCOL>(aCellPos.Tab()), 0, 0 ).Format(
+ ScAddress( static_cast<SCCOL>(aCellPos.Tab()), 0, 0 ).Format(
aFuncResult, (SCA_COL_ABSOLUTE|SCA_VALID_COL), NULL, pDok->GetAddressConvention() );
aFuncResult += ':';
String aCellStr;
@@ -2669,7 +2775,7 @@ static ::rtl::OUString lcl_convertIntoFullWidth( const ::rtl::OUString & rStr )
{
aTrans.loadModuleByImplName( ::rtl::OUString::createFromAscii( "HALFWIDTH_FULLWIDTH_LIKE_JIS" ), LANGUAGE_SYSTEM );
bFirstJISCall = false;
- }
+ }
return aTrans.transliterate( rStr, 0, (USHORT) rStr.getLength(), NULL );
}
@@ -3079,7 +3185,7 @@ double ScInterpreter::IterateParameters( ScIterFunc eFunc, BOOL bTextAsZero )
case ifPRODUCT: fRes *= fVal; break;
case ifCOUNT:
if ( nGlobalError )
- {
+ {
nGlobalError = 0;
nCount--;
}
@@ -4310,6 +4416,7 @@ void ScInterpreter::ScCountIf()
SCCOL nCol2;
SCROW nRow2;
SCTAB nTab2;
+ ScMatrixRef pQueryMatrix;
switch ( GetStackType() )
{
case svDoubleRef :
@@ -4326,6 +4433,24 @@ void ScInterpreter::ScCountIf()
nRow2 = nRow1;
nTab2 = nTab1;
break;
+ case svMatrix:
+ {
+ pQueryMatrix = PopMatrix();
+ if (!pQueryMatrix)
+ {
+ PushIllegalParameter();
+ return;
+ }
+ nCol1 = 0;
+ nRow1 = 0;
+ nTab1 = 0;
+ SCSIZE nC, nR;
+ pQueryMatrix->GetDimensions( nC, nR);
+ nCol2 = static_cast< SCCOL>( nC - 1);
+ nRow2 = static_cast< SCROW>( nR - 1);
+ nTab2 = 0;
+ }
+ break;
default:
PushIllegalParameter();
return ;
@@ -4367,15 +4492,37 @@ void ScInterpreter::ScCountIf()
rParam.nCol1 = nCol1;
rParam.nCol2 = nCol2;
rEntry.nField = nCol1;
- ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
- // Entry.nField im Iterator bei Spaltenwechsel weiterschalten
- aCellIter.SetAdvanceQueryParamEntryField( TRUE );
- if ( aCellIter.GetFirst() )
+ if (pQueryMatrix)
{
- do
+ // Never case-sensitive.
+ ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
+ ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
+ if (nGlobalError || !pResultMatrix)
+ {
+ PushIllegalParameter();
+ return;
+ }
+
+ SCSIZE nSize = pResultMatrix->GetElementCount();
+ for (SCSIZE nIndex = 0; nIndex < nSize; ++nIndex)
+ {
+ if (pResultMatrix->IsValue( nIndex) &&
+ pResultMatrix->GetDouble( nIndex))
+ ++fSum;
+ }
+ }
+ else
+ {
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
+ // Entry.nField im Iterator bei Spaltenwechsel weiterschalten
+ aCellIter.SetAdvanceQueryParamEntryField( TRUE );
+ if ( aCellIter.GetFirst() )
{
- fSum++;
- } while ( aCellIter.GetNext() );
+ do
+ {
+ fSum++;
+ } while ( aCellIter.GetNext() );
+ }
}
}
else
@@ -4399,6 +4546,7 @@ void ScInterpreter::ScSumIf()
SCROW nRow3 = 0;
SCTAB nTab3 = 0;
+ ScMatrixRef pSumExtraMatrix;
bool bSumExtraRange = (nParamCount == 3);
if (bSumExtraRange)
{
@@ -4423,6 +4571,10 @@ void ScInterpreter::ScSumIf()
case svSingleRef :
PopSingleRef( nCol3, nRow3, nTab3 );
break;
+ case svMatrix:
+ pSumExtraMatrix = PopMatrix();
+ //! nCol3, nRow3, nTab3 remain 0
+ break;
default:
PushIllegalParameter();
return ;
@@ -4498,6 +4650,7 @@ void ScInterpreter::ScSumIf()
SCCOL nCol2;
SCROW nRow2;
SCTAB nTab2;
+ ScMatrixRef pQueryMatrix;
switch ( GetStackType() )
{
case svRefList :
@@ -4522,13 +4675,31 @@ void ScInterpreter::ScSumIf()
nRow2 = nRow1;
nTab2 = nTab1;
break;
+ case svMatrix:
+ {
+ pQueryMatrix = PopMatrix();
+ if (!pQueryMatrix)
+ {
+ PushIllegalParameter();
+ return;
+ }
+ nCol1 = 0;
+ nRow1 = 0;
+ nTab1 = 0;
+ SCSIZE nC, nR;
+ pQueryMatrix->GetDimensions( nC, nR);
+ nCol2 = static_cast< SCCOL>( nC - 1);
+ nRow2 = static_cast< SCROW>( nR - 1);
+ nTab2 = 0;
+ }
+ break;
default:
PushIllegalParameter();
return ;
}
if ( nTab1 != nTab2 )
{
- PushIllegalParameter();
+ PushIllegalArgument();
return;
}
@@ -4544,15 +4715,29 @@ void ScInterpreter::ScSumIf()
// instead of the result range.
SCCOL nColDelta = nCol2 - nCol1;
SCROW nRowDelta = nRow2 - nRow1;
- if (nCol3 + nColDelta > MAXCOL)
+ SCCOL nMaxCol;
+ SCROW nMaxRow;
+ if (pSumExtraMatrix)
{
- SCCOL nNewDelta = MAXCOL - nCol3;
+ SCSIZE nC, nR;
+ pSumExtraMatrix->GetDimensions( nC, nR);
+ nMaxCol = static_cast< SCCOL>( nC - 1);
+ nMaxRow = static_cast< SCROW>( nR - 1);
+ }
+ else
+ {
+ nMaxCol = MAXCOL;
+ nMaxRow = MAXROW;
+ }
+ if (nCol3 + nColDelta > nMaxCol)
+ {
+ SCCOL nNewDelta = nMaxCol - nCol3;
nCol2 = nCol1 + nNewDelta;
}
- if (nRow3 + nRowDelta > MAXROW)
+ if (nRow3 + nRowDelta > nMaxRow)
{
- SCROW nNewDelta = MAXROW - nRow3;
+ SCROW nNewDelta = nMaxRow - nRow3;
nRow2 = nRow1 + nNewDelta;
}
}
@@ -4592,30 +4777,119 @@ void ScInterpreter::ScSumIf()
rParam.nCol1 = nCol1;
rParam.nCol2 = nCol2;
rEntry.nField = nCol1;
- SCCOL nColDiff = nCol3 - nCol1;
- SCROW nRowDiff = nRow3 - nRow1;
- ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
- // Increment Entry.nField in iterator when switching to next column.
- aCellIter.SetAdvanceQueryParamEntryField( TRUE );
- if ( aCellIter.GetFirst() )
+ SCsCOL nColDiff = nCol3 - nCol1;
+ SCsROW nRowDiff = nRow3 - nRow1;
+ if (pQueryMatrix)
{
- do
+ // Never case-sensitive.
+ ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
+ ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
+ if (nGlobalError || !pResultMatrix)
{
- aAdr.SetCol( aCellIter.GetCol() + nColDiff);
- aAdr.SetRow( aCellIter.GetRow() + nRowDiff);
- ScBaseCell* pCell = GetCell( aAdr );
- if ( HasCellValueData(pCell) )
+ PushIllegalParameter();
+ return;
+ }
+
+ if (pSumExtraMatrix)
+ {
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
{
- fVal = GetCellValue( aAdr, pCell );
- if ( bNull && fVal != 0.0 )
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
{
- bNull = FALSE;
- fMem = fVal;
+ if (pResultMatrix->IsValue( nCol, nRow) &&
+ pResultMatrix->GetDouble( nCol, nRow))
+ {
+ SCSIZE nC = nCol + nColDiff;
+ SCSIZE nR = nRow + nRowDiff;
+ if (pSumExtraMatrix->IsValue( nC, nR))
+ {
+ fVal = pSumExtraMatrix->GetDouble( nC, nR);
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = FALSE;
+ fMem = fVal;
+ }
+ else
+ fSum += fVal;
+ }
+ }
}
- else
- fSum += fVal;
}
- } while ( aCellIter.GetNext() );
+ }
+ else
+ {
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ {
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ {
+ if (pResultMatrix->GetDouble( nCol, nRow))
+ {
+ aAdr.SetCol( nCol + nColDiff);
+ aAdr.SetRow( nRow + nRowDiff);
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( HasCellValueData(pCell) )
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = FALSE;
+ fMem = fVal;
+ }
+ else
+ fSum += fVal;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
+ // Increment Entry.nField in iterator when switching to next column.
+ aCellIter.SetAdvanceQueryParamEntryField( TRUE );
+ if ( aCellIter.GetFirst() )
+ {
+ if (pSumExtraMatrix)
+ {
+ do
+ {
+ SCSIZE nC = aCellIter.GetCol() + nColDiff;
+ SCSIZE nR = aCellIter.GetRow() + nRowDiff;
+ if (pSumExtraMatrix->IsValue( nC, nR))
+ {
+ fVal = pSumExtraMatrix->GetDouble( nC, nR);
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = FALSE;
+ fMem = fVal;
+ }
+ else
+ fSum += fVal;
+ }
+ } while ( aCellIter.GetNext() );
+ }
+ else
+ {
+ do
+ {
+ aAdr.SetCol( aCellIter.GetCol() + nColDiff);
+ aAdr.SetRow( aCellIter.GetRow() + nRowDiff);
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( HasCellValueData(pCell) )
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = FALSE;
+ fMem = fVal;
+ }
+ else
+ fSum += fVal;
+ }
+ } while ( aCellIter.GetNext() );
+ }
+ }
}
}
else
@@ -4650,9 +4924,9 @@ void ScInterpreter::ScLookup()
case svDoubleRef:
{
SCTAB nTabJunk;
- PopDoubleRef(nResCol1, nResRow1, nResTab,
+ PopDoubleRef(nResCol1, nResRow1, nResTab,
nResCol2, nResRow2, nTabJunk);
- if (nResTab != nTabJunk ||
+ if (nResTab != nTabJunk ||
((nResRow2 - nResRow1) > 0 && (nResCol2 - nResCol1) > 0))
{
// The result array must be a vector.
@@ -5762,6 +6036,52 @@ void ScInterpreter::ScDBVarP()
}
+ScTokenArray* lcl_CreateExternalRefTokenArray( const ScAddress& rPos, ScDocument* pDoc,
+ const ScAddress::ExternalInfo& rExtInfo, const ScRefAddress& rRefAd1,
+ const ScRefAddress* pRefAd2 )
+{
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ size_t nSheets = 1;
+ const String* pRealTab = pRefMgr->getRealTableName( rExtInfo.mnFileId, rExtInfo.maTabName);
+ ScTokenArray* pTokenArray = new ScTokenArray;
+ if (pRefAd2)
+ {
+ ScComplexRefData aRef;
+ aRef.InitRangeRel( ScRange( rRefAd1.GetAddress(), pRefAd2->GetAddress()), rPos);
+ aRef.Ref1.SetColRel( rRefAd1.IsRelCol());
+ aRef.Ref1.SetRowRel( rRefAd1.IsRelRow());
+ aRef.Ref1.SetTabRel( rRefAd1.IsRelTab());
+ aRef.Ref1.SetFlag3D( true);
+ aRef.Ref2.SetColRel( pRefAd2->IsRelCol());
+ aRef.Ref2.SetRowRel( pRefAd2->IsRelRow());
+ aRef.Ref2.SetTabRel( pRefAd2->IsRelTab());
+ nSheets = aRef.Ref2.nTab - aRef.Ref1.nTab + 1;
+ aRef.Ref2.SetFlag3D( nSheets > 1 );
+ pTokenArray->AddExternalDoubleReference( rExtInfo.mnFileId,
+ (pRealTab ? *pRealTab : rExtInfo.maTabName), aRef);
+ }
+ else
+ {
+ ScSingleRefData aRef;
+ aRef.InitAddressRel( rRefAd1.GetAddress(), rPos);
+ aRef.SetColRel( rRefAd1.IsRelCol());
+ aRef.SetRowRel( rRefAd1.IsRelRow());
+ aRef.SetTabRel( rRefAd1.IsRelTab());
+ aRef.SetFlag3D( true);
+ pTokenArray->AddExternalSingleReference( rExtInfo.mnFileId,
+ (pRealTab ? *pRealTab : rExtInfo.maTabName), aRef);
+ }
+ // The indirect usage of the external table can't be detected during the
+ // store-to-file cycle, mark it as permanently referenced so it gets stored
+ // even if not directly referenced anywhere.
+ pRefMgr->setCacheTableReferencedPermanently( rExtInfo.mnFileId,
+ rExtInfo.maTabName, nSheets);
+ ScCompiler aComp( pDoc, rPos, *pTokenArray);
+ aComp.CompileTokenArray();
+ return pTokenArray;
+}
+
+
void ScInterpreter::ScIndirect()
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::ScIndirect" );
@@ -5780,15 +6100,46 @@ void ScInterpreter::ScIndirect()
SCTAB nTab = aPos.Tab();
String sRefStr( GetString() );
ScRefAddress aRefAd, aRefAd2;
- if ( ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, aRefAd2, aDetails) ||
+ ScAddress::ExternalInfo aExtInfo;
+ if ( ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, aRefAd2, aDetails, &aExtInfo) ||
(bTryXlA1 && ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd,
- aRefAd2, aDetailsXlA1)))
- PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(),
- aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() );
- else if ( ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, aDetails) ||
+ aRefAd2, aDetailsXlA1, &aExtInfo)))
+ {
+ if (aExtInfo.mbExternal)
+ {
+ /* TODO: future versions should implement a proper subroutine
+ * token. This procedure here is a minimally invasive fix for
+ * #i101645# in OOo3.1.1 */
+ // Push a subroutine on the instruction code stack that
+ // resolves the external reference as the next instruction.
+ aCode.Push( lcl_CreateExternalRefTokenArray( aPos, pDok,
+ aExtInfo, aRefAd, &aRefAd2));
+ // Signal subroutine call to interpreter.
+ PushTempToken( new FormulaUnknownToken( ocCall));
+ }
+ else
+ PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(),
+ aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() );
+ }
+ else if ( ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, aDetails, &aExtInfo) ||
(bTryXlA1 && ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd,
- aDetailsXlA1)))
- PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() );
+ aDetailsXlA1, &aExtInfo)))
+ {
+ if (aExtInfo.mbExternal)
+ {
+ /* TODO: future versions should implement a proper subroutine
+ * token. This procedure here is a minimally invasive fix for
+ * #i101645# in OOo3.1.1 */
+ // Push a subroutine on the instruction code stack that
+ // resolves the external reference as the next instruction.
+ aCode.Push( lcl_CreateExternalRefTokenArray( aPos, pDok,
+ aExtInfo, aRefAd, NULL));
+ // Signal subroutine call to interpreter.
+ PushTempToken( new FormulaUnknownToken( ocCall));
+ }
+ else
+ PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() );
+ }
else
{
do
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index cd2fccc..cf8dc7e 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -3812,6 +3812,15 @@ StackVar ScInterpreter::Interpret()
default : PushError( errUnknownOpCode); break;
}
+ // If the function signalled that it pushed a subroutine on the
+ // instruction code stack instead of a result, continue with
+ // execution of the subroutine.
+ if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall)
+ {
+ Pop();
+ continue; // while( ( pCur = aCode.Next() ) != NULL ...
+ }
+
// Remember result matrix in case it could be reused.
if (pTokenMatrixMap && sp && GetStackType() == svMatrix)
pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( pCur,
diff --git a/sc/source/core/tool/reftokenhelper.cxx b/sc/source/core/tool/reftokenhelper.cxx
index 8ecb44a..07db9fd 100644
--- a/sc/source/core/tool/reftokenhelper.cxx
+++ b/sc/source/core/tool/reftokenhelper.cxx
@@ -54,8 +54,9 @@ void ScRefTokenHelper::compileRangeRepresentation(
const sal_Unicode cSep = ';';
const sal_Unicode cQuote = '\'';
+ bool bFailure = false;
sal_Int32 nOffset = 0;
- while (nOffset >= 0)
+ while (nOffset >= 0 && !bFailure)
{
OUString aToken;
ScRangeStringConverter::GetTokenByOffset(aToken, rRangeStr, nOffset, cSep, cQuote);
@@ -66,14 +67,49 @@ void ScRefTokenHelper::compileRangeRepresentation(
aCompiler.SetGrammar(FormulaGrammar::GRAM_ENGLISH);
auto_ptr<ScTokenArray> pArray(aCompiler.CompileString(aToken));
- // There should only be one reference per range token.
- pArray->Reset();
- FormulaToken* p = pArray->GetNextReference();
- if (!p)
- continue;
+ // There MUST be exactly one reference per range token and nothing
+ // else, and it MUST be a valid reference, not some #REF!
+ USHORT nLen = pArray->GetLen();
+ if (!nLen)
+ continue; // Should a missing range really be allowed?
+ if (nLen != 1)
+ bFailure = true;
+ else
+ {
+ pArray->Reset();
+ const FormulaToken* p = pArray->GetNextReference();
+ if (!p)
+ bFailure = true;
+ else
+ {
+ const ScToken* pT = static_cast<const ScToken*>(p);
+ switch (pT->GetType())
+ {
+ case svSingleRef:
+ if (!pT->GetSingleRef().Valid())
+ bFailure = true;
+ break;
+ case svDoubleRef:
+ if (!pT->GetDoubleRef().Valid())
+ bFailure = true;
+ break;
+ case svExternalSingleRef:
+ if (!pT->GetSingleRef().ValidExternal())
+ bFailure = true;
+ break;
+ case svExternalDoubleRef:
+ if (!pT->GetDoubleRef().ValidExternal())
+ bFailure = true;
+ break;
+ default:
+ ;
+ }
+ if (!bFailure)
+ rRefTokens.push_back(
+ ScSharedTokenRef(static_cast<ScToken*>(p->Clone())));
+ }
+ }
- rRefTokens.push_back(
- ScSharedTokenRef(static_cast<ScToken*>(p->Clone())));
#if 0
switch (p->GetType())
{
@@ -93,7 +129,10 @@ void ScRefTokenHelper::compileRangeRepresentation(
;
}
#endif
+
}
+ if (bFailure)
+ rRefTokens.clear();
}
bool ScRefTokenHelper::getRangeFromToken(ScRange& rRange, const ScSharedTokenRef& pToken, bool bExternal)
diff --git a/sc/source/filter/excel/xichart.cxx b/sc/source/filter/excel/xichart.cxx
index 8364ccf..e48179d 100644
--- a/sc/source/filter/excel/xichart.cxx
+++ b/sc/source/filter/excel/xichart.cxx
@@ -633,8 +633,11 @@ Reference< XLabeledDataSequence > lclCreateLabeledDataSequence(
// ----------------------------------------------------------------------------
XclImpChSourceLink::XclImpChSourceLink( const XclImpChRoot& rRoot ) :
- XclImpChRoot( rRoot ),
- mpTokenArray(static_cast<ScTokenArray*>(NULL))
+ XclImpChRoot( rRoot )
+{
+}
+
+XclImpChSourceLink::~XclImpChSourceLink()
{
}
@@ -645,6 +648,7 @@ void XclImpChSourceLink::ReadChSourceLink( XclImpStream& rStrm )
>> maData.mnFlags
>> maData.mnNumFmtIdx;
+ mpTokenArray.reset();
if( GetLinkType() == EXC_CHSRCLINK_WORKSHEET )
{
// read token array
@@ -686,31 +690,34 @@ sal_uInt16 XclImpChSourceLink::GetCellCount() const
using namespace ::formula;
sal_uInt32 nCellCount = 0;
- mpTokenArray->Reset();
- for (const FormulaToken* p = mpTokenArray->First(); p; p = mpTokenArray->Next())
+ if( mpTokenArray.is() )
{
- switch (p->GetType())
+ mpTokenArray->Reset();
+ for (const FormulaToken* p = mpTokenArray->First(); p; p = mpTokenArray->Next())
{
- case svSingleRef:
- case svExternalSingleRef:
- // single cell
- ++nCellCount;
- break;
- case svDoubleRef:
- case svExternalDoubleRef:
+ switch (p->GetType())
{
- // cell range
- const ScComplexRefData& rData = static_cast<const ScToken*>(p)->GetDoubleRef();
- const ScSingleRefData& s = rData.Ref1;
- const ScSingleRefData& e = rData.Ref2;
- SCsTAB nTab = e.nTab - s.nTab;
- SCsCOL nCol = e.nCol - s.nCol;
- SCsROW nRow = e.nRow - s.nRow;
- nCellCount += static_cast<sal_uInt32>(nCol+1) *
- static_cast<sal_uInt32>(nRow+1) *
- static_cast<sal_uInt32>(nTab+1);
+ case svSingleRef:
+ case svExternalSingleRef:
+ // single cell
+ ++nCellCount;
+ break;
+ case svDoubleRef:
+ case svExternalDoubleRef:
+ {
+ // cell range
+ const ScComplexRefData& rData = static_cast<const ScToken*>(p)->GetDoubleRef();
+ const ScSingleRefData& s = rData.Ref1;
+ const ScSingleRefData& e = rData.Ref2;
+ SCsTAB nTab = e.nTab - s.nTab;
+ SCsCOL nCol = e.nCol - s.nCol;
+ SCsROW nRow = e.nRow - s.nRow;
+ nCellCount += static_cast<sal_uInt32>(nCol+1) *
+ static_cast<sal_uInt32>(nRow+1) *
+ static_cast<sal_uInt32>(nTab+1);
+ }
+ break;
}
- break;
}
}
return limit_cast<sal_uInt16>(nCellCount);
@@ -736,25 +743,23 @@ Reference< XDataSequence > XclImpChSourceLink::CreateDataSequence( const OUStrin
{
Reference< XDataSequence > xDataSeq;
Reference< XDataProvider > xDataProv = GetDataProvider();
- if( xDataProv.is() )
+ if( xDataProv.is() && mpTokenArray.is() )
{
- if (mpTokenArray)
+ ScCompiler aComp( GetDocPtr(), ScAddress(), *mpTokenArray );
+ aComp.SetGrammar( ::formula::FormulaGrammar::GRAM_ENGLISH );
+ OUStringBuffer aRangeRep;
+ aComp.CreateStringFromTokenArray( aRangeRep );
+ try
{
- ScCompiler aComp(GetDocPtr(), ScAddress(), *mpTokenArray);
- aComp.SetGrammar(::formula::FormulaGrammar::GRAM_ENGLISH);
- OUStringBuffer aBuf;
- aComp.CreateStringFromTokenArray(aBuf);
- xDataSeq = xDataProv->createDataSequenceByRangeRepresentation(
- aBuf.makeStringAndClear());
+ xDataSeq = xDataProv->createDataSequenceByRangeRepresentation( aRangeRep.makeStringAndClear() );
+ // set sequence role
+ ScfPropertySet aSeqProp( xDataSeq );
+ aSeqProp.SetProperty( EXC_CHPROP_ROLE, rRole );
}
- else
+ catch( Exception& )
{
DBG_ERRORFILE( "XclImpChSourceLink::CreateDataSequence - cannot create data sequence" );
}
-
- // set sequence role
- ScfPropertySet aSeqProp( xDataSeq );
- aSeqProp.SetProperty( EXC_CHPROP_ROLE, rRole );
}
return xDataSeq;
}
diff --git a/sc/source/filter/excel/xistyle.cxx b/sc/source/filter/excel/xistyle.cxx
index 7f1627e..a83e203 100644
--- a/sc/source/filter/excel/xistyle.cxx
+++ b/sc/source/filter/excel/xistyle.cxx
@@ -1088,26 +1088,25 @@ void XclImpXF::ReadXF( XclImpStream& rStrm )
}
}
-void XclImpXF::SetStyleName( const String& rStyleName )
+void XclImpXF::SetStyleName( const String& rStyleName, bool bBuiltIn, bool bForceCreate )
{
DBG_ASSERT( IsStyleXF(), "XclImpXF::SetStyleName - not a style XF" );
- DBG_ASSERT( rStyleName.Len(), "XclImpXF::SetStyleName - style name empty" );
- if( IsStyleXF() && !maStyleName.Len() )
+ DBG_ASSERT( rStyleName.Len() > 0, "XclImpXF::SetStyleName - style name empty" );
+ if( IsStyleXF() && (rStyleName.Len() > 0) )
{
maStyleName = rStyleName;
- mbForceCreate = true;
+ mbWasBuiltIn = bBuiltIn;
+ mbForceCreate = bForceCreate;
}
}
-void XclImpXF::SetBuiltInStyleName( sal_uInt8 nStyleId, sal_uInt8 nLevel )
+void XclImpXF::ChangeStyleName( const String& rStyleName )
{
- DBG_ASSERT( IsStyleXF(), "XclImpXF::SetStyleName - not a style XF" );
- if( IsStyleXF() && !maStyleName.Len() )
- {
- mbWasBuiltIn = true;
- maStyleName = XclTools::GetBuiltInStyleName( nStyleId, nLevel );
- mbForceCreate = nStyleId == EXC_STYLE_NORMAL; // force creation of "Default" style
- }
+ DBG_ASSERT( IsStyleXF(), "XclImpXF::ChangeStyleName - not a style XF" );
+ DBG_ASSERT( rStyleName.Len() > 0, "XclImpXF::ChangeStyleName - new style name empty" );
+ DBG_ASSERT( maStyleName.Len() > 0, "XclImpXF::ChangeStyleName - old style name empty" );
+ if( IsStyleXF() && (rStyleName.Len() > 0) )
+ maStyleName = rStyleName;
}
void XclImpXF::CreateUserStyle()
@@ -1239,6 +1238,7 @@ ScStyleSheet* XclImpXF::CreateStyleSheet()
{
if( !mpStyleSheet && maStyleName.Len() ) // valid name implies style XF
{
+ bool bCreatePattern = false;
// there may be a user-defined "Default" - test on built-in too!
bool bDefStyle = mbWasBuiltIn && (maStyleName == ScGlobal::GetRscString( STR_STYLENAME_STANDARD ));
if( bDefStyle )
@@ -1249,16 +1249,23 @@ ScStyleSheet* XclImpXF::CreateStyleSheet()
mpStyleSheet = static_cast< ScStyleSheet* >( GetStyleSheetPool().Find(
ScGlobal::GetRscString( STR_STYLENAME_STANDARD ), SFX_STYLE_FAMILY_PARA ) );
DBG_ASSERT( mpStyleSheet, "XclImpXF::CreateStyleSheet - Default style not found" );
+ bCreatePattern = true;
}
else
{
- /* mbWasBuiltIn==true forces renaming of equal-named user defined styles
- to be able to re-export built-in styles correctly. */
- mpStyleSheet = &ScfTools::MakeCellStyleSheet( GetStyleSheetPool(), maStyleName, mbWasBuiltIn );
+ /* #i103281# do not create another style sheet of the same name,
+ if it exists already. This is needed to prevent that styles
+ pasted from clipboard get duplicated over and over. */
+ mpStyleSheet = static_cast< ScStyleSheet* >( GetStyleSheetPool().Find( maStyleName, SFX_STYLE_FAMILY_PARA ) );
+ if( !mpStyleSheet )
+ {
+ mpStyleSheet = &static_cast< ScStyleSheet& >( GetStyleSheetPool().Make( maStyleName, SFX_STYLE_FAMILY_PARA, SFXSTYLEBIT_USERDEF ) );
+ bCreatePattern = true;
+ }
}
// bDefStyle==true omits default pool items in CreatePattern()
- if( mpStyleSheet )
+ if( bCreatePattern && mpStyleSheet )
mpStyleSheet->GetItemSet().Put( CreatePattern( bDefStyle ).GetItemSet() );
}
return mpStyleSheet;
@@ -1274,6 +1281,16 @@ XclImpXFBuffer::XclImpXFBuffer( const XclImpRoot& rRoot ) :
void XclImpXFBuffer::Initialize()
{
maXFList.Clear();
+ maStyleXFs.clear();
+ /* Reserve style names that are built-in in Calc. For BIFF4 workbooks
+ which contain a separate list of styles per sheet, reserve all existing
+ names if current sheet is not the first sheet. This will create unique
+ names for styles in different sheets with the same name. */
+ bool bReserveAll = (GetBiff() == EXC_BIFF4) && (GetCurrScTab() > 0);
+ SfxStyleSheetIterator aStyleIter( GetDoc().GetStyleSheetPool(), SFX_STYLE_FAMILY_PARA );
+ for( SfxStyleSheetBase* pStyleSheet = aStyleIter.First(); pStyleSheet; pStyleSheet = aStyleIter.Next() )
+ if( bReserveAll || !pStyleSheet->IsUserDefined() )
+ maStyleXFs[ pStyleSheet->GetName() ] = 0;
}
void XclImpXFBuffer::ReadXF( XclImpStream& rStrm )
@@ -1282,9 +1299,9 @@ void XclImpXFBuffer::ReadXF( XclImpStream& rStrm )
pXF->ReadXF( rStrm );
maXFList.Append( pXF );
+ // set the name of the "Default" cell style (always the first XF in an Excel file)
if( (GetBiff() >= EXC_BIFF3) && (maXFList.Count() == 1) )
- // set the name of the "Default" cell style (always the first XF in an Excel file)
- pXF->SetBuiltInStyleName( EXC_STYLE_NORMAL, 0 );
+ CalcStyleName( *pXF, EXC_STYLE_NORMAL, 0 );
}
void XclImpXFBuffer::ReadStyle( XclImpStream& rStrm )
@@ -1301,7 +1318,7 @@ void XclImpXFBuffer::ReadStyle( XclImpStream& rStrm )
{
sal_uInt8 nStyleId, nLevel;
rStrm >> nStyleId >> nLevel;
- pXF->SetBuiltInStyleName( nStyleId, nLevel );
+ CalcStyleName( *pXF, nStyleId, nLevel );
}
else // user-defined styles
{
@@ -1310,8 +1327,20 @@ void XclImpXFBuffer::ReadStyle( XclImpStream& rStrm )
aStyleName = rStrm.ReadByteString( false ); // 8 bit length
else
aStyleName = rStrm.ReadUniString();
- if( aStyleName.Len() ) // #i1624# #i1768# ignore unnamed styles
- pXF->SetStyleName( aStyleName );
+
+ if( aStyleName.Len() > 0 ) // #i1624# #i1768# ignore unnamed styles
+ {
+ // #i103281# check if this is a new built-in style introduced in XL2007
+ bool bBuiltIn = false;
+ if( (GetBiff() == EXC_BIFF8) && (rStrm.GetNextRecId() == EXC_ID_STYLEEXT) && rStrm.StartNextRecord() )
+ {
+ sal_uInt8 nExtFlags;
+ rStrm.Ignore( 12 );
+ rStrm >> nExtFlags;
+ bBuiltIn = ::get_flag( nExtFlags, EXC_STYLEEXT_BUILTIN );
+ }
+ CalcStyleName( *pXF, aStyleName, bBuiltIn );
+ }
}
}
}
@@ -1345,6 +1374,49 @@ void XclImpXFBuffer::ApplyPattern(
}
}
+void XclImpXFBuffer::CalcStyleName( XclImpXF& rXF, const String& rStyleName, bool bBuiltIn )
+{
+ DBG_ASSERT( rStyleName.Len() > 0, "XclImpXFBuffer::CalcStyleName - style name empty" );
+ if( rStyleName.Len() > 0 )
+ {
+ String aStyleName = bBuiltIn ? XclTools::GetBuiltInStyleName( rStyleName ) : rStyleName;
+ SetStyleName( rXF, aStyleName, bBuiltIn, !bBuiltIn );
+ }
+}
+
+void XclImpXFBuffer::CalcStyleName( XclImpXF& rXF, sal_uInt8 nStyleId, sal_uInt8 nLevel )
+{
+ // force creation of "Default" style
+ SetStyleName( rXF, XclTools::GetBuiltInStyleName( nStyleId, nLevel ), true, nStyleId == EXC_STYLE_NORMAL );
+}
+
+void XclImpXFBuffer::SetStyleName( XclImpXF& rXF, const String& rStyleName, bool bBuiltIn, bool bForceCreate )
+{
+ DBG_ASSERT( rXF.IsStyleXF(), "XclImpXFBuffer::SetStyleName - not a style XF" );
+ if( rXF.IsStyleXF() )
+ {
+ // find an unused name
+ String aUnusedName( rStyleName );
+ sal_Int32 nIndex = 0;
+ while( maStyleXFs.count( aUnusedName ) > 0 )
+ aUnusedName.Assign( rStyleName ).Append( ' ' ).Append( String::CreateFromInt32( ++nIndex ) );
+
+ // move old style to new name, if new style is built-in
+ if( bBuiltIn && (aUnusedName != rStyleName) )
+ {
+ XclImpXF*& rpXF = maStyleXFs[ aUnusedName ];
+ rpXF = maStyleXFs[ rStyleName ];
+ if( rpXF )
+ rpXF->ChangeStyleName( aUnusedName );
+ aUnusedName = rStyleName;
+ }
+
+ // insert new style
+ maStyleXFs[ aUnusedName ] = &rXF;
+ rXF.SetStyleName( aUnusedName, bBuiltIn, bForceCreate );
+ }
+}
+
// Buffer for XF indexes in cells =============================================
IMPL_FIXEDMEMPOOL_NEWDEL( XclImpXFRange, 100, 500 )
diff --git a/sc/source/filter/excel/xltools.cxx b/sc/source/filter/excel/xltools.cxx
index ef38a00..a84aaba 100644
--- a/sc/source/filter/excel/xltools.cxx
+++ b/sc/source/filter/excel/xltools.cxx
@@ -511,7 +511,8 @@ sal_Unicode XclTools::GetBuiltInDefNameIndex( const String& rDefName )
// built-in style names -------------------------------------------------------
-const String XclTools::maStyleNamePrefix( RTL_CONSTASCII_USTRINGPARAM( "Excel_BuiltIn_" ) );
+const String XclTools::maStyleNamePrefix1( RTL_CONSTASCII_USTRINGPARAM( "Excel_BuiltIn_" ) );
+const String XclTools::maStyleNamePrefix2( RTL_CONSTASCII_USTRINGPARAM( "Excel Built-in " ) );
static const sal_Char* const ppcStyleNames[] =
{
@@ -534,7 +535,7 @@ String XclTools::GetBuiltInStyleName( sal_uInt8 nStyleId, sal_uInt8 nLevel )
if( nStyleId == EXC_STYLE_NORMAL ) // "Normal" becomes "Default" style
aStyleName = ScGlobal::GetRscString( STR_STYLENAME_STANDARD );
else if( nStyleId < STATIC_TABLE_SIZE( ppcStyleNames ) )
- aStyleName.Assign( maStyleNamePrefix ).AppendAscii( ppcStyleNames[ nStyleId ] );
+ aStyleName.Assign( maStyleNamePrefix1 ).AppendAscii( ppcStyleNames[ nStyleId ] );
if( (nStyleId == EXC_STYLE_ROWLEVEL) || (nStyleId == EXC_STYLE_COLLEVEL) )
aStyleName.Append( String::CreateFromInt32( nLevel + 1 ) );
@@ -542,6 +543,11 @@ String XclTools::GetBuiltInStyleName( sal_uInt8 nStyleId, sal_uInt8 nLevel )
return aStyleName;
}
+String XclTools::GetBuiltInStyleName( const String& rStyleName )
+{
+ return String( maStyleNamePrefix1 ).Append( rStyleName );
+}
+
bool XclTools::IsBuiltInStyleName( const String& rStyleName, sal_uInt8* pnStyleId, xub_StrLen* pnNextChar )
{
// "Default" becomes "Normal"
@@ -553,10 +559,15 @@ bool XclTools::IsBuiltInStyleName( const String& rStyleName, sal_uInt8* pnStyleI
}
// try the other built-in styles
- xub_StrLen nPrefixLen = maStyleNamePrefix.Len();
sal_uInt8 nFoundId = 0;
xub_StrLen nNextChar = 0;
- if( rStyleName.EqualsIgnoreCaseAscii( maStyleNamePrefix, 0, nPrefixLen ) )
+
+ xub_StrLen nPrefixLen = 0;
+ if( rStyleName.EqualsIgnoreCaseAscii( maStyleNamePrefix1, 0, maStyleNamePrefix1.Len() ) )
+ nPrefixLen = maStyleNamePrefix1.Len();
+ else if( rStyleName.EqualsIgnoreCaseAscii( maStyleNamePrefix2, 0, maStyleNamePrefix2.Len() ) )
+ nPrefixLen = maStyleNamePrefix2.Len();
+ if( nPrefixLen > 0 )
{
String aShortName;
for( sal_uInt8 nId = 0; nId < STATIC_TABLE_SIZE( ppcStyleNames ); ++nId )
@@ -583,14 +594,14 @@ bool XclTools::IsBuiltInStyleName( const String& rStyleName, sal_uInt8* pnStyleI
if( pnStyleId ) *pnStyleId = EXC_STYLE_USERDEF;
if( pnNextChar ) *pnNextChar = 0;
- return false;
+ return nPrefixLen > 0; // also return true for unknown built-in styles
}
bool XclTools::GetBuiltInStyleId( sal_uInt8& rnStyleId, sal_uInt8& rnLevel, const String& rStyleName )
{
sal_uInt8 nStyleId;
xub_StrLen nNextChar;
- if( IsBuiltInStyleName( rStyleName, &nStyleId, &nNextChar ) )
+ if( IsBuiltInStyleName( rStyleName, &nStyleId, &nNextChar ) && (nStyleId != EXC_STYLE_USERDEF) )
{
if( (nStyleId == EXC_STYLE_ROWLEVEL) || (nStyleId == EXC_STYLE_COLLEVEL) )
{
@@ -617,24 +628,25 @@ bool XclTools::GetBuiltInStyleId( sal_uInt8& rnStyleId, sal_uInt8& rnLevel, cons
// conditional formatting style names -----------------------------------------
-const String XclTools::maCFStyleNamePrefix( RTL_CONSTASCII_USTRINGPARAM( "Excel_CondFormat_" ) );
+const String XclTools::maCFStyleNamePrefix1( RTL_CONSTASCII_USTRINGPARAM( "Excel_CondFormat_" ) );
+const String XclTools::maCFStyleNamePrefix2( RTL_CONSTASCII_USTRINGPARAM( "ConditionalStyle_" ) );
String XclTools::GetCondFormatStyleName( SCTAB nScTab, sal_Int32 nFormat, sal_uInt16 nCondition )
{
- return String( maCFStyleNamePrefix ).Append( String::CreateFromInt32( nScTab + 1 ) ).
+ return String( maCFStyleNamePrefix1 ).Append( String::CreateFromInt32( nScTab + 1 ) ).
Append( '_' ).Append( String::CreateFromInt32( nFormat + 1 ) ).
Append( '_' ).Append( String::CreateFromInt32( nCondition + 1 ) );
}
bool XclTools::IsCondFormatStyleName( const String& rStyleName, xub_StrLen* pnNextChar )
{
- xub_StrLen nPrefixLen = maCFStyleNamePrefix.Len();
- if( rStyleName.EqualsIgnoreCaseAscii( maCFStyleNamePrefix, 0, nPrefixLen ) )
- {
- if( pnNextChar ) *pnNextChar = nPrefixLen;
- return true;
- }
- return false;
+ xub_StrLen nPrefixLen = 0;
+ if( rStyleName.EqualsIgnoreCaseAscii( maCFStyleNamePrefix1, 0, maCFStyleNamePrefix1.Len() ) )
+ nPrefixLen = maCFStyleNamePrefix1.Len();
+ else if( rStyleName.EqualsIgnoreCaseAscii( maCFStyleNamePrefix2, 0, maCFStyleNamePrefix2.Len() ) )
+ nPrefixLen = maCFStyleNamePrefix2.Len();
+ if( pnNextChar ) *pnNextChar = nPrefixLen;
+ return nPrefixLen > 0;
}
// stream handling ------------------------------------------------------------
diff --git a/sc/source/filter/inc/xichart.hxx b/sc/source/filter/inc/xichart.hxx
index 0ec9ca4..aeafdc5 100644
--- a/sc/source/filter/inc/xichart.hxx
+++ b/sc/source/filter/inc/xichart.hxx
@@ -44,8 +44,6 @@
#include "xistring.hxx"
#include "xiroot.hxx"
-#include <boost/shared_ptr.hpp>
-
namespace com { namespace sun { namespace star {
namespace frame
{
@@ -375,6 +373,7 @@ public:
public:
explicit XclImpChSourceLink( const XclImpChRoot& rRoot );
+ virtual ~XclImpChSourceLink();
/** Reads the CHSOURCELINK record (link to source data). */
void ReadChSourceLink( XclImpStream& rStrm );
@@ -410,7 +409,7 @@ private:
// Tokens representing data ranges. This must be ref-counted to allow the
// parent class to be stored in a STL container.
- ::boost::shared_ptr<ScTokenArray> mpTokenArray;
+ ScfRef< ScTokenArray > mpTokenArray;
};
typedef ScfRef< XclImpChSourceLink > XclImpChSourceLinkRef;
diff --git a/sc/source/filter/inc/xistyle.hxx b/sc/source/filter/inc/xistyle.hxx
index fe43aa7..2fe3a6e 100644
--- a/sc/source/filter/inc/xistyle.hxx
+++ b/sc/source/filter/inc/xistyle.hxx
@@ -397,15 +397,13 @@ public:
/** Reads an XF record. */
void ReadXF( XclImpStream& rStrm );
- /** Sets the style name of this XF, if it is a style XF.
- @descr Additionally creates this user-defined style in the Calc document. */
- void SetStyleName( const String& rStyleName );
- /** Sets the style name of this XF from a built-in Excel style, if it is a style XF.
- @descr Does not create the style in the Calc document. This is done on demand
- in CreatePattern(), if the style is really used. */
- void SetBuiltInStyleName( sal_uInt8 nStyleId, sal_uInt8 nLevel );
-
+ /** Sets the style name of this XF, if it is a style XF. */
+ void SetStyleName( const String& rStyleName, bool bBuiltIn, bool bForceCreate );
+ /** Changes the style name of this XF, if it is a style XF. */
+ void ChangeStyleName( const String& rStyleName );
+ /** Returns the style name of this XF, if it is a style XF. */
inline const String& GetStyleName() const { return maStyleName; }
+
inline sal_uInt8 GetHorAlign() const { return maAlignment.mnHorAlign; }
inline sal_uInt8 GetVerAlign() const { return maAlignment.mnVerAlign; }
inline sal_uInt16 GetFontIndex() const { return mnXclFont; }
@@ -501,7 +499,15 @@ public:
SCTAB nScTab, const XclImpXFIndex& rXFIndex );
private:
+ void CalcStyleName( XclImpXF& rXF, const String& rStyleName, bool bBuiltIn );
+ void CalcStyleName( XclImpXF& rXF, sal_uInt8 nStyleId, sal_uInt8 nLevel );
+ void SetStyleName( XclImpXF& rXF, const String& rStyleName, bool bBuiltIn, bool bForceCreate );
+
+private:
+ typedef ::std::map< String, XclImpXF* > XclImpStyleXFMap;
+
ScfDelList< XclImpXF > maXFList; /// List of contents of all XF record.
+ XclImpStyleXFMap maStyleXFs; /// Maps style names to style XF records.
};
// Buffer for XF indexes in cells =============================================
diff --git a/sc/source/filter/inc/xlstyle.hxx b/sc/source/filter/inc/xlstyle.hxx
index 303da21..b8e682f 100644
--- a/sc/source/filter/inc/xlstyle.hxx
+++ b/sc/source/filter/inc/xlstyle.hxx
@@ -242,6 +242,12 @@ const sal_uInt8 EXC_STYLE_USERDEF = 0xFF; /// No built-in styl
const sal_uInt8 EXC_STYLE_LEVELCOUNT = 7; /// Number of outline level styles.
const sal_uInt8 EXC_STYLE_NOLEVEL = 0xFF; /// Default value for unused level.
+// (0x0892) STYLEEXT ----------------------------------------------------------
+
+const sal_uInt16 EXC_ID_STYLEEXT = 0x0892;
+
+const sal_uInt8 EXC_STYLEEXT_BUILTIN = 0x01;
+
// Structs and classes ========================================================
// Color data =================================================================
diff --git a/sc/source/filter/inc/xltools.hxx b/sc/source/filter/inc/xltools.hxx
index 2c16c05..d818fa9 100644
--- a/sc/source/filter/inc/xltools.hxx
+++ b/sc/source/filter/inc/xltools.hxx
@@ -1,7 +1,7 @@
/*************************************************************************
*
* 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
@@ -197,6 +197,8 @@ public:
@param nLevel The zero-based outline level for RowLevel and ColLevel styles.
@return The style name or an empty string, if the parameters are not valid. */
static String GetBuiltInStyleName( sal_uInt8 nStyleId, sal_uInt8 nLevel );
+ /** Returns the passed style name with a special built-in prefix. */
+ static String GetBuiltInStyleName( const String& rStyleName );
/** Returns true, if the passed string is a name of an Excel built-in style.
@param pnStyleId If not 0, the found style identifier will be returned here.
@param pnNextChar If not 0, the index of the char after the evaluated substring will be returned here. */
@@ -230,8 +232,10 @@ public:
// ------------------------------------------------------------------------
private:
static const String maDefNamePrefix; /// Prefix for built-in defined names.
- static const String maStyleNamePrefix; /// Prefix for built-in cell style names.
- static const String maCFStyleNamePrefix; /// Prefix for cond. formatting style names.
+ static const String maStyleNamePrefix1; /// Prefix for built-in cell style names.
+ static const String maStyleNamePrefix2; /// Prefix for built-in cell style names from OOX filter.
+ static const String maCFStyleNamePrefix1; /// Prefix for cond. formatting style names.
+ static const String maCFStyleNamePrefix2; /// Prefix for cond. formatting style names from OOX filter.
};
// read/write colors ----------------------------------------------------------
diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index 728a90d..780fa22 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -3308,7 +3308,7 @@ void ScXMLExport::WriteExternalRefCaches()
return;
ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
- pRefMgr->resetSrcFileData();
+ pRefMgr->resetSrcFileData(GetOrigFileName());
sal_uInt16 nCount = pRefMgr->getExternalFileCount();
for (sal_uInt16 nFileId = 0; nFileId < nCount; ++nFileId)
{
diff --git a/sc/source/filter/xml/xmlexternaltabi.cxx b/sc/source/filter/xml/xmlexternaltabi.cxx
index ca94d26..b953b26 100644
--- a/sc/source/filter/xml/xmlexternaltabi.cxx
+++ b/sc/source/filter/xml/xmlexternaltabi.cxx
@@ -100,6 +100,32 @@ SvXMLImportContext* ScXMLExternalRefTabSourceContext::CreateChildContext(
return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
}
+/**
+ * Make sure the URL is a valid relative URL, mainly to avoid storing
+ * absolute URL as relative URL by accident. For now, we only check the first
+ * three characters which are assumed to be always '../', because the relative
+ * URL for an external document is always in reference to the content.xml
+ * fragment of the original document.
+ */
+static bool lcl_isValidRelativeURL(const OUString& rUrl)
+{
+ sal_Int32 n = ::std::min( rUrl.getLength(), static_cast<sal_Int32>(3));
+ if (n < 3)
+ return false;
+ const sal_Unicode* p = rUrl.getStr();
+ for (sal_Int32 i = 0; i < n; ++i)
+ {
+ sal_Unicode c = p[i];
+ if (i < 2 && c != '.')
+ // the path must begin with '..'
+ return false;
+ else if (i == 2 && c != '/')
+ // a '/' path separator must follow
+ return false;
+ }
+ return true;
+}
+
void ScXMLExternalRefTabSourceContext::EndElement()
{
ScDocument* pDoc = mrScImport.GetDocument();
@@ -107,7 +133,7 @@ void ScXMLExternalRefTabSourceContext::EndElement()
return;
ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
- if (!maRelativeUrl.equals(mrExternalRefInfo.maFileUrl))
+ if (lcl_isValidRelativeURL(maRelativeUrl))
pRefMgr->setRelativeFileName(mrExternalRefInfo.mnFileId, maRelativeUrl);
pRefMgr->setFilterData(mrExternalRefInfo.mnFileId, maFilterName, maFilterOptions);
}
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index 7032b2d..15eaf67 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -143,7 +143,8 @@ private:
// ============================================================================
ScExternalRefCache::Table::Table()
- : mbReferenced( true) // Prevent accidental data loss due to lack of knowledge.
+ : meReferenced( REFERENCED_MARKED )
+ // Prevent accidental data loss due to lack of knowledge.
{
}
@@ -151,14 +152,25 @@ ScExternalRefCache::Table::~Table()
{
}
+void ScExternalRefCache::Table::setReferencedFlag( ScExternalRefCache::Table::ReferencedFlag eFlag )
+{
+ meReferenced = eFlag;
+}
+
void ScExternalRefCache::Table::setReferenced( bool bReferenced )
{
- mbReferenced = bReferenced;
+ if (meReferenced != REFERENCED_PERMANENT)
+ meReferenced = (bReferenced ? REFERENCED_MARKED : UNREFERENCED);
+}
+
+ScExternalRefCache::Table::ReferencedFlag ScExternalRefCache::Table::getReferencedFlag() const
+{
+ return meReferenced;
}
bool ScExternalRefCache::Table::isReferenced() const
{
- return mbReferenced;
+ return meReferenced != UNREFERENCED;
}
void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex)
@@ -737,21 +749,57 @@ bool ScExternalRefCache::setCacheDocReferenced( sal_uInt16 nFileId )
return areAllCacheTablesReferenced();
}
-bool ScExternalRefCache::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName )
+bool ScExternalRefCache::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets, bool bPermanent )
{
- size_t nIndex = 0;
- TableTypeRef pTab = getCacheTable( nFileId, rTabName, false, &nIndex);
- if (pTab.get())
+ DocItem* pDoc = getDocItem(nFileId);
+ if (pDoc)
{
- if (!pTab->isReferenced())
+ size_t nIndex = 0;
+ String aTabNameUpper = ScGlobal::pCharClass->upper( rTabName);
+ if (lcl_getTableDataIndex( pDoc->maTableNameIndex, aTabNameUpper, nIndex))
{
- pTab->setReferenced( true);
- addCacheTableToReferenced( nFileId, nIndex);
+ size_t nStop = ::std::min( nIndex + nSheets, pDoc->maTables.size());
+ for (size_t i = nIndex; i < nStop; ++i)
+ {
+ TableTypeRef pTab = pDoc->maTables[i];
+ if (pTab.get())
+ {
+ Table::ReferencedFlag eNewFlag = (bPermanent ?
+ Table::REFERENCED_PERMANENT :
+ Table::REFERENCED_MARKED);
+ Table::ReferencedFlag eOldFlag = pTab->getReferencedFlag();
+ if (eOldFlag != Table::REFERENCED_PERMANENT && eNewFlag != eOldFlag)
+ {
+ pTab->setReferencedFlag( eNewFlag);
+ addCacheTableToReferenced( nFileId, i);
+ }
+ }
+ }
}
}
return areAllCacheTablesReferenced();
}
+void ScExternalRefCache::setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets )
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (pDoc)
+ {
+ size_t nIndex = 0;
+ String aTabNameUpper = ScGlobal::pCharClass->upper( rTabName);
+ if (lcl_getTableDataIndex( pDoc->maTableNameIndex, aTabNameUpper, nIndex))
+ {
+ size_t nStop = ::std::min( nIndex + nSheets, pDoc->maTables.size());
+ for (size_t i = nIndex; i < nStop; ++i)
+ {
+ TableTypeRef pTab = pDoc->maTables[i];
+ if (pTab.get())
+ pTab->setReferencedFlag( Table::REFERENCED_PERMANENT);
+ }
+ }
+ }
+}
+
void ScExternalRefCache::setAllCacheTableReferencedStati( bool bReferenced )
{
if (bReferenced)
@@ -791,9 +839,17 @@ void ScExternalRefCache::setAllCacheTableReferencedStati( bool bReferenced )
TableTypeRef & xTab = rDocItem.maTables[i];
if (xTab.get())
{
- xTab->setReferenced( false);
- rDocReferenced.maTables[i] = false;
- rDocReferenced.mbAllTablesReferenced = false;
+ if (xTab->getReferencedFlag() == Table::REFERENCED_PERMANENT)
+ addCacheTableToReferenced( nFileId, i);
+ else
+ {
+ xTab->setReferencedFlag( Table::UNREFERENCED);
+ rDocReferenced.maTables[i] = false;
+ rDocReferenced.mbAllTablesReferenced = false;
+ // An addCacheTableToReferenced() actually may have
+ // resulted in mbAllReferenced been set. Clear it.
+ maReferenced.mbAllReferenced = false;
+ }
}
}
}
@@ -989,7 +1045,7 @@ void ScExternalRefLink::DataChanged(const String& /*rMimeType*/, const Any& /*rV
else
{
// The source document has changed.
- pMgr->switchSrcFile(mnFileId, aFile);
+ pMgr->switchSrcFile(mnFileId, aFile, aFilter);
maFilterName = aFilter;
}
}
@@ -1480,9 +1536,19 @@ bool ScExternalRefManager::setCacheDocReferenced( sal_uInt16 nFileId )
return maRefCache.setCacheDocReferenced( nFileId);
}
-bool ScExternalRefManager::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName )
+bool ScExternalRefManager::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets )
+{
+ return maRefCache.setCacheTableReferenced( nFileId, rTabName, nSheets, false);
+}
+
+void ScExternalRefManager::setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets )
{
- return maRefCache.setCacheTableReferenced( nFileId, rTabName);
+ if (isInReferenceMarking())
+ // Do all maintenance work.
+ maRefCache.setCacheTableReferenced( nFileId, rTabName, nSheets, true);
+ else
+ // Set only the permanent flag.
+ maRefCache.setCacheTableReferencedPermanently( nFileId, rTabName, nSheets);
}
void ScExternalRefManager::setAllCacheTableReferencedStati( bool bReferenced )
@@ -1824,24 +1890,17 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, Stri
if (!pFileData)
return NULL;
+ // Always load the document by using the path created from the relative
+ // path. If the referenced document is not there, simply exit. The
+ // original file name should be used only when the relative path is not
+ // given.
String aFile = pFileData->maFileName;
+ maybeCreateRealFileName(nFileId);
+ if (pFileData->maRealFileName.Len())
+ aFile = pFileData->maRealFileName;
+
if (!isFileLoadable(aFile))
- {
- // The original file path is not loadable. Try the relative path.
- // Note that the path is relative to the content.xml substream which
- // is one-level higher than the file itself.
-
- if (!pFileData->maRelativeName.Len())
- return NULL;
-
- INetURLObject aBaseURL(getOwnDocumentName());
- aBaseURL.insertName(OUString::createFromAscii("content.xml"));
- bool bWasAbs = false;
- aFile = aBaseURL.smartRel2Abs(pFileData->maRelativeName, bWasAbs).GetMainURL(INetURLObject::NO_DECODE);
- if (!isFileLoadable(aFile))
- // Ok, I've tried both paths but no success. Bail out.
- return NULL;
- }
+ return NULL;
String aOptions;
ScDocumentLoader::GetFilterName(aFile, rFilter, aOptions, true, false);
@@ -1893,6 +1952,9 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, Stri
bool ScExternalRefManager::isFileLoadable(const String& rFile) const
{
+ if (!rFile.Len())
+ return false;
+
if (isOwnDocument(rFile))
return false;
@@ -1927,6 +1989,32 @@ void ScExternalRefManager::maybeLinkExternalFile(sal_uInt16 nFileId)
maLinkedDocs.insert(LinkedDocMap::value_type(nFileId, true));
}
+void ScExternalRefManager::SrcFileData::maybeCreateRealFileName(const String& rOwnDocName)
+{
+ if (!maRelativeName.Len())
+ // No relative path given. Nothing to do.
+ return;
+
+ if (maRealFileName.Len())
+ // Real file name already created. Nothing to do.
+ return;
+
+ // Formulate the absolute file path from the relative path.
+ const String& rRelPath = maRelativeName;
+ INetURLObject aBaseURL(rOwnDocName);
+ aBaseURL.insertName(OUString::createFromAscii("content.xml"));
+ bool bWasAbs = false;
+ maRealFileName = aBaseURL.smartRel2Abs(rRelPath, bWasAbs).GetMainURL(INetURLObject::NO_DECODE);
+}
+
+void ScExternalRefManager::maybeCreateRealFileName(sal_uInt16 nFileId)
+{
+ if (nFileId >= maSrcFiles.size())
+ return;
+
+ maSrcFiles[nFileId].maybeCreateRealFileName(getOwnDocumentName());
+}
+
bool ScExternalRefManager::compileTokensByCell(const ScAddress& rCell)
{
ScBaseCell* pCell;
@@ -1997,12 +2085,17 @@ sal_uInt16 ScExternalRefManager::getExternalFileId(const String& rFile)
return static_cast<sal_uInt16>(maSrcFiles.size() - 1);
}
-const String* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId) const
+const String* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId)
{
if (nFileId >= maSrcFiles.size())
return NULL;
- return &maSrcFiles[nFileId].maFileName;
+ maybeCreateRealFileName(nFileId);
+
+ if (maSrcFiles[nFileId].maRealFileName.Len())
+ return &maSrcFiles[nFileId].maRealFileName;
+ else
+ return &maSrcFiles[nFileId].maFileName;
}
bool ScExternalRefManager::hasExternalFile(sal_uInt16 nFileId) const
@@ -2071,10 +2164,17 @@ void ScExternalRefManager::breakLink(sal_uInt16 nFileId)
notifyAllLinkListeners(nFileId, LINK_BROKEN);
}
-void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const String& rNewFile)
+void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const String& rNewFile, const String& rNewFilter)
{
maSrcFiles[nFileId].maFileName = rNewFile;
maSrcFiles[nFileId].maRelativeName.Erase();
+ maSrcFiles[nFileId].maRealFileName.Erase();
+ if (!maSrcFiles[nFileId].maFilterName.Equals(rNewFilter))
+ {
+ // Filter type has changed.
+ maSrcFiles[nFileId].maFilterName = rNewFilter;
+ maSrcFiles[nFileId].maFilterOptions.Erase();
+ }
refreshNames(nFileId);
}
@@ -2108,19 +2208,18 @@ bool ScExternalRefManager::hasExternalData() const
return !maSrcFiles.empty();
}
-void ScExternalRefManager::resetSrcFileData()
+void ScExternalRefManager::resetSrcFileData(const String& rBaseFileUrl)
{
- INetURLObject aBaseURL(getOwnDocumentName());
- aBaseURL.insertName(OUString::createFromAscii("content.xml"));
- String aBaseUrlStr = aBaseURL.GetMainURL(INetURLObject::NO_DECODE);
for (vector<SrcFileData>::iterator itr = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
itr != itrEnd; ++itr)
{
- if (!itr->maRelativeName.Len())
- {
- itr->maRelativeName = URIHelper::simpleNormalizedMakeRelative(
- aBaseUrlStr, itr->maFileName);
- }
+ // Re-generate relative file name from the absolute file name.
+ String aAbsName = itr->maRealFileName;
+ if (!aAbsName.Len())
+ aAbsName = itr->maFileName;
+
+ itr->maRelativeName = URIHelper::simpleNormalizedMakeRelative(
+ rBaseFileUrl, aAbsName);
}
}
More information about the ooo-build-commit
mailing list