[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